# Tuesday, October 16, 2007

(Deutsche Version)

In my article Acrobat PDF Form Felder auf Ebenen I have explained the problem in detail: I want to create layers in a PDF file and put Form Fields or Annotations into these layers or Optional Content Groups (OCG).

Back then, I solved the problem by means of Acrobat SDK Snippet Runner. An architecture that enables you to run individual Snippets as a plug-in in Acrobat. Quite nice for a first try, but in the end not a solution that should be distributed. Developery only.

For this reason, I took a closer look at the SDK and built a proper plug-in:

Acrobat CPTec Layer Plugin Menu

The plug-in links into the Advanced menu of Acrobat and is only active when a document is loaded. When called, it asks for a text file. This file determines which annotations are put into which layers. Layers that are not present will be created.

The structure of the text file is very simple. Each line contains the name of an annotation, the | character, and then the name of the related layer:

TestAnnotation1|TestLayer1
TestAnnotation2|TestLayer2

When editing in Acrobat, it is possible that the layer information for the Annotations gets lost. In this case, simply run the same text file again. Assigning fields that are already present does not have any negative effect.

Disclaimer:

  • I am not much of a C++ programmer.
  • This is my first Adobe Acrobat plug-in.
  • The plug-in has only been tested with Acrobat 8.1 Professional.
  • I do not assume responsibility for anything: If Acrobat crashes or all PDF files are destroyed, it is not my fault.
  • Use at your own risk.
  • Please pay attention to the MIT/X11 License in the Zip file.

Have fun with the plug-in, and maybe you want to send me a feedback:

CPTecLayerPlugin.zip (180 KB)

Tuesday, October 16, 2007 5:25:09 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [1]  | 

(English version)

In meinem Beitrag Acrobat PDF Form Felder auf Ebenen habe ich das Problem ausführlich erklärt: Ich möchte in einem PDF Ebenen erzeugen und Form Fields bzw. Annotations auf diese Ebenen oder Optional Content Groups (OCG) legen.

Damals kam ich zu einer Lösung über den Acrobat SDK Snippet Runner. Einer Architektur, die es ermöglicht einzelne Snippets als Plug-in im Acrobat laufen zu lassen. Für erste Schritte ist das ganz nett, aber man hat am Ende leider keine verteilbare Lösung. Ein Entwickler Tool eben.

Also habe ich mich noch weiter in die SDK gestürzt und ein richtiges Plug-in gebastelt:

Acrobat CPTec Layer Plugin Menu 

Das Plug-in bindet sich in das Advanced Menü von Acrobat ein und ist nur aktiv, wenn ein Dokument geladen ist. Beim Aufruf verlangt es nach einer Textdatei. Diese Datei steuert, welche Annotations auf welche Ebene gelegt werden sollen. Nicht vorhandene Ebenen werden erzeugt.

Die Struktur der Datei ist sehr einfach. Pro Zeile wird der Name einer Annotation und durch ein | getrennt der Name der zugehörigen Ebene angegeben:

TestAnnotation1|TestLayer1
TestAnnotation2|TestLayer2

Beim Editieren in Acrobat kann eventuell die Ebenen-Information der Annotations verloren gehen. Dann hilft einfach ein erneuter Lauf mit der gleichen Textdatei. Eine erneute Zuordnung vorhandener Felder hat keine nachteiligen Effekte.

Disclaimer / Haftungsausschluss:

  • Ich kann eigentlich nicht in C++ programmieren.
  • Das ist mein erstes Adobe Acrobat Plug-in.
  • Das Plug-in wurde nur mit Acrobat 8.1 Professional getestet.
  • Ich übernehme keine Verantwortung für Irgendwas: Ob Acrobat abstürzt oder alle PDFs zerstört werden ist nicht meine Schuld.
  • Benutzung auf eigene Gefahr.
  • Bitte die MIT/X11 Lizenz in der Zip-Datei beachten.

Dann viel Spaß damit und vielleicht gibt es ja Rückmeldungen:

CPTecLayerPlugin.zip (180 KB)

Tuesday, October 16, 2007 4:23:01 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Monday, October 15, 2007

Der Acrobat Reader kann PDF Dateien nicht nur als normale Applikation darstellen, er bindet sich auch als Plug-In in den Webbrowser ein. Gerade dieser Integration in den Browser und damit in das Internet hat viel zur Beliebtheit von PDF beigetragen.

Aus der Sicht von JavaScript verhält sich aber Acrobat eingebettet im Browser ein bisschen anders, als im eigenständigen Modus. Um auf diese Unterschiede reagieren zu können, gibt es am Doc Objekt, das einem PDF Dokument entspricht, die Eigenschaft external. Im Kontext eines Dokuments kann dieser Zustand einfach mit this.external abgefragt werden. Aus der JavaScript Referenz:

Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser).

Ich möchte diesen Wert beim Laden des Dokuments abfragen. Da ich aber zur Erzeugung der PDF Dateien Acrobat automatisiere, werden in diesem Prozess auch die Dokumente einmal geladen. Ein automatisierter Acrobat mag aber offensichtlich diesen Wert nicht verraten und hängt sich auf.

Alternative frage ich jetzt einfach die path Eigenschaft ab. Damit erhält man den Pfad zum PDF Dokument. Fängt der mit http an, dann kam die Datei vom Webserver und man ist damit im Webbrowser:

// Mag Acrobat nicht immer
var external1 = this.external;
// Workaround
var external2 = (this.path.substr(0, 4) == "http");
Monday, October 15, 2007 6:20:57 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Friday, October 12, 2007

Software Entwicklung ist ein sehr kreativer Prozess. Nur wenn der Strom weg ist, bleibt selten etwas Sichtbares zurück. Papier ist immer noch gefragt um Daten für Anwender zu zugänglich zu machen.

Der Weg von einer Datenbank zu einem Produkt Katalog wird gerne Database Publishing genannt. Vor ca. 9 Jahren haben wir begonnen für den Automobilzulieferer FTE einen Aftermarket Produkt Katalog in Papierform zu erstellen. Dieser Katalog wird seitdem alle 2 Jahre neu aufgelegt.

Der Prozess sollte vollständig automatisiert sein und die Daten mussten stark verdichtet werden. Die Verdichtung der Datenfülle war notwendig, da für jeden PKW Typ alle verfügbaren FTE Produkte ausgegeben werden sollten. Die Ausgabe redundanter Information musste vermieden werden.

Dennoch sind wir inzwischen an die Grenzen der Buchbinderei gestoßen:

fte_katalog

Ein Telefonbuch wirkt wie ein Flyer daneben. Der FTE Ersatzteil-Katalog ist 5,5 cm dick und der letzte PKW Typ, der WARTBURG 353 Tourist (10.1967-05.1991) ist auf Seite 1824 zu finden. Nur mit Spezial-Papier und einem fähigen Buchbinder konnte das Werk überhaupt noch produziert werden.

FTE PKW PDF

Die ausgelieferte PDF Datei wirkt mit 145 MB Dateigröße noch gar nicht so mächtig. Stecken doch so viele kleine Icons und Detailinformationen in Ihr:

FTE Katalog - offen

Ich freue mich jedes Mal auf den fertigen Katalog in Papierform. Da hat man wirklich etwas in der Hand. Inzwischen ist der Ablauf eingespielt und auch die Rechner sind so leistungsfähig, dass die Abwicklung nicht mehr klemmt. Aber vor 8 Jahren, war der Weg schon spürbar steinig. Auch die Wahl der Tools ist historisch begründet.

Ausgangspunkt sind die TecDoc Stammdaten zusammen mit den FTE Einspeiser Daten. Das sind standardisierte Textdateien die wir über ein Visual FoxPro Import Tool in den MS SQL Server 7 eingelesen haben. Inzwischen verwenden wir natürlich den MS SQL Server 2005 :)

Auf diese Datenbank greift ein weiteres FoxPro Programm zu. In diesem Katalog Programm werden alle Verdichtungen der Daten durchgeführt und schließlich über OLE Automatisierung in Word Dokumente ausgegeben. Richtig gelesen: Wir waren kühn genug, mit Word 97 automatisiert 1500 Seiten Dokumente zu erzeugen! Damals waren es nur 1500 Seiten.

Heute kann man darüber nur schmunzeln. Damals habe ich geschwitzt. Es hat einiger Workarounds und Tricks bedurft, um diese Dokumente zu erstellen. Die Rechenzeiten waren enorm, jeder Fehlversuch hat viel Zeit gekostet. Es liefen diverse Rechner parallel um den Vorgang zu beschleunigen. War endlich das Word Dokument erstellt, musste noch ein PDF über den Acrobat Distiller Druckertreiber erstellt werden. Das dauert noch mal und auch dabei konnte Word abstürzen.

* Word starten und die Vorlage laden
oWord=CreateObject("Word.Application")
oWord.Options.CheckSpellingAsYouType=.F.
oWord.Options.CheckGrammarAsYouType=.F.
oWord.Documents.Add(out_name,.F.)
oDoc=oWord.ActiveDocument
oDoc.Windows(1).View.ShowFieldCodes=.F.
oDoc.SaveAs(out_name)
oWord.ActiveWindow.View.Type = 1

* dann ganz viele Elemente hinzufügen
oDoc.Tables.Add()
oDoc.Paragraphs.Add()

* Fertig
oDoc.Save()
oWord.Quit(0)

So lässt sich der FoxPro Code zusammenfassen :)

Wer übrigens FTE Ersatzteile ohne diesen Katalog finden möchte, für den haben wir auch einen kleinen Web-Katalog gebastelt: FTE Katalog. Da schwitzt nur die PHP Engine und nicht der Buchbinder.

Friday, October 12, 2007 4:06:47 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Tuesday, October 09, 2007

In einem PDF können verschiedene Ebenen definiert werden. Ebenen heißen auf Englisch Layers. Diese Layers gibt es in vielen Zeichen- und Designprogrammen. So auch im Adobe Illustrator oder im Adobe Photoshop. Auf diesen Layern können Objekte gruppiert werden, die irgendwie zusammengehören. Man kann diese Ebenen sperren oder unsichtbar machen. Das hilft beim Arbeiten, man behält die Übersicht.

Acrobat PDF Layers

Mit den PDF Annotations / Form Fields hat man in einem PDF die Möglichkeit mit dem Benutzer zu interagieren. Da wäre es sehr praktisch, diese UI-Elemente auf Layern anzuordnen und in Abhängigkeit des Zustandes des Formulars sichtbar zu machen. In Windows Forms gibt es dazu das beispielsweise das TabControl.

Leider fehlt im Adobe Acrobat die Möglichkeit Ebenen zu erzeugen! Wie? Da oben ist doch ein Screenshot mit dem Layers Dialog? Tja, der kann aber nur Ebenen umschalten oder zusammenfassen.

Schade, Ebenen erzeugt man in der Adobe Welt mit dem Illustrator oder InDesign. Beide Tools können die internen Ebenen in ein PDF exportieren. Das geht auch mit einem ansonsten leeren Dokument. Sehr umständlich, aber wenn es den sein muss.

Das leere, aber mit Ebenen versehene PDF (Layered PDF) kann man in Acrobat laden und die Ebenen selektieren. Also wähle ich die gewünschte Ebene aus und erzeuge eine List Box. Ups, die landet nicht in der Ebene sondern im Dokument selbst. Was mache ich falsch? Wo kann man Objekte den Ebenen zuweisen? Irgendwann rückt die Acrobat Hilfe damit raus:

You can add content, such as review comments, stamps, or form fields, to layered documents just as you would to any other PDF document. However, the content is not added to a specific layer, even if that layer is selected when the content is added. Rather, the content is added to the entire document.

An der Stelle würde ich normalerweise aufgeben. Acrobat kann einfach mit Ebenen nicht umgehen. Fertig!

Ich habe aber bereits ein PDF mit Form Objekten auf Ebenen gesehen. Das PDF habe ich noch mal in Acrobat geladen. Keine Täuschung, es stimmt. Wie haben die das nur gemacht? Vielleicht mit JavaScript?

In der JavaScript SDK finden sich tatsächlich einige Methoden zur Manipulation von Layern. Nur dauert das ein bisschen. Außer in der Benutzeroberfläche heißen die Layers bei Acrobat nämlich Optional Content Groups (OCG). Aber auch in JavaScript kann man keine Objekte gezielt diesen OCGs zuweisen.

Mit diesem Terminus findet Google aber jetzt auch mehr technische Beiträge. Zum Beispiel diesen Trick: Buttons on Adobe PDF Layers. Es werden per InDesign CS3 Buttons auf Ebenen erzeugt, die beim PDF Export zu PDF Form Buttons werden. Die Ebeneninformation bleibt dabei erhalten. Leider schließt der Beitrag mit:

What about Text fields? Unfortunately we don’t yet have an option in InDesign to convert a text frame to an Acrobat text form field. Any fields you create in Acrobat will be visible on all layers.

Ich will aber meine List Box! Es geht, ich habe den Beweis! In der Adobe Acrobat User Community gibt es die Rubrik Ask an expert. Die Antwort zum Thema Move an object to an existing layer:

Unfortunately, you can't change layer data in Acrobat. You can neither add new layers to a PDF, move data between layers, or introduce new data on a given layer. You need to return to Illustrator and recreate the PDF if you want to change the layer data.

Jetzt kommt der finale C++ Hammer: In der Acrobat API Referenz findet sich die Methode PDAnnotSetOCMD. Damit kann man eine Annotation (Form Field) einem optional-content membership dictionary (OCMD) zuweisen. Dieses Dictionary stellt die Verbindung von OCG und Annotation dar. Genau was ich brauche. Nebenbei findet sich dann noch die Methode PDOCGCreate um Ebenen zu erzeugen.

Diese API steht aber nur einem C++ Acrobat Plug-In zur Verfügung. Aber auch hier hilft die SDK weiter: Adobe hat einen Snippet Runner beigelegt. Zusammen mit einer Visual Studio Solution und einigen Beispiel Snippets. Der Snippet Runner kompiliert zu einem Acrobat Plug-In, das man in das Acrobat Verzeichnis kopiert. Beim nächsten Start von Acrobat, startet das Plug-In mit und startet dient als Server. Auf diesen Server wiederum greift das Snippet Runner Common Interface 2.0 zu. Witzigerweise eine Adobe Flex 2 Applikation. Also quasi eine getarnte Flash Applikation:

SnippetRunner

Über dieses Interface kann man gezielt sein eigenen Snippets im Acrobat Plug-In Kontext laufen lassen. Der Code der Snippets ist dabei mit in den Server kompiliert. Das Frontend liefert den Auswahl Mechanismus und die Konsolen-Ausgabe.

Ich kann mich nicht erinnern, wann ich zuletzt in C++ unterwegs war. Es ist sehr lange her und war auch damals nur sehr kurz. Sprich, ich habe eigentlich keine Ahnung. Aber irgendwie hat es für diese Funktionalität gereicht und ich kann jetzt mit zwei Methoden meine Ebenen erzeugen und Form Objekte anhand deren Namen in diese Ebenen verschieben:

PDOCG ocgSubparts = CPTecCreateOCG("Subparts", true);
PDOCG ocgAssembly = CPTecCreateOCG("Assembly", false);
CPTecMoveAnnot("TestSubparts", ocgSubparts);
CPTecMoveAnnot("TestAssembly", ocgAssembly);

Der zweite Parameter bei CPTecCreateOCG gibt an, ob die Ebene beim Laden das PDFs sichtbar sein soll. Falls bereits eine Ebene mit dem gewünschten Namen vorhanden ist, wird diese zurückgegeben. Die zweite Methode CPTecMoveAnnot weist der Annotation mit dem übergebenenNamen die entsprechende Ebene zu. Damit ist ein mehrfacher Lauf des Snippets problemlos möglich.

Und so sieht das Ergebnis im PDF aus. Zwei List Boxen, die auf Ebenen liegen, die man später auch programmatisch umschalten kann.

PDF Layers On

PDF Layers Subparts

PDF Layers Assembly

Ist das Ergebnis den Aufwand wert? Ja klar. Ärgerlich wäre nur, wenn Acrobat 8.2 den Layer Dialog um diese Funktionen erweitern würde. Bis dahin kann ich ja noch grübeln, ob ich meine beiden C++ Plug-In Methoden vielleicht veröffentliche :)

Update:
Ich habe nicht den Code, sondern gleich ein fertiges Plug-in veröffentlicht: CPTec Layer Plugin für Acrobat

Tuesday, October 09, 2007 7:00:13 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [1]  | 
# Thursday, October 04, 2007

ScottGu hat die Neuigkeit gerade bekannt gegeben: Releasing the Source Code for the .NET Framework Libraries 

One of the things my team has been working to enable has been the ability for .NET developers to download and browse the source code of the .NET Framework libraries, and to easily enable debugging support in them.

Today I'm excited to announce that we'll be providing this with the .NET 3.5 and VS 2008 release later this year.

Das bedeutet das Debugging endet nicht an den Basisklassen. Wenn man bisher eine Ahnung davon kriegen wollte, wie es nach dem eigenen Code im Framework weitergeht, musste man mit Reflector selber die Libraries untersuchen. Das ist aber kein Vergleich zu einem echten Debugging. Jetzt sollen wohl sogar die Kommentare zur Verfügung stehen.

Zusätzlich wird dabei sicher die Code Qualität des Frameworks verbessert. Wenn jetzt viele Entwickler problemlos den Framework Code im Kontext Ihrer eigenen Programme debuggen können, ist das ein sehr tiefgreifender Code Review.

Super tolle Sache. Danke Microsoft, danke ScottGu!

Update: Golem hat den Inhalt des Artikel weitergehend ins Deutsche übertragen.

Thursday, October 04, 2007 9:53:48 AM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Friday, September 28, 2007

Wir testen gerade, ob für uns Windows Live Custom Domains WLCD eine Alternative zum eigenen Mail-Server sein kann. Inzwischen hat sich der Outlook Connector entschlossen, nicht mehr mit dem Server reden zu wollen.

Vorher:

Outlook Connector - Server Status

Nachher:

WLCD - Outlook Connector - Server Error

Zur Zeit möchte er sich nicht anmelden. Gestern wollte er mir erklären, dass ich für den Dienst bezahlen soll. Ich denke, ich verwende die aktuelle Version: 12.0.4518.1063

Andere haben das Problem auch: Technical Support - Domain Live Account and OUTLOOK CONNECTOR. Es scheint nur den Connector und die Custom Domain Accounts zu betreffen. Das Web Interface geht.

Windows Live Help Community - Beta

Google hat es vorgemacht: Alles ist Beta, bis es eingestellt oder durch den Nachfolger abgelöst wird. Die Beta Hemmschwelle ist sehr niedrig geworden. Sogar die Seite, die gemeinschaftliche Hilfe anbietet ist Beta.

Das ganze holpert im Moment also noch. Unsere Haupt Domain werden wir definitiv nicht so schnell umziehen.

Wir wollen aber auch den mobilen Zugriff testen. Der ursprüngliche Auslöser für unsere Aktivitäten war der Abwesenheits-Assistent. Wieso sollen wir allen Spammern während einer Dienstreise unsere E-Mail-Adresse bestätigen? Besser als eine "Out of Office" Nachricht ist doch ein Push-Mail Dienst und eine entsprechende Reaktion des Empfängers.

Für eine Übergangsfrist werden wir das vielleicht so lösen, dass nicht der Abwesenheits-Assistent, sondern eine Weiterleitung auf das sekundäre Hotmail Konto vor einer Dienstreise aktiviert wird.

Nur welches Windows Mobile 6 Handy sollen wir testen?

Update: Der Outlook Connector verbindet sich jetzt wieder erfolgreich.

Friday, September 28, 2007 11:32:14 AM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [2]  | 
# Friday, September 21, 2007

 For those who aren’t familiar with Custom Domains, we provide free hosted e-mail for your domain.  Let’s say you own the domain name, “wingtiptoys.com.”   With Custom Domains, you get unlimited, free e-mail accounts at that domain.  You can open accounts for sales@wingtiptoys.com, owner@wingtiptoys.com, etc.  Oh wait, did we mention that it’s free?  This isn’t one of those “free during beta” trial offers.  This is free for life. 

Das konnte man letztes Jahr im Custom Domains Blog lesen. Inzwischen gibt schon Version 2.0.

E-Mail gibt es ja schon länger als kostenlose, webbasierte Lösung. Gmx, Hotmail, Gmail und viele andere. Die Postfächer sind dabei immer größer geworden. Als Google Gmail startete, waren die 1GB Platz schon sehr beachtlich. Unter 2GB braucht man inzwischen nicht mehr antreten.

Jetzt gehen die Großen einen Schritt weiter: Man kann jetzt seine eigene Domain in der Adresse verwenden. Also nicht user@hotmail.com, sondern in unserem Fall, user@cptec.org. Bei Google heißt es Google Apps und bei Microsoft wieder mal ein bisschen länger, aber dafür inzwischen mit Abkürzung Windows Live Custom Domains WLCD. Bei Microsoft kriegt man dabei 500 Benutzer mit je 5GB großen Postfächern. Umsonst!

Dazu verändert man ein paar DNS Einträge seiner Domain. Unter anderem zeigt der MX Record jetzt auf einen Hotmail Server. Die nötigen Einträge werden bei den Einstellungen schön angezeigt und auch überwacht. Windows Live überprüft die DNS Einstellung und schaltet die weiteren Funktionen frei, wenn alles passt.

Windows Live Custom Domains - Add Domain

Eine grüne Active Lampe! Microsoft ist mit meinen DNS Einträgen zufrieden. Jetzt kann man die einzelnen Postfächer anlegen. Wir werden die 500 Benutzer so schnell nicht brauchen.

Windows Live Custom Domains - Member Accounts

Als kleinen Bonus kann man noch eine Subdomain einrichten, die direkt auf das E-Mail Web Interface verweist. Dann braucht man sich nur mail.cptec.de merken.

Windows Live Custom Domains - Custom Addresses

Das ganze ist bis dahin derart unkompliziert, dass man die längste Zeit damit verbringt, zu warten, bis die DNS Einträge propagiert sind.

Was der Anwender jetzt zur Verfügung hat, ist das aktuelle mail.live.com Web Interface. Natürlich mit allen AJAX - Web 2.0 Wassern und Ladezeiten gewaschen. Viele sagen, dass es Gmail um Längen schlagen würde. Da sage ich nichts dazu. Für eine E-Mail zwischendurch taugen sie alle.

Interessant wird es dann sicher, wenn man sich noch für ein Windows Mobile Device in Version 6 entscheidet. Dann hat man auch noch Push E-Mail gratis dabei: Windows Live for Windows Mobile. Unser Reisender Geschäftsführer wird sich freuen.

Für den Desktop kann ich aber meiner Vorliebe für echte Desktop Applikationen treu bleiben. Ich kann weiter Outlook verwenden. Microsoft hat vor kurzem die finale Version des Microsoft Outlook Connector für Outlook 2003/2007 veröffentlicht. Dieser Connector synchronisiert die Windows Live Mail Informationen. Man erhält in Outlook ein weiteres Postfach, dessen Daten über ein neues Protokoll mit dem  Microsoft Server abgeglichen werden. Dieses neue Protokoll Delta Sync soll besonders effizient Informationen übertragen.

Outlook Connector - Postfach

Synchronisiert werden dabei die Mails selbst und Kontakte. Kalender-Synchronisation ist im Moment nur für zahlende Kunden möglich. Ich denke aber, das wird sich noch ändern.

Outlook Connector - Server Status

Bis dahin bin ich sehr zufrieden mit dieser interessanten Alternative zum eigenen Mail Server. Leider sind dann aber auch schnell ein paar gravierende Nachteile aufgefallen:

Keine externe E-Mail Weiterleitung. Der entsprechende Dialog lässt nur interne Adressen zu.

You can forward your mail to one other e-mail address that ends in hotmail.com, msn.com, live.com, or custom domains.

Wenn man voll auf Custom Domains setzt, ist die Einschränkung nicht so schlimm. Gerade in einer Test- über Übergangsphase ist aber eine externe Weiterleitung schon sehr praktisch.

Keine E-Mail Verteiler. Im Moment wird jede E-Mail Adresse einem echten Account zugeordnet. Ich möchte aber innerhalb einer Domain Aliase einrichten. Und diese Aliase möchte ich bereits auf der Administrator Ebene definieren können. Also ohne den Umweg über Accounts mit Passwörtern und anschließenden Regeln in den Profilen.

Ich denke, man wird auf diese Wünschen reagieren. Sonst macht es der Konkurrent. Es ist nur eine Frage der Zeit. Wenn diese Dienste jetzt noch nicht unseren internen Mail Server ersetzen können, dann sicher in naher Zukunft.

Wir werden mit unseren sekundären Adressen jetzt einige Zeit dieses System testen. Über weitere Erfahrungen werde ich hier berichten.

Friday, September 21, 2007 5:01:14 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Tuesday, September 18, 2007

FTP ist grausam. Das Protokoll ist so unglaublich anders und unhandlicher als neuere Internet Protokolle, dass es einen schaudert.

Beim Active Mode öffnet der Client einen zufälligen Port und übermittelt die Information an den Server, der darauf versucht sich mit diesem Port zu verbinden. Da wird kein NAT oder Firewall auf der Client Seite mitspielen.

Beim Passive Mode läuft das Spiel anders herum. Der Server öffnet fröhlich Ports, auf die sich der Client verbinden soll. Also ist es schwierig den Server hinter einer Firewall in Sicherheit zu bringen.

Passwörter werden im Klartext übertragen. Die Daten auch.

Eine schönes Gemotze ist da angesagt: FTP Must Die

FTP is an outdated, insecure, slow, unfriendly pig of a protocol. It's got no business being on the Internet in the 21st century.

Ich habe bereits die administrative Verantwortung für unseren FTP Server abgegeben. Für dieses Protokoll stehe ich nicht mehr ein.

Grundsätzlich steigen wir auf http basierte Übertragungen um. Das aktuelle Projekt mit WebDAV über https benötigt nur noch ein gültiges Zertifikat :).

Update: Wir haben ein Zertifikat. Sogar ein gültiges ;)

Tuesday, September 18, 2007 11:26:33 AM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  | 
# Monday, September 17, 2007

Ich bin ein JavaScript Anfänger. Vor dem aktuellen Projekt gab es nur ein bisschen Html mit JavaScript als DOM Manipulator dazwischen. Echte Profis werden sicher nichts lernen können.

Ein Problem bei JavaScript ist, dass das Web voller kleiner Snippets ist, die tolle Sachen im Browser anstellen. Man findet nicht sehr viel zu den Konzepten der Sprache. JavaScript ist eine gute Ergänzung zu Html, weil es ebenso tolerant ist. Kein Compiler achtet auf die Typisierung, implizite Typkonvertierung überall.

Natürlich kann eine Sprache, die sehr schnell zu "es funktioniert" führt, auch zu unsauberem Code verleiten. Wer die Sprache konzeptionell missbraucht gerät in Gefahr, über unangenehme Randbedingungen zu stolpern, die nicht mehr funktionieren.

Ein Beispiel sind zwei sehr häufig benötigte Konstruktionen, das Array und die Hashtable.

JavaScript verfügt über ein Array Objekt das sich wie erwartet verhält. Nur ein bisschen dynamischer. So passt sich die Länge zum Beispiel automatisch an:

var testArray = new Array();
testArray[0] = "Test0";
testArray[99] = "Test99";
// Der Test liefert true:
if (testArray.length = 100)
    result = "Array Länge: 100";

Für die Hashtable gibt es aber kein entsprechendes Objekt. Aber dafür gibt es eine sehr interessante Eigenschaft von JavaScript. Alle Eigenschaften (und Methoden) eines Objekt sind, wie für eine dynamische Sprache zu erwarten, dynamisch. Können also zu jeder Zeit verändert werden. Der JavaScript Interpreter verwaltet diese Eigenschaften offensichtlich in einer Hashtable. Diese Objekt-Hashtable steht auch dem Entwickler zur Verfügung. Eine Einschränkung hat diese Objekt-Hashtable aber: Nachdem Objekt Eigenschaften benannt sind, können die Keys der Hashtable auch entsprechend nur Namen oder allgemeiner Zeichenketten sein. Genauso können natürlich als Hash Key keine Schlüsselworte des Core Objects verwendet werden (z. B: "toString").

var hashObject = new Object();
// Werte zuweisen
hashObject["key1"] = "Wert1";
hashObject["key2"] = 1234;
// Werte auslesen über Hashtable
var test = hashObject["key1"];
// Werte auslesen über Eigenschaft
var test2 = hashObject.key2
// Test, ob ein Wert vorhanden ist
if (hashObject.hasOwnProperty("key1"))
    result = "vorhanden";

Mit der for...in und der for each...in Schleife kann man ganz einfach über die Schlüsselworte oder Schlüsselwerte der Objekt-Hashtable iterieren.

for (key in hashObject)
    allKeys += key;

Bis dahin kann man das alles ganz einfach aus der JavaScript Referenz lernen. Leider liest man nicht immer die komplette Dokumentation, bevor man sich in einer neuen Sprache austobt. Google liefert zu jeder Frage sehr viele kleine Lösungen. Leider kann Google die Qualität des Codes nicht beurteilen. Schlechter Code prominent platziert führt zu neuen Programmierern mit schlechtem Stil.

Der häufigste Fehler in diesem Zusammenhang ist, dass man das Array als Hashtable verwendet:

var newHashObject = new Array();

JavaScript ist eine objektbasiert Skriptsprache und damit ist auch das Array ein Objekt. Damit funktioniert zunächst alles wie bisher. Trotzdem sollte man das so nicht machen.

Erstens leidet die Lesbarkeit. Wenn man Array definiert, erwartet man ein Array. Wenn der Zugriff dann über Variablen erfolgt, ahnt man vielleicht nicht, dass gar keine Array Indizes, sondern Hashtable Keys verwandt werden:

var result = hashObject[item];

Ist item ein Integer, mit dem auf das Array zugegriffen wird? Oder ist item ein String, mit dem auf eine Objekt Eigenschaft zugegriffen wird?

Auch der Entwickler kann sich selbst verwirren. Die Länge des Arrays wird über length abgefragt. Missbraucht man das Array als Objekt-Hashtable liefert length natürlich den falschen Wert (0).

Richtig ärgerlich wird es aber dann bei dem in Operator, der unter anderem in den Schleifen zum Einsatz kommt. Eigenschaften der vordefinierten Core Objekte werden dabei nicht ausgegeben. Nur per Code definierte Eigenschaften werden berücksichtigt, dafür aber über die ganze Prototypen Hierarchie (JavaScripts quasi Vererbung).

Ich wollte zum Beispiel das Array per Prototype um eine contains Methode erweitern.

Array.prototype.contains = function(element) 
{
    for (var i = 0; i < this.length; i++) 
    {
        if (this[i] == element) 
        {
            return true;
        }
    }
    return false;
};

Diese Erweiterung funktioniert toll. Nur jedes Array hat jetzt ein weiteres Hash Element mit dem Key contains. Bei einer Schleife wird dieses Element mit ausgegeben. Und zwar bei jeder Objekt-Hashtable, die fälschlicherweise mit "new Array" statt "new Object()" definiert wurde.

Merke: Kein Array verwenden, wenn eigentlich nur ein Object gebraucht wird!

Monday, September 17, 2007 1:21:25 PM (W. Europe Daylight Time, UTC+02:00)  #
  Disclaimer  |  Comments [0]  |