Archiv 26.7.2005 - 4.8.2005

Passwörter als Hashes speichern - sicher?

Nicht mehr ganz neu (Sommer letzten Jahres war es neu, aber da hab ich es irgendwie verpasst, das zugrundeliegende Paper ist sogar schon 2 Jahre alt), aber immer noch interessant: Project RainbowCrack ist ein Projekt das die Erstellung von Tools zum schnelleren Knacken von Hashes zum Ziel hat. Hashes können normalerweise nur durch brute force aufgelöst werden - unterstützt durch algorithmische Schwächen (wie kürzlich bei MD5 und SHA1 gefunden). Es gibt aber einen Ansatz die aufwändigeren Berechnungen die beim brute-force-Vorgang anfallen (also im Prinzip algorithmische Teilschritte) schon im Vorhinen zu erstellen - zum Beispiel wenn man eh nur vor hat z.B. Passwörter mit maximaler Zeichenzahl zu knacken.

Das ganze kommt natürlich nicht umsonst: man tauscht Rechenzeit gegen Speicherplatz ein. Tabellen zum Knacken von bis zu 14 stelligen Windows Passwörtern belegen lockere 64 GiB an Speicher. Die praktische Relevanz des Ansatzes und der Tools wird aus diesem Zitat vielleicht offensichtlich:

Some ready to work lanmanager and md5 tables are demonstrated in Rainbow Table section. One interesting stuff among them is the lm #6 table, with which we can break any windows password up to 14 characters in a few minutes.

Zu Project RainbowCrack gibts auch noch eine Weboberfläche zu einem verteilten Rechencluster über die man MD5-Hashes an einen MD5-Cracker schicken kann und der dann - sofern es ein maximal 8 Zeichen langer String ist - den Klartext rausspuckt. Und das Teil baut nebenbei immer mehr Rainbow Tables auf, wodurch das Knacken nach und nach schneller wird.

Nur so als Warnung für diejenigen, die meinen das ein einfacher MD5 Hash (oder letztendlich nahezu jeder Hash) auf das Passwort ausreichend wäre. Unix-Systeme benutzen üblicherweise salted hashes - das Passwort wird um einen offenen Text erweitert und damit zusammen dann der Hash gebildet. Das verlängert im Prinzip das Passwort, auch wenn natürlich die Verlängerung nicht geheim ist - für die Rechenzeit oder die Tabellengrösse ist das wurscht, die Passwörter sind einfach länger und damit schwerer zu knacken. Ist aber auch nur eine Frage von Platz, bis die nicht sicher sind.

Besser sind Passphrases statt Passwörter - eben einfach normal lange Sätze. Zum Einen kann man sich diese häufig besser merken (viele Menschen können sich keine Telefonnummer merken, aber Zeilen aus Gedichten zitieren) und zum Anderen sind sie einfach länger (und vor allem flexibel lang), so das Rainbow Tables als Angriffsmethode ausscheiden. Die algorithmischen Schwächen von MD5 und SHA1 bleiben natürlich erhalten.

Shoot-to-Kill Direktiven - und die Welt wird ein Egoshooter

Bruce Schneier über Shoot-to-Kill und dabei speziell ein Vorschlag der International Association of Chiefs of Police . Übersetzt aus dem Vorschlag:

... eine solche Person zeigt "verschiedene ungewöhnliche Verhaltensweisen" wie einen schweren Mantel oder eine dicke Jacke bei warmem Wetter tragen, einen Koffer, eine Umhängetasche oder einen Rucksack mit Ausbeulungen oder erkennbaren Drähten tragen. Die Person zeigt Nervosität, vermeidet Augenkontakt oder schwitzt stark. Möglicherweise sind chemische Rückstände an der Kleidung oder an den Händen. Die Person murmelt möglicherweise Gebete oder schaukelt vor und zurück.

Wohlgemerkt, was mit solchen Personen zu geschehen hat, ist den Chiefs of Police klar: in den Kopf schiessen. Finaler Tötungsschuss. Und natürlich brauchts dafür keinen weiteren Anlass:

... die Bedrohung des Polizisten braucht nicht unmittelbar zu sein, wie bei normaler Vorgehensweise gelehrt wird. Polizisten brauchen nicht zu warten bis eine als Attentäter verdächtigte Person eine Bewegung macht, wie es bei normaler Vorgehensweise für den Einsatz von Schusswaffen notwendig wäre. Ein Polizist braucht nur eine begründete Vermutung für den Verdacht zu haben das der Verdächtige eine Bombe zünden könnte.

Bruce Schneier fragt zu Recht ob wir uns wirklich sicher fühlen dürften wenn eine solche Richtlinie umgesetzt würde. Jeder Taschendieb zeigt genug Merkmale um demnächst dann einfach mal eben abgeknallt zu werden, würde eine so menschenverachtende Richtlinie tatsächlich umgesetzt.

Wir wissen ja wie schnell menschenverachtende Ideen hier dann plötzlich auch auf die Tagesordnung kommen ...

Ein Treeview in JavaScript der innerhalb von Seiten (ohne Frames) benutzt werden kann und trotzdem sich State merkt.

Ciscos Kundenpasswörter sind weg - das ist so peinlich, das tut schon richtig weh. Oha. Und das Cisco.

Django, Apache und FCGI

In Django, lighttpd und FCGI, zweiter Versuch habe ich eine Methode beschrieben, wie man Django mit FCGI hinter einer lighttpd-Installation ausführen kann. Ich habe die Django-FCGIs als eigenständige Server ausgeführt, sodass Sie sie unter unterschiedlichen Benutzern als der Webserver ausführen können. Dieses Dokument gibt Ihnen die benötigten Informationen, um dasselbe mit Apache 1.3 zu tun.

Aktualisierung: Ich pflege meine Beschreibungen jetzt in meinem Trac-System. Siehe die Apache+FCGI-Beschreibung für Django.

Aktualisierung: Ich habe von der Verwendung von Unix-Sockets zur Verwendung von TCP-Sockets in der Beschreibung gewechselt. Der Grund ist, dass Unix-Sockets Schreibzugriff von beiden Prozessen - Webserver und FCGI-Server - benötigen und das manchmal schwer einzurichten ist. TCP-Sockets sind nur ein bisschen langsamer, aber viel einfacher einzurichten.

Zuerst die Hauptfrage, die einige stellen könnten: Warum Apache 1.3? Die Antwort ist einfach: Viele Menschen haben immer noch Apache 1.3 als ihren Hauptserver laufen und können nicht leicht auf Apache 2.0 aktualisieren - zum Beispiel, wenn sie große Codebasen in mod_perl oder mod_python ausführen, werden sie Probleme bei der Migration haben, weil Apache 2.0 mod_perl2 oder mod_python2 erfordert und beide nicht vollständig kompatibel mit älteren Versionen sind. Und obwohl lighttpd ein fantastischer Webserver ist, wenn Sie bereits Apache 1.3 ausführen, gibt es möglicherweise einfach keinen Bedarf für einen weiteren Webserver.

Was benötigen Sie also - neben den Python- und Django-Dingen - für Apache 1.3 mit FastCGI? Nur das mod_rewrite-Modul und das mod_fastcgi-Modul installiert, das ist alles. Beide sollten mit der Verteilung Ihres Systems geliefert werden. Sie werden immer noch alle Python-Dinge benötigen, die ich im lighttpd-Artikel aufgeführt habe.

mod_fastcgi ist etwas eigenwillig in seiner Installation, ich musste ein bisschen damit herumspielen. Es gibt ein paar Stolpersteine, an die ich denken kann:

  • Die Angabe des Sockets kann kein absoluter Pfad sein, sondern muss ein relativer Pfad in Bezug auf das FastCgiIpcDir sein.
  • Die Angabe des FCGI selbst (auch wenn es rein virtuell ist) muss in einer vollständig qualifizierten Form in Bezug auf das Dokumentenstammverzeichnis, das Sie verwenden möchten. Wenn Sie einen relativen Pfad verwenden, wird er relativ zum Dokumentenstammverzeichnis des Standard-Virtual-Hosts sein - und das ist mit Sicherheit nicht das Dokumentenstammverzeichnis, das Sie verwenden werden, wenn Sie einen Virtual-Host mit dem FCGI einrichten möchten.
  • Das FCGI selbst kann nicht innerhalb eines Virtual-Hosts definiert werden - es muss in der Hauptserverkonfiguration definiert werden. Hier kommt das Problem der relativen Adressierung ins Spiel.
  • Die Socket-Datei muss sowohl vom FCGI-Benutzer als auch vom Apache-Benutzer lesbar und beschreibbar sein. Normalerweise tun Sie dies, indem Sie die Socket-Datei gruppenschreibbar ändern und die Gruppe dieser Socket-Datei in eine Gruppe ändern, der sowohl der Benutzer als auch der Apache angehören.

Hier ist der Konfigurationsausschnitt, den Sie zu Ihrer httpd.conf hinzufügen müssen. Ich verwende die gleichen Verzeichnisse wie im lighttpd-Beispiel, Sie werden dies wahrscheinlich an Ihre Situation anpassen müssen.


FastCgiExternalServer /home/gb/work/myproject/publichtml/admin.fcgi -host 127.0.0.1:8000
FastCgiExternalServer /home/gb/work/myproject/publichtml/main.fcgi -host 127.0.0.1:8001

<VirtualHost *>
ServerAdmin gb@bofh.ms
Servername www.example.com
ErrorLog /home/gb/work/myproject/logs/django-error.log
CustomLog /home/gb/work/myproject/logs/django-access.log combined
DocumentRoot /home/gb/work/myproject/public_html
RewriteEngine On
RewriteRule ^(/admin/.)$ /admin.fcgi$1 [L]
RewriteRule ^(/main/.)$ /main.fcgi$1 [L]
</VirtualHost> ```

Sie müssen dem Webserver Schreibzugriff auf das Log-Verzeichnis ermöglichen, daher möchten Sie möglicherweise einen anderen Ort dafür verwenden - möglicherweise in `/var/log/apache/` oder wo auch immer Ihr Apache seine Logs hinstellt. Die FastCgiExternalServer-Direktiven müssen außerhalb der Virtual-Host-Definitionen stehen, müssen aber auf Dateien innerhalb des Dokumentenstammverzeichnisses der Virtual Hosts verweisen. Diese Dateien müssen jedoch (und sollten wahrscheinlich nicht) im Dateisystem existieren, sie sind rein virtuell. Die gegebene Einrichtung spiegelt die Einrichtung wider, die ich für das lighttpd-Szenario vorgenommen habe.

Starten Sie nun Ihren Apache neu, starten Sie Ihr django-fcgi.py und Sie sollten auf Ihre Django-Anwendung zugreifen können. Vergessen Sie nicht, die admin_media-Dateien in das Dokumentenstammverzeichnis zu kopieren, sonst wird Ihr Admin sehr hässlich aussehen.

django-fcgi.py --settings=myproject.settings.main --host=127.0.0.1 --port=8000 --daemon django-fcgi.py --settings=myproject.settings.admin --host=127.0.0.1 --port=8001 --daemon


Viel Spaß.

EU-Hirnriss zu Urheberrechtsverletzungen

Was für ein Unfug. Kommt der Vorschlag durch, wird Open-Source-Einsatz riskant:

Ein neuer Gesetzesentwurf der Europäischen Kommission soll beim Verdacht auf Urheberrechtsverletzung bei Software auch Klagen gegen die Anwender erlauben. Neben dem Verursacher würden damit Unternehmen, die sich anhand ihrer Lizenzen in Sicherheit wiegen, ins Schussfeld geraten. Das berichtete das britische Branchenmagazin 'ZDNet UK'.

Gerade unter dem aktuellen Eindruck des SCO-Verfahrens müsste eigentlich jedem klar sein das so eine Idee vollkommener Hinriss ist - denn genau das war es ja was SCO machen wollte, alle Linux-Benutzer zu erpressen. Es gibt wirklich kaum eine Idee die dumm genug ist das sie nicht einem Politiker ins Hirn kommen könnte ...

Geocaching im Münsterland

Da ich jetzt einen Garmin Geko 201 habe, muss ich mir natürlich mal die Infos zu Geocaching angucken. Jemand einen guten Link zu Geocaching-Aktivisten in Münster und Umgebung? Wär was für unseren anstehenden Urlaub, Jutta schimpft immer das Sie das Münsterland nicht gut genug kennt, da wäre das Abklappern von Geocaches doch die ideale Methode die Gegend zu erkunden.

Als erster Startpunkt werd ich mir mal die Eintragungen bei geocaching.de für Ruhrpott und Emsland angucken - wir sind zwar weder Ruhrpott noch Emsland, aber nah genug dran um bei beiden mit drauf zu sein.

Ausserdem hab ich jetzt einen guten Grund gegenüber Jutta warum ich mir das Teil gekauft habe

Und wenn ich mir Anleitungen wie zu Vaders Stein angucke, dann wird das sogar genau für Jutta passen - Rätselspiele mag sie nämlich sehr. Hey, könnte glatt ein neues Hobby werden ...

Mal wieder neues bei Django

Neues gibts da ja dauernd, aber diesmal wieder ein sehr interessantes Feature: das inspectdb Kommando liefert nämlich aus einer PostgreSQL Datenbank die ganzen Tabellen und Felder im Format eines Python Datenmodells. Zusätzlich werden - sofern in der Datenbank abgelegt - auch Fremdschlüssel gefunden. Sehr praktisch wenn man eine Oberfläche für eine bestehende Datenbank bauen muss, man spart sich viel Tipparbeit.

Soziale Netzwerkerei

Tja, ich bin jetzt auch in einem dieser tollen sozialen (in diesem Fall dann eher business-sozialen) Netzwerke registriert, und zwar in der O'Reilly Connection. Will ja nicht als verhärmt und vergreist gelten

Wers schafft mich dort zu finden darf ne Connection zu mir definieren. Und sich über mein blödes Foto lustig machen ...

Ian Bicking darüber was bei SQLObject derzeit passiert - es war ja recht still um einen der nettesten SQL-Object-Layer für Python geworden, aber jetzt gehts weiter. Für mich interessantester Punkt: Toolunterstützung für Datenbankupgrades. Ein Punkt der zum Beispiel auch bei Django noch fehlt.

Aber Patente sind ja sooo toll ...

... dumm nur, wenn dann die eigene Zentralbank Ziel einer Patentklage ist: Europäische Zentralbank wegen Patentverletzung verklagt. Wird das vielleicht mal beim EU-Rat die Leute aufwecken? Ach watt, vergesst es, die wachen in diesem Leben nicht mehr auf, dann müssten sie ja ihre eigene Korruption erkennen ...

Das Äquivalent zum Apple FileSafe unter Linux: Automatically mount dm-crypt encrypted home with pam_mount. Gerade für Notebooks sehr sinnvoll, aber auch bei Arbeitsplatzrechnern von Administratoren (wegen der vielen sicherheitsrelevanten Files die sich so im Homeverzeichnis ansammeln).

Coroutinen für Python

Philip J. Eby hat einen Patch zur Implementation von PEP 342 geliefert. Damit stehen die Chancen das Python in Zukunft Coroutinen haben wird sehr gut.

Und das wiederum bedeutet das Python eine - wenn auch primitive - Form von Continuations bekommt. Jetzt fehlt nur noch das sowas wie statesaver mit in Python integriert wird - für Multishot Continuations (ok, erstmal nur copyable Coroutines, aber das wäre immerhin der Anfang).

Das alles natürlich nur um dann endlich in Webframeworks mit Continuations arbeiten zu können. Ok, geht mit CherryFlow jetzt schon, aber es wäre schon wenn das ganze in das Mainstream-Python wandern würde.

Wer sich mal mit grösserer Erlang-Software beschäftigen möchte und einen Jabber-Server ausprobieren will, für den ist vielleicht ejabberd interessant - ein Jabber-Server der all die netten Features von Erlang ausnutzt um zum Beispiel einfaches Clustering und gute Datenverteilung zu bieten.

Hell freezes over - a second time

Erst Intel-Prozessoren und jetzt mehr als eine Maustaste. Und sogar sowas ähnliches wie ein Scrollrad. Schockierend.

Und noch einer Linux-auf-Mac Story. Diesmal ein iBook und Gentoo. Für eine kleine und preiswerte Linux-Kiste für Unterwegs ganz brauchbar.

Die Linux on an Apple Powerbook HOWTO liefert genau das was ich bräuchte, wenn ich mein 12" Powerbook auf Linux umstellen wollen würde - der Autor benutzt sogar genau mein Modell. Und nein, noch will ich nicht umsteigen

The Illusive setdefaultencoding

Ian Bicking hat in seinem Artikel über setdefaultencoding einen Verweis auf einen netten Trick drin: einfach mit reload(sys) das sys-Modul neu laden, damit setdefaultencoding verfügbar ist.

setdefaultencoding dient dazu einzustellen, welches Standardencoding bytestrings benutzen. Normalerweise ist das ASCII, kann aber auch auf iso-8859-1 oder utf-8 umgestellt werden - wenn man setdefaultencoding überhaupt hat. Das wird nämlich dummerweise beim Start der Python Laufzeitumgebung gelöscht - weil die Python-Macher da mal wieder die User bevormunden wollen.

reload(sys) ist natürlich etwas das nicht unbedingt für Vertrauen sorgt - sys ist ja ein nicht ganz unwichtiges Modul. Aber in meinen Experimenten hat es bisher gut geklappt und es hilft definitiv bei der ganzen Unicode-Problematik wenn man seinen programmen ein anderes Encoding als Standard verpassen kann.

Schöner wärs natürlich wenn in der Standarddistribution setdefaultencoding nicht mehr gelöscht würde. Klar, kann man auch erreichen durch einen Patch von site.py, aber das ist auch nicht besser als sys neu zu laden ...

(Un)trusted platform Apple?

Da es gerade modern ist zu erklären das man switched, wenn Apple TPA - oder wie auch immer das Zeugs dann in Zukunft heissen mag - einsetzt: erstmal abwarten. Angucken was Apple macht und wie - Gerüchte gibts vorher immer.

Wenn dann tatsächlich TPA drin ist: Linux kann auch ein brauchbares System sein, auch wenn die Oberflächen ziemlich krank sind (wobei aktuelle XFCE-Versionen garnicht mal so übel aussehen) und wenn in Apple-Hardware eh kein PPC mehr drin steckt und man Linux draufpackt: da kann man auch sein Notebook bei IBM kaufen. Die haben nette Geräte die auch ganz hervorragend unter Linux funktionieren.

Und last but not least: nur weil neue Apple-Hardware anders ist verändert sich die schon gekaufte Hardware nicht - und die hält Apple-typisch meist ein paar Jahre länger. Und unter Linux wird mancher Mac sogar schneller als unter OS X

Wohin Abmahnwahn und vorauseilender Gehorsam führen können

hat gerade die FFII gemerkt: Nutzwerk ließ FFII.org abschalten(etwas mehr Infos wie üblich bei Heise).

Nun war zwar die entsprechende IP-Adresse durchweg erreichbar, doch der als technischer Ansprechpartner für die Domain FFII.org eingetragen DNS-Provider kam der Forderung Nutzwerks nach und schaltete die Domain FFII.org am vergangenen Freitag Nachmittag ab. Die Namensauflösung von FFII.org sowie entsprechender Subdomains funktionierte vorübergehend nicht. Nach einer Intervention des FFII hat der DNS-Provider die Domain am Abend des gleichen Tages aber wieder frei geschaltet und will Nutzwerk um eine Präzisierung des Ansinnens bitten, so FFII-Vorstand Hartmut Pilch gegenüber Golem.de.

Ein echtes Dilemma: Dienstleister wollen sich selber schützen und leider wird durch das Teledienstgesetz eben diesen Dienstleistern das Leben schwer gemacht: auf Inhalte hingewiesen die einen Rechtsverstoß darstellen muss man diese Inhalte unverzüglich entfernen. Nur wie will man beurteilen ob Inhalte jetzt einen Rechtsverstoß darstellen? Ganz besonders wenn es um solche Sachen wie bei Nutzwerk gehen - wo kritische Berichterstattung von der Firma als Rechtsverstoß definiert wird?

Letzten Endes wird so den Firmen ein Zensurmittel in die Hand gegeben, ohne den Dienstleistern (und natürlich den Seitenbetreibern selber!) vernünftige Möglichkeiten zur Abwehr zu geben. Wie soll sich ein kleinerer Provider zum Beispiel vor Abmahnungen mit absurden Streitwerten - wie sie z.B. von der Musikindustrie mit Vorliebe eingesetzt werden - schützen? Rechtsschutzversicherungen helfen da nicht.

Kein Wunder das mancher Provider in dem Fall im vorauseilenden Gehorsam die richtige Strategie sieht - er verliert so maximal den Kunden den er abgeschaltet hat, eventuell ein bischen negative Presse, aber den Kampf gegen eine Firma mit überzogenen Vorstellungen aufnehmen, dabei kann er nicht viel gewinnen.

Wer dann so wie ich im Vorstand eines privat betriebenen Providers sitzt, der kommt bei solchen Entwicklungen schon ins Grübeln, was eigentlich die Zielsetzung dieser Gesetzesänderungen im Zuge des Teledienstgesetzes wirklich war ...

Auswirkungen von Gen-Raps und Co.

Beim Isotopp einen Pointer auf Informationen zum britischen Evaluierungsprojekt zu gentechnisch verändertem Saatgut gefunden. Erschreckend, welche Auswirkungen das zum Beispiel auf verwandte Wildkräuter hat und was das auf Dauer für uns bedeuten wird. Aber es ist ja alles sooo sicher und sooo wichtig für uns - dabei gehts eben wirklich nur um die Einnahmen für die Gentechnik-Firmen, nicht aber um das was die Verbraucher wirklich wollen.

Aber natürlich wird weiterhin jeder Kritiker von gentechnisch verändertem Saatgut als Spinner von der Wirtschaft und deren Schergen (wie z.B. Clement und manch anderer Politiker) abgetan.

Daves neuer OPML Editor mit Blog

Ich spiele gerade mit dem OPML-Editor von Dave Winer rum, mit dem er jetzt sein Blog macht. Sieht ganz witzig aus und kann einiges. Mein OPML-Blog hat einige der Erkenntnisse die ich damit gemacht habe gesammelt. Ich werde jetzt sicherlich nicht einfach mal eben so umsteigen - das wäre Quark, das ist nicht unbedingt meine Zielsoftware. Aber es macht Spaß mal wieder mit etwas ganz anderem zu spielen.

Leider hat der OPML Editor einige der Krankheiten von Radio Userland und Frontier geerbt, speziell Umlautehandhabung ist nicht so wirklich rund (ich hätte gerne endlich mal durchgängige UTF-8 Unterstützung) und das Laufzeitverhalten ist zwar besser als bei Radio, aber es zieht immer noch sporadisch zu viel CPU.

Das Konzept von gerenderten Outlines hat aber durchaus Charme. Nur leider sind noch viele Teile des Renderings nicht wirklich für normale User zugänglich - man kann zwar das uralte Table-Layout editieren und was anderes draus machen, aber die OPMLs werden mit dem internen OPML Renderer umgesetzt und die HTML-Fragmente sind nicht so einfach zu ändern - und damit zum Beispiel die Änderung der Sprache recht mühsam, genauso wie die vollständige Ausmerzung von Layouttabellen.

Mehr wird sicherlich nach und nach auf dem OPML Blog landen, hier werd ich maximal ein paar Fazits schreiben.

HEW Cyclassics 2005

Ein wirklich nettes Rennen - immer wieder erstaunlich wie selbst fast eine Viertelstunde Vorsprung nicht ausreicht um bei dem Rennen auch einen Sieg nach Hause zu fahren. Auch immer wieder erstaunlich wie die Kommentatoren jedes Mal erzählen das das Hauptfeld zu spät anfährt - so langsam sollten die das doch kennen.

Die Quickstep-Aktion jedenfalls war klasse - so sauber den Fassa Bortolo Leuten nach deren Sprintaufbau den Sieg und die Treppchenpositionen wegzunehmen ist wirklich super. Auch wenn ich natürlich lieber Zabel vorne gesehen hätte

Merkelnix krampft auch

Nur damit niemand glaubt nur die SPD hätte hirnlose Parolen in die Welt zu schreien: "Arbeit wieder in Deutschland möglich machen" ist der Grund warum sie die Mehrwertsteuer erhöhen wollen:

Unions-Kanzlerkandidatin Angela Merkel hat die von CDU und CSU geplante Erhöhung der Mehrwertsteuer verteidigt. Die Union wolle damit das Ziel erreichen, die Arbeitskosten zu senken, sagte sie in einem Interview des "Bericht aus Berlin". Es gehe darum, "Arbeit wieder in Deutschland möglich zu machen und damit die soziale Sicherung zu ermöglichen", sagte die CDU-Chefin weiter.

Sorry, aber wie saublöd ist das denn? Soziale Sicherung durch eine Anhebung der Mehrwertsteuer, die am heftigsten die trifft, die ihren Konsum nicht weiter reduzieren können weil er eh nur noch aus Grundnahrungsmitteln und anderen fürs Überleben notwendigen Ausgaben besteht?

Softwarepatente - Kommentar bei der NY Times

Die NY Times fragt warum Bill Gates 3,000 neue Patente will und findet eine massive Belagerung des Patentbüros mit Bergen von Softwarepatenten, die oft einfach nur Trivialpatente sind (wie das zitierte Patent zum Zufügen/Entfernen von Leerzeichen in Dokumenten). Der Kommentator stellt in dem Kommentar eine Forderung auf (nachdem er überlegt ob man Microsoft nicht einfach alle Patente entziehen sollte die sie schon haben):

Perhaps that is going too far. Certainly, we should go through the lot and reinstate the occasional invention embodied in hardware. But patent protection for software? No. Not for Microsoft, nor for anyone else.

Und das aus dem Land das die Softwarepatente schon lange hat und das immer wieder von den Softwarepatentproponenten in der EU als Grund für eine notwendige weltweite Harmonisierung gebracht wird.

Nein, Softwarepatente sind auch dort nicht gern gesehen und nicht wirklich sinnvoll. Auch Dan Bricklin - dem einen oder anderen noch als Visicalc-Vater bekannt - findet das:

Mr. Bricklin, who has started several software companies and defensively acquired a few software patents along the way, says he, too, would cheer the abolition of software patents, which he sees as the bane of small software companies. "The number of patents you can run into with a small product is immense," he said. As for Microsoft's aggressive accumulation in recent years, he asked, "Isn't Microsoft the poster child of success without software patents?"

Und warum macht Microsoft das jetzt? Der dafür zuständige Manager gibt einen Grund, wie er nur einem BWLer einfallen kann, so blöd ist der:

"We realized we were underpatenting," Mr. Smith explained. The company had seen studies showing that other information technology companies filed about two patents for every $1 million spent on research and development. If Microsoft was spending $6 billion to $7.5 billion annually on its R&D, it would need to file at least 3,000 applications to keep up with the Joneses.

Ok, alleine schon die Idee der Patentanmeldung alleine von Zahlen aus der Branche zu orientieren ist hirnrissig, aber wie blöd muss man sein um einen Bezug zwischen der Patentanzahl und dem Umsatz im Bereich Forschung und Entwicklung zu ziehen?

Die NY Times zieht da auch die Parallele zur Pharmaindustrie, die - zumindestens laut eigenen Aussagen - bei einem Forschungseinsatz von 20 Millionen froh ist dann ein Patent auf ein Medikament zu bekommen (wobei das schon kritisch genug ist, wie man gerade bei der AIDS-Bekämpfung in Afrika sehen konnte).

Und der Fallout wird bei der NY Times auch gut zusammengefasst:

Last year at a public briefing, Kevin R. Johnson, Microsoft's group vice president for worldwide sales, spoke pointedly of "intellectual property risk" that corporate customers should take into account when comparing software vendors. On the one side, Microsoft has an overflowing war chest and bulging patent portfolio, ready to fight - or cross-license with - any plaintiff who accuses it of patent infringement. On the other are the open-source developers, without war chest, without patents of their own to use as bargaining chips and without the financial means to indemnify their customers.

Die Frage, was Jefferson (der Gründer des US Patentsystems) dazu sagen würde, was heute alles Patente bekommen soll, ist da durchaus berechtigt. In seinem Sinne - der ja eigentlich eher auf den Schutz der wirklichen erfinderischen Genialität vor der Ausnutzung durch Konzerne galt - ist das ganze definitiv nicht.

Wahlkampf, Wahlkrampf ...

Münte on the Roll: Linkspartei "politisch und juristisch abstrus". Ich hab allerdings den Eindruck das er der SPD mehr damit helfen würde ihr ein Programm zu verpassen das die normalen Bürger wieder anspricht, anstatt einfach nur die Angst vor Links zu schüren und Verleumdungen (sorry, aber die Kombination aus PDS und WASG in der offenen Liste ist vielleicht merkwürdig, aber juristisch wohl einwandfrei - etwas anderes zu behaupten also schlicht Verleumdung) zu verbreiten.

Wenn die SPD im Wahlkampf nicht mehr schafft als nur ins Horn der Unionsparteien gegen die angebliche Gefahr von Links zu stossen, wird die SPD sich schlicht ins politische Aus begeben - mit so einem Murks gewinnt man keine Wahl. Wenn die SPD nur noch eine Union mit roter Krawatte ist, kann sie mir gestohlen bleiben ...

Einfacher Dateisystem-Browser mit Django schreiben

Dieser Artikel ist mal wieder in Englisch, da er auch für die Leute auf #django interessant sein könnte. Dieser Beitrag zeigt, wie man einen sehr einfachen Dateisystem-Browser mit Django erstellt. Dieser Dateisystem-Browser verhält sich größtenteils wie ein statischer Webserver, der die Verzeichnisnavigation ermöglicht. Die einzige Besonderheit ist, dass Sie das Django-Admin verwenden können, um Dateisysteme zu definieren, die in den Namensraum des Django-Servers eingebunden werden. Dies dient nur zur Demonstration, wie eine Django-Anwendung verschiedene Datenquellen neben der Datenbank nutzen kann. Es ist nicht wirklich dazu gedacht, statischen Inhalt zu servieren (obwohl es mit hinzugefügter Authentifizierung quite nützlich für eingeschränkten statischen Inhalt sein könnte!).

Auch wenn die Anwendung sehr einfache Sicherheitsprüfungen an den übergebenen Dateinamen durchführt, sollten Sie dies nicht auf einem öffentlichen Server ausführen - ich habe keine Sicherheitstests durchgeführt und es könnte buttloads von schlechten Dingen geben, die Ihre privaten Daten der Welt preisgeben könnten. Sie wurden gewarnt. Wir beginnen wie üblich mit der Erstellung der Dateisystem-Anwendung mit dem Befehl django-admin.py startapp filesystems. Machen Sie es einfach so, wie Sie es mit Ihrer Umfrageanwendung im ersten Tutorial gemacht haben. Nur zur Orientierung, so sieht die myproject-Verzeichnis auf meiner Entwicklungsmaschine aus:


.
|-- apps
| |-- filesystems
| | |-- models
| | |-- urls
| | `-- views
| `-- polls
| |-- models
| |-- urls
| `-- views
|-- public_html
| `-- admin_media
| |-- css
| |-- img
| | `-- admin
| `-- js
| `-- admin
|-- settings
| `-- urls
`-- templates
 `-- filesystems

Nach der Erstellung der Infrastruktur beginnen wir mit dem Aufbau des Modells. Das Modell für die Dateisysteme ist sehr einfach - nur ein Name für das Dateisystem und ein Pfad, an dem die Dateien tatsächlich gespeichert sind. Hier ist es also, das Modell:


 from django.core import meta

class Filesystem(meta.Model):

fields = ( meta.CharField('name', 'Name', maxlength=64), meta.CharField('path', 'Path', maxlength=200), )

def repr(self): return self.name

def get_absolute_url(self): return '/files/%s/' % self.name

def isdir(self, path): import os p = os.path.realpath(os.path.join(self.path, path)) if not p.startswith(self.path): raise ValueError(path) return os.path.isdir(p)

def files(self, path=''): import os import mimetypes p = os.path.realpath(os.path.join(self.path, path)) if not p.startswith(self.path): raise ValueError(path) l = os.listdir(p) if path: l.insert(0, '..') return [(f, os.path.isdir(os.path.join(p, f)), mimetypes.guess_type(f)[0] or 'application/octetstream') for f in l]

def file(self, path): import os import mimetypes p = os.path.realpath(os.path.join(self.path, path)) if p.startswith(self.path): (t, e) = mimetypes.guess_type(p) return (p, t or 'application/octetstream') else: raise ValueError(path)

admin = meta.Admin( fields = ( (None, {'fields': ('name', 'path')}), ), list_display = ('name', 'path'), search_fields = ('name', 'path'), ordering = ['name'], )


Wie Sie sehen können, ist das Modell und das Admin eher langweilig. Was interessant ist, sind jedoch die zusätzlichen Methoden `isdir`, `files` und `file`. `isdir` überprüft, ob ein gegebener Pfad unter dem Dateisystem ein Verzeichnis ist oder nicht. `files` gibt die Dateien des angegebenen Pfades unter dem Basispfad des Dateisystems zurück und `file` gibt den echten Dateipfad und den MIME-Typ einer gegebenen Datei unter dem Basispfad des Dateisystems zurück. Alle drei Methoden überprüfen die Gültigkeit des übergebenen Pfades - wenn der resultierende Pfad nicht unter dem Basispfad des Dateisystems liegt, wird eine ValueError ausgelöst. Dies soll sicherstellen, dass niemand `..` im Pfadnamen verwendet, um aus dem definierten Dateisystem-Bereich auszubrechen. Das Modell enthält also spezielle Methoden, die Sie verwenden können, um auf den Inhalt des Dateisystems selbst zuzugreifen, ohne sich Gedanken darüber zu machen, wie dies in Ihren Ansichten zu tun ist. Es ist die Aufgabe des Modells, solche Dinge zu kennen.

Der nächste Teil Ihres kleinen Dateisystem-Browsers wird die URL-Konfiguration sein. Sie ist eher einfach, sie besteht aus der Zeile in `settings/urls/main.py` und dem Modul `myproject.apps.filesystems.urls.filesystems`. Zuerst die Zeile im Haupt-URLs-Modul:

from django.conf.urls.defaults import *

urlpatterns = patterns('', (r'^files/', include('myproject.apps.filesystems.urls.filesystems')), )


Als nächstes das eigene URLs-Modul der Dateisysteme:

from django.conf.urls.defaults import *

urlpatterns = patterns('myproject.apps.filesystems.views.filesystems', (r'^$', 'index'), (r'^(?P.?)/(?P.)$', 'directory'), )


Sie können die Anwendung nun der Haupt-Einstellungsdatei hinzufügen, damit Sie es später nicht vergessen. Suchen Sie einfach nach der Einstellung INSTALLED_APPS und fügen Sie den Dateibrowser hinzu:

INSTALLED_APPS = ( 'myproject.apps.polls', 'myproject.apps.filesystems' )


Ein Teil fehlt noch: die Ansichten. Dieses Modul definiert die extern erreichbaren Methoden, die wir im URL-Mapper definiert haben. Wir benötigen also zwei Methoden, `index` und `directory`. Die zweite funktioniert tatsächlich nicht nur mit Verzeichnissen - wenn sie eine Datei übergeben bekommt, präsentiert sie einfach den Inhalt dieser Datei mit dem richtigen MIME-Typ. Die Ansicht macht Gebrauch von den in dem Modell definierten Methoden, um auf den tatsächlichen Dateisysteminhalt zuzugreifen. Hier ist der Quellcode für das Ansichtsmodul:

from django.core import template_loader from django.core.extensions import DjangoContext as Context from django.core.exceptions import Http404 from django.models.filesystems import filesystems from django.utils.httpwrappers import HttpResponse

def index(request): fslist = filesystems.getlist(orderby=['name']) t = templateloader.gettemplate('filesystems/index') c = Context(request, { 'fslist': fslist, }) return HttpResponse(t.render(c))

def directory(request, filesystem_name, path): import os try: fs = filesystems.getobject(name exact=filesystemname) if fs.isdir(path): files = fs.files(path) tpl = templateloader.gettemplate('filesystems/directory') c = Context(request, { 'dlist': [f for (f, d, t) in files if d], 'flist': [{'name':f, 'type':t} for (f, d, t) in files if not d], 'path': path, 'fs': fs, }) return HttpResponse(tpl.render(c)) else: (f, mimetype) = fs.file(path) return HttpResponse(open(f).read(), mimetype=mimetype) except ValueError: raise Http404 except filesystems.FilesystemDoesNotExist: raise Http404 except IOError: raise Http404


Sehen Sie, wie die Elemente des Verzeichnismusters als Parameter an die Directory-Methode übergeben werden - der Dateisystemname wird verwendet, um das richtige Dateisystem zu finden, und der Pfad wird verwendet, um den Inhalt unter dem Basispfad dieses Dateisystems zuzugreifen. MIME-Typen werden mit dem mimetypes-Modul aus der Python-Distribution ermittelt, übrigens.

Der letzte Teil unseres kleinen Tutorials sind die Vorlagen. Wir benötigen zwei Vorlagen - eine für den Index der definierten Dateisysteme und eine für den Inhalt eines Pfades unter einem Dateisystem. Wir benötigen keine Vorlage für den Dateiinhalt - der Dateiinhalt wird roh geliefert. Zuerst also die Hauptindexvorlage:

{% if fslist %}

definierte Dateisysteme

{% else %}

Entschuldigung, es wurden keine Dateisysteme definiert.

{% endif %}

Die andere Vorlage ist die Verzeichnisvorlage, die den Inhalt eines Pfades unter dem Basispfad des Dateisystems anzeigt:

{% if dlist or flist %}

Dateien in //{{ fs.name }}/{{ path }}

    {% for d in dlist %}
  • {{ d }}
  • {% endfor %} {% for f in flist %}
  • {{ f.name }} ({{ f.type }})
  • {% endfor %}
{% endif %}


Beide Vorlagen müssen irgendwo in Ihrem TEMPLATE-PFAD gespeichert werden. Ich habe einen Pfad im TEMPLATE-PFAD mit dem Namen der Anwendung eingerichtet: `filesystems`. Dort habe ich die Dateien als `index.html` und `directory.html` gespeichert. Natürlich würden Sie normalerweise eine Basisvorlage für die Website erstellen und diese in Ihren normalen Vorlagen erweitern. Und Sie würden eine `404.html` hinzufügen, um 404-Fehler zu behandeln. Aber das bleibt als Übung für den Leser. Nachdem Sie Ihren Entwicklungsserver für Ihr Admin gestartet haben (vergessen Sie nicht, DJANGO SETTINGS MODULE entsprechend einzustellen!), können Sie ein Dateisystem zu Ihrer Datenbank hinzufügen (haben Sie irgendwann zwischenzeitlich `django-admin.py install filesystems` gemacht? Nein? Machen Sie es jetzt, bevor Sie Ihren Server starten). Jetzt stoppen Sie den Admin-Server, ändern Sie Ihr DJANGO SETTINGS MODULE und starten Sie den Haupt-Einstellungsserver. Jetzt können Sie zu [http://localhost:8000/files/](http://localhost:8000/files/) surfen (zumindest wenn Sie Ihre URLs und Ihren Server so eingerichtet haben wie ich) und die Dateien in Ihrem Dateisystem durchsuchen. Das ist alles. War nicht sehr kompliziert, oder? Django ist wirklich einfach zu verwenden.

Zerospan scheint eine P2P-Software mit Verschlüsselung und Integration von Bonjour (ex-Rendevouz, ex-Zeroconf) zu sein. So richtig schlau werd ich nicht draus, denn der Download enhält keine Doku und das Wiki mit der Doku ist zur Zeit kaputt, daher mal geblogmarked um es mir später mal anzugucken.

Ausbildung als Billiglohnschiene

Was hinter der Forderung des DIHK nach Halbierung des Lehrlingsgrundgehaltes und Flexibilisierung der Arbeitszeiten steckt, wird einem klar wenn man sich Zitate des DIHK-Vorsitzenden ansieht:

"Mein Vorschlag ist, eine bundesweite Basisvergütung von 270 Euro einzuführen", sagte er der Zeitung "Die Welt". Er rechtfertigte seinen Vorstoß damit, dass so mehr Lehrstellen finanziert werden könnten. "Eine Ausbildungsvergütung von bis zu 800 Euro ist für viele Betriebe einfach zu hoch."

"Die Arbeitszeiten müssen den Bedürfnissen der Branchen besser angepasst werden." Es ergebe keinen Sinn, dass eine 17-jährige Restaurantfachfrau um 22.00 Uhr gehen müsse, "wenn noch alle Tische besetzt sind"

Da gehts einfach nur darum billige Arbeitskräfte zu haben, aber nicht darum eine fachgerechte Ausbildung zu gewährleisten. Aber die Forderungen sind ja nicht neu.

Und was die deutsche Wirtschaft von Ausbildung hält, sieht man ja auch an der Tatsache das die Ausbildungsplätze im Vergleich zum Vorjahr wieder 10% runter sind - und damit wieder Jugendliche ohne Ausbildungsplätze geblieben sind, trotz aller Versprechungen der Wirtschaft. Ohne Nichtausbildungsabgabe für grössere Unternehmen wird sich das auch nicht ändern. Aber darüber jammern das es keine ausgebildeten Fachkräfte gibt, das kann die Wirtschaft ganz famos ...

Beckstein on the Roll

Keine Ahnung wie das Kraut heisst das er nimmt, aber es hinterlässt schwere Hirnschäden: Beckstein will deutsches Guantanamo. Abgesehen davon das er auch Verdächtigen in den Kopf schiessen will und Ausländer erstmal in Lager packen will, weil ja auf keinen Fall potentielle Terroristen frei rumlaufen dürfen (durchgeknallte Politiker wie er dürfen aber nicht nur frei rumlaufen sondern auch noch frei ihre Meinung äussern), er ist auch verfassungsfeindlich eingestellt:

Beckstein kritisierte auch das Urteil des Bundsverfassungsgericht, dass in einem Urteil zur niedersächsischen Gesetzgebung klare Eingrenzungen bei der vorbeugenden Telefonüberwachung verlangt hatte. Es müsse zwischen Sicherheits- und Freiheitsinteressen neu abgewogen werden, sagte Beckstein: "Dass der Intimbereich von Terroristen geschützt sein soll, ist für mich schwer erträglich."

Tut mir leid, Herr Beckstein, aber Sie sind in der Prüfung durchgefallen. Denn das Verfassungsgericht schützt nicht explizit den Intimbereich von Terroristen - sondern den Intimbereich der Bürger. Und der steht als schützenswertes Gut im Grundgesetz.

Warum wird eigentlich so einer nicht vom Verfassungsschutz beobachtet? Seine Verfassungsfeindlichkeit ist doch wirklich mehrfach dokumentiert ...

Novell will SCO an den Kragen

Und ihre Betrachtungen über die Rechtslage würden - wenn sie denn vor Gericht Bestand haben - SCO wirklich eine empfindliche Schlappe verpassen.

Der ganze SCO-Linux-Film ist ja recht spannend, aber ganz ehrlich: die Längen zwischen den Actionszenen sind doch ein bischen übertriebn

Pluto raus oder ein Neuer rein?

Astronomen haben ausserhalb der Pluto-Umlaufbahn einen Matschklumpen gefunden der mindestens so gross, warscheinlich aber sogar deutlich grösser als Pluto ist - Planet or Not, Pluto Now Has Far-Out Rival:

Astronomers announced yesterday that they had found a lump of rock and ice that was larger than Pluto and the farthest known object in the solar system. The discovery will probably rekindle debate over the definition of "planet" and whether Pluto still merits the designation.

Jetzt gehts drum ob Pluto seinen Planetenstatus verliert, oder der Neue auch Planet wird.

Wer mit PostgreSQL und Frontier arbeiten will, einfach die PostgreSQL Extension for Frontier installieren. Für Mac und Windows.

Vom Umgang mit Security

Unter ISS geht gegen Veröffentlichung des Vortrags über Cisco-Schwachstellen vor findet man eine Beschreibung wie sich Cisco und ISS Sicherheit vorstellen: massive Eingriffe in die Äusserungsrechte eines Vortragenden auf der Black-Hat-Konferenz. Ok, der war Ex-Mitarbeiter von ISS und hat wohl Informationen genutzt die er nicht veröffentlichen sollte - aber genau diese hirnrissige Geheimniskrämerei ist es ja, die Sicherheit unterminiert - denn das die Angreifer dieses Wissen früher oder später erlangen ist garantiert - wenn Sicherheitslücken existieren, werden sie früher oder später gefunden. Findet Sie jemand der darüber öffentlich berichtet, kann man sich wenigstens dagegen wehren und Gegenmaßnahmen einleiten. Wird die Veröffentlichung unterdrückt, ist der Leidtragende letztendlich der Endanwender - der keine Möglichkeit bekommt sich überhaupt abzusichern - und sei es im Notfall durch Wechsel zu einem anderen Routerhersteller.

Von daher ist es in der Tat so: weder ISS noch Cisco machen damit ein gutes Bild in der Öffentlichkeit. Im Gegenteil, deren Zensurversuche sind eigentlich nur noch ein Argument bei zukünftigen Produktentscheidungen sich gegen Cisco zu entscheiden - denn man kann deren Sicherheitsaussagen ja ganz offensichtlich nicht trauen.

Wer glaubte das ISO Zeitangaben einfach nur die YYYY-MM-TT HH:MM:SS.HS ist, vergesst es: International standard date and time notation. War ja klar, ist ja ein ISO Standard ...

Leichen im Keller

Jede Software hat sie - irgendwelche Leichen im Keller die anfangen zu stinken wenn man sie findet. Django leider auch. Und zwar die Behandlung von Unicode. Der automatisch generierte Admin in Django schickt immer XHTML und utf-8 raus an den Browser. Die Browser schicken daher auch utf-8 zurück. Jetzt gibt es aber Browser die bei solchen Sachen dann ein etwas anderes Format für die zu schickenden Daten benutzen - das sogenannte Multipart-Format. Dieses wird verwendet weil es die einzige garantierte Methode in HTTP-POST ist, bei der man einen Zeichensatz mitschicken kann.

Dummerweise parsed Django diese Multipart-POSTs mit dem email Modul von Python. Dieses produziert dann fleissig Unicode-Strings aus den als utf-8 markierten Parts. Was ja auch an und für sich korrekt ist - nur sind im Django-Source überall im Sourcecode str() Aufrufe verstreut. Und die krachen dann natürlich, wenn sie unicode vorgeworfen bekommen in dem Zeichen oberhalb von chr(128) drin sind.

Ich hab mir den Source mal angeguckt, der realistischste Ansatz dürfte sein in Django einfach generell dafür zu sorgen das auch Unicode-Ergebnisse dann wieder nach utf-8 gewandelt werden, so das intern nur normale Python-Strings benutzt werden. Das klappt auch soweit, aber es gibt dann noch Probleme mit manchen Datenbanken die bei Speicherung von utf-8 Inhalten das erkennen und dann beim Lesen der Inhalte wieder Unicode produzieren - SQLite ist so eine Datenbank.

Tja, das wird nicht ganz einfach zu beheben sein. Ich hab mich schon mal dran versucht, das ist ein ziemlich ekliges Thema und leider in Django überhaupt nicht berücksichtigt worden - und daher kracht es an allen Ecken und Enden. Mal gucken ob ich da nicht doch noch was brauchbares hinkriege ...

Was mir auch noch aufgefallen ist: Django schickt den Content-type nur über ein meta-Tag mit http-equiv raus. Das ist ein übler Hack, wesentlich besser wäre es wenn der Content-type korrekt als Header gesetzt wäre, dann kann auch nix schief gehen wenn z.B. Apache einen Default-Charset zufügen will. Und die Browser würden auch wesentlich reproduzierbarer reagieren.

Jedenfalls ist das wieder der typische Fall von amerikanischen Programmierern. Die erzählen einem gerne das man einfach nur auf Unicode und utf-8 wechseln soll wenn man von seinen Zeichensatzkodierungsproblemen berichtet, aber ich habe bisher noch keine Software eines amerikanischen Programmierers gesehen die Unicode korrekt gehandhabt hätte ...

Ansonsten gibts in Django noch so die eine oder andere Klinke - besonders nervig, weil nicht dokumentiert, aber leicht zu lösen: die Standard-Zeitzone in Django ist America/Chicago. Dazu muss man dann nur eine Variable TIME_ZONE mit 'Europe/Berlin' als Wert in sein settings-File schreiben und noch einen kleinen Patch anwenden, damit Django mit dem '-' als Zeitzonentrennzeichen klarkommt. Oh Mann, wenn Amerikaner schon mal Software schreiben ...

Irgendwie steigt im Moment gerade meine Motivation mir doch erstmal Ruby on Rails genauer anzugucken, schliesslich sind das Dänen die damit angefangen haben und die sollten zumindestens solche Sachen richtig hinkriegen (wenn nur nicht dieser nette automatische Administrationsteil von Django wäre - der ist es ja genau auf den ich es abgesehen hätte. Warum hat sowas nur keiner für ROR eingebaut, menno ...)

Update: Ich hab am entsprechenden Ticket zum Unicode-Problem einen Patch angehängt (einfach nach ganz unten scrollen) der erstmal das Problem halbwegs in den Griff bekommt - sofern man kein SQLite einsetzt, da SQLite immer Unicode-Strings zurückliefert und die dann auch wieder Stress machen. Aber zumindestens mit PostgreSQL funktionieren jetzt Umlaute in Django. Die Lösung ist nicht wirklich perfekt, aber zumindestens mit nur wenig Codeänderung reinzubringen. Eine richtige Lösung würde wohl grössere Codeumbauten erfordern.

Ein weiterer Patch hängt am Ticket zum Zeitzonenproblem, mit dem Patch kann man dann auch TIME_ZONE = 'Europe/Berlin' benutzen um die Zeitangaben zum Beispiel in der Änderungshistorie in der richtigen Zeitzone zu bekommen.

In solchen Momenten wünscht man sich commit-Rechte zu Django, um solche recht überschaubaren Patches selber reinstellen zu können

Noch ein Update: Adrian war im Chat gestern und heute und die Probleme mit Unicode sind weitestgehend raus. Nur mit SQLite gibts noch Stress, aber da hab ich den Patch schon fertig. Und die Zeitzonengeschichte ist auch behoben im SVN. Und er hat Unittests begonnen. Sehr sinnvoll, wenn man dann mal auf Dauer das ganze Framework sauber durchtesten kann nach einem Patch ...

Linkhaftung nach dem Heise-Urteil

Nach diesem Interview beim WDR gilt: "Jeder, der so einen Link setzt, ist dran":

Man muss eben sehr gut aufpassen. Aufgrund dieser neuen Urteile muss man sich überlegen: Auf wen setze ich einen Link? Früher hat man als Privatperson gesagt: 'Komm, ich hau da hundert Links hintereinander' und war ganz stolz. Heute muss man sich wirklich überlegen, ob der, auf den man einen Link setzt, wirklich vertrauenswürdig ist. Man muss diese Links dann auch in regelmäßigen Abständen gegenchecken und prüfen, was sich auf der gelinkten Seite tut.

Womit - wenn es denn tatsächlich so wäre - faktisch das privat betriebene Infoangebot tot wäre auf kurz oder lang, denn niemand kann seine ganzen Links durchprüfen. Ich hab hier fast 5000 Artikel im Blog, die werd ich garantiert nie alle durchgucken können ob da irgendwo irgendwas ist das irgendwem quer aufstösst.

Und so hat dieses Urteil wieder einen weiteren Nagel in den Sarg des Internet getrieben, nur weil Richter immer wieder diese Scheinrechte von Rechteabzockern höher als die freie Meinungsäusserung und die freie Berichterstattung einstufen

Wer wie ich in die Situation kommt das er die Unicode-Strings in PySQLite2 nicht mag und utf8 Bytestrings braucht: PysqliteFactories sind hier die Lösung, nicht Konverter. Denn Konverter müssten auf jede Spielart von varchar registriert werden die in Benutzung ist - die Row Factories hingegen sind da ziemlich agnostisch und praktisch. Und wenn man schon eine eigene Cursor-Klasse benutzt: diese einfach als Cursor Factory auslegen die dann mit self.row_factory der Instanz eine Row Factory verpasst.

Sysadmins Day

Lisa9 zeigt wie man anständig einem Sysadmin huldigt! Sogar DAU-tauglich mit bebilderter Anleitung

Abridged guide to HTTP Caching ist eine Beschreibung der wichtigsten Caching-Header in HTTP und wie sie verwendet werden sollten.

JSAN ist das für JavaScript was CPAN für Perl ist - ein zentrales Verzeichnis und Downloadbereich für JavaScript Sourcen und Paket.

Linux-VServer ist ein Kernel-Patch und ein Satz Utilities die es ermöglichen auf einer Basismaschine eine Reihe von virtuellen Linux-Kisten laufen zu haben deren Resourcen stark gegeneinander abgeschottet sind. chroot on steroids, oder am ehesten mit BSD Jails zu vergleichen. Interessant für Hosting-Projekte bei denen virtuelle Rootserver gefordert sind. Ist sogar in der aktuellen Debian drin.

Tor Network Status liefert eine Übersicht über Exit-Nodes im tor Netzwerk mit Trafficangaben, erlaubten Ports und IP-Daten. Nett. (gefunden über den Rabenhorst)

typo ist eine Blogsoftware für Ruby on Rails mit scheinbar schon recht weit ausgebauten Features. Speziell auch mit gutem Caching (produziert statische Seiten) für High-Traffic-Sites, bei denen dann Teile per JavaScript weiter dynamisch gehalten werden. Klingt danach das ich mir das nochmal angucken werde wenn mein ROR-Buch ankommt ...

Und die Erde ist doch eine Scheibe - von wegen. Dagegen ansingen!

Django, lighttpd und FCGI, zweiter Versuch

In meinem ersten Versuch mit diesem Zeug habe ich ein Beispiel gegeben, wie man Django-Projekte hinter lighttpd mit einfachen FCGI-Skripten, die in den Server integriert sind, ausführen kann. Ich werde ein wenig mehr über dieses Zeug erzählen, mit einer Möglichkeit, lighttpd und Django zu kombinieren, die viel mehr Flexibilität bei der Verteilung von Django-Anwendungen über Maschinen bietet. Dies ist besonders wichtig, wenn Sie mit hohen Lasten auf Ihren Servern rechnen. Natürlich sollten Sie den Django-Caching-Middleware verwenden, aber es gibt Zeiten, in denen selbst das nicht ausreicht und die einzige Lösung darin besteht, mehr Hardware an das Problem zu werfen.

Aktualisierung: Ich pflege meine Beschreibungen jetzt in meinem Trac-System. Siehe die lighty+FCGI-Beschreibung für Django.

Hinweis: Da Django sehr neue Software ist, habe ich keine Produktionserfahrungen damit. Daher handelt es sich hier eher um einen theoretischen Standpunkt, in den Wissen einfließt, das ich durch den Betrieb von Produktionssystemen für mehrere größere Portale gewonnen habe. Am Ende kommt es nicht so sehr darauf an, welche Software Sie verwenden - es kommt nur darauf an, wie Sie sie über Ihren Server-Farm verteilen können.

Um dieser Dokumentation zu folgen, benötigen Sie die folgenden Pakete und Dateien, die auf Ihrem System installiert sind:

  • [Django][2] selbst - derzeit aus dem SVN geholt. Folgen Sie den Setup-Anweisungen oder verwenden Sie python setup.py install.
  • [Flup][3] - ein Paket mit verschiedenen Möglichkeiten, WSGI-Anwendungen auszuführen. In dieser Dokumentation verwende ich den threaded WSGIServer.
  • [lighttpd][4] selbstverständlich. Sie benötigen mindestens die FastCGI-, die Rewrite- und die Accesslog-Module, diese werden in der Regel mit dem System kompiliert.
  • [Eunuchs][5] - nur erforderlich, wenn Sie Python 2.3 verwenden, da Flup socketpair in den vorkompilierten Servern verwendet und dies erst ab Python 2.4 verfügbar ist.
  • [django-fcgi.py][6] - mein FCGI-Server-Skript, das eines Tages Teil der Django-Distribution sein könnte, aber für den Moment einfach hier herunterladen. Legen Sie dieses Skript irgendwo in Ihren $PATH, z.B. /usr/local/bin und machen Sie es ausführbar.
  • Wenn das oben genannte aus irgendeinem Grund nicht funktioniert (vielleicht unterstützt Ihr System socketpair nicht und kann daher den vorkompilierten Server nicht verwenden), können Sie [django-fcgi-threaded.py][7] - eine Alternative, die den Threading-Server mit all seinen Problemen verwendet. Ich verwende es zum Beispiel auf Mac OS X für die Entwicklung.

Bevor wir beginnen, lassen Sie uns ein wenig über Serverarchitektur, Python und hohe Last sprechen. Die noch bevorzugte Installation von Django erfolgt hinter Apache2 mit mod python2. mod python2 ist eine recht leistungsfähige Erweiterung für Apache, die einen vollständigen Python-Interpreter (oder sogar viele Interpreter mit unterschiedlichen Namensräumen) in den Apache-Prozess integriert. Dies ermöglicht es Python, viele Aspekte des Servers zu steuern. Aber es hat einen Nachteil: Wenn der einzige Zweck darin besteht, Anfragen von Benutzern an die Anwendung weiterzuleiten, ist es eine ziemliche Übertreibung: Jeder Apache-Prozess oder Thread wird einen vollständigen Python-Interpreter mit Stack, Heap und allen geladenen Modulen enthalten. Apache-Prozesse werden auf diese Weise etwas fett.

Ein weiterer Nachteil: Apache ist einer der flexibelsten Server da draußen, aber im Vergleich zu kleinen Servern wie lighttpd ein Ressourcenfresser. Und - aufgrund der Architektur der Apache-Module - wird mod_python die vollständige Anwendung im Sicherheitskontext des Webservers ausführen. Zwei Dinge, die Sie in Produktionsumgebungen nicht oft mögen.

Ein natürlicher Ansatz ist also die Verwendung leichterer HTTP-Server und das Hinterlegen Ihrer Anwendung dahinter - unter Verwendung des HTTP-Servers selbst nur zum Servieren von Medien und unter Verwendung von FastCGI, um Anfragen vom Benutzer an Ihre Anwendung weiterzuleiten. Manchmal stellen Sie diesen kleinen HTTP-Server hinter einen Apache-Front, der nur mod_proxy (entweder direkt oder über mod_rewrite) verwendet, um Anfragen an den Webserver Ihrer Anwendung weiterzuleiten - und glauben Sie es oder nicht, dies ist tatsächlich viel schneller als das Servieren der Anwendung direkt mit Apache!

Die zweite Falle ist Python selbst. Python hat eine recht schöne Threading-Bibliothek. Es wäre also ideal, Ihre Anwendung als Thread-Server zu erstellen - weil Threads viel weniger Ressourcen als Prozesse verbrauchen. Aber das wird Sie beißen, wegen einer speziellen Funktion von Python: der GIL. Der gefürchtete globale Interpreter-Lock. Dies ist kein Problem, wenn Ihre Anwendung zu 100% Python ist - der GIL greift nur, wenn interne Funktionen verwendet werden oder wenn C-Erweiterungen verwendet werden. Schade, dass fast alle DBAPI-Bibliotheken mindestens einige Datenbank-Client-Code verwenden, der eine C-Erweiterung verwendet - Sie starten einen SQL-Befehl und das Threading wird deaktiviert, bis der Aufruf zurückkehrt. Keine mehreren Abfragen laufen ...

Die bessere Option ist also die Verwendung eines Fork-Servers, weil der GIL dann nicht greift. Dies ermöglicht einem Fork-Server, mehrere Prozessoren in Ihrer Maschine effizient zu nutzen - und so auf lange Sicht viel schneller zu sein, trotz des Overheads von Prozessen gegenüber Threads.

Für diese Dokumentation nehme ich einen dreischichtigen Ansatz zur Verteilung der Software: Die Front wird Ihr vertrauenswürdiger Apache sein, der einfach alles an Ihren projektspezifischen lighttpd weiterleitet. Der lighttpd hat Zugriff auf das Dokumentenstammverzeichnis Ihres Projekts und leitet spezielle Anfragen an Ihren FCGI-Server weiter. Der FCGI-Server selbst kann auf einem anderen Rechner laufen, wenn dies für die Lastverteilung erforderlich ist. Er wird einen vorkompilierten Server verwenden, weil es in Python ein Threading-Problem gibt, und er kann Multiprozessor-Maschinen nutzen.

Ich werde nicht viel über die erste Ebene sprechen, weil Sie dies leicht selbst einrichten können. Leiten Sie einfach Dinge an die Maschine weiter, auf der Ihr lighttpd läuft (in meinem Fall läuft der Apache normalerweise auf anderen Maschinen als die Anwendungen). Schauen Sie in der mod_proxy-Dokumentation nach, normalerweise ist es nur ProxyPass und ProxyPassReverse.

Die zweite Ebene ist interessanter. lighttpd ist ein bisschen seltsam in der Konfiguration von FCGI-Dingen - Sie benötigen FCGI-Skripte im Dateisystem und müssen diese mit Ihrem FCGI-Serverprozess verbinden. Die FCGI-Skripte müssen tatsächlich keinen Inhalt enthalten - sie müssen nur im Dateisystem vorhanden sein.

Wir beginnen also mit Ihrem Django-Projektverzeichnis. Legen Sie einfach ein Verzeichnis public_html dort hinein. Das ist der Ort, an dem Sie Ihre Mediendateien ablegen, z.B. das Admin-Media-Verzeichnis. Dieses Verzeichnis wird das Dokumentenstammverzeichnis für Ihren Projekt-Server sein. Stellen Sie sicher, dass Sie nur Dateien dort ablegen, die keine privaten Daten enthalten - private Daten wie Konfigurationen und Module sollten besser an Orten bleiben, die nicht vom Webserver zugänglich sind. Als Nächstes richten Sie eine lighttpd-Konfigurationsdatei ein. Sie werden nur die Rewrite- und die FastCGI-Module verwenden. Keine Notwendigkeit, ein Zugriffsprotokoll zu führen, dies wird von Ihrer ersten Ebene, Ihrem Apache-Server, geschrieben. In meinem Fall befindet sich das Projekt in /home/gb/work/myproject - Sie müssen dies an Ihre eigene Situation anpassen. Speichern Sie den folgenden Inhalt als /home/gb/work/myproject/lighttpd.conf


 server.modules = ( "mod_rewrite", "mod_fastcgi" )
 server.document-root = "/home/gb/work/myproject/public_html"
 server.indexfiles = ( "index.html", "index.htm" )
 server.port = 8000
 server.bind = "127.0.0.1"
 server.errorlog = "/home/gb/work/myproject/error.log"

fastcgi.server = (
"/main.fcgi" => (
"main" => (
"socket" => "/home/gb/work/myproject/main.socket"
 )
 ),
"/admin.fcgi" => (
"admin" => (
"socket" => "/home/gb/work/myproject/admin.socket"
 )
 )
 )

url.rewrite = (
"^(/admin/.*)$" => "/admin.fcgi$1",
"^(/polls/.*)$" => "/main.fcgi$1"
 )

mimetype.assign = (
".pdf" => "application/pdf",
".sig" => "application/pgp-signature",
".spl" => "application/futuresplash",
".class" => "application/octet-stream",
".ps" => "application/postscript",
".torrent" => "application/x-bittorrent",
".dvi" => "application/x-dvi",
".gz" => "application/x-gzip",
".pac" => "application/x-ns-proxy-autoconfig",
".swf" => "application/x-shockwave-flash",
".tar.gz" => "application/x-tgz",
".tgz" => "application/x-tgz",
".tar" => "application/x-tar",
".zip" => "application/zip",
".mp3" => "audio/mpeg",
".m3u" => "audio/x-mpegurl",
".wma" => "audio/x-ms-wma",
".wax" => "audio/x-ms-wax",
".ogg" => "audio/x-wav",
".wav" => "audio/x-wav",
".gif" => "image/gif",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
".xbm" => "image/x-xbitmap",
".xpm" => "image/x-xpixmap",
".xwd" => "image/x-xwindowdump",
".css" => "text/css",
".html" => "text/html",
".htm" => "text/html",
".js" => "text/javascript",
".asc" => "text/plain",
".c" => "text/plain",
".conf" => "text/plain",
".text" => "text/plain",
".txt" => "text/plain",
".dtd" => "text/xml",
".xml" => "text/xml",
".mpeg" => "video/mpeg",
".mpg" => "video/mpeg",
".mov" => "video/quicktime",
".qt" => "video/quicktime",
".avi" => "video/x-msvideo",
".asf" => "video/x-ms-asf",
".asx" => "video/x-ms-asf",
".wmv" => "video/x-ms-wmv"
 )

Ich binde den lighttpd nur an die localhost-Schnittstelle, weil in meiner Testumgebung der lighttpd auf demselben Host wie der Apache-Server läuft. In Multi-Server-Einstellungen werden Sie den lighttpd-Servern natürlich an die öffentliche Schnittstelle binden. Die FCGI-Skripte kommunizieren in dieser Einstellung über Sockets, weil in dieser Testumgebung ich nur einen Server für alles verwende. Wenn Ihre Maschinen verteilt wären, würden Sie die "host" und "port" Einstellungen anstelle der "socket" Einstellung verwenden, um mit FCGI-Servern auf verschiedenen Maschinen zu verbinden. Und Sie würden mehrere Einträge für die "main" Sache hinzufügen, um die Last der Anwendung auf mehrere Maschinen zu verteilen. Schauen Sie in der lighttpd-Dokumentation nach, welche Optionen Sie haben werden.

Ich richte zwei FCGI-Server für dies ein - einen für die Admin-Einstellungen und einen für die Haupt-Einstellungen. Alle Anwendungen werden durch die Haupt-Einstellungen FCGI weitergeleitet und alle Admin-Anfragen werden an den Admin-Server geleitet. Dies geschieht mit den beiden Rewrite-Regeln - Sie müssen eine Rewrite-Regel für jede Anwendung hinzufügen, die Sie verwenden.

Da lighttpd die FCGI-Skripte benötigt, um sie zu existieren, um den PATH_INFO an das FastCGI weiterzugeben, müssen Sie die folgenden Dateien berühren: /home/gb/work/myprojectg/public_html/admin.fcgi ``/home/gb/work/myprojectg/public_html/main.fcgi

Sie müssen keinen Code enthalten, sie müssen nur im Verzeichnis aufgeführt sein. Ab lighttpd 1.3.16 (zum Zeitpunkt der Abfassung dieser Zeilen nur in svn) können Sie ohne die Stubs für die .fcgi laufen - Sie fügen einfach "check-local" => "disable" zu den beiden FCGI-Einstellungen hinzu. Dann sind die lokalen Dateien nicht mehr erforderlich. Wenn Sie also diese Konfigurationsdatei erweitern möchten, müssen Sie nur einige sehr grundlegende Regeln beachten:

  • jede Einstellungsdatei benötigt ihren eigenen .fcgi-Handler
  • jeder .fcgi muss im Dateisystem berührt werden - dies könnte in einer zukünftigen Version von lighttpd verschwinden, aber für den Moment ist es erforderlich
  • die Lastverteilung erfolgt auf Ebene der .fcgi - fügen Sie mehrere Server oder Sockets hinzu, um die Last auf mehrere FCGI-Server zu verteilen
  • jede Anwendung benötigt eine Rewrite-Regel, die die Anwendung mit dem .fcgi-Handler verbindet

Jetzt müssen wir die FCGI-Server starten. Das ist eigentlich ganz einfach, verwenden Sie einfach das bereitgestellte django-fcgi.py-Skript wie folgt:


 django-fcgi.py --settings=myproject.work.main
 --socket=/home/gb/work/myproject/main.socket
 --minspare=5 --maxspare=10 --maxchildren=100
 --daemon

django-fcgi.py --settings=myproject.work.admin
 --socket=/home/gb/work/myproject/admin.socket
 --maxspare=2 --daemon

Diese beiden Befehle starten zwei FCGI-Serverprozesse, die die angegebenen Sockets zur Kommunikation verwenden. Der Admin-Server wird nur zwei Prozesse verwenden - dies liegt daran, dass der Admin-Server oft nicht der Server mit den vielen Hits ist, das ist der Hauptserver. Daher erhält der Hauptserver eine höhere als Standard-Einstellung für Reserveprozesse und maximale Kindprozesse. Natürlich ist dies nur ein Beispiel - passen Sie es an Ihre Bedürfnisse an.

Der letzte Schritt ist das Starten Ihres lighttpd mit Ihrer Konfigurationsdatei: lighttpd -f /home/gb/work/myproject/lighttpd.conf

Das war's. Wenn Sie jetzt entweder den lighttpd direkt unter http://localhost:8000/polls/ oder durch Ihren Front-Apache zugreifen, sollten Sie die Ausgabe Ihrer Anwendung sehen. Zumindest, wenn alles richtig gelaufen ist und ich nicht zu viele Fehler gemacht habe.

Eunuchs liefert ein paar Funktionen nach die unter Python 2.3 noch nicht verfügbar sind. Speziell socketpair und recvmsg/sendmsg sind da sehr wichtig - für Serverprogrammierung mit preforked Servern zum Beispiel.

Noch son Fragebogen

Aus meiner Mailbox von Lisa Sonnabend:

Im Rahmen meiner Abschlussarbeit am Institut für Kommunikationswissenschaft und Medienforschung der Ludwigs-Maximilians-Universität München führe ich eine Befragung unter Webloglesern zum Thema „Glaubwürdigkeit von Weblogs“ durch. Es handelt sich um eine der ersten wissenschaftlichen Untersuchungen zum Phänomen Weblogs in Deutschland.

Es soll geklärt werden, ob Weblogs in gewissen Punkten wie Fairness oder Unvoreingenommenheit bereits als ähnlich vertrauenswürdig und kompetent gesehen werden wie traditionelle Medien – und in welchen Punkten große Unterschiede herrschen. Darüber hinaus wird mit der Befragung untersucht, welche besonderen Qualitäten Weblogs aus Sicht der Rezipienten haben und welchen Stellenwert diese für die Nutzer spielen. Anhand der Ergebnisse soll anschließend eine Prognose über das zukünftige Gewicht von Weblogs in der Medienlandschaft gefällt werden.

Und ich soll den Link ins Blog packen, damit Leute dabei mitmachen. Nagut, mach ich das doch mal, auch wenn ich mich frage was für eine Kompetenz und Vertrauenswürdigkeit die alten Medien eigentlich haben sollen

Hier gehts zum Fragebogen

präventive Telefonüberwachung is nich

Denn das Verfassungsgericht erklärt präventive Telefonüberwachung für nichtig. Betrifft primär Niedersachsen, aber ähnliche Situationen gibt es auch in anderen Bundesländern. Gut wenn mal dem ganzen Überwachungsfetischismus ein Riegel vorgeschoben wird.

es gibt Tage da hasst mein Computer mich

Zum Beispiel wenn ich mit Flup spiele und statt des threaded Servers einen forked Server nehmen will. Und feststelle, das der dann aber die Funktion socketpair benötigt. Die aber dummerweise nur ab Python 2.4 verfügbar ist, welches zwar auf Debian Sarge da ist, aber dafür gibts in der Debian Sarge für Python 2.4 keinen Psycopg - welcher wiederum Voraussetzung für Django und PostgreSQL ist, weshalb ich mich überhaupt ja nur mit FastCGI beschäftige. PsycoPG selber installieren macht keinen Spaß, da man dafür nicht nur die PostgreSQL Header braucht, die normal installiert werden, sondern auch ein paar interne Header - also im Prinzip einen Build-Tree. Und dann braucht man noch die egenix-mx-base Header, die man nur für Python 2.3 kriegt, also müsste man das auch selber installieren. Backports aus der nächsten Debian geht auch nicht, da die gerade auf PostgreSQL 8.0 umbauen und Sarge ja noch 7.4 benutzt und ich nicht gleich das ganze System upgraden wollte. Und so dreht man sich im Kreis und kommt sich leicht verarscht vor vor lauter Abhängigkeiten und Versionskonflikten.

Und was macht man also als Lösung, weil der threaded Server dummerweise nur Segfaults im Psycopg produziert? Man nimmt den threaded Server, verbietet ihm das threaden und startet ihn über den spawn-fcgi vom lighttpd, oder direkt vom lighttpd. Was aber irgendwie auch wieder dämlich ist, da dann immer pro FCGI-Server 3 Threads rumgammeln, von denen 2 nur in der Prozessliste stehen und nix zu tun haben. Und das alles nur weil mod python2 (was für Django gebraucht wird) Apache2 voraussetzt, der wiederum mod perl2 voraussetzt, welches inkompatibel zum alten mod perl ist, weshalb bei mir eine ganze Reihe von meinen Sites nicht mehr laufen würden, würde ich auf Apache2 umstellen. Was ich eh nicht will, weil Apache2 mit mod python arschlangsam ist. Und schon wieder verarscht worden. Ich hätte mir echt einen sinnvolleren Beruf suchen sollen.

Wer nix kapiert hat: macht nix, ist Technik, ist nicht wichtig, wollte das einfach nur mal gesagt haben.