Tobi's Blog

Archiv für die 'Perl' Kategorie

Allgemeines zu Perl und all seinem Macken

RFC konforme E-Mail-Header

Erstellt von Tobi am 13. November 2008

Wie schon bei den Problemen mit UTF-8 E-Mails berichtet, gibt es eine Spezifikation, wie ein Mail-Header zu kodieren ist. Und als Header zählt auch der Betreff.

Laut dieser Vorgabe (RFC 1522) dürfen in E-Mail-Headern nur die ersten 127 Zeichen des ASCII-Zeichensatzes benutzt werden. Quasi nur alphanumerische Zeichen und eine Hand voll Sonderzeichen. Also auf keinen Fall Umlaute oder ähnliches.

Wenn man zum Versenden z.B. das Perl-CPAN-Modul MIME::Lite benutzt, werden die nicht erlaubten Zeichen nicht automatisch konvertiert. Da muss man sich selber kümmern.

Am leichtesten geht es mit dem Perl-CPAN-Modul MIME::EncWords. Die Funktion MIME::EncWords::encode_mimewords(STRING) : QUOTED_STRING macht eben genau diese Konvertierung, wobei es interessanter weise den aktuellen Zeichensatz erraten kann. Diesen Teil werde ich noch mal genauer unter die Lupe nehmen, da es schon länger auf meiner Liste steht.

Wie oben schon erwähnt, kann und sollte man alle E-Mail-Header quoten. Die Funktion ändert im übrigen den übergebenen String nur, wenn es wirklich nötig ist. Reine Ascii-Inhalte, die unterhalb der 127 Zeichens liegen, werden so belassen wie sie sind. Den E-Mail-Inhalt sollte man aber nicht damit übersetzen lassen. Das funktioniert zwar auch soweit, aber die Zeilenumbrüche sind bei mir dabei verloren gegangen.

Abgelegt unter Perl, Programmierung | Keine Kommentare »

Stolperfallen in Perl’s Spezialmethoden: DESTROY

Erstellt von Tobi am 15. Juli 2008

Durch einen Kollegen bin ich auf ein Problem aufmerksam geworden, was ein verwirrendes Verhalten von globalen Variablen in Verbindung mit DESTROY beschreibt. Man nehme folgenden Code und betrachte speziell den unteren eval-Block:

use Test::More tests => 1;
{
package Foo;
sub new {
bless([])
}
sub DESTROY {
eval {
die('destroy');
}
}
sub bar {
die('bar');
}
}
eval {
my $foo = Foo->new();
$foo->bar();
};
main::diag($@);

in $@ sollte eigentlich sowas wie bar at Test.pm line x erscheinen, aber er ergibt destroy at…. Was ist also passiert? Es ist, wie in der “Fehlerbeschreibung” erwähnt eigentlich kein Fehler, sondern eine Nebenwirkung davon, dass in Perl fast alles mit globalen Variablen gelöst wird. Wenn man den Code ein wenig erweitert, sieht man deutlich, was passiert:

#!perl -T
use Test::More tests => 1;
{
package Foo;
sub new {
main::diag('new() called');
bless([])
}
sub DESTROY {
main::diag('DESTROY() called');
eval {
die('destroy');
}
}
sub bar {
main::diag('bar() called');
die('bar');
}
}
main::diag('eval-START');
eval {
my $foo = Foo->new();
$foo->bar();
}; # HERE!
main::diag('eval-END');
like($@, qr/^destroy/, 'croak in DESTROY()');

Folgende Ausgabe wird erzeugt:
# eval-START
# new() called
# bar() called
# DESTROY() called
# eval-END

Zwischen dem Aufruf von bar() und eval-end mogelt sich das DESTROY frech dazwischen. Es gibt hier eine Nebenläufigkeit, da $foo am Ende des Eval-Blockes nicht mehr existiert und der GarbadgeCollector artig DESTROY() auf das Objekt aufruft. Da es aber nur eine Kopie von $@ gibt, wird der Inhalt durch das DESTROY-eval{} einfach überschrieben, denn das soll eval{} bei jedem Aufruf ja auch tun.

In der “Fehlerbeschreibung” ist als mögliche Lösung angegeben, man soll immer local verwenden, um z.B. $@ nicht zu überschreiben. Um auf “Hat Fehler” zu prüfen würde ich lieber ein
my $ok = eval {
#...some code
return 1;
};

verwenden, da man da erst gar nicht auf $@ angewiesen ist. Der Inhalt von $@ wird damit aber immer noch überschrieben werden.

Dieses Verhalten hat mir mal wieder gezeigt, dass mit allen Spezialmethoden von Perl, also import(), BEGIN, CHECK, END, INIT, DESTROY() und alle anderen, die zu bestimmten Ereignissen aufgerufen werden, immer sehr umsichtig umgegagnen werden muss. Am besten viele Diagnosemeldungen ausgeben lassen, damit man nicht den Überblick verliert.

Abgelegt unter Perl, Perl::Kinky | 1 Kommentar »

Ändern und mehrfaches Installieren von Perl-Modulen

Erstellt von Tobi am 14. Mai 2008

Wenn man aus einem Perl-Modul per perl Makefile.PL;make;make install das Modul installiert, dann den Quellcode ändert und es nochmal installieren will, MUSS man make clean ausführen oder die vom Makefile angelegten Daten selber löschen. Ansonsten wird immer wieder das “alte” installiert.

Ich hab gerade ein paar Minuten damit zugebracht, ein Modul zu aktualisieren und hatte mich gewundert, warum meine Änderungen keine Wirkung hatten.

Abgelegt unter Perl | 1 Kommentar »

Vorhandensein von Methoden in Klassen prüfen

Erstellt von Tobi am 17. April 2008

Wenn man wissen will, ob eine Methode in einer Klasse nur deklariert (sub method;) oder ob eben auch ein Methodenkörper existiert (sub method { die 1; }) sollte man sich nicht nur auf can() verlassen.

sub existing_sub;
sub defined sub { die 1; }
print __PACKAGE__->can('notexisting_sub'); #false
print exists(&notexisting_sub); # false
print defined(&notexisting_sub); # false
print __PACKAGE__->can('existing_sub'); #true
print exists(&existing_sub); # true
print defined(&existing_sub); # false
print __PACKAGE__->can('defined_sub'); #true
print exists(&defined_sub); # true
print defined(&defined_sub); # true

Der Aufruf einer Methode, die nur deklariert, führt zu einem “Undefined subroutine .. called” fehler, den man ja eigentlich mit dem can() verhindern wollte. Mir ist noch nie eine solche, blanke Deklaration über den Weg gelaufen, aber man weiß ja nie.

Abgelegt unter Perl, Perl::Kinky | 2 Kommentare »

Anti-Patterns

Erstellt von Tobi am 16. April 2008

Design-Patterns in der Software-Entwicklung sind mir schon eine Weile bekannt und das es so etwas wie Anti-Patterns gibt, hab ich auch mal gehört. Aber dass die auch so detailiert beschrieben sind, war mit neu. In diese Anti-Pattern Wikipedia-Artikel ist das wunderbar beschrieben. Diese Anti-Patterns gibt es im übrigen auch für andere Bereiche, nicht nur die Entwicklung selbst.

Einiges kommt, zumindest mir, bekannt vor. Speghetti-Code, Gott-Objekt und die Spinnen sehr ich schon sehr oft. Höchste Zeit, das zu ändern. :(

Abgelegt unter Perl | Keine Kommentare »