About towo

towo has been writing stuff on the Internet on and off for years. He also thinks that author blurbs are silly.

pisg: patch to irssi parser for euIRC ‘admin’ user mode

As pisg is ill-equipped to handle sup­port for ‘admin’ users in the stan­dard con­fi­gu­ra­tion, I went on a quick code hunt to find the bit of code responsi­ble for strip­ping nick modes from a log line. A bit counter-intuitively, this func­tion is cal­led normalline, and not some­thing like normalize or strip_mode.

Anyhow, here’s a small patch to fix the pro­blem for the Irssi par­ser module:

--- modules/Pisg/Parser/Format/irssi.pm.old	2008-02-13 21:40:25.000000000 +0100
+++ modules/Pisg/Parser/Format/irssi.pm	2010-03-16 02:29:42.000000000 +0100
@@ -10,7 +10,7 @@
     my ($type, %args) = @_;
     my $self = {
         cfg => $args{cfg},
-        normalline => '^(\d+):\d+[^<*^!]+<[@%+~& ]?([^>]+)> (.*)',
+        normalline => '^(\d+):\d+[^<*^!]+<[@%+~&! ]?([^>]+)> (.*)',
         actionline => '^(\d+):\d+[^ ]+ +\* (\S+) (.*)',
         thirdline  => '^(\d+):(\d+)[^-]+-\!- (\S+) (\S+) (\S+) (\S+) (\S+)(.*)',
     };

Or you could just down­load the diff directly.

A new reason for leaving Ubuntu

So, if you’re won­de­ring your­self: “Why, Ubuntu is in the pro­cess of making ever­y­thing quite a bit more annoy­ing and fucking things up”, yet still think “that might just be mis­jud­ged opi­nion”, then fret no more. There’s an easy way to now know that Cano­ni­cal has offi­ci­ally gone bonkers.

The Ubuntu One Music Store.

After instal­ling an annoy­ing App Market-like “Soft­ware cen­ter” by default, swit­ching users over to a IM cli­ent that’s only remo­tely usa­ble, try­ing to sell you a cloud-based sto­rage solu­tion and swit­ching to Yahoo as the default search engine, you really have to won­der what the guys responsi­ble are up to.

So.

In short, Cano­ni­cal is on the verge of going Apple. Just bail boat while you still can.

D&D item: Martyr’s Collar

See­ing how ever­yone else is cur­rently crea­ting inte­res­ting items, I thought that I should throw one of my ideas into the mix. And after a bit of tin­ke­ring with how it should work, I present:

Martyr’s Col­lar Level 5

Res­ting tight against the throat, the wea­rer is always remin­ded of the price of sacrifice.

Lv 5   1.000 gp

Item slot:
Neck
Pro­perty:
This item can mean instant death for the cha­rac­ter. To wield it, the cha­rac­ter must suc­ceed at a hard will­power check. After three failu­res, the cha­rac­ter needs to take an exten­ded rest before try­ing again.
Power (At-Will ♦ Necrotic):
Stan­dard action. A con­scious and wil­ling cha­rac­ter may activate the col­lar while it is around their throat. The col­lar magi­cally con­stricts, seve­r­ing the user’s head from their body. The user’s life energy ser­ves as a power source for the col­lar and sends every attu­ned ally in range (burst 10) to the point defined by the attu­ning pro­cess.
Being able to sur­vive the deca­pi­ta­tion does not save the user, as all of their life energy is used up to power the collar’s magic.
The allies do not need to be wil­ling, con­scious, or even alive. If, for wha­te­ver rea­son, the desti­na­tion is not reachable, the col­lar will not activate. After the tele­por­ta­tion, the col­lar expands to its nor­mal pro­por­ti­ons and loses any attunement.
Power (Daily):
Stan­dard action. Every wil­ling ally in a burst 5 are attu­ned to the col­lar, and the item its­elf is attu­ned to the loca­tion. When the at-will power is used, all allies attu­ned and in range are trans­por­ted back to the cur­rent loca­tion. The col­lar does not need to be worn to be attu­ned; any cha­rac­ter tou­ch­ing the item can initiate the pro­cess. When pas­sing bet­ween owners, the item does not lose con­nec­tion to any attu­ned user or the attu­ned location.

Nobody really knows how these devices ever came to be, but they seem to have been used by devout and loyal war­ri­ors throug­hout time to save com­ra­des from cer­tain death by using their own life to shield them. The ulti­mate heroic sacri­fice, most souls sacri­fi­cing their bodies this way ascend to the Astral Sea.

Trusting self-signed certificates with Google Chrome on Linux

Update: added the “C” flag to SSL attri­bu­tes which I acci­den­tally for­got to include.
Also chan­ged $HOST to $host, as $HOST is the shell para­me­ter for the cur­rent hostname…

If you’re not really sure about how you can stop Chrome from per­man­ently remin­ding you that the ser­ver you’re con­nec­ting to is a bad boy (read: using a self-signed cer­ti­fi­cate), you’ll pro­bably end up loo­king at CACert’s Brow­ser Cli­ent page by way of Google. With a bit of rea­ding docu­men­ta­tion, you can pro­bably find out how to import a self-signed cer­ti­fi­cate and mark it as trus­ted, but since you’re pro­bably lazy, you’d rather just copy and paste a few instructions.

First, I have to stress is that blindly trus­ting a cer­ti­fi­cate you down­load off the inter­net is a Bad Idea. But expres­sing a cer­tain laissez-faire atti­tude: if you’re stu­pid enough to copy and paste blindly, you deserve it.

Second, sim­ple copy and paste instructions:

openssl s_client -connect $host:443 -showcerts > temporary_file
certutil -d sql:$HOME/.pki/nssdb -A -t CP,,C -n "$host" -i temporary_file

Third, expla­na­ti­ons:

  • s_client just con­nects to the given host­name, 443 being, as you should know, the (default) HTTP SSL port.
  • –show­certs shows all kinds of infor­ma­tion about the cer­ti­fi­cate, inclu­ding the cer­ti­fi­cate its­elf. You will pro­bably have to hit ^C/^D to stop s_client.
  • If you get mul­ti­ple (and dif­fe­rent) cer­ti­fi­ca­tes, first one will be the ser­ver cer­ti­fi­cate, and second one the CA certificate.
  • cer­tu­til (package hint: libnss3-tools can be used to manage your local «Net­work Secu­rity Ser­vices» SQLite database.
  • The spe­ci­fied argu­ment for cer­tu­til are:
    1. The data­base to use (in this case, the user-specific NSS database).
    2. The flag to add some­thing to the data­base (-A).
    3. The “trust types” for the cer­ti­fi­cate, in “SSL, S/MIME, CA” noti­fi­ca­tion: “P” for a trus­ted peer, and “C” for a cer­ti­fi­cate aut­ho­rity that may issue ser­ver certificates.
    4. A short­name to iden­tify the cer­ti­fi­cate in the data­base. The host­name works well and is fairly obvious.

A records on top level domains

After I stum­bled upon the won­der­ful URL shor­te­ner http://to/ today and imme­dia­tely began pos­ting it on IRC, I recei­ved a com­ment that someone didn’t even know that is was pos­si­ble to do so. I, of course, could only com­ment “of course it’s pos­si­ble”. But in the same train of thought, I just had to have a look at who else has a valid A record on their top level domain. So I fet­ched the IANA TLD list and, after being baff­led by the puny­code TLDs, threw some sh at the pro­blem:
(for domain in $(grep -v '^#' tlds-alpha-by-domain.txt); do host -t A "${domain}."; done) | grep -v 'has no A record'

For the sake of enjoy­a­bi­lity, I thus offer the results in table form, along with what kind of site is run­ning on port 80. Data time­stamp is 2010–01-08T16:05:00+0100, loca­tion for rou­ting is DTAG-DIAL26 / AS3320.

TLD IP con­tent (port 80)
AC 193.223.78.210 “Always con­nec­ted” (NIC.AC)
AI 209.59.119.34 “Off­shore Infor­ma­tion Services”
BI 196.2.8.205 “It works!”
CM 195.24.205.60 cm [195.24.205.60] 80 (www) : Connection refused
DK 193.163.102.23 “DK Host­mas­ter” (NIC.DK)
GG 87.117.196.80 Chan­nel Isles Domain Registration
HK 203.119.2.28 hk [203.119.2.28] 80 (www) : No route to host
IO 193.223.78.212 NIC.IO
JE 87.117.196.80 Chan­nel Isles Domain Registration
PH 203.119.4.7 HTTP 500.100 via bro­ken Micro­soft IIS
PN 80.68.93.100 Apa­che default home page
PW 203.199.114.33 pw [203.199.114.33] 80 (www) : No route to host
SH 64.251.31.234 sh [64.251.31.234] 80 (www) : No route to host
TK 217.119.57.22 “TK your long URL”, free .tk domain name registry
TM 193.223.78.213 NIC.TM
TO 216.74.32.107 TO./ URL shortener
UZ 91.212.89.8 some WAP page I can’d decipher
WS 63.101.245.10 ws [63.101.245.10] 80 (www) : Connection timed out

So, in short, 5 of 18 (27%) are down­right bro­ken, one is being autistic, and a fur­ther 2 (11%) are not con­fi­gu­red to do anything mea­ningful, lea­ding to a total of 8 — or 44% — of TLD A records being use­l­ess. Bonus: none of the sites have AAAA records and, thus, no IPv6 availability.

Der schmale Schatten hinter mir

Ich fragte mich oft, warum die Men­schen mich immer so selt­sam anschauten.

Es war, als hätte ich irgend­eine große Narbe auf der Stirn. Dau­ernd schauen die Leute mich für einen kur­zen Blick, der vor Ent­set­zen nur so strotzte, an, wenn ich sie frisch ken­nen­lerne. Ich habe keine Ahnung, was ihnen da durch den Kopf geht. Immer, wenn ich sie danach frage, sagen sie, daß da nichts sei, und es nur irgend­eine Zuckung war.

Ich glaube ihnen nicht, denn einige schauen immer noch an die glei­che Stelle dabei, wenn sie das sagen; eine Frau wurde sogar mal bleich.

Aber selbst wenn ich mich im Spie­gel anschaue oder Pho­tos von mir mache, so sehe ich doch nie, was denn bitte unge­wöhn­lich sein soll. Ich habe sol­che Bil­der auch schon mal Leu­ten aus dem Inter­net geschickt, die mich nicht kann­ten: nie­mand hatte da irgend­was aus­zu­set­zen oder ein Pro­blem mit.

Doch immer, wenn sie mich dann doch mal sahen, ergriff sie für genau jenen kur­zen Moment das pure Grauen. Einige wirk­ten, als hät­ten sie gerade eine Lei­che gese­hen, andere, als würde man ihnen ein Mes­ser zwi­schen die Rip­pen ram­men, und wie­der andere, als wäre ich ein Ungeheuer.

Wenn sie dann mit mir reden ist aber alles nor­mal. Nur wenige zucken mit den Augen noch nach oben, um diese komi­sche Stelle zu begut­ach­ten. Mich irri­tiert das umso mehr.

Aber nie­mand will mir sagen, was es ist.


Letz­tens ver­brachte ich etwas Zeit in einer die­ser modi­schen Kaf­fee­bars. An einem der andere Tische saß ein jun­ges Mädel, in die­sem Emo­s­til geklei­det, und schaute regel­mä­ßig zu mir her­über. Ich glaubte, daß auch sie mir auf mein mys­te­riö­ses Merk­mal schaut. Verstörend.

Einige Zeit spä­ter war sie weg. Ich hatte nicht wirk­lich bemerkt, daß sie gegan­gen ist, aber sie war ja auch nur ein Emo. Ich sah aber, daß an ihrem Platz noch etwas Papier lag. Ich hatte bemerkt, daß sie am Schrei­ben war, und wo sie doch die ganze Zeit zu mir rüber geschaut hatte, da packte mich jetzt die Neugier.

Ich ging hin­über zu ihrem Platz und nahm mir das Blatt. Es war in einer ecki­gen, abge­hack­ten Schrift beschrie­ben, ganz ungleich der flie­ßen­den, goti­schen Schrift, die ich jetzt erwar­tet hatte. Geschrie­ben stand:

“Er sitzt mir gegen­über. Er weiß es nicht. Er hat ein Mons­ter hin­ter sich, lang und dünn ragt es hin­ter sei­nem Kopf her­vor. Es ist pech­schwarz, mager wie ein Ske­lett. Nur die Hände sind weiß — und das kno­chige Gesicht, wel­ches ein angst­ein­flö­ßen­des Lächeln beher­bergt. Krank­haft lange, fili­grane Fin­ger stre­cken sich von die­sem Ding fort und schei­nen ihm in den Kopf zu ste­chen. Immer, wenn er sich wen­det, fließt es mit. Es bleibt immer hin­ter ihm. Er weiß nicht, daß es da ist. Es hat kein Spie­gel­bild. Es ist der pure Ter­ror. Sobald man ihn anschaut, wen­det sich das Mons­ter einem zu und grinst einen an. In die­sem Grin­sen… da ist eine Dro­hung. Ich habe Angst. Ich muß gehen.”

Ich sackte auf den Stuhl zurück. Sowas kann doch nicht wahr sein.

Es würde alles erklä­ren, aber es kann doch echt nicht wahr sein. Es gibt keine Mons­ter, sowas gibt es nicht. Das kann nicht sein.

Ich ver­suchte, hin­ter mich zu schauen. Ich ver­suchte, mich schwung­haft umzu­dre­hen, um irgend­et­was, was hin­ter mir sei, zu über­ra­schen. Die Leute schau­ten mich komisch an, als ich mich durch die Bar wand. Ängst­lich. Eine der Damen vom Per­so­nal bat mich, die Örtlich­kei­ten zu ver­las­sen. Ich schaute sie böse an, und sie zuckte merk­lich zusammen.

Ich ging.


Vor eini­gen Tagen habe ich erfah­ren, daß das junge Mädel gestor­ben ist. Das machte mir Angst. Ich habe ange­fan­gen, mich weni­ger mit Men­schen abzu­ge­ben. Meine Angst davor, daß noch jemand ster­ben muß, weil sie sich wagen, die­ses Ding zu erwäh­nen, ist uner­meß­lich. Wie soll man so etwas ver­ant­wor­ten kön­nen? Wer kann mir helfen?

Warum trifft sowas gerade mich?


Ich bin mal wie­der ein­kau­fen. Wie­der in einem neuen Laden; ich will nicht, daß die Leute sich zu sehr an mich gewöh­nen. Eine Frau ver­sucht, mich anzu­lä­cheln. Ich run­zele die Stirn und gebe ihr einen bösen Blick. Sie wen­det sich ab.

Die Ver­käu­fe­rin schaut mich an. Sie schaut nicht auf meine Stirn, oder an mir vor­bei. Sie schaut mich direkt an. Schein­bar ist das Vieh cle­ve­rer gewor­den, so daß es nicht mehr auf­fällt, wenn es Leute einschüchtert.

Ich darf nicht zurück­fal­len, ich muß einen Schritt vor­aus sein. Ich gebe ihr das Geld und wende mich ab, und rette sie durch meine Ignoranz.

Die­ses Mons­ter wird keine Chance mehr bekom­men, ande­ren Leu­ten weh zu tun. Nicht, solange ich sie nicht vor­her ver­trei­ben kann.

Schon wieder nicht da

Sonn­tag Nacht. Mal wie­der liege ich in mei­nem Bett und wälze mich umher, nichts stört mich dabei. Zu viele Gedan­ken sind in mei­nem Kopf unter­wegs. Gedan­ken an Dich.

Ich weiß, das klingt jetzt wie­der sehr dra­ma­tisch. Aber Sonn­tag Nacht um Zwei, da soll­test Du bei mir sein. So, wie ich Dich kenne, bist Du sicher gerade wie­der bei einem ande­ren Kerl. Mit ihm, im Bett. Und ich kann nicht mal sauer auf Dich sein dafür, das ist das Schlimmste.

Egal, was ich auch tue, es nützt nichts: nie bleibst Du bei mir. Und selbst wenn Du mal bei mir bist, so ver­schwin­dest Du doch meist Mor­gens und bist weg, wenn mein Wecker ertönt.

Ich weiß, es wäre schlecht für uns, dau­ernd zusam­men zu sein. Am Ende würde es mich umbrin­gen. Aber ohne Dich kann ich mir mein Leben auch nicht vorstellen.

Kein Gedanke hilft, keine noch so große Zuwen­dung. Aber wenn ich nachts daheim, allein aus Kum­mer saufe, gerade dann machst Du einen Dei­ner Zufalls­be­su­che und bist auf ein­mal bei mir.

Aber zum Alko­ho­li­ker will ich auch nicht wer­den, das ist keine Lösung. Dann wür­dest Du eh nicht mehr wie immer so gele­gen kom­men, und über­haupt ist Alko­hol keine Lösung.

Also sitze ich hier und darf mein Leid kla­gen, wäh­rend ich dar­auf warte, daß Du end­lich kommst.

Weißt Du, manch­mal hasse ich Dich, Schlaf.

Auf dem Heimweg

Es ist Win­ter, und der Tag war lang. Obwohl es erst kurz vor fünf ist, so ist die Sonne doch schon ver­schwun­den, und Du fährst im Dun­keln heim.

Die Men­schen am Bar­ba­rossa­platz drän­gen sich vor der Stra­ßen­bahn; der Win­ter nähert sich wie­der, die Tem­pe­ra­tu­ren fal­len in Rich­tung 0. All die Leute wol­len nur mög­lichst schnell nach Hause, in die warme Stube, weg von ihrem Berufs­all­tag und rein in die pri­vate Zuflucht.

Auch Du fährst gerade mit einer Freun­din nach Hause. Die Stra­ßen­bahn kommt und ihr steigt ein, vor­sich­tig durch den Strom der Men­schen kämp­fend. Ihr wer­det umher­ge­scho­ben, da andere Leute sich hef­tig durch die Menge drän­geln. Einige von ihnen erkämp­fen sich sogar einen Sitz­platz, doch viele brei­ten sich ein­fach nur im Ein­gangs­be­reich aus, unacht­sam der ver­ein­zel­ten Sitz­plätze, die man noch bekom­men kann.

Deine Freun­din und Du, ihr seht ein paar Sitz­plätze an ver­schie­de­nen Bän­ken.. Mit einem Nicken teilt ihr euch auf, und Du setzt Dich an einen noch freien Platz. Du wech­selst ein paar höf­li­che Worte mit der Frau neben Dir, weil Du gegen sie gesto­ßen bist. Der Höf­lich­keit hal­ber lächelst Du.

Dein Platz ist am Fens­ter. Der Blick nach drau­ßen nur eine trübe, dunkle Welt zeigt, von den Lich­tern der Stadt durch­setzt, und Du lehnst den Kopf leicht ans Glas. Deine Augen spre­chen von Dei­ner Trau­rig­keit. Mit einem fal­sches Lächeln auf den Lip­pen schaust Du Dich gele­gent­lich um, suchst hin und wie­der auch die Augen Dei­ner Freundin.

Einige Sta­tio­nen spä­ter ist die Dame neben Dir weg, und Deine Freun­din setzt sich her­über. Ihr kommt ins Gespräch, und sie lächelt sehr viel, doch Du teilst es nicht. Ihr redet über einige Dinge aus eurem Leben, und Du kommst auf Ent­schei­dun­gen zu spre­chen, die Dich miss­mu­tig stim­men. Du seufzt beim Reden.

Beim Stu­den­ten­dorf steigt Deine Bekannte aus. Gegen­über hat sich vor kur­zem ein Mann hin­ge­setzt, schein­bar nicht ganz bei Sin­nen. Er sprach schon eine Weile vor sich hin, irgendwo zwi­schen Gebet und Hil­fe­su­che. Er riecht nach Alkohol.

In der Hand hält er eine Plas­tik­tüte, dadrin eine Fla­sche. Was es ist kannst Du nicht genau sagen. Er fragt Dich, ob Du sie weg­wer­fen sollst. Du nickst und sagst, er solle sie wegwerfen.

Er redet eine Weile lang wei­ter vor sich hin, und in Dei­nen trau­ri­gen Blick mischt sich nur ein klei­nes biss­chen Abscheu. Du schaust den Mann dane­ben an, der Dir direkt gegen­über­sitzt. Ihr habt Augen­kon­takt. Er zuckt mit den Ach­seln, und Du zuckst zurück. Du lächelst.

Deine Augen lächeln nicht mit.

Der Betrun­kene hat inzwi­schen ange­fan­gen, seine schöne Toch­ter anzu­prei­sen, und ver­sucht sie, dem Mann neben Dir schmack­haft zu machen. Er ver­sucht dies nur zag­haft, als wüsste er, daß es so nicht rich­tig ist. Den Ver­sucht lässt er auch kurz dar­auf sein.

Kurz ver­sucht er noch, den Mann dazu bewe­gen, ihm den Alko­hol abzu­neh­men, doch über­legt es sich kurz dar­auf anders. Wenig spä­ter hat er eine Fla­sche Wodka aus der Tüte her­vor­ge­zau­bert, und schaut sie an, als würde er sie jetzt trin­ken. Du sprichst ihn an, und sagst, daß er nicht tun soll.

Er igno­riert Dich und winkt ab.

Du sagst, daß er es nicht machen soll, da es ver­bo­ten sei, Alko­hol in der Bahn zu trinken.

Er igno­riert Dich und winkt wie­der ab.

Du erin­nerst ihn daran, daß er die Fla­sche weg­wer­fen wollte.

Er nimmt einen Schluck.

Du wen­dest Dei­nen Blick ab, suchst Augen­kon­takt mit dem ande­ren Mann Dir gegen­über. Ihr schaut euch wie­der an, und seufzt beide leise, wäh­rend ihr lang­ge­zo­gen die Ach­seln zuckt.

Der Mann Dir gegen­über steht auf und manö­vriert sich vor­sich­tig an dem Alko­ho­li­ker vor­bei. Es ist auch Deine Hal­te­stelle, und Du folgst ihm.

An der Tür trefft ihr euch noch­mal. „Mich inter­es­siert ja, warum er so abge­stürzt ist.“ sagt der Mann. Du ant­wor­test ihm, und Deine Ant­wort ist niedergeschlagen.

Die Tür öffnet sich, und er lässt Dir den Vor­tritt. Du knickst leicht und steigst aus, er folgt.

Du gehst nach rechts weg, nach Hause.

Der Mann geht nach links.

Und immer noch ist es Dei­nem Lächeln ein­sam auf den Lippen.

Shadowrunning GTA4

One of the things I recently noti­ced is that GTA actually gives you a fair amount of choice on how to do some mis­si­ons, but doesn’t really adver­tise the fact.

Play­ing the game after some time (and only few days after a Shado­wrun ses­sion), I went ahead and got to do the mis­sion “Dining Out”, where Yours Truly (on his ava­tar in this case, Niko Bel­lic) had to run a hit on one Kim Young-Guk. Young-Guk was dining at a place cal­led Mr. Fuk.

Warily, I drove Niko to the encoun­ter, inves­ti­ga­ting the site — a rather acces­si­ble and free-standing restau­rant. Tired of all pre­vious hit mis­si­ons, which mostly ended up in me cha­sing the per­son on bicy­cle or car most of the time, I deci­ded to try to be crea­tive. I went around the back, and indeed, in the par­king lot I found a motor­cy­cle and a PMP 600 (which is a remake of one of those Chrys­ler esta­tes). Fea­ring that this would exactly end up as I pre­dic­ted, I rang up Packie and got mys­elf a nice little car bomb.

Pla­c­ing this under the PMP 600, I went inside and sure enough, the stale air in the restau­rant had an unhe­althy dose of lead after a couple of seconds. So one kills all the goons, goes ups­tairs and talks (while sight­ing down along the sights of the gun) to the mana­ger, who said that Kim just fled out through the kit­chen. Of course.

Cha­sing Kim down, one bad­gers through the kit­chens, only to find that Korean bug­ger alre­ady having jum­ped down the fire escap, dod­ging into his PMP 600. One would then have to jump down after him and swing your­self unto the motorcycle.

Smir­king, I let Niko pull out his mobile phone and call (han­dily pre­selec­ted) the bomb, which promptly blows up the car and Kim with it. $13,250 ear­ned wit­hout having to break your neck on the motor­cy­cle and pro­bably crash into some­thing with a spec­ta­cu­lar slow motion scene.

The thing is that GTA often silently encou­ra­ges such beha­viour. There’s a few mis­si­ons where the city gets mission-specific instan­ces, thus undo­ing some chan­ges to the sce­nery you might have cau­sed. But more often than not, you can just start lay­ing traps if you eit­her sus­pect or know what’s going to hap­pen. Place bombs, blo­ckade exits with a lorry, ram down fen­ces to get other ways of access to a loca­tion, start sni­ping people from some totally dif­fe­rent loca­tion, or just go all Altaïr and shuf­fle to a site via the rooftops.

It’s fun, really.

Gaim to Pidgin log conversion

I was brow­sing through some older files of mine and clea­ning up when I stum­bled over a bunch of old instant mes­sen­ging log files. These logs were still in the legacy uni­fied log file for­mat which Gaim (today knows as Pid­gin) used in the begin­ning. I didn’t find a con­ver­ter after about ten seconds of using Google, so I went ahead and wrote my own.

It’s mostly feature-complete, and will split up any num­ber of [something].log you pass to it into [something]/[date].txt style files. What it can’t really do is deter­mine what kind of pro­to­col it’s dea­ling with, so you’ll still have to move the log direc­tory manu­ally to the appro­priate pro­to­col direc­tory inside of ~/.purple/logs. Be wary when moving files, though, as you might acci­den­tally over­write other log files. Use rsync.

Anyhoo, you can eit­her get the file directly or just try this deli­cious copypasta:

#!/usr/bin/perl
# gaim2pidgin.pl
# author:  towo <towo@ydal.de>
# version: 3
# license: CC-BY-DE-3.0
 
use strict;
 
# convert short month names to numbers.
my %shortmonths = (
	'Jan' => '01',
	'Feb' => '02',
	'Mar' => '03',
	'Apr' => '04',
	'May' => '05',
	'Jun' => '06',
	'Jul' => '07',
	'Aug' => '08',
	'Sep' => '09',
	'Oct' => '10',
	'Nov' => '11',
	'Dec' => '12'
);
 
# go through files
FILE: foreach my $file (@ARGV) {
	my ($header, $target);
 
	# sanity checks
	unless (-f $file) {
		warn "$file is not a file.\n";
		next FILE;
	}
	unless(open(LOG, $file)) {
		warn "Unable to open $file for reading: $!\n";
		next FILE;
	}
 
	# get file header, get target name
	chomp($header = <LOG>);
	$header =~ s#<.*?>##g;
	$target = $file;
	$target =~ s/\.log$//;
 
	# check header for correctness
	unless($header =~ m{^(<HTML><HEAD><TITLE>)?IM Sessions with .*? \
                             (</TITLE></HEAD><BODY BGCOLOR=".*?">)?$}i) {
		warn "$file does not seem to be a gaim conversation.\n";
		next FILE;
	}
 
	# read LOG to file
	my @contents = <LOG>;
	close(LOG);
 
	# parse log file (one loop ^= one chat session)
	while(@contents) {
		my ($session, $identifier, $date);
 
		# get session identifier
		chomp($session = shift @contents);
 
		# Strip HTML.
		#$session =~ s#<.*?>##g;
		$session =~ s#</?(FONT|B|I|ALIGN|HTML|HEAD|TITLE|HR|BR|BODY|H3).*?>##ig;
 
		# sanity check for the session identifier
		unless ($session =~ m/^ ?---- New Conversation @ \w{3} (\w{3}) ([0-9 ]{2}) \
                                      (\d{2}):(\d{2}):(\d{2}) (\d{4}) ----$/) {
			warn "Could not recognize session identifier: «$session»\n";
			next FILE;
		}
 
		# extract date from session identifier and create target identifier
		$date = "$6-$shortmonths{$1}-" . sprintf("%02d", $2) . ".$3$4$5";
		$identifier = "$target/$date.txt";
 
		# sanity check for target directory
		unless (-d $target) {
			unless(mkdir $target) {
				warn "Could not create directory $target: $!\n";
				next FILE;
			}
		}
 
		# open output file
		unless(open(OUTPUT, "> $identifier")) {
			warn "Could not write to $identifier: $!\n";
			next FILE;
		}
		select OUTPUT;
 
		# extract log to log file
		until($contents[0] =~ m/^(<HR><BR><H3 Align=Center>)? ?---- New Conversation/ \
                                      or !@contents) {
			my $line = shift @contents;
			$line =~ s#<.*?>##g;
			print $line;
		}
		close OUTPUT;
	}
}

Creative Commons License Licen­sed as CC-BY-DE-3.0.