Diskettenschätzchen

Im Laufe des mit Computern befassten Lebens entstehen sie, die Datenträgerschätzchen. Alte Disketten und manchmal auch Streamertapes mit mehr oder weniger wichtigen Daten aus längst vergangenen Zeiten. Briefe, Dokumente, Präsentationen, kleine Datenbanken mit Adressen, Buchinventaren, Bilder usw. sind die persönlichen Schätze, für die man manchmal auch noch geeignete Software braucht. Wer kennt noch Framework oder Open Access? Da war manchmal die Entscheidung richtig weise, PDF-Dateien zu erstellen.
Und natürlich gibt es auch Software, die man schon vergessen hat. Das DashBoard von HP oder SideKick von Borland. Borland sowieso mit Turbo Pascal, Prolog und ObjectVision.
Und so schlummern diese Schätze auf  3.5"-Disktten oder gar auf 5.25"-Disketten und warten darauf, dass man sich ihrer annimmt. Am besten wäre es, wenn man sie kopieren könnte ... als Datenträger ... und dann in einem beliebigen Windows wieder 'mounten' könnte.
Zum Kopieren habe ich einen WindowsXP-PC mit einem alten 5.25"-Laufwerk ausgestattet. So richtig wird das Laufwerk zwar nicht erkannt - es denkt, es sei ein 3.5"-Laufwerk - aber man kann auf die Disketteninhalte zugreifen. Das reicht erst einmal. Natürlich gibt es einen gewissen Schwund. Nicht jede Diskette - oft ja aus den Gründerjahren des PC ... 1981 - kann man lesen. Das mag sowohl am Format, an den damals verwendeten Kopierschutztechniken, aber auch am Zahn der Zeit liegen.
Zum Erstellen des Disketten-Images habe ich das Programm RawWrite for Windows gefunden. Man muss es nicht installieren; aufrufen genügt. Den kleiner Schönheitsfehler habe ich schon genannt: Es liest halt die 1.2"-Disketten so als wären es 1.44"er.
Wie kommt man nun an den Inhalt eines Disketten-Images heran? Es gibt einige virtuelle Floppy-Programme. Zwei habe ich ausprobiert.
Die Virtual Floppy for Windows aus dem Jahre 2008 und der IMDisk Virtual Disk Driver aus dem Jahre 2012. Beide klemmen sich hübsch in das Explorer-Kontext-Menü ein. Bislang habe ich noch keine Probleme feststellen können.

AirPrint unter Windows Vista

AirPrint ist gut fürs iPad, dann man kann dann recht einfach drucken. Manche WiFi/WLAN-Drucker - wie z.B. mein Epson Stylus Photo PX730WD - sind recht einfach in der Handhabung: einmal eingerichtet als WLAN-Drucker und schon sieht man sie in der Druckeroptionen des iPads.

Aber es soll ja auch für die anderen Drucker gehen. Drucker, die per USB an einem Windows-PC angeschlossen sind, welcher dann wiederum per Netzwerkkabel an einem Router hängen, welcher auch WLAN kann. Hierzu gab es einige Installationsprogramme und -anleitungen, wie z.B. diese hier. Leider funktioniert das wohl nur bis IOS 4.x. Offensichtlich ist in Sachen User-Zugriffsberechtigung etwas dazugekommen.

Es gibt für IOS 5+ eine Anpassung (mitsamt einem hübschen Konfigurationsfenster), die es nun auch schafft, meinen Samsung SCX-4300 (wieder) zu einem AirPrinter zu machen. Hier steht, was wichtig ist und vor allem auch eine Downloadmöglichkeit der aktualisierten Installationsdateien.

Meine Erfahrungen:
(1) in der Diensten den bisherigen AirPrint-Service stoppen (sofern man ihn hat laufen lassen)
(2) unter "Program Files (x86)" das Verzeichnis "AirPrint" umbenennen oder löschen
(3) die heruntergeladene Installationsdatei in einem Entpacker betrachten und eine der beiden ".reg" aufrufen (32/64)
(4) die "AirPrint_Installer.exe" aufrufen und sich an dem Konfigurationsmenü erfreuen

Ich habe den "Windows User Account" ausgewählt und mit meinem üblichen User versehen; beim (ersten) Ausdrucken musste ich mich dann als solcher auch auf dem iPad anmelden. Wahrscheinlich kann man hier ein wenig herumspielen und die für einen am besten passende Möglichkeit austesten. Auf jeden Fall wird der Samsung sofort im iPad angezeigt und druckt.

Ach ja - bevor ich das vergesse. Wenn man die Geschichte zum ersten Mal probiert, meldet sich noch die Windows-Firewall ... falls nicht, sollte man sich die genauer anschauen: Der AirPrint-Dienst muss natürlich durchgelassen werden, also Port 631.

Noch eine Bemerkung: Ich habe den PC nicht neu gestartet, was aber nicht unbedingt immer so sein muss.

iPad Pages nach MS Word transportieren

Nun wird jeder sagen, auf dem iPad in Pages gibt es in er Funktion "Freigabe & Drucken" dann schon eine Auswahl, ob man sein Geschreibsel in dem Pages eigenen Format oder in PDF oder als Word-Datei kopieren möchte, wenn man WebDAV oder eine andere Cloud-Variante wählt. Warum dort nicht die Word-Variante verwenden? Klar doch, das geht! Aber was machen, wenn man zwar Zugriff auf die Pages-Dateien hat, aber keinen iPad dazu? Und auch jetzt völlige Zustimmung: Einfach einen neuen iPad kaufen *gg*.

Aber ernsthafter. Da geistern im Web zu diesem Thema iWorks-Pages-Tipps herum: Die Pages-Datei umbenennen und zur .zip-Datei machen (falls der Entpacker widerspenstig sein sollte) und entpacken, denn die Pages-Datei ist eigentlich ein Archiv. Dann Ausschau halten nach einem Ordner namens "QuickLook" und darin nach einer PDF-Datei. Diese sollte nun samt allen Formatierungen das Pages-Dokument enthalten. Völlig abgefahren sind dann meist die Vorschläge: ausdrucken und wieder einscannen. Besser wären dann schon die Vorschläge, sich nach einem Web-Dienst um zuschauen, welcher aus PDF dann Word-Dateien macht. Aber man kann auch einfach nur eine der vielen OpenOffice-Versionen benutzen.

Nun ist dieser Tipp leider nicht für iPad-Pages-Dokumente zu gebrauchen. Zwar gibt es dort auch ein Verzeichnis "QuickLook", aber da drin befindet sich keine PDF-Datei (zumindest bei mir ist das so); alles was ich da gefunden habe, ist eine Bild-Datei namens "Thumbnail.jpg", also das kleine Vorschaubildchen in der Dokumenten-Übersicht des iPad-Pages. Also bleibt nur die Datei "index.xml" übrig. Tipps, dass man diese per Notes-Version xyz gelesen bekommt, mögen stimmen ... aber wer hat das jetzt gerade auf seinem Rechner. Aber es ist schon diese Datei, welche alles zum Dokument beträgt. Man kann sich diese Datei einfach einmal aus dem ZIP extrahieren und mit dem Internet-Explorer anschauen. Dieser kann das XML schön als Textbaum anzeigen und ganz ganz weit am Ende, findet man auch den Text des Dokumentes.

XML-Tools gibt es schon. Auch Word kann diese XML-Datei lesen und anzeigen. Allerdings sieht es nicht gerade hübsch aus; was man allerdings mit ein wenig XLS hin bekommen kann ... aber wer wird sich die Zeit nehmen, das gerade jetzt zu lernen?

Wie geht es einfacher und vor allem Ziel führender? Ich hab zum Entpacken den 7z genommen und da kann man sich auch den Inhalt einer XML-Datei mit der Funktion "Bearbeiten" in das Windows-Notepad holen. Klar wissen wir, die Datei ist groß und erst am Ende steht der Dokumententext. Aber das sollten ja nicht schwierig sein. Ich habe den Textanfang gesucht und mich auf mit dem Cursor vor das erste Tag ("<...>") gestellt und ab da alles ausgewählt und in die Zwischenablage kopiert. Dann alles im Notepad-Fenster gelöscht und die Auswahl aus der Zwischenablage einkopiert. Mit der Notepad-Funktion "Bearbeiten->Ersetzen" den Text "sf:p" gesucht und gegen "p" ersetzt und die Datei als xyz.html abgespeichert. Jetzt kann diese Datei (xyz.html) mit dem Firefox oder einem anderen Browser aufgerufen werden und schon sieht man den 'hübschen' Text des Pages-Dokuments. Wie viel nun von der Formatierung dabei ist, mag im Einzelfall nicht den Erwartungen entsprechen, aber der Text ist da und kann nun ganz einfach über die Zwischenablage vom Browser nach Word transportiert werden.

Mal eben ungestört per TV-Lösung einen Film schauen

Nun ja, im Haushalt stehen ein paar TVs herum; ältere noch mit Röhre und jüngere mit Flachbildschirm. Eigentlich in jedem Lebensraum (also Räume, in denen man sich länger aufhält). Natürlich nicht im Bad und in der Küche und leider auch nicht in meinem Bürozimmerchen. Klar stehen da Laptops und Bildschirme herum und es gibt auch eine TV-Karten-Server-Lösung, mit der man DBV-T-Sendungen aufzeichnen kann und natürlich kann man sich auch vor den Laptop setzen und das Programm live erleben. Aber - da steht auch noch ein bequemer Sessel in der Ecke und von da ist das alles zu weit weg und hin- und herräumen nur für mal eine Sendung zu sehen, ist das alles zu kompliziert. Eigentlich fehlt nur so ein kleines Teil mit 9"-Bildschirm, eingebauter DBV-T-Karte ... gibt es ja alles mit einer Auflösung die arg bescheiden ist. Warum macht man da nichts Gescheites? Also HDTV-Screen, BluRay-Abspieler, DBV-T und den ganzen Krempel, den man für die Schüssel und das Kabel braucht inkl. CI-Modul-Schacht, USB-Anschluß zum Abspielen und Aufnehmen, SD-Kartenschächte für alles was man so kennt, DLNA per Ethernet-Kabel (GBit) und WLAN mit gutem Durchsatz und kein Format bleibt unverstanden ... Gibt es nicht - selbst wenn du 1000 Euronen hinlegst nicht. Wobei 300 Euronen für den Spaß die Obergrenze sein müsste, denn ohne Bildschirm gibt es das ja alles in kleinen feinen Boxen getarnt als Mediaplayer.

Also erst ein Mal Frust, weil die technische Seele unverstanden ist. Dann der Augenaufschlag ... das meiste könnte ja ein Tablet bis auf die BluRay-Geschichte. Warum also nicht ein Tablet? Oder andersherum: was brauchste, um ein iPad in Sache TV zum Fliegen zu bringen? Einen DBV-T-Karte, die man direkt an das iPad anschließen kann. Für rund 70 Euronen biste dabei. Ist das nicht die Lösung? Dies Kästchen will per USB geladen werden, damit es läuft und das geht wohl nicht im laufenden Betrieb - und das iPad kann, weil ja der Stecker belegt ist, auch nicht tanken. Das verspricht höchst unspontan zu werden.

Gibt es andere Lösungen? Da bewerben 4 Firmen ein Kästchen, das wohl ein wenig anders tickt, gleich aussieht und doch unterschiedlich ist. Zunächst die Lösung des Problems: das Kästchen wird nicht an den iPad angeschlossen per Kabel oder Stecker, sondern sendet die TV-Bilder per WLAN an das iPad. Damit ist die Stromzufuhr zum iPad möglich. Hacken! Das Kästchen hat zwar einen Akku für ca. 3,5 Stunden, kann aber auch an einer USB-Leitung tanken und gleichzeitig aufladen und betrieben werden. Also quasi stationär, aber für meinen Bedarf passend.

Zwei der Firmen sind sozusagen die Knowhow-Lieferanten: Elgato und Equniux. Beide haben ein und denselben Hardwarehersteller, unterscheiden sich aber durch die Firmware und die Apps. Equniux ist ganz den Apple-Produkten verschrieben und bietet auch Innovationen in Richtung TV-Aufzeichungsspeicher-Lösung an. Elgato kann auch Windows-PC und (ich hoffe das stimmt), sich auch per USB-Leitung der Daten bedienen.

Die beiden anderen Firmen sind sozusagen die Kostgänger: Belkin bietet die Equniux Tizi-Lösung zu einem besonders günstigen Preis an (man findet das Gerät im Tschibo-Versand fast für die Hälfte des offiziellen Equniux-Listen/Homepage-Preis); Apps und Firmware sind identisch. Hauppauge folgt der Elgato Tivizen-Lösung und ist offiziell ein wenig günstiger und hat auch eine Apps auf eigenen Markennamen gelabelt. Die gesamte Preisbandbreite bewegt sich irgendwo zwischen 80 und 150 Euro; da es für ein iPad eingesetzt wird, wäre jedes Modell gleich gut verwendbar - also das günstigste tut es auch.

Ich hab mir einen Tizi geholt und die Installation ist eine Freude. Stecker zum Aufladen. Apps im iPad installiert. Hotspot-WLAN-Verbindung zwischen iPad und Tizi hergestellt und schon sucht die Apps die Sender. Keine Minute lang und das erste Programm (hihi) säuselt vor sich hin. Ich habe dann sofort den Tizi auf die neuste Firmware gebracht und ausprobiert, wie sich die Integration ins bestehen Home-WLAN anfühlt. Wenn da gerade nichts läuft, ist die FritzBox einigermaßen schnell (und klar, je näher, desto schöner) und man kann sich am kaum ruckelnden Bild erfreuen. Aber ich hab dann wieder auf den Hotspot-Mode umgestellt, denn da ist der Kanal nicht durch weitere Geräte belegt und die beiden Geräte sind sich auch näher - was sich in einem exzellenten Filmgenuss widerspiegelt.

Die Senderliste enthält einige Dubletten (mache gehen gar nicht richtig). Deswegen hab ich bereinigt und die Senderliste auf dem Tizi abgespeichert. Vorteil: jeder weitere iPad, iPod touch, iPhone kann sich diese Liste holen und es fällt daher keine erneute Arbeit an. Der Parallelbetrieb ist zwar nicht vorgesehen, aber man kann einen iPad touch zur Fernbedienung für den iPad machen. Ansonsten sind die üblichen Funktionen des versetzten Abspielens (Timeshift) und Aufzeichnens verfügbar.

So jetzt werde ich erst einmal einen TV-Abend machen und vielleicht gibt es danach noch einiges zu berichten ... gute und schlechte Erfahrungen.

Alles weg ...

Manchmal hat man Pech. Bei mir war es ein kleines Programm, dass eine per USB angeschlossene Platte Nullen sollte, damit sie als 'frisch' von einem kleinen SAN-Teil erkannt wird. Nun was soll ich sagen, irgendwie hab ich das falsche Laufwerk ausgewählt und meine im Laptop eingebaute Platte wurde genullt. Sofort wieder angehalten ... aber es war zu spät. Die Platte ließ sich nicht mehr zum Starten des Notebooks verwenden.

Ausbauen und an einen andere Rechner anschließen. Ich habe da so einen USB-ATA-Adapter, mit dem das recht einfach geht.

Die erste Frage ist natürlich, wie groß ist der Schaden. Kann man die Platte unter einem anderen Windows im Disk-Manager sehen? Nein. Gibt es ein Programm, mit dem man aufspüren kann, was noch auf der Platte zu lesen ist? Ja, das gibt es zum Beispiel Partition Find and Mount. Läuft unter Windows und findet recht schnell eine von 3 Partitionen auf der Platte und lässt die auch mounten. Ich sehe, es ist zumindest in dieser Partition noch alles da.

Wie kann man nun die Partitions-Tabelle reparieren, so dass die Partition zukünftig auch ohne Spezialtool unter Windows zu sehen ist? Auch hierfür gibt es ein gutes Werkzeug: TestDisk. Man kann einfach die Platte durchsuchen lassen und das Tool stellt eine Liste mit möglichen Partitions-Einträgen zusammen, die dann als Partionstabelle geschrieben werden können. Nach dem Lauf sehe ich auch die beiden anderen Partitionen. Schnell fixe ich die Dinge und probiere nun wieder den Windows-Diskmanager aus.

Leider findet dieser nur 'raw'-Partitionen und will sie neu formatieren. Das ist natürlich unschön. Ein anderes Partitions-Manager muss her: Ich habe noch auf einer CHIP-CD die Personal-Version vom 2008er Paragon Partition Manager gefunden. Schnell die Produktregistrierung durchgeführt und schon läuft das Teil und findet alle 3 Partitionen. Allerdings werden nur die beiden ersten richtig von Dateisystemtyp erkannt; die dritte - ja die die ich schon vorhin lesen konnte - nicht. Was ist das los? Ich schau mit die Eigenschaften in beiden Tools noch einmal an und stelle fest: der Beginn der dritten Partition ist unterschiedlich.

Wie kann man den Anfang einer Partition ändern? Neben der blöden Umrechnerei von CHS (Cylinder - Head - Sector) auf die LBA-Blocknummer feht es an einem geeigneten Tool. Nach ein wenig Gesuche habe ich dann etwas gefunden: plppart32.exe. Im Rahmen des Suchens bin ich aber auf eine weitere Information gestoßen: Man kann TestDisk mit einem 'deep scan' laufen lassen; das hatte ich beim ersten Mal gar nicht probiert. Also noch mal. Und siehe da, er werden 7 Partitionen gefunden, von denen am Schluss 3 als richtig erkannt werden. Treffer! Nun erkennt auch der Partition Manager alle 3 Partitionen. Leider immer noch nicht Windows. Klar wenn der Partitions Manager die Arbeit für Windows abnimmt, geht es schon. Aber wenn die Platte einfach so einbaut wird, dann wird sie immer noch nicht erkannt.

Es fehlen die Boot-Konfigurationen. Hier bietet sich eine Vista-DVD an, die man zur Reparatur dieser Boot-Konfiguration einsetzen kann. Das geht auch ohne weitere Probleme: Es werden 2 Vista-Partitionen erkannt und eingerichtet. Ein Systemstart zeigt, dass beide auch funktionieren. Freude kommt auf - die Datenrettung scheint erfolgreich gewesen zu sein.

Nach dem Start der zweiten Vista-Partition versuche ich den Windows-Explorer aufzurufen, rührt sich nicht. Hatte ich schon erwähnt, dass auf der ersten Partition ein Vista-32 und auf der zweiten ein Vista-64 liegt. Beide habe die gleichen User und recht ähnliche Programme installiert. Ich schau ins DOS-Fenster: Ups. Die Plattenzuordnungen sind nicht korrekt. Offensichtlich verwendet das Vista-64 auf der 2. Partition irgendwann nach dem Start die Programme und Dateien der ersten Vista-32-Partition und das geht nicht immer gut. Normalerweise wird beim Starten von der zweiten Partition diese zum Laufwerk C: und die erste Partition zum Laufwerk D: und genau das ist wohl nicht geschehen.

Wie kann man nun die Laufwerks-Buchstaben vertauschen? Der Windows Disk Manager lässt sich ja nicht starten und außerdem kann man einem Systemlaufwerk nicht einfach einen neuen Laufwerks-Buchstaben verpassen. Und von dem Vista der anderen Partition wiederum lässt sich das auch nicht erledigen. Kann man das möglicherweise in den Boot-Konfigurations-Datei einstellen? Oder kann man das Laufwerk einfach 'ausblenden'?

Schnell wieder mit dem Vista der funktionierende Partition starten und nach schauen. Nein Laufwerke ausblenden geht ja nicht, denn die Boot-Konfiguration steht ja auf der ersten Vista-(32)-Partition; auf der zweiten ist sie ja gar nicht vorhanden. Bleibt also nur das Laufwerk-Buchstaben-Vertauschen. Nach etwas längerer Suche gibt es die ersten Hinweise: In der Registry kann man unter dem Schlüssel HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices die Namen der DosDevices-Einträge umändern: was vorher C: war wird Z:, was D: war nun C: und Z: wird zu D:.

Nun neu gestartet und alles ist wieder so wie es sein soll.

Windows Home Server

Seit einigen Wochen besitze ich einen Windows Home Server (WHS) von acer. Ein schönes Teil: schnell, einfach zu bedienen, die PC-Backups sind sehr komfortabel und es ist einfach zu erweitern, da Windows.

Geräte, die ich schon angeschlossen habe:

  • Samsung SCX-4300 (Laserdrucker und Scanner)
  • Sony MPD-AP20U (DVD-Brenner)
  • Fujitsu ScanSnap fi-5110E0X2 (Scanner)
  • Terratec H5 (Video-USB-Stick)

Habe auch versucht, mein Netgear SC101 (NAS) zu betrieben, aber da hab ich mir irgendwann wohl mal mit NTFS die Platten verratzt. Man kann zwar die SC101 sehen (sowohl im SCM als auch im Windows Disk-Manager), aber die Versuche, die Platten zu formatieren, sind noch nicht erfolgreich.

Software-seitig habe ich XAMPP erfolgreich eingespielt; auch die Video-Software für den Stick läuft einwandfrei ...

Da die neue Firmware von Synology mittlerweile auch iSCSI-Targets zur Verfügung stellen kann, habe ich den W2003-Server-Initiator (von Microsoft) installiert und eine Diskstation-iSCSI-Partition in den WHS eingehängt, mit NTFS formatiert und getestet: geht!

Heute morgen gab es Irritationen: der WHS-Server ließ sich nicht per Konsole bzw. Remotedesktop aufrufen. Netzwerk-Shares und Datensicherung gingen immer noch. Es gibt im Netz verschiedene Ursachenbeschreibungen und Gerüchte, was denn der Auslöser für ein solches Verhalten ist. Ein Tipp war, sich per IP-Adresse via Remotedesktop anzumelden und das ging dann auch. Ein Ping brachte dann noch mehr Helligkeit ins Dunkle: die Namen werden falsch aufgelöst - offensichtlich gab es keinen dominanten DHCP-Server in LAN, der das außerhäusliche DNS-Abfragen verhindert hat. Die Lösung, die mir dann geholfen hat, war, den Windows-Namen des WHS-Servers in die hosts aufzunehmen, dann geht der Remotedesktop schon wieder per Namen ... zuletzt den WHS-Konnektor deinstalliert und wieder neu eingerichtet - das war es dann. Ich vermute sehr stark, dass mein DNS-Auflösungsgewurschtel irgendwie im Heimnetz durcheinander gekommen war, aber das ist auch nur ein Vermutung.

Im Moment bin ich mit dem WSH-Server sehr zufrieden und kann ihn nur jedem empfehlen, der sich nicht mit Linux-NAS-Systemen auseinander setzen mag. Der easyStore von acer kann 4 Platten aufnehmen und könnte auch per Adapter-Kabel oder per Grafik-Karte zum richtigen PCs aufgerüstet werden. Allerdings ist der Atom-Prozessor dann wahrscheinlich schnell am Anschlag ... aber als Einstieg in die NAS-Welt ist er brauchbar. Da ich auch bei meinen Synology-NAS-Systemen völlig vom RAIDen abgekommen bin (Backups sind soviel spannender), ist das Fehlen der RAID-Fähigkeit beim easyStore nicht wirklich zu beklagen. Soweit ich weiß, ist die maximale Nutzung von 10 PCs möglich - das wäre die einzige wirkliche Einschränkung ... aber wie gesagt, ich habe keine praktische Erfahrung mit diesem Limit und kann daher nicht sagen, ob das auf gleichzeitigen Online-Betrieb basiert oder bereits bei der Definition der Sicherungseintragungen zuschlägt.

Vistas Explorer-Startordner

Da habe ich gerade einen kleinen Artikel darüber gelesen, wie man bei XP den Explorer-Startordner ändert. Ist ja eigentlich ganz einfach. Man nehme den RegEditor und gehe auf den Schlüssel: HKEY_CLASSES_ROOT\Folder\shell\explore\ddeexec\(Standard) und öffnet den Parameter. Dann ersetzt man in der Zeichenfolge [ExploreFolder(„%I“, %I, %S)] das mittler %I durch den gewünschten Pfad, also wenn man den Explorer auf D:\ stehen haben möchte, dann wird es zu [ExploreFolder(„%I“, D:\, %S)].

Soweit so gut. Aber unter Vista gibt es den besagten Schlüssel nicht. Man kann dafür aber den folgenden verwenden: HKEY_CLASSES_ROOT\Folder\shell\explore\command\(Standard). Hier würde man den obigen Effekt mit dem Startlaufwerk D:\ wie folgt erzielen: %SystemRoot%\Explorer.exe /e, D:\.

Man kann sich auch hierfür das kleines Tool Set Explorer Default Directory 1.2 von Mark T. Vitt installieren, welches diese Aufgabe übernimmt.

Nun würde ich gerne statt eines Startlaufwerks oder -ordners den Desktop als Startposition auswählen. Sicherlich gibt es hierfür unterschiedliche Lösungen. Allerdings habe ich per Google auf die Schnelle keine wirklich einfache gefunden.

Wie spricht man unter Vista den Desktop an? Unter XP gibt es für den Desktop eine CLSID, nämlich {00021400-0000-0000-C000-000000000046}. So wie es für auch für den Arbeitsplatz die CLSID {20D04FE0-3AEA-1069-A2D8-08002B30309D} oder für den Papierkorb die CLSID {645FF040-5081-101B-9F08-00AA002F954E} oder für die Systemsteuerung die CLSID {21EC2020-3AEA-1069-A2DD-08002B30309D} gibt. Ein wenig goggeln und schon bekommt man sie zusammen. Blöd ist nur, dass es die CLSID des Desktops für Vista nicht mehr gibt ...

Als Lösung habe ich gefunden, dass man den Desktop mit shell:Desktop ansprechen kann. Für die Explorer Start-Ordner-Einstellung bedeutet das nun, dass der Schlüssel HKEY_CLASSES_ROOT\Folder\shell\explore\command\(Standard) gesetzt wird auf: %SystemRoot%\Explorer.exe /e, shell:Desktop. Und alles wird schön.

CSS3 und Firefox 3.1 Beta

Abwechselnd Zeilen in einer Tabelle unterschiedlich farbig hinterlegen "Zebrastreifen"). Wie geht das nur mit CSS? CSS3! Mit der Pseudo-Klasse :nth-child!

Mit :first-child, :last-child und :nth-child können spezielle Elemente abhängig von der Anzahl ihrer Geschwister angesprochen werden. Zum Beispiel können alle gerade Zeilen einer Tabelle per

:nth-child(even) {background-color: #ccc;}

und alle ungeraden Zeilen per

:nth-child(odd) {background-color: #fff;}

eingefärbt werden.

Leider sind die meisten Browser noch nicht soweit, CSS3 zu unterstützen. So habe ich mir den Firefox 3.1 Beta heruntergeladen, um mir das mal ansehen zu können. Fantastisches Teil - auch wenn meine Firefox-Erweiterungen noch nicht alle mitmachen. Kann ich nur empfehlen.

Vorgeschmack, wenn CSS3 dann implementiert ist:

Erste Zeile
Zweite Zeile
Dritte Zeile

twitter.com

What's the hell is twitter?

Twitter is a service for friends, family, and co–workers to communicate and stay connected through the exchange of quick, frequent answers to one simple question: What are you doing?

Twitter ist ein Micro-Blog. Jeder kann der Welt in 140 Zeichen langen Nachrichten von sich und über irgendwas eine Nachricht zukommen lassen. Eine Auswahl dieser Nachrichten bekommt man angezeigt und kann sich bei Gefallen, etwas über den Absender anzeigen lassen und ihm folgen. Wenn man sich entschlossen hat, jemandem zu folgen, bekommt man alle seine Nachrichten zu sehen (wie ein Abo). Das bedeutet auch umgekehrt, dass andere den eigenen Nachrichten folgen können. Beides wird von beiden Parteien bemerkt.

So entsteht ein kleines Netzwerk, welches auch noch durch persönliche Nachrichten und durch gerichtete Posts (man schreibt dem anderen eine Nachricht, die aber die Welt mitlesen kann) ergänzt werden. So kann man einen Dialog entwickeln. Und was ist schöner, als Meinungen und Dialoge mit Menschen, die einem aus irgendeinem Grunde aufgefallen sind zu führen. Unverbindlich, herzlich und natürlich weltumspannend.

"Zwitschern". Ja so ungefähr hört bzw. liest es sich. Es ist kunterbunt und absolut zufällig und spontan. Auf diese Weise werden Gerüchte in die Welt gesetzt oder tiefschürfende Lebensphilosophien gesponnen. Oder man erfährt die einfachen Dinge des Lebens: Was machen die anderen da draußen eigentlich so.

Durch eine Reihe von hübschen Zusatzmodulen, ist man nicht ausschließlich auf einen Webbrowser angewiesen; auch auf dem Handy lässt sich twittern. Ich verwende zum Beispiel für meinen Windows PC Spaz: Sieht schön aus und funktioniert perfekt.

Ach ja - bevor ich es vergesse: Natürlich legt man sich eine Web-Personality zu mit Bild und Legende. Das Rollenspielen kann beginnen.

cms4xml hat eine kleine Schwester bekommen

Um auch mit den knappen Ressourcen und dem standardmäßig installierten Apache und PHP auf der Disk Station ein kleines, ultraschnelles CMS verfügbar zu haben, habe ich vor nicht allzu langer Zeit ein CMS-Projekt und der deutschen Synology-Community angefangen. Ich hatte ja schon einen Beitrag hierzu verfasst. Wer sich also hierfür interessiert, kann den Thread hier verfolgen.

cms4ds heißt dieses CMS-System und benutzt weitestgehend die gleiche Architektur wie cms4xml, nur ohne XML und Datenbankabstraktion PEAR MD2:

  • einfaches und kleines User-Interface, fast nur CSS-gesteuert
  • statischer und dynamischer Content
  • dynamischer Content wird mittels AJAX eingebunden
  • RSS, Browser-Suche-Integration, Feed-Zugriff und History wie bei cms4xml
  • Header und Footer per SSI eingebunden
  • SQL-Datenbank-Schnittstelle für den Zugriff auf beliebigen Content
  • automatische Seiten-Menü-Generierung (Inhaltsverzeichnis pro Page)
  • Protokollierung der Seitenzugriffe mit Counter

Wer Lust hat, kann sich ja mal die Web-Seite dazu anschauen; sie wurde auch mit cms4ds gestaltet. Hier ist der Link: cms4ds

Ich würde mich freuen, wenn es gefällt.

Kombination von SSI und PHP im Apache 2

Das Problem ist einfach geschildert: Ich möchte gerne in einer PHP-Datei eine weitere Datei per Server Side Includes (SSI) inkludieren.

Dazu ist die Apache-Direktive

AddOutputFilter INCLUDES .php

entweder in die http.conf oder in eine .htaccess einzutragen. Danach funktioniert zum Beispiel in einer .php-Datei:

<!--#include virtual="weitere_Datei.html" -->

Sogar eine weitere PHP-Datei könnte man inkludieren, deren Inhalte dann auch erst einmal durch den PHP-Prozessor gehen:

<!--include virtual="phpinfo.php" -->

Angezeigt wird die allseits bekannte PHP-Info-Seite.

Die Abarbeitungs-Reihenfolge ist bei der .php-Datei: Zuerst wird der PHP-Code interpretiert und ausgeführt, danach werden die SSI-Klauseln verarbeitet. Tritt hierbei ein Datei-Inklusion auf, wird diese als separater Prozesse komplett ausgeführt und erneut interpretiert, wieder in der gleichen Reihenfolge. Dies kann beliebig geschachtelt werden (sagt zumindest das Apache-Tutorial).

Server Side Includes

Da spielt man schon einige Jahre mit Webseiten herum und dann lernt man doch wieder etwas Neues dazu: Server Side Includes (SSI). Klar hatte ich die schon mal überflogen, aber nie so wirklich was damit anfangen können, bis ich vor einigen Tagen wieder einmal vor der Frage stand: Muss du immerzu das gleiche Zeugs von einer HTML-Datei in die nächste schaufeln, weil HTML keine include-Mechanik kennt?

Der Tipp kam unverhofft und erst einmal überraschend: Setzt doch SSI ein! Ja, muss man da erstmal was installieren bei meinem Apache? Wie konfiguriert und nutzt man das? Ein Link auf das folgende sehr gut erklärende Tutorial beseitigte alle Hemmschwellen.

Szenario: Also eine HTML-Datei namens 'header.html' soll in eine HTML-Datei namens 'index.html' inkludiert werden. In der 'index.html' wird an die Stelle, wo die Einfügung stattfinden soll, der folgende Text eingetragen:

<!--#include virtual="header.html" -->

Die Apache httpd.conf bzw. .htaccess benötigt in den Options die Erweiterung Includes bzw. +Includes. Und schon kennt der Apache die SSI-Erweiterung. Damit man zwischen Dateien mit und ohne SSI differenzieren kann, könnte man die folgenden beiden Zeilen einsetzen:

AddType text/html .shtml
AddHandler server-parsed .shtml

Bei manchen Apaches heißt es statt server-passed INCLUDES. Als Alternative zur Dateiendung gibt es den XbitHack:

XbitHack on

Setzt man diesen und setzt unter Linux bzw. Unix das Dateirecht 'Ausführen' (chmod +x), dann braucht man keine spezielle Dateiendung, sondern alle HTML-Dateien, die das Ausführungsrecht haben, werden durch den Ausgabefilter gejagt. Das ist praktisch, weil man eine bereits vorhandene Datei-Struktur nicht umbennen muss.

Muss ich noch erwähnen, dass es mehr Einzustellen gibt (Umdefinieren der Start/Stop-Tags) und auch mehr als nur den Datei-Include? Nein, wenn man sieht, dass ein Parser einsetzt wird ähnlich wie PHP, dann kann man sich bereits alles weitere vorstellen. Nützlich sind die Möglichkeiten Variablen zu definiere, Logik einzubauen und auch auf Betriebssystem-Kommandos zuzugreifen.

cms4ds

Seit geraumer Zeit ist eine kleine NAS mein eigen, die Synology DS207+. Neben den vorgefundenen Möglichkeiten machst es riesig Spaß neue kleine Webanwendungen zu entwickeln und auch - wegen der etwas beschränkten XML-Möglichkeiten - ein umgeschriebenes auf die Disk Station angepasstes cms4xml, das cms4ds zu veröffentlichen.

Ich habe im deutschen Synology-Community-Forum einen kleinen Workshop aufgesetzt, in dem Schritt für Schnitt dieses kleine, sehr schnelle CMS entwickelt wird. Wer einen Blick darauf werfen möchten, findet hier den Thread.

One Time Passwords

Vor ein paar Jahren war ich auf der CeBIT an einem Stand vorbeigeschlendert, der kleine Papierkärtchen an die Leute verteilte. Neugierig ging ich hin und kam ins Gespräch. Es handelte sich um Kennwort-Management.

Auf einer Karte sind 22 x 11 zufällige Zeichen wie auf einem Schachbrett oder einer Excel-Tabelle eingerahmt von Zeilen-Nummern und Spalten-Buchstaben. Wenn man ein Kennwort braucht, dann positioniert man sich gedanklich auf eine Startposition und kann dann ab dort die Zeichen nacheinander, untereinander, in L-Form oder Rösselsprung ablesen, ganz wie man möchte. Niemand kennt die Methode sowie die Länge des Schlüssels und somit ist die Gefahr des Verlierens, Kopierens usw. vernachlässigbar.

Wenn man nun eine Software hat, die die jeweilige Karte und Methode kennt, dann kann sie sogar den Startpunkt vorgeben und nur der Besitzer der Karte und gleichzeitig Kenner der Methode wird das richtige Kennwort eingeben können. Damit wäre der Weg frei für Einmal-Kennworte bzw. One-Time-Passwords. Schicke und genial einfache Sache.

Hier findet man die Firma, die dies anbietet.

Wie ein neuer Web-Server auf meinem Synology DS 207+ entstanden ist

Über meine ersten Schritte und Erfahrungen mit dem kleinen NAS-Server vor Synology habe ich bereits an anderer Stelle berichtet. Hier will ich nun beschreiben, wie ich den Apache-Web-Server neu aufgesetzt habe. Ziel dabei ist es, einen völlig neuen, mit allen notwendigen Funktionen ausgestatteten Web-Server zu installieren, der ohne die Restriktionen des mitgelieferten Web-Servers laufen kann.

Voraussetzungen für die Installation sind ein ftp-Client auf dem Windows-PC (muss man unter Programme/Windows-Funktionen aktivieren, falls man nicht irgendwelche andere Software für den Kontakt zu einem Linux-System hat. Den Telnet startet man unter Vista am besten in einem Administrator: Eingabeaufforderungs-Fenster, also einem cmd.exe-Fenster, welches man mit der Option als Adminstrator ausführen startet.

Auf dem Synology-Server legt man am besten zwei Gemeinsamen Ordner namens opt und web an. Der Ordner web kann schon bereits existieren, wenn man die Web Station mal aktiviert hatte. Am besten schaltet man unter Netzwerkdienste/Webdienste/Webanwendungen Web Station und MySQL aus.

Zum Zwecke der Installation der neuen Software brauchen wir ein Package Management System namens ipkg. Die Quellen und Anweisungen für die Installation dieses Systems findet man hier. Für die Ausführung der Installation meldet man sich beim Synology-Server per ftp-Client an (user: root,  password: xxx (xxx ist das Passwort, welches man in der Administrationsoberfläche vereinbart hat). Man arbeitet dann sozusagen im Zeilenkommando-Modus.

Wichtige Kommandos sind:

ls -l listet den Inhalt eines Verzeichnisse an
cp file1 file2 kopiert file1 nach file2
pwd zeigt den Namen des Verzeichnisses an, auf dem man gerade steht
cd dir1 wechselt in des Verzeichnis dir1 (/ ist das oberste Verzeichnis)
find / -name file1 -print sucht die Datei file1 und zeigt den/die Pfad(e) an
ps -l | grep file1 zeigt an, ob und wie oft das Programm file1 läuft
vi file1 Editoraufruf für Datei file1
ipkg list zeigt die möglichen zu installierenden Pakete an
ipkg install paket1 installiert paket1

 

Nachdem ipkg installiert ist (dabei wird schon ein Menge Zeugs in das Verzeichnis /opt kopiert), kann man die Software für den Web-Server installieren:

ipkg install php-apache und
ipkg install php-mysql und eventuell noch
ipkg install php-pear

Der neu-installierte Apache-Server müßte laufen (mit ps -l | grep httpd) überprüfen. Man kann den Apache-Server mit folgender Zeile beeinflussen:

/opt/etc/init.d/S80apache start|stop|restart

Zusammenhang: Dienste werden durch die Datei /etc/rc gestartet; diese ruft auch die Datei /etc/rc.local auf. Diese wiederum ruft die Datei /opt/etc/rc.optware auf. Dort wiederum wird nachgeschaut, ob im Verzeichnis /opt/etc/init.d Dateien mit S anfangen (S wie Start). Wenn ja, werden diese ausgeführt. Mit dieser Verkettung wird also beim Systemstart irgendwann das Skript S80apache (S-8-Null-apache) aktiviert.

Der Apache-Web-Server wird durch die Datei /opt/etc/apache2/httpd.conf konfiguriert. Hier muss man IP-Adresse oder Name des Servers, Port-Nummer, usw. einrichten. Ist recht gut kommentiert, und man findet hierzu gute Anleitungen. Ist so einzurichten wie bei jedem Apache-Web-Server. Wichtig sind nun zwei Dinge, damit es gleich auf der DS 207+ läuft:

(1) den Pfad für für die Web-Pages anpassen:

DocumentRoot "/volume1/web"  

Damit hätte man wieder den Order, der auch bei den Web-Diensten angelegt und vielleicht schon verwendet wurde.

(2) den Pfad für die PHP-Modul-Zuordnung eintragen:

Include etc/apache2/conf.d/php.conf

Bitte auch überprüfen, ob diese Datei die Eintragungen:

LoadModule libexec/libphp5.so 
AddType application/x-httpd-php .php

enthält.

Apache-Web-Server restarten mit:

/opt/etc/init.d/S80apache restart 

damit die Änderungen auch wirksam werden.

Nun ist die Konfiguations-Datei für PHP an der Reihe: /opt/etc/php.ini. Auch hier bitte in der einschlägigen Dokumentation nachschauen, was man damit so alles anstellen kann. Nachprüfen, ob die extension=dom.so, xml.so und xsl.so eingetragen sind und unter der Rubrik [MySQL] überprüfen, ob der

mysql.default_port = 3306

eingetragen ist. Falls was geändert wird und sich dann nicht auswirkt, nochmal den Apache restarten.

Auch MySQL hat noch eine Konfigurations-Datei: /opt/etc/my.cnf. Hier wird unter anderem die Einstellungen für den Port aus Sicht von MySQL vorgenommen. Aber für das erstmalige Funktionieren, braucht man nichts eintragen oder ändern. Falls man etwas ändert, muss man auch den MySQL-Server wieder neu starten. Leider funktionierte der restart bei mir nicht, daher:

/opt/etc/init.d/S70mysqld stop
/opt/etc/init.d/S70mysqld start

Für die Datenbank-Administration empfiehlt sich phpMyAdmin, mit dem man seine Datenbanken anlegen und pflegen (auch sichern) kann. Die eigentlichen Datenbankinhalte stehen übrigens jetzt unter /opt/var/lib/mysql. Das ist manchmal für die physikalische Sicherung einer Datenbank von Bedeutung - wobei auch klar sein muss, dass es wenig Sinn hat, im laufenden Betrieb zu sichern.

Nachdem ich nun noch meine Web-Pages mit dem Windows-Explorer ins Verzeichnis /volume1/web kopiert habe und ein wenig meine .htaccess-Files (wegen mod_alias und mod_rewrite) angepasst habe, läuft alles wie am Schnürchen.

Synology DS207+ - Resümee einer Installation

Ich habe mir deshalb den DS207+ NAS-Server zum Geburtstag gewünscht, weil er recht gute Kritiken bekommen hatte und in den Foren bei Synology (und auch bei anderen) als leistungsfähig, ausbaubar, leise und schnell beschrieben worden ist.

Gestern habe ich ihn dann in Betrieb genommen: Sieht schon schön aus das Teil :). Schnell zwei ganz leise und stromsparende Platten eingebaut (Samsung HD502IJ = 500 GB pro Stück), Netzkabel dran und Strom drauf. Dann die Software -CD von Synology auf dem PC eingelegt und gestartet. Der Server wird sogleich gefunden und für das Aufspielen der Software vorbereitet. Wie professionell das alles wirkt.

Dann eine Meldung ... sinngemäß: ich kann leider das alte Zeugs auf der CD nicht installieren; lad dir doch bitte was Neueres runter zum Aufspielen. Ups, da passt wohl irgendwas nicht zusammen.

Eigentlich hätte ich mir gewünscht, dass man erstmal alles installiert bekommt und dann die freundliche Nachfrage kommt, ob man sich wohl um Updates bemühen sollte und diese dann in der Nacht nach installiert mag. So kenn ich das von Windows.

Na gut. Also kurz die fehlende Datei von Synology heruntergeladen und installiert. Alles bestens. Nach ein paar Minuten erfolgt ein Reboot. Auch ok. Und dann kann man sich schon in einer freundliche Administrations-Oberfläche aussuchen, was es alles so gibt. Und der Funktionen sind reichlich. Also es soll ja ein Web-Server werden; daher erst einmal eine feste IP-Adresse vergeben. IPv4 natürlich. Gut dass ich mein Home-Netwörk noch nicht auf IPv6 umgestellt habe. Dann schnell einen Zeitserver zugeordnet, einen neuen Benutzer angelegt und die Platten formatiert: RAID1 soll es werden. Da läuft auch schon die Synchronisation der Platten. Hab ich was falsch gemacht? Es ist doch noch nichts drauf, warum will er denn nun den Spiegel wiederherstellen? Und das auch noch so langsam? Es wird wohl mehr als eine Stunde dauern. Versteh ich nicht ganz ... Spiegel anlegen und Spiegel wiederherstellen sind für mich schon zwei verschiedene Dinge. Aber was soll es - Mittagspause ist ja auch nicht schlecht.

Man hört ihn schon von weitem, den kleinen süßen NAS-Server. Und dabei stand im Prospekt: Cool & Quiet Design. Wahrscheinlich ist das ein Bezeichnung wie seinerzeit das Frog-Design - hat nicht wirklich was mit kalt und leise zu tun. Warum dröhnt das Teil eigentlich so wie ein Staubsauger mit vollem Beutel? Also an den Platten kanns nun wirklich nicht liegen. Es muss wohl der Venti sein. Strom aus und aufgemacht das Teil. Strom an. Der Venti bläst, aber eigentlich recht leise. so ja auch temperaturgesteuert sein. Mal fühlen, ob die Platten warm sind. Sind sie nicht. Ach da ist ja auch eine Anzeige für die Plattentemperatur in der Admin-Oberfläche: 31° und 32° Celsius und irgendwas höheres in Fahrenheit. Kannste doch vergessen: ist kalt das Teil. Und warum bläst er dann? Fragen über Fragen.

Wenn man den Server offen auf die Seite legt, dann ist er recht leise. Na ja, im Hochtonbereich gibt es noch ein leises Säuseln, aber das hat man auch beim Laptop. Warum ist das Teil so laut, wenn man die Verkleidung wieder draufsetzt? Üiii, die Verkleidung ist ein Resonator und zwar ordentlich. Resonator kennen wir ja alle bei so Musikinstrumenten wie bei der Geige und Gitarre. Es gibt ja auch das Gegenteil: die Schallschlucker äh -dämpfer ^_ ^. Im Forum irgendwo ist ein Bastelanleitung, wie man das Gehäuse mit Schalldämpfern ausstatten kann. Na gut. Da liegen noch ein paar alte Neopren-Mauspads rum; schnell mal zerschnitten und eingesetzt. Ja ... Dämpfung kann man sich einbilden, aber nicht wirklich.

Mein Tipp: Deckel ab und am besten den Venti abschalten. Ich denke mal, dass ohne Deckel keine Gefahr für einen Hitzestau entstehen kann (wo nichts ist, kann sich auch nichts stauen), aber da gibt es ein kleines Problem: Das Teil piepst erbärmlich, schreibt ins Logbuch, dass der Fan aus kapot ist (kaputt kommt von dem französischen kapot - und ist erst seit dem 18.Jahrhundert bei uns bekannt). Den Ton könnte man ja auch noch abstellen (wo Drähte sind, kann man sie auch unterbrechen *gg*), aber leider schaltet sich das Teil einfach aus und das war es dann. Nix Hitze oder Thermostat oder so - einfache Willkür.

Nun aber mal wieder zur Software. Hab da ja meine Webseite, die hier drauf soll. Erstklassiges AJAX, XML und MySQL-Datenbank - nur das Feinste vom Feinsten: PEAR-Klassen. Dass er kein PEAR kann (vor allem nicht aktuelles Zeugs), dass verzeiht man (mein Provider, der nicht mal bis 3 zählen kann, hat das ja auch nicht, aber man kanns ja selbst draufkopieren), aber dass XML ein Tabu-Thema ist, wusst ich bislang noch nicht. phpinfo() zeigt sehr schön an, dass XML nicht wirklich dabei ist -  und es gibt wohl noch mehr, was fehlt, wenn ich den Leidensgenossen in diversen Foren glauben darf.

Was ist das nur für ein Scheiß, dass das fehlt. Haben sie bei Synology nicht mehr alle, oder für wen ist das Teil gemacht? Ich versteh das einfach nicht: Media-Ströme, Konfigurationen, ja sogar das XHTML - alles XML und da nehmen sie das aus PHP einfach raus? Wie soll man denn da XMLRPC fahren? Oder andere Protokolle? Große Enttäuschung!

Vor lauter Frust stöbere ich durch die Foren und lese, dass es nicht nur mir so geht. Will mal schauen, ob man das XML nicht nachrüsten kann. Nach vielen vergeblichen hin- und hergehüpfe endlich ein knapper Beitrag PHP extensions ... the definitve answer:

You'll see that dynamic library support is not included. You'll never be able to load ... You need to install the php ipkgs ...

ipkg - das kenn ich doch irgendwo her *Hoffnung kehrt langsam zurück*. Und ja, da gibt es in einem Wiki eine Anleitung Overview on modifying the Synology Server, bootstrap, ipkg etc  Die Anleitung ist gut. Ratz fatz ist das ipkg installiert und schon kann man seine php-Module herunterladen. Das weitere gehört ja nicht mehr in diese Foren-Rubrik, deshalb beschreib ich das an anderer Stelle.

Ergebnis: Apache, PHP und MySQL der Original-Software sind bei mir stillgelegt worden. Ich arbeite mit vollem Erfolg mit den zusätzlich geladenen Teilen - bislang geht alles, was ich mir wünsche. Aber es hat nun doch rund 10 Stunden Arbeit gekosten. Ob ich die von Synology bezahlt bekommen werde?

Noch eine abschließende Bemerkung: Ich schreibe meine Web-Seiten per Hand (mit einem eigenen CMS): HTML, XML, CSS usw., weil ich es leid war, immer und immer wieder eine neue CMS-Oberfläche, -Philosophie und ggf. -Konfigurationssprache (ich mag deshalb Typo 3 net) zu lernen. Es ist auch nicht wirklich schwierig, C, C++, Java oder Shell-Programme zu lesen und zu schreiben. Was schwierig ist, ist, dass immer und immer wieder administratives Zeug versteckt wird, angeblich um den unbedarften User nicht zu überfordern. Es kostet irrsinnige Zeit, hinter die Winkelzüge und Konfigurationen zu kommen. Das ist auch bei der Linux-Version der DS207+ so. Mein Tipp: Lasst es einfach sein - nicht immer noch eine include-File oder ein Verzeichnis, in dem nichts steht. Legt einen simplen Texteditor bei (für alle die, die den vi nicht mögen) und schriebt gute Anleitungen. Schließlich wollen wir uns nicht mit Hardware und Software unnötig lange beschäftigen bis sie läuft, sondern genießen, was sie uns bietet.

ADS - Alternate Data Streams in NTFS

Es ist schon ein Weile her, da hatte ich mich einmal intensiv mit diesem Thema auseinander gesetzt. Jetzt bin ich wieder darauf gestoßen, weil ich ein nettes Tool hierzu gefunden habe, den Stream Explorer. Bei der Gelegenheit erinnerte ich mich daran, dass ich per Kommando-Zeile vor nicht allzu langer Zeit irgendwas falsch eingeben hatte (ich glaube, ich wollte was auf LPT1: oder PRN: drucken) und es gab eigenartiger Weise keine Fehlermeldung. Wahrscheinlich hatte ich aus Versehen :LPT1 eingegeben oder so. Ja, da hatte ich wohl einen ADS fürs current Directory erzeugt ...

Neugierig auf das Thema geworden, schaute ich mal im Web nach, was es denn insgesamt an Neuigkeiten gibt. Ein paar Pages sind hervorzuheben:

Alternate data streams gibt als Wiki einen guten Überblick und ist eine gute Zusammenfassung für die Verwendung von ADS-Dateien per Kommando-Zeile. Leider sind die Links (der Artikel ist aus 2006) zu den Microsoft-Quellen nicht mehr stimmig. Hier findet man auch die Links zu den gängigen Tools:

  • SysInternals has a free Streams program that will enumerate streams.
  • LADS is also another free utility that enumerates streams.
  • ADS Spy a nice free GUI tool for searching and removing streams.
  • ADS Locator a free GUI tool that searches for streams.

Ebenfalls aus dem Jahre 2006 ist die PowerPoint-Präsentation zu ADS von Keith Palmgren.

Noch ein Tool ist der StreamViewer.

Ein weiteres hübsches Tool ist ADS 1.0. Der Erläuterungstext zu diesem Programm hat mich dann doch überrascht:

In Vista, but not in XP, you can open a DOS box and use dir /R to display the alternate data streams whose name is displayed in the form: file_name:stream_name:$DATA.

Das ist neu! Also schnell einmal ein Konsol-Fenster aufgemacht (natürlich mit Admin-Rechten) und ausprobiert:

dir /R

Ja, damit werden sie angezeigt, die alternate data streams - auch der vom Directory! Wer es schnell mal unter Vista im Konsol-Fenster ausprobieren möchte: Erzeugen kann man einen ADS (hier im Beispiel ads.txt genannt) einfach mit

echo "irgendwas" >datei.txt:ads.txt

oder

more <datei_rein.txt >datei.txt:ads.txt 

bzw.

type datei_rein.txt >datei.txt:ads.txt

oder mit dem Notepad

notepad datei.txt:ads.txt

Alle Stream-benutzenden Kommandos (zur Erinnerung: stdin, stdout, <, >, |) und auch selbst geschriebene Programme können mit ADS umgehen. Auch der Windows-Scripting-Host kann ein wenig mit den ADS umgehen (show_ads.vbs):

set fs = createObject("Scripting.FileSystemObject") 
set file= fs.openTextFile("datei.txt:ads.txt") 
MsgBox file.ReadAll

Leider geht auch nicht viel mehr - das Löschen oder Kopieren oder Umbenennen eines einzelnen ADS geht zum Beispiel nicht. Aber Lesen und Schreiben geht!

Es gibt vielerorts das Bedürfnis, ADS-Dateien aufzuspüren und die Streams (bis auf den Hauptstream) zu löschen. Unter Vista könnte man das nun auch auf der Kommando-Zeile halbwegs hinbekommen. Man kann die ADS zwar nicht löschen, aber ihren Inhalt schon (Länge: 0 Bytes). Die Idee lässt sich in 2 Schritten umsetzen: (1) Man erzeuge eine Liste aller ADS-Dateinamen und (2) man überschreibe diese Streams mit einer NUL-Datei.

dir /R | find "$DATA" > ADS_LISTE 
for /F "tokens=2" %i in (ADS_LISTE) do type NUL: > %i

Mit einem dir /R /S kann man auch alle Unterverzeichnisse absuchen ...

Die Frage stellt sich nun: Warum gibt es eigentlich kein(e) offiziellen Kommando-Zeilen-Tool(s) von Microsoft, mit dem/denen man die ADS löschen (bearbeiten) kann? So schwer kann das ja eigentlich nicht sein, denn sie haben doch Mark Russinovich eingekauft mit seinen Mannen und Tools: Streams zeigt ADS an und kann sie auch entfernen. Und auch  hier gibt es kostenlos die lang vermissten Tools:

cs - copy stream
ds - delete stream  
ls - list stream
rs - rename stream
sf - strip file (delete all streams)

Noch ein Hinweis, wie man in XP und Vista spezielle ADS (zone information) unterbinden kann, die einen möglicherweise daran hindern, kopierte Dateien auszuführen:

gpedit.msc
User Configuration > Administrative Templates > Windows Components > Attachment Manager
Enable: Do not preserve zone information in file attachments.

Weitere Lösungen zu diesem speziellen Problem hier.

Clipboard oder auch Zwischenablage genannt

Neuerdings unter Vista gibt es ein neues Tool mit dem man in der Kommando-Zeile den Output eines Kommandos in die Zwischenablage umlenken kann: clip.exe. Das ist natürlich nur für Texte gedacht, also alle anderen Formate werden wohl nicht unterstützt - denke ich mal, weil ausprobiert habe ich das nicht. Das Tool ist zweckmäßig und nett. Und in der ein oder anderen Form gab es das ja auch schon früher.

Auf der Suche nach dem Komplement, den Text in der Zwischenablage wieder als Input einem anderen Programm auf der Kommando-Zeile zuzuführen, beißt man sich die Zähne aus. Clipboard-Programme gibt es wie Sand am Meer (mein Liebling ist hier), aber so ein kleines Tool wie clip.exe nur anders herum, das gibt es wohl nicht. Seltsam eigentlich. Vor langer Zeit habe ich mir mal den Windows-Scripting-Host angesehen und da auch feststellt, dass man fast auf alles zugreifen kann, nur auf die Zwischenablage nicht. Irgendwo habe ich gelesen, dass man das Auslesen der Zwischenablage als Sicherheitsrisiko versteht und nur sehr sparsam mit automatischen Tools drauf zugreifen kann.

Trotzdem bliebt die Frage, ob man nicht doch - trotz Risikos - eine Lösung finden kann. Ja, zwar etwas umständlicher als man denkt, aber es geht. In einem .vbs-Script lässt sich der Internet Explorer zum Zwecke des Auslesens der Zwischenablage benutzen. Die Idee stammt von hier. Man muss noch ein wenig die Sicherheits-Standards des IE verfeinern, damit keine Meldungen kommen.

Hier das Skript clipread.vbs:

On Error Resume Next
Err.Clear
Dim C
C = ReadClipboard
Wscript.echo C
function ReadClipboard
with createObject("internetexplorer.application")
.navigate "about:blank"
ReadClipboard = .document.parentwindow.clipboardData.getData("text")
.quit
end with
end function

Läuft natürlich auch auf der Kommando-Zeile und gibt je nach dem, ob es als WScript oder CScript ausgeführt wird, den Zwischenablage-Inhalt in einer Message-Box oder auf StdOut (Standard-Out) aus. Umschalten zwischen diesen beiden Modi kann man mit

WSCRIPT //H:CSCRIPT

bzw. wieder zurück mit

WSCRIPT //H:WSCRIPT

Auf der Kommando-Zeile kann man die Ausgabe weiterverwenden mittels einer Pipe (|) oder Redirektion (>), zum Beispiel kann man die Ausgabe auf einen Drucker umlenken:

clipread > lpt2

Wenn man seine eigenen Drucker als Netzwerk-Drucker freigibt und mit

use lpt2 //Computername/Druckername

eine Zuordnung trifft, dann kann man auf fast jedem Drucker eine Ausgabe hinbekommen.

Wenn es einem nur ums ausdrucken geht, kann man auch direkt aus dem IE den Druck starten. Ich habe das mal clipprint.vbs genannt:

On Error Resume Next
Err.Clear
ReadClipboard
function ReadClipboard
with createObject("internetexplorer.application")
.navigate "about:blank"
.document.body.innerHTML = "<pre>"
+ .document.parentwindow.clipboardData.getData ("text")
+ "</pre>"
.document.parentwindow.print ()
end with
end function

Damit die Zeilenvorschübe auch vom IE ausgegeben werden, wird der Inhalt der Zwischenablage zwischen <pre>-Tags gesetzt. Das Druck-Fenster wird automatisch aufgerufen und man kann seinen Lieblings-Drucker aussuchen und ggf. noch Einstellungen vornehmen. Eine Verknüpfung auf das Skript gelegt, auf den Desktop geschoben und mit einer Funktionstaste versorgt, wird daraus fast ein Komfort-Zwischenablage-Druck-Programm ^_^.

Internet Explorer: Laufzeitfehler Zeile:1 Ungültiges Zeichen

Da probiere ich gerade was aus: Lade eine HTML-Datei lokal in den Browser und erhalte eine seltsame Fehlermeldung:

Egal was ich auch mache, ich komme nicht dahinter: Debugger startet nicht - und in der Datei ist auch nichts in Zeile 1 falsch. In dem Skript werden ActiveXObject genutzt, aber die produzieren schon ihre eigenen Fehler, wenn die Datei nicht als .hta gestartet wird. Was ist da los?

Mal im Web gesucht: Oft gibt es den Hinweis, schalte doch die Fehleranzeige in den Browser-Optionen aus. Naja, das macht mich nicht grad klüger. Browser-Cache soll noch geleert werden, Add-Ins deinstalliert und wieder neu installiert werden. Richard hat eine Erklärung, die mich überzeugt:

Invalid character means in MS terminology "file doesn't exist". This may happen, if you specified wrong file path or if IE is unable to open a file due to security restrictions built into the browser. The security is tighter in IE7, that's why you get more errors in the new version

Und Recht hat er, denn nun finde ich den Fehler: Eine JavaScript-Datei soll eingebunden werden und der Pfad stimmte nicht. Alles klar, aber bei der Fehlermeldung oben kommt man nicht so schnell drauf :)

How to become a famous blogger

cartoon from www.weblogcartoons.com

Cartoon by Dave Walker. Find more cartoons you can freely re-use on your blog at We Blog Cartoons.

Kalender 2008

Es ist zwar schon ein wenig her, das mit dem Jahresanfang. Aber ich hab erst jetzt die Zeit gefunden, meinen Ferienkalender auf den neuesten Stand zu bringen.

Wenn man auf die Bundesländer klickt, dann werden die Ferien als Balken eingeblendet. Natürlich sind die Ferientermine ohne Gewähr, Irrtum vorbehalten, wie man so schön sagt. Zudem jedes Bundesland die Möglichkeit hat, auch kurzfristig noch die Termine zu ändern. Wer sich an der Quelle informieren möchte, der suche mal die Kultusministerkonferenz per Suchmaschine auf. Und es wird ein wohl gehütetes Geheimnis bleiben, warum manchmal die Schulferien am Freitag und manchmal am Samstag enden. Also zumindest mir bleibt der tiefere Sinn verschlossen; denn zur Erinnerung: Schulferien heißt ja für Lehrer/Hausmeister usw. nicht, dass sie automatisch Urlaub haben - das gleiche gilt unter Umständen auch für die Schüler. Aber was soll es: Eine Welt ohne Geheimnisse und Unerklärlichem wäre ja auch fad.

In dem Kalender oben, kann man auch einzelne Tage anklicken und markieren. Außerdem sind die Feiertage eingetragen und werden angezeigt, wenn man mit der Maus über das entsprechende Datum geht. Ausdrucken ist auch möglich.

Wer mag, kann ihn sich hier herunterladen und als lokale Datei im Browser ausführen.

Ich habe den Kalender zusammen mit einer Uhr plus Wecker als Vista-Gadget geschrieben. Auch das kann man sich herunterladen.

Wer eigene Urlaubsplanung damit machen möchte, schreibe mir einen Kommentar mit E-Mail (wird nicht veröffentlicht - wir verhandeln dann über die Größe der Lösung, mit oder ohne Server usw. und deren Preis ^_^

Eine neue Platte für den Vista-Laptop

Nun der Laptop ist jetzt auch schon wieder 3 Jahre alt und auf der 40GB-Platte geht es schon wieder reichlich eng her: Zwei Partitionen, Vista und natürlich noch XP, zweimal Linux auf virtuellen PCs mit dazugehörigen virtuellen Platten, Webserver, Datenbanken (3 GB) und ein bischen Entwickler-Software und natürlich hunderte von Software-Proben und Pröbchen.

Also mal geschaut, was es für 2,5-Platten gibt, IDE natürlich noch. Leise soll sie sein, und möglichst wenig Strom fressen und immer schön kühl bleiben. Und - na klar - größer *gg*

160GB sind es nun geworden.

Und nun stellt sich die Frage nach dem Wie bekommt man denn alles rüber ohne was neu installieren zu müssen? Die Platte muss am besten erstmal als USB-Laufwerk angeschlossen werden. Externe USB-Festplatte ... ja da war doch noch eine feine kleine Platte irgendwo im Schrank. Gehäuse aufgemacht und Plattentausch. Angeschlossen. Und? Alles klar, ist da!

Wie bekommt man zwei Partitionen auf eine externe Festplatte kopiert. Ein wenig recherchiert und ein Programm gefunden, dass vielversprechend kling: Disk Copy 2.0.

Man erhält ein ISO-Image und muss es auf eine CD brennen. Geht mit Imgburn. Ist schnell erledigt. Dann System-Neu-Start von gerade erstellter CD, denn das Kopieren von Partitionen geht am einfachsten, wenn keine Programme auf ihnen aktiv sind. Ist zwar mittlerweile durch die Shadow-Volumes-Geschichten von Vista nicht unbedingt mehr nötig, aber man soll nicht klagen, weil Disk Copy ja gratis ist.

Disk Copy sieht Windows-like aus; der Dialog ist klar und verständlich. Der Datentransfer ist OK: 1 GB knapp 2 Minuten. Nachdem beide Partitionen kopiert sind, kommt der Test. Werden die neuen Partitionen von Vista erkannt? Also Neustart und geschaut, ob die Partitionen im Datei-Explorer erscheinen. Und so ist es - alles OK. Dann schnell noch die zweite Partition ein wenig mit der Datenträgerverwaltung unter Vista vergrößert. 3 Sekunden und fertig. Nun der Umbau: alte Platte aus dem Laptop raus und die gerade erstelle rein.

Beim Starten wird eine Fehlermeldung ausgegeben: eine Datei (.../system32/winload) kann nicht gefunden werden oder so. Man möge doch bitte vom Original-Vista-Medium den Reparatur-Vorgang auswählen. Also Vista-DVD rein und nochmal gestartet. Die Reparatur dauerte gerade mal 10 Sekunden. Wieder Neustart und nun ist die Welt wieder heil - alles so wie sonst. Alles? Nein ein freundliches Fenster erscheint und erklärt, dass sich in der Hardware was geändert hat und mal bitte Vista wieder aktivieren muss, sonst hört es nach 3 Tagen auf. Aktivierung angeklickt und 20 Sekunden gehörte das auch zur Vergangenheit.

Das Klonen der Festplatte ist gelungen und war alles in allem schnell und ohne wirkliche Probleme vor sich gegangen. Gegen die Reparatur und Reaktivieren von Vista kann man nichts haben. Und das die Vergrößerung der Vista-Partition mit Bordmittel durchgeführt werden konnte, ist auch schön. Das spart das Hinzuziehen eines speziellen Partitionsmanager-Programms. Dass das Kopieren seine Zeit braucht, ist klar, da darf man auch nicht mosern. Die meiste Zeit braucht man ja nicht dabei zu sitzen. Fazit: Auch unter Vista ist das Tauschen und Vergrößern der Systemplatte kein Problem.

Gadgets für Vista

Wie man für die Vista Sidebar ein Gadget erstellt, kann man an anderer Stelle nachlesen. Wie man ein Gadget per AJAX mit Seiten versorgt, kann man im Folgenden lesen.

Das Grundgerüst für die Gadget-File ist ein HTML-Gerüst:

<html lang="de" xml:lang="de" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http_equiv="content-type" content="text/html; charset=utf-8">
<style>body {margin:0px;width:375px;height:290px;}</style>
</head>
<body onload="init()"></body>
</html>

Ganz rudimentär - muss nicht so sein, ist aber in dem Beispiel so. Der init()-Aufruf haucht dem Ganzen das Leben ein. Was soll eigentlich passieren? In den body wird ein iframe integriert, welches dann per AJAX von einer anderen HTML-Page gefüttert wird. Warum? Weil man leider nicht direkt in einem Gadget andere Pages aufrufen kann; es wird halt immer ein neues Browser-Fenster geöffnet. Und deshalb muss man die Seiten per AJAX hinein laden sowie die Navigation's-Events abfangen, um weitere Pages auch wieder per AJAX laden zu können. Das Laden wird über eine Funktion namens get(url,type,msg) erledigt. Die drei Argumente sind url, type (GET|POST) und msg für das Senden von Inhalten an den Server. Also in der Funktion init() steht dann erstmal:

function init() { get('http://irgendwas','GET'); }

In der Funktion get wird das XMLHTTPRequest-Objekt erzeugt und an die URL gesendet, wenn die Antwort von Content-Type 'text/html' ist, dann wird das iframe angelegt und die empfangene Page hineingeschrieben:

var z,hostpath;
function get(url,type,msg){
hostpath=url.substr(0,url.lastIndexOf("/"));
var myXMLHTTPRequest = new ActiveXObject("Microsoft.XMLHTTP");
myXMLHTTPRequest.open(type, url, false);
myXMLHTTPRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
myXMLHTTPRequest.send(msg);
if (myXMLHTTPRequest.getResponseHeader('Content-Type').indexOf("html")!=-1) {
if (z) document.body.removeChild(z);
var item=document.createElement("iframe"); item.setAttribute("src","");
z = document.body.appendChild(item);
z.style.top='0px'; z.style.width='800px';z.style.height='600px';
var r = myXMLHTTPRequest.responseText;
z.contentWindow.document.write(r);
z.contentWindow.document.close();
if(z.contentWindow.document.forms[0])
z.contentWindow.document.forms[0].onsubmit=myEventHandler1;
z.contentWindow.document.body.onclick=myEventHandler1;
}
else { window.open(url,''); }
}

Ach ja, z ist das iframe-Element und das wird jedesmal gelöscht, damit die neuen Inhalte per write nicht hinten dran gehangen werden, sondern frisch an erster Stelle stehen. Aus unerfindlichen Gründen muss man für das iframe das Attribut src auf einen leeren String setzen :). Die style-Angaben sind auch notwendig, weil das iframe sonst sehr klein ist. Falls das per XMLHTTPRequest-Aufruf Erhalte nicht 'html' ist, wird ein neues Fenster für diese Page aufgemacht (z. B. für XML oder PDF).

Pages, die Bilder und andere verlinkten Dinge enthalten, brauchen noch eine base-Eintragung, damit sie auch gefunden werden. Das muss noch vor dem write passieren; also wird die Zeile mit dem responseText erweitert:

var r = myXMLHTTPRequest.responseText.replace(/<head>/,'<head><base href='+url+' />');

Damit kann man schon Pages laden und anzeigen. Aber die Interaktion fehlt noch. Dazu müssen nun für das iframe Event abgefangen werden. Im Beispiel sind das click und submit. Damit hätte man das Abschicken von Formularen und das Anklicken von Links im Griff. Nach dem close noch die Event-Behandlung (bei den Forms wird geprüft, ob es überhaupt welche gibt!).

Und natürlich brauchen wir nun die EventHandler-Funktion. Da wir es mit Windows und dem Internet Explorer bei einem Vista Gadget zu tun haben, wird nur die IE-Form notiert:

function myEventHandler1() {
var e=z.contentWindow.event;
if (e.type=='click') {
var s=z.contentWindow.event.srcElement;
if (s.href || s.parentNode.href) {
href=s.href?s.href:s.parentNode.href;
get(href,'GET');
return false;
}
}
else {
var f=z.contentWindow.document.forms[0];
if (f.action.indexOf('http://')==-1) f.action=hostpath+f.action;
var q=""; for (var i=0; i<f.length; i++) q+=f[i].name+'='+escape(f[i].value)+'&';
if (f.method && (f.method=="post" || f.method=="POST")) {get(f.action,'POST',q);}
else {get(f.action+'?'+q,'GET');}
return false;
}
}

Der Reihe nach: Der Event aus dem iframe wird der Variablen e zugeordnet; dann wird der Event-Typ inspiziert ('click') und nach der Herkunft des Click-Events geschaut (scrElement). Falls das Element ein Attribut namens href hat (oder sein Eltern-Element, denn oft wird im A-Tag nochmal hervorgehoben), dann wird die get-Funktion mit dieser neuen URL aufgerufen. Alle anderen click-Events werden nicht behandelt und bleiben beim iframe, was auch immer dort der Code auch macht :). Liegt ein submit-Event vor, wird der Alternativ-Zweig durchlaufen. Hier wird zunächst geschaut, ob im action-Attribut der form ein vollständiger Pfad vorliegt, falls nicht, wird ergänzt. Hierfür mussten wir in der get-Funktion noch zu Beginn vorsorgen mittels eines

hostpath=url.substr(0,url.lastIndexOf("/"));

Und natürlich muss die Variable hostpath global zu den Funktionen deklariert sein.

Als nächstes werden die Formular-Felder zu einem URI-Komponenten-String zusammengefasst. Ob man das mit escape() oder besser mit encodeURI() bzw. encodeURIComponent() macht, muss man für sich entscheiden. Als nächstes wird das method-Attribut der form untersucht, weil ja je nach Methode die Versandart für den XMLHTTPRequest gewählt werden muss. Der zu sendende Inhalt wird also entweder als Parameter oder als Anhängsel verschickt. Wichtig ist noch die Zeile return false, damit der iframe nicht noch den Event für sich auswertet.

Simple Tag-Cloud für Blogger bzw. WordPress

Tag-Clouds geben knapp und intuitiv die Relevanz von Informationen in einer visuellen Übersicht aus. Also die Schlagworte (Tags) hier im Blog werden zum Beispiel gezählt und man kann jetzt entweder auf die herkömmliche Art eine Statistik über die Häufigkeit ausgeben oder sie durch unterschiedliche Buchstaben-Größen anzeigen. Das dabei erzeugte Text-Bild ist Namensstifter für die Wolke.

WordPress bzw. Blogger liefert die Anzahl, so dass eigentlich nur die Aufbereitung mit unterschiedlichen Buchstabengrößen zu tun ist. Ich habe nicht so viele Tags, so dass mein Algorithmus schlicht ist: Ausgangsgröße der Fonts = 10px und jeder Treffer wird einfach darauf addiert, also 5 Treffer = 15px! Wenn man mehr Treffen hat, dann muss man halt die Trefferzahl geeignet teilen oder so, bevor man sie addiert (ich überlasse das mal der Fantasie jedes einzelnen, damit zurecht zu kommen).

Wie wird nun die Addition auf die Font-Größe vorgenommen? Mit einem 2-Zeiler in JavaScript. Wer das nachbauen will, muss beim Blogger ins Menü 'Layout->HTML bearbeiten' und dann Haken rein in 'Vorlagen zum Erweitern von Widgets'! Am Besten mit der Browser-Suche das Stichwort 'Tags' suchen. Der folgende Code-Abschnitt enthält alle Informationen:

<b:widget id='Label1' locked='false' title='Tags' type='Label'>
<b:includable id='main'>
<b:if cond='data:title'>
  <h2><data:title/></h2>
</b:if>
<div class='widget-content'>
    <!--<ul>-->
  <b:loop values='data:labels' var='label'>
      <!--<li>-->
      <b:if cond='data:blog.url == data:label.url'>
        <span expr:dir='data:blog.languageDirection'>
          <data:label.name/>
        </span>
      <b:else/>
        <a expr:dir='data:blog.languageDirection' expr:href='data:label.url'>
           <span expr:style='&quot;font-size:&quot; + data:label.count +
            &quot;px;font-size:expression(eval(10+&quot; + 
            data:label.count + &quot;))&quot;' name='tagcloud'>
               <data:label.name/>
           </span>
        </a>
      </b:if>
        <!--<span dir='ltr'>(<data:label.count/>)</span>-->
      <!--</li>-->
  </b:loop>
    <!--</ul>-->
    <script>var taglist=document.getElementsByName(&quot;tagcloud&quot;);
            for (var i=0; i &lt; taglist.length; ++i) { s = taglist[i].style; 
              s.fontSize = (parseInt(s.fontSize)+10)+&#39;px&#39;; }
  </script>
  <b:include name='quickedit'/>
</div>
</b:includable>
</b:widget>

Wie immer, muss man beim IE einen kleinen extra-Schlenker per expression machen, aber das war es auch schon :)

Midas: Firefox und Rich Text Editing

Vor ein paar Jahren bin ich beim Schmökern der Referenz-Seiten des IE_DOMs über eine Property (Eigenschaft) namens isContentEditable gestolpert, die einem beliebigen Tag auf der HTML-Seite Editor-Fähigkeiten zuschusterte. Es gab auch einen Beispiel-Editor, den ich aber nicht mehr finde. Mittlerweile ist daraus ein ganzes Thema bei Microsoft geworden: How to Create an HTML Editor Application. Da ich dann auch noch andere auf Webseiten einbaubare Editoren, wie TinyMCE oder htmlArea gefunden habe, die Plattform übergreifend funktioniert haben, ist mein Interesse abgeklungen, sich damit weiter zu beschäftigen.

Per Zufall bin ich vor ein paar Tagen wieder mit dem Thema konfrontiert worden. Diesmal war die Frage, gibt es einen eingebauten Editor auch beim Firefox. Ja, gibts! Geht aber anders, siehe Midas Specification. Es gibt hier kein für alle Tags geltendes Attribut; man kann nur das ganze Dokument (DOM-Node: document) editierbar machen oder nicht und zwar mit document.designMode="on" und das gilt dann für alle Elemente in diesem Dokument. Da man fast immer außer dem Editieren noch was anderes im Dokument stehen hat (Benutzeroberfläche usw.), gibt es eigentlich nur einen praktischen Weg: Man integriert den zu editierenden Bereich in ein iframe und gibt dem iframe das designMode-Attribute auf on mit:

<iframe id="editor" src="about:blank"
onload="javascript:this.contentDocument.designMode='on';"
>/iframe>

Es gibt eine Reihe von Kommandos, die auf das Editor-Verhalten einwirken. Das funktioniert alles so leidlich, dass es fast schön ist. <div>-Elemente, die man mit dem style="position:absolute" in den Editor-Bereich einfügt, lassen sich sogar wie Objekte anklicken und verschieben/in der Größe verändern. Einige Kommandos sind auch durch Tasten zu aktivieren (Strg-Z, Strg-Shift-Z, Strg-A, Strg-C, Strg-X, Strg-V). Etwas lästig ist das Fehlen einer de-select-Funktionalität (Gegenstück zu selectAll), weil wenn man ein <div>-Objekt angeklickt hat, wird es eingerahmt und diese Einrahmung wird man nicht wieder los. Aber man den de-select nachbauen, indem man kurzzeitig den designMode deaktiviert und dann wieder aktiviert.

Da der Editor die Events deaktiviert bzw. auf sich umleitet, gehen die onclick, onmouseover usw. nicht mehr. Daher muss man per EventHandler Events wie Click, DblClick usw. abfangen:

function myEventHandler(mEvent) {
 alert(mEvent.clientX+','+mEvent.clientY); }

Den EventHandler muss man an geeignet Stelle aufrufen, z. B. im body-Tag per onload:

<body onload="document.getElementById('editor').contentWindow
.addEventListener('click', myEventHandler, true);">

Man kann den Midas zu einem einfachen Editor ausbauen; ist ja fast alles an Board. An den gesamten Inhalt (<body>) des <iframe> gelangt man über das weiter unten beschriebene outerHTML; über das Lesen und Speichern von lokalen Dateien hab ich ja auch bereits weiter unten was geschrieben. Das Abspeichern auf dem Web-Server kann man per AJAX erledigen.

Kann ein Browser auf lokale Dateien zugreifen?

Die Antwort lautet: "ja". Ganz allgemein gesprochen, kann ein Browser (ich nehme mal den Firefox als Beispiel) Dateien aus dem Dateisystem laden (Datei öffnen) und auch speichern (Seite speichern unter oder Ziel speichern unter). Und natürlich gibt es die Cookies und ähnliche Speichermöglichkeiten (man denke an Flash). Und man kann natürlich auch einen Datei-Upload (lokale Datei nach Web-Server) durchführen. Meist wird der Benutzer in einen entsprechenden Dialog verwickelt bzw. muss von sich aus aktiv werden. Na ja, bei den Cookies usw. eher nicht. Aber das sind Antworten, die nicht wirklich spannend sind.

Die eigentlich interessantere Frage ist eher: "Gibt es per JavaScript eine Möglichkeit, auf lokale Dateien zuzugreifen?" Und natürlich ist die Antwort erst einmal "Nein", weil wir ja die Sicherheit des Browsers (Sandbox-Modell) unterstellen. Wäre die Antwort positiv, dann würden wir das als Fehler bzw. als Sicherheitsrisiko verstehen und darauf hoffen, dass jemand den Fehler behebt, damit der Zugriff unterbleibt, denn wir wollen (!) ja nicht, dass ein Web-Seitenaufruf Schaden auf dem lokalen PC anrichtet.

Allerdings gibt es manchmal Problemstellungen in speziellen Situationen, da würden wir gerne auf das lokale Dateisystem zugreifen, vielleicht, weil wir eine schöne JavaScript-Anwendung geschrieben haben, die sowieso nur lokal laufen soll oder nicht immer ein Web-Server zur Verfügung steht. Vielleicht auch, weil uns der Browser als User-Interface gefällt. In diesen Fällen gibt es Möglichkeiten, den Browser um entsprechende Zugriffs-Komponenten zu erweitern. Entweder wir laden unsere Anwendung statt mit dem http-Protokoll mit dem file-Protokoll, oder wir setzten bestimmte Datei-Endungen ein (.hta bei Microsoft, .xul bei Mozilla/Firefox) und werden beim (erstmaligen) Start gefragt, ob wir das Sicherheitsrisiko auch eingehen wollen. Manchmal kann man auch in den Browser-Einstellungen solches vereinbaren.

Im folgenden ein mit XPCOM-Komponenten angereichertes Java-Skript für den Firefox, welches in einer ganz normalen html-Datei stehen könnte:

<script>
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file =
 Components.classes["@mozilla.org/file/local;1"]
 .createInstance(Components.interfaces.nsILocalFile);
file.initWithPath('C:\\example.txt');
var outputStream =
 Components.classes["@mozilla.org/network/file-output-stream;1"]
 .createInstance( Components.interfaces.nsIFileOutputStream );
outputStream.init(file, 0x04 | 0x08 | 0x20, 777, 0);
var output = 'hello world';
outputStream.write(output, output.length);
outputStream.close();
</script>

Kurze Erläuterung: Erwerb von Nutzungs-Privilegien, Schnittstelle zum lokalen Dateisystem herstellen, Dateizuordnung treffen, Ausgabe-Stream herstellen und auf die Datei binden und entsprechende Verarbeitungs-Einstellungen vornehmen (Zugriffsart: lesen/schreiben usw., Zugriffsrechte), den Ausgabetext in den Ausgabe-Stream stellen und das Ganze schreiben und schließen.

Konzept und Referenz findet man. Das knappe Code-Beispiel will nur das Zusammenspiel zeigen, weil das in anderen Darstellungen fehlt oder oft überladen ist. Das Skript läuft sowohl auf dem lokalen Server als auch mit dem Protokoll file:. Ähnliches gibt es auch für den Internet Explorer.

Zuletzt ein Anwendungsbeispiel eines lokal zu startenden Wikis, welches per AJAX auch noch den Up- bzw. Download zu einem Server demonstriert: TiddlyWiki.

outerHTML - und wie man mit JavaScript neue Attribute für eine Klasse definiert

Was macht man, wenn man in einer HTML-File ein Body-Tag mit Attributen hat und alles inklusive dieser Attribute auf einen Rutsch und möglichst einfach abgreifen möchte, zum Beispiel um eine Kopie auf den Server per AJAX abzulegen.

Nahe liegend ist zunächst der Gedanke: Da muss es doch etwas geben wie innerHTML. Und es gibt ja auch beim Internet Explorer etwas, das dort schlicht outerHTML heißt. Man kann nun darüber nachdenken, ob man nicht auch mit etwas rekursiven DOM-Gebrösele den Baum abläuft (hab ich vor längerem mal weiter unter beschrieben). Oder man googelt und schaut nach, ob nicht andere ein ähnliches Problem gelöst haben. Wie immer findet man irgendwann ein paar Lösungen, die mehr oder weniger elegant sind. Die folgende Lösung ist ein wenig abgekupfert und ein wenig ergänzt, damit sie auch schick ist.

<html>
<head>
<script>
var d = Element.prototype;
d.__defineGetter__("outerHTML", function() {
 var item=document.createElement("div");
 item.setAttribute("style","display:none");
 document.body.appendChild(item);
 var temp=this.cloneNode(true);
 item.appendChild(temp);
 var out=item.innerHTML;
 document.body.removeChild(item);
 return out;
 }
);
</script>
</head>
<body onload="alert(document.getElementById('a').outerHTML)">
<div id="a">
<p id="b">cde</p><p>xyz</p>
</div>
</body>

Zunächst ein Blick auf die letzten Zeilen. Dort ist ein <div>-Tag mit der id="a". Dieses soll per alert()-Funktion ausgegeben werden. Die Ausgabe wird im <body>-Tag mit dem onload-Event ausgelöst. Und hier steht, wie bei dem bekannten innerHTML nun outerHTML. Also als Eigenschaft (Property) einer DOM-Klasse und nicht als Methode, wie zu sehen ist. Das gefällt :)

Wie kann man nun aus einer Methode/Funktion ein Objekt-Attribut machen? Man muss eine prototype-getter-Implementation vornehmen. Also zunächst die Stelle in der Objekt-Hierarchie des DOMs suchen, wo das Attribut am besten hineinpasst: Document? Node? Element? Man achte bitte auf die Schreibweise mit großem Anfangsbuchstaben: Das sind die Klassen für die DOM-Objekte! Ich habs probiert und finde, dass Element eine gute Stelle für die Implementierung ist. Damit sind auch alle Navigationen (getElementById ... , firstChild, parentNode ...) abgedeckt, so dass man outerHTML wirklich wie innerHTML verwenden kann.

Also nachdem Element geeignet schient, die Definition vereinbart. Das geht mit prototype, einem Objekt, das für eine Konstruktorfunktion Eigenschaften und Methoden definiert, die allen mit dieser Konstruktorfunktion erzeugten Objekten gemeinsam sind. Anmerkung: Das läuft rekursiv und wirkt sich auch nachträglich aus.

Nun müssen wir noch einen Funktionsaufruf zum Attribut machen und das geschieht über die __defineGetter bzw. __defineSetter__-Methoden. Man vereinbart zunächst den Namen und beschreibt anschließend die Funktion. Und man kann in dieser Funktion auch mit dem this-Zeiger/Pointer arbeiten :), welcher später auf das Objekt zeigt, mit dem wir die Methode verwenden wollen.

So und wie erhalten wir nun ohne lange Übung die Attribute des Tags und aller darunter liegenden Tags? Wir legen ein neues unsichtbares <div>-Element an und machen einen Klon von dem Element, dessen outerHTML wir erhalten wollen. Danach weisen wir den Klon dem versteckten <div>-Element zu; holen uns den neuen Inhalt in eine Zwischenvariable, damit wir noch in Ruhe das nicht mehr benötigte <div>-Element wieder löschen können und geben das Ergebnis aus. Durch die cloneNode-Methode, wird die Lösung doch recht einfach.

Mit PHP Outlook-Termine auslesen

Für eine Terminplanungsgeschichte wollte ich die Termine in Outlook 2007 auslesen. Mittels MAPI und COM sollte das in PHP geschrieben auf meinem PC stattfinden, denn auf meinem PC läuft ein Apache-Server. Die Verbindung wird über die COM-Klasse hergestellt:

$outlook = new COM("outlook.application") or die("Konnte Outlook nicht instantiieren");
print "Outlook Version {$outlook->Version}, Product-Code {$outlook->ProductCode}";
$myNameSpace = $outlook->GetNamespace("MAPI");
$myNameSpace->Logon('Outlook'); // Standardanmeldung für die normale .pst-File
$myFolder = $myNameSpace->GetDefaultFolder(9)->Folders["my"]; // zweiter Kalender :)
$colItems = $myFolder->Items;
foreach($colItems as $item) {
  $data['Von']         =$item->Start;
  $data['Bis']         =$item->End;
  $data['Ort']         =$item->Location;
  $data['Betreffzeile']=$item->Subject;
  $data['Privat']      =$item->Sensitivity;
  $data['body']        =$item->Body;
  $data['LastChange']  =$item->LastModificationTime;
  var_dump($data);  // oder irgendwas anderes schlaues
  }

Natürlich gibt es noch viel mehr Felder und man kann auch auf andere Folder zugreifen (Termine ist Nummer 9). Ist bei MSDN recht gut dokumentiert. Das Ganze geht auch andersrum: aus SQL-Datenbank Termine holen und mittels PHP-Skript in Outlook einpflegen. Wenn man das LastModificationTime-Feld prüft, kann man auch zwischen SQL-Datenbank und Outlook synchronisieren: der jüngste Eintrag gewinnt :)

Etwas Kummer machen am Anfang die Fehlermeldungen und Abstürze *gg*, weil man zwar Outlook konnektieren kann, aber dann nicht weiter kommt. Es liegt an den Zugriffsrechten, die der Apache braucht, um die .pst-File zu lesen. Einfach mal den Apache-Dienst mit der eigenen User-Kennung starten, dann sieht man schon, das es geht. Allerdings sollte man sich überlegen, wie man die Rechte setzt, damit man im Falle eines Angriffs nicht alles zu weit auf gemacht hat.

Kennen Sie JavaScript von Microsoft?

Nun denken Sie, wer interessiert sich schon für eine spezielle Variante von JavaScript. Das ist doch Standard (ECMA) und in alle Browsern je nach Version gleich. Ja - es gibt verschiedene DOM-Implementationen und Box-Modelle; da muss man sich drum kümmern. Aber doch nicht um JavaScript.

Hab ich bis gestern auch gedacht. Aber da ist mir was passiert. Probieren Sie mal folgendes kleine Skript aus:

<script>alert("a:b:c".split(/(:)/));<script>

Zu erwarten ist folgende Ausgabe: a,:,b,:,c. Warum? Weil in der Beschreibung von JavaScript steht: Wenn der 'Begrenzer' ein RegExp mit einem in Klammern stehenden Teileausdruck ist, wird der Begrenzungstext, auf den der Teileausdruck passt, mit in das zurückgegebene Array aufgenommen. Nochmal auf Englisch: If separator is a regular expression that contains capturing parentheses, then each time separator is matched the results (including any undefined results) of the capturing parentheses are spliced into the output array.

Und nun probieren Sie mal statt des Firefox den Internet Explorer. Was kommt raus? a,b,c.

Ja und es scheint ein Feature zu sein, wenn man den Recherchen anderer glauben darf. Denn auch in weiteren MS-Programmiersprachen tritt dieses Phänomen auf. Nun werden Sie sagen: Wer braucht das denn? Warum ist das so wichtig? Nun, man kann mit dem split Strings parsen und manchmal möchte man irgend etwas zerlegen ohne dabei Text zu verlieren. Aber ich finde, die Frage nach der Anwendung nicht vorrangig, sondern ich finde es schlimm, dass man sich nicht auf einen Standard verlassen kann, ob man ihn nun wirklich einsetzt oder nicht, ist dabei nicht entscheidend.

Es gibt eine Lösung dieses Problems in Steven Levithan Blog, die gut funktioniert.

Archivieren: Nein - Danke?!

Per Zufall fiel mein Auge auf eine Meldung in einer PC-Zeitschrift: "ISO-Logo: so lange hält ein Rohling". Naja, erst einmal scherzhaft verstanden als "gibt es jetzt ein Verfallsdatum für DVD-Rohlinge im Shop?"

Aber dann doch ernsthaft: Wie lange sind Daten, selbst auf eine DVD gebrannt, haltbar. Die Fragestellung gilt gleichermaßen auch für CDs usw. Die Kauf-CDs/DVS sind anders hergestellt und fallen erst mal aus der Betrachtung. Also, wie sicher und vor allem wie lange sicher sind die Daten auf einer DVD?

Damit Vergleiche möglich sind, ist es sinnvoll, eine Normung für das Messverfahren zu haben. Das ist die Botschaft der Meldung. Die ECMA ist eine Organisation, die sich für Standards einsetzt, sie vorbereitet usw. und diese Organisation hat eine Meldung zu dem Prüfverfahren von optischen Datenträgern (ECMA-379) im Februar verfasst, die nun zur ISO/IEC 10995-Norm erhoben wurde. Ziel des Ganzen: Wenn ein Hersteller seine Angaben zu Haltbarkeit gemäß ISO/IEC 10995 macht, dann weiss man nun, nach welchen Verfahren sie zu dieser Aussage gekommen sind. Da man ja keine Langzeiterfahrungen hat, muss man eine besondere Umgebung (Tempertur, Luftfeuchtigkeit) herstellen, eine Gruppe von DVDs testen und anhand der Trendwerte eine Haltbarkeit prognostizieren. Dabei ist es interessant, dass die Alterungsprognose hauptsächlich von der Höhe der Temperatur und der relativen Luftfeuchtigkeit abhängig gemacht wird. Das ist auch von anderer Seite schon festgestellt worden. Was mich verblüfft hat, ist die dort gefundene Prognose: 10°/25% ca. 75 Jahre, 28°/50% ca. 2 Jahre. Das die Umgebung so stark auf die Haltbarkeit wirkt, ist schon bemerkenswert und sollte auch für die eigene Lagerung von DVDs beachtet werden.

Daneben gibt es ja auch noch andere Faktoren wie UV-Strahlung, mechanische Belastungen (Kratzer, Staub, Fliehkräfte usw.) und chemische Einwirkungen (Verunreinigungen in der Luft, Weichmacher im Kunststoff, Reinigungslösungen, Reaktionen zwischen den einzelnen Beschichtungen usw.) zu berücksichtigen. Wenn man dann noch die Aufnahmesituation einbezieht: irgendein Laufwerk eines Herstellers kombiniert mit irgendeinem Rohling (Kalibrierung, Brennrezepte, Brenngeschwindigkeit), dann wird klar, dass bei der Aufnahme eigentlich schon viel falsch gemacht werden kann und nicht die Alterung alleine die Wiedergabequalität nach Jahren nach unten zieht.

Tests und Qualitätssiegel können so schon eine Auswahlhilfe dabei sein. In vielen Foren kann man die Diskussion darüber verfolgen, welcher Brenner, welche Firmware, welche Aufnamesoftware mit welchen Rohlingen und Rohlingstypen (DVD-RAM, DVD-RW, DVD-R, plus/minus) am besten miteinander kombiniert werden sollten. Und auch der Rezepte zur Vermeidung von fehlerhaften Aufnahmen gibt es viele: doppelte Medien, keine Aufkleber, Brennen und nach 48-Stunden testen, nicht die maximale Brenngeschwindigkeit, aber auch nicht weniger als 50% der Geschwindigkeit, die Brenner und Medien können. Aber die Angst vor dem Verlust der gespeicherten Daten, Bilder usw. bleibt.

Alternativen werden angeboten: Sicherung auf Festplatte, auf Memory-Speicher (Sticks), MO-Datenträger. Sogar die alten ZIP-Laufwerke werden erwähnt. Aber auch die Erfahrung, dass selbst RAID-Einheiten nicht nicht fehlerfrei sein müssen bzw. anderen Gefahren ausgesetzt sein können (Viren, Controller-Crash). Nebenbei bemerkt habe ich etwas ältere Platten (40MB hihi) versucht wieder mal zu lesen: außer Knirschen im Laufwerk war nichts mehr zu machen. Und sie lagerten in einer nicht häufig genutzten Schublade. Meine alten Wechselplatten (anno 1995) sind auch kaum mehr zu lesen, von Disketten ganz zu schweigen. Jaja, ich habe noch Diskettenlaufwerke :).

Was also tun, wenn man seine digitale Schätze erhalten möchte und sich nicht der Meinung anschließen will, dass sowieso nichts für die Ewigkeit ist. Man muss wohl oder übel über eine regelmäßige Umkopiererei nachdenken. Also alle 2 Jahre lesen und auf neue Datenträger schreiben. Dass nun externe Wechselplatten an erster Stelle stehen, ist nicht verwunderlich, da sie zur Zeit große Kapazitäten zu geringen Kosten bereitstellen und mit einen minimalen Kopieraufwand verbunden sind. Dateisystem? Ich glaube, NTFS oder ein Linux-Format sind zur Zeit ok. Aber das kann man ja auch immer wieder neu festlegen. Dateinamen nicht länger als 128 Zeichen - daran hat man sich ja auch bei CD schon gewöhnen müssen. Eine oder zwei Kopien? RAID? Ja! JA, wenns sicher sein soll. Auch eine DVD-nach-DVD-Kopiererei mag sinnvoll sein. Es ist halt aufwendiger, hat dafür aber andere Qualitäten. Man denke an Laufwerkprobleme, oder wenn der Datenträger defekt ist, dann sind es halt nicht alle (DVDs). Außerdem kann man bei nur einmal-beschreibbaren DVDs (eher) davon ausgehen, dass zwischenzeitlich nichts gelöscht oder verändert wurde. Aber immer daran denken, dass eine oder zwei Tage nach der Aufnahme nochmal eine Prüfung der DVDs (z. B. CD-DVD-Speed) gemacht werden sollte, sonst stellt man sich schon Schrott ins Regal.

Ein Beitrag in einem Forum zu diesem Thema hat mich auch noch nachdenklich gemacht. Der Autor geht davon aus, dass wir uns von der ich-kauf-mir-eine-DVD-und-stell-sie- ins-Regal bzw. ich-mach-eine-Sicherung-und-habs-für-immer Mentalität bald verabschieden müssen und uns daran gewöhnen, dass wir die Dinge nicht mehr haben (besitzen) werden, sondern nur noch nutzen können. Ein anderer Autor fragt nach einem Provider, der ihm garantiert, dass seine hoch geladenen Daten langzeit archiviert werden. Auch ein Aspekt über den man intensiv nachdenken muss.

CSS: @media print

Eigentlich ist es schon ein alter Hut über die CSS-Format-Definitionen für unterschiedliche Ausgabe-Medien nachzudenken, wenn ... ja wenn nicht gerade mal wieder ein Problem damit verbunden wäre.

Wozu braucht man überhaupt alternative CSS-Formate? Zum Beispiel, um das Layout zurechtzurücken, weil beim Drucken das Seitenverhältnis des Ausgabemediums "Papier" meist hochkant (Portrait) statt wie beim Bildschirm quer (Landscape) normal ist. Oder weil man transparente Bilder hat, deren Transparenz beim Ausdruck schlicht in schwarz oder weiß umgesetzt wird und auf die man daher beim Ausdruck gerne verzichten möchten (display:none). Oder weil man seine Adresse noch schön auf den Ausdruck platzieren möchte, also noch etwas hinzufügen möchte, was auf dem Bildschirm nicht drauf ist. Oder oder oder...

Bei einem meiner Projekte habe ich die Textausgabe in einen Bereich geschrieben, der sich dynamisch an die Fenstergröße anpasst (und einen Scroll-Schieber hat, wenn der Text zu groß wird). Ist ja eigentlich ganz einfach: Man legt einen Event onload in den body-Tag und fragt die Bildschirmgröße mit window.innerHeight bzw. document.documentElement.clientHeight ab und setzt die style.height-Eigenschaft des Bereichs auf einen entsprechende Wert:

wh=window.innerHeight || document.documentElement.clientHeight;
h=(675>wh)?500:wh-150;
document.getElementById('content').style.height=h+'px';

Geht passabel in allen aktuellen Browsern. Und nun wird es spannend! Beim Ausdruck wird natürlich nur der Inhalt ausgedruckt, der in dem Bereich auf dem Bildschirm auch sichtbar ist (wie so ein Screenshot). Will man den ganzen Text ausdrucken, weil das Papier ja auch hochkant genug Platz hätte, dann müsste man für den Ausdruck eine CSS-Format-Definition @media print mit einer größeren Höhe (height) für diesen Bereich anlegen bzw. eventuell auch eine mit kleinerer Höhe für den @media screen. Aber wie macht man das, den Style für eine Ausgabe dynamisch zurecht zu schneidern?

Zunächst die Information, dass man nicht nur auf den Style eines DOM-Elements zugreifen kann, sondern auch auf die Stylesheet-Objects. Leider wiedermal Browser spezifisch. Kurze Übersicht über die Methoden und Attribute findet man hier. Das Konzept und Beispiele findet man hier.

Nun noch die "missing-information", wie man das mit den @media-Zuordnungen macht. Vorher noch kurz die Anmerkung, dass man den <style>-Tags bzw. dem <link>-Tags id-Attribute zuordnenen kann und so etwas einfacher die Referenz herstellt:

if (isie) { // isie muss man irgendwo als Funktion schreiben
   s=document.styleSheets['default'];  // default ist die id der style-Eintragung
   s.cssText+='@media screen {#content,{height:'+h+'px;}}';
   s.cssText+='@media print {#content{height:1000px;}}';
   }  
else {
   s=document.getElementById('default').sheet;
   s.insertRule('@media screen {#content{height:'+h+'px;}}',s.cssRules.length);
   s.insertRule('@media print {#content{height:1000px;}}',s.cssRules.length);
   }

Damit hätte man für IE und FF eine Lösung. Andere Browser hab ich nun nicht ausprobiert.