Archiv der Kategorie Entwicklung

Feature Detection, my ass!

Ein Tag wie jeder andere “im IE funktioniert die Anwendung nicht mehr, nichts lädt mehr”. Man ist es ja eigentlich gewohnt, zumal es sich hierbei ja um eine umfangreiche RIA in Ext JS handelt. Trotz laufender JSLint-Überwachung für Fehler wie trailing comma mogelt sich immer mal wieder ein Problem herein. Ungewöhnlich war diesmal allerdings, dass bei der weiteren Untersuchung auffiel, dass das Problem auf einem IE9 auftrat (Hut ab vor Microsoft, IE9 ist eigentlich sehr gut). Ein Gegencheck in der VM mit IE6 und IE8 zeigte das Verhalten nicht. Auch die Prüfung auf einem realen Windows 7-System mit IE9 war problemlos.

Nun ja, genauer gesagt, das Problem trat auf einem (Test-) Windows Server 2008 mit IE9 auf. Aha..?

Nach einem schnellen Aufschalten auf den Testserver und dem Aufruf der Debugging-Tools offenbarte, dass der IE9 an genau einer Stelle auf Nase flog: aAudio=”Audio”in window?new Audio(“”):{} Im Prinzip ein ganz normale Art und Weise, eine Feature Detection durchzuführen. Für diejenigen, die nicht in JavaScript firm sind: Die Variable aAudio wird, falls im Objekt window eine Eigenschaft Audio vorhanden ist, mit einer neuen Instanz eben dieser Audio-Klasse belegt, andernfalls mit einem leeren Objekt (hilfreich ist hierbei zu wissen, dass window der Standardscope ist).

Das heißt also, nur wenn der Browser die HTML5-API “Audio” kann, wird auch eine Instanz davon erstellt. Weiter später wird im Script auf eine spezielle Eigenschaft/Methode dieser Variable geprüft: Damit lässt sich dann feststellen, ob HTMl5-Audio implementiert wird (hier: canPlay). Das gesamte Problem gilt natürlich auch analog für die HTML5-API des Tags video.

Eine Exception “Not implemented”, die nicht aus der Anwendung kam, nicht aus dem Framework und auch nicht aus dem Plugin, welches im Endeffekt diese Zeile beinhaltet, wurde geschmissen und stoppte die gesamte Anwendung bzw. das verursachende Script. Und genau diese Zeile war die Feature Detection für HTML5-Audio in einer Sammlung von Flash/Video/Audio-Funktionalitäten.

Lange Rede, kurzer Sinn: Der Internet Explorer 9 hat u.a. die HTML5-APIs für Audio und Video implementiert — eigentlich. Nicht jedoch auf einem Windows Server 2008, denn dort wird dafür ein optional zu installierendes Feature — so called Desktop Experience Feature — des Betriebssystems benötigt. Und damit das ganze auch richtig gegen die Wand fahren kann und muss, tut man (der Browser) erstmal so, als würde er HTML5-Audio anbieten können (API window.Audio gibt es!), schmeißt dann aber eine Exception, wenn man das Objekt tatsächlich nutzt.

Tatsächlich ist die einzige Lösung, dies mit einem billigen try-catch zu lösen. Eine Post-Recherche ergab, die Macher von Feature-Detection-Framework Modernizr haben das genauso gemacht.

Es hat sich in den Jahren nicht viel geändert: Sonderwürste für den IE stehen weiterhin an.

Hintergrund – oder: Die Sache selbst

Eine granulare Feature Detection ist heutzutage bei modernen Webanwendungen oder besser -frameworks quasi Pflicht. Hat man früher noch eine grobe Browser Detection (Browserhersteller und -version) vorgenommen, um daraus herzuleiten, ob Feature X unterstützt wird, so prüft man heute besser auf dieses Feature direkt. Erstens sind die Features unzählig mehr geworden, zum anderen benötigt das das “Wissen”, welcher Browser welches Feature kann. Außerdem ist es mit den modernen Workingdraft/Livingstandard-Trends quasi unmöglich geworden, Features zu bestimmten Browsern zuzuordnen. Chrome und Firefox aktualisieren sich mittlerweile  mehr oder weniger selbstständig; und überhaupt ist die Geschwindigkeit der Browserentwicklungen so schnell geworden, dass eine Browser-basierte Herleitung von Feature-Verfügbarkeiten schwierig wird. Ein ganz gutes Beispiel ist HTML5 — denn HTML5 ist als Standard weder komplett fertig, noch in einem/jedem Browser gleichwertig implementiert.

In der Regel läuft eine Feature-Detection wie folgt ab: Man prüft, ob die Voraussetzungen bspw. für einen Tag oder eine DOM-API-Funktion vorhanden ist und ermittelt gegebenenfalls noch weitere Ausprägungen.

Beispiele

  • navigator.geolocation ist nicht undefined, wenn der Browser die Geolocation-API kann.
  • document.createElement(‘canvas’).getContext ist nicht undefined, wenn der Browser Canvas-Tags unterstützt und damit Canvas zeichnen kann.
  • document.createElement(‘audio’).canPlay ist nicht undefined, wenn der Browser HTML5-Audio-Tags unterstützt und demnach HTML5-Audio abspielen kann.

Weitere Links

CSS3: SASS, Compass und PIE

Nach einer längeren Pause gibt es heute ein paar kurze Notizen zum Thema CSS3 und Internet Explorer.

Aber der Reihe nach.

SASS

So schön CSS ist, so alt und stupide ist der Spielraum zum entwickeln und konzipieren. CSS kann keine Vererbung, keine Strukturierungen, keine Kapselungen bzw. Mixins. Das einzige, was CSS kann: eine Aneinanderreihung von Tags, bspw. #element ul > li

Mit SASS ist das alles möglich. Es sind hierarchische Strukturen möglich, man kann Mixins (Kurzanweisungen für ein Set von Funktionen/Attributen, Stichwort: Browser-Cross-Features) oder endlich Variablen im CSS nutzen. Der Code-Syntax ist dabei eine Erweiterung von CSS3* (d.h. CSS selber ist weiterhin möglich) und wird üblicherweise in .scss-Dateien abgelegt. Jedes öffentlich zugängliche Stylesheet muss dann in ein “normales” CSS umgeschrieben werden, das erledigt SASS wahlweise auf Knopfdruck oder mit einem Watchdog (Befehl watch). Mit letzterem geschieht die Generierung on-the-fly, d.h. man kann zwischen SCSS und Browser genauso wechseln wie beim guten alten CSS.

* So lange man natürlich kein CSS3 nutzt, ist man auch CSS2 kompatibel.

Compass

Als Erweiterung für SASS gedacht, erweitert Compass das Funktionsspektrum um einige hilfreiche CSS(3)-Features. Die Referenz zeigt stets den aktuellen Stand und auf GitHub sind die Sourcen offen zugänglich. Um beispielsweise die mittlerweile zahlreichen (6!) vendor-spezifischen Anweisungen eines linearen Gradienten (hier: weiß zu schwarz) zu erzeugen, reicht das simple Mixin linear-gradient(color-stops(white, black)).

Nett: Als Pull bekam das Projekt auch schließlich einen experimentellen Hack, damit Gradienten out-of-the-box im IE6-8 funktionieren. So funktioniert Open Source.

PIE

CSS3PIE ist eine winzige Library, die in Form einer HTC (so genannte HTML Components, eine microsoft-spezifische JavaScript-Datei) weitestgehend die CSS3-Features border-radius, box-shadow und linear-gradient bereitstellt.

In Compass ist PIE optional verfügbar. Mit der Ergänzung einer Zeile SCSS-Code ist damit ein runder, schattierter Button real.

Beispiele

Da war noch was…

CSS3PIE wurde dieses Jahr ein Teil von Sencha. Da ist es nicht verwunderlich, dass Sencha selber für ihren Theme-Generator (Bestandteil der Sencha SDK Tools)  für ExtJS/SenchaTouch auf Compass, PhantomJS u.a. setzt.

Autodiscovery der Searchengine in Google Chrome + OpenSearch

Unter dem Titel “Suche in Chrome per type=search anmelden” fand ich die Tage einen netten Hinweis von Markus. Es geht darum, dass der Chrome automatisch Suchmaschinen hinzufügt. Auch ich dachte bisher, dass Google einfach nur eine gute Liste eingepflegt hat (bspw. mit amazon.de), aber mitnichten: Die Amazon.de-Suchmaschine ist bei mir nur deswegen drin, weil ich die Amazonseite besucht habe und Chrome dort eine Suchmaschine “gefunden” hat. Aber warum gerade Amazon.de? Warum dict.cc?

Markus erster Hinweis war, dass es mit dem neuen HTML-Inputfeld-Typ “search” zusammenhängt. Ein anderer Kommentator brachte noch OpenSearch ins Spiel.. und als meine ersten Tests überhaupt nicht fruchteten, setzte ich mich mal genauer an das Thema heran. Den Großteil des Ergebnisses habe ich bereits in Markus’ Beitrag als Kommentar geschrieben.

OpenSearch

Beginnen wir mit OpenSearch: Dies ist ein — noch nicht standardisierter — Entwurf für ein Dokument, welches die Metainformationen einer Suchmaschine beschreibt: Name, Beschreibung, URL-Pattern, Sprache, usw.

Ein solches OSDD (OpenSearch Description Document) sieht dabei vereinfacht und exemplarisch so aus:

<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Example</ShortName>
<Description>My example search engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image height="16" width="16" type="image/x-icon">http://example.org/favicon.ico</Image>
<Url type="text/html" template="http://example.org/index.html#search={searchTerms}"/>
</OpenSearchDescription>

Damit ein Browser die OSDD auch finden kann, muss sie innerhalb des HTML-Heads als Metainformation eingefügt werden:

<link title="Example" type="application/opensearchdescription+xml" rel="search" href="http://example.org/opensearch.xml">

Voilá! Ein Firefox findet damit bereits die Suchmaschine und bietet, wenn man auf den kleinen Pfeil unter dem aktuellen Suchmaschinen-Icon klickt, das Hinzufügen der neuen an. Das gilt im Übrigen auch für den Internet Explorer 8. Ab FF 2 und IE7 kann zudem explizit auf eine solche OSDD per JavaScript verwiesen werden:

window.external.AddSearchProvider("http://example.org/opensearch.xml");

Autodiscovery Mode in Chrome

Google Chrome erkennt auch diese OSDD, stellt aber zur Zeit keine geeignete UI wie etwa Firefox oder Internet Explorer zur Verfügung. Vielmehr werden hier die Suchmaschinen automatisch erkannt, eingetragen und über die kombinierte Adress- und Suchleiste zur Verfügung gestellt.

Der Trigger für den Autodiscovery Mode ist dabei zwar ein INPUT-Field mit dem Typ “search” oder wahlweise mit dem Typ “text” und dem Namen “s”. Der eigentliche Clou Witz an der Sache ist jedoch, dass Chrome dieses HTML-Element explizit auf der Startseite der Domain erwartet. Es muss also auf der example.org/index.html oder example.org/startseite.jsp auftauchen. Funktioniert die OSDD prinzipiell von allen Seiten aus, so funktioniert der Autodiscovery Mode in keinem (virtuellen) Unterverzeichnis.

Interessanterweise spielt es aber keine Rolle, wie lange die Seite angezeigt wird. Liegt also bspw. eine example.org/index.html vor, die einen Meta-Refresh nach 0 Sekunden (sprich: sofort) macht, dann funktioniert der Autodiscovery Mode dennoch. Zusätzlich kann man das Formular auch unsichtbar machen, dies hat keine Auswirkungen.

Im Grunde reicht also dieses Schnippselchen, sofern man keine adäquate oder sinnvolle Startseite hat:

<form style="display: none;"><input type="search" name="s" /></form>

Die eigentliche Konfiguration holt sich Chrome wiederum aus der OSDD.

Drawbacks

  • Apple Safari scheint bis dato keinerlei native Unterstützung für OSDD oder vergleichbares zu haben. Am nächsten kommt das Plugin Inquisitor.
  • Internet Explorer 9 scheint auf den ersten Blick keine Unterstützung für OSDD zu haben. Evtl. habe ich es aber auch noch nicht gefunden?
  • Opera hat auch keine Unterstützung.
  • Spezialfall: Im Verbund mit einem Suchparameter via Hash (Ajax/RIAs) wird bei Firefox nur der location.hash ausgetauscht (die Applikation bleibt). Google hingegen veranlasst einen kompletten neuen Request auf location.href, womit die gesamte Applikation neu geladen wird.

tl;dr: in a nutshell und lost facts

  • Die opensearch.xml stellt Metainformationen für eine Suchmaschine bereit und muss auf der HTML-Seite verlinkt werden.
  • Für den Autodiscovery Mode von Chrome muss auf einer Seite im Domain-Root ein INPUT-Feld “type=search” oder “name=s” vorhanden sein.
  • Das Formular respektive Feld muss weder für den Benutzer sichtbar sein (CSS), noch lange angezeigt werden (Redirect nach 0 Sekunden).
  • Manuelles Hinzufügen über eine API in nahezu allen aktuellen Browsern möglich.
  • Es können mehrere Suchmaschinen je Seite verwaltet werden (betrifft OSDD).

Links

Update: Martin Thoma hat einen englischen Artikel (http://martin-thoma.com/search-engine-autodiscovery/) geschrieben, der auf diesem basiert. Ergänzende Informationen sind zum Beispiel die aktualisierten Kompatibilitäten (IE7).

IE9 – 99% von was?

IE9 HTML5 Tests 99%… Bogus

IE9 has none of them, nor does it have any validation, or ranges or the new types… and worst of all for my Uploader widget, still, after all these years, does not support multiple file uploads. So the 99% isn’t 99% of all HTML5 features — it’s 99% of the tests that IE implemented. This is like writing your own test and bragging that you passed it.

Ein (weiterer) schöner Artikel über den Bullshit Microsofts. Obwohl der IE9 grundlegende und zahlreiche neue Features von HTML5 implementiert, fehlen im Vergleich zu den anderen Browsern noch etliche.. abgesehen davon, das auch diese noch nicht alles implementiert haben.

Insofern ist die Aussage einer 99% HTML5 (Test)-Abdeckung genauso viel aussagekräftig, wie das Entwickeln und Nutzen von 99 Testfällen bei Hunderten Fallunterscheidungen.

Wetten, dass demnächst etliche Zeitungen, Magazine oder gar Blogs von der überragenden HTML5-Kompatibilität der IE9 berichten werden?

Eine Jar (OJDBC) nachträglich in die Ziel-Jar integrieren

Für das visualDependencies-Projekt stand ich eben vor dem Problem, dass zur Laufzeit ein Oracle-JDBC-Treiber benötigt wird. Leider kann man ihn jedoch nicht als Abhängigkeit konfigurieren, da zum einen das Projekt unter der GPL läuft, und zum anderen es überhaupt keinen offiziellen Weg dafür gibt. Für den eigenen Buildprozess kann man selbstverständlich ein lokales Repository nutzen, das Artefakt lokal deployen bzw. den Buildserver entsprechend konfigurieren.

Da jedoch das Projekt im Form des Sourcecodes “für alle” erreichbar sein soll, fallen diese Optionen zumindest für diese Situationen weg. Es muss also eine Möglichkeit geben, den OJDBC-Treiber nachträglich in das fertige Applikations-Jar zu integrieren. Und ja, das ist eigentlich sehr trivial.

Im folgenden Ant-Script werden sowohl die Applikations-Jar (visualDependencies.one-jar.jar) als auch der JDBC-Treiber (ojdbc14.jar) in der Konfiguration vorbelegt. Selbstverständlich kann man alle Properties überschreiben bzw. das Script entsprechend anpassen.

Die wichtigen Teile sind: Das Ant-Jar-Command muss den Zusatz “update” erhalten, denn die Ziel-Jar soll nicht ersetzt werden. Außerdem muss ein Fileset mit einer Verzeichnisstruktur angegeben werden, da die Treiber-Jar innerhalb der Ziel-Jar im Verzeichnis lib liegen muss (Struktur einer One-Jar). Das war’s.

Hinweis: Das Ant-File ist für den Gebrauch in einer Maven-Umgebung konfiguriert (basedir=../../../ entspricht dem Root-Verzeichnis bei der Annahme, dass Script unter src/main/scripts/ liegt).

<?xml version="1.0" encoding="UTF-8"?>
<project name="visualDependencies" default="help" basedir="../../../">
	<!-- The path of the actual artifact (project name), without the file suffix. -->
	<property name="project.name" value="visualDependencies.one-jar" />
	<!-- The path of the ojdbc driver, without the file suffix. -->
	<property name="ojdbc.name" value="ojdbc14" />
	<!-- DO NOT CHANGE THIS LINES UNLESS YOU KNOW WHAT YOU DO! -->
	<property name="project.jar" value="${project.name}.jar" />
	<property name="ojdbc.jar" value="${ojdbc.name}.jar" />
	<!-- Set actual paths of artifacts. -->
	<property name="application.path" location="${basedir}/target/${project.jar}" />
	<property name="ojdbc.parent.path" location="${basedir}/oracle" />
	<property name="ojdbc.path" location="${ojdbc.parent.path}/lib/${ojdbc.jar}" />
	<!-- Shows help (default target) -->
	<target name="help">
		<echo message="See http://www.knallisworld.de/blog/2010/11/23/eine-jar-ojdbc-nachtraglich-in-die-ziel-jar-integrieren/" />
		<echo message="Usage: attachOJDBC" />
	</target>
	<!-- Checks if the artifacts are available. Throws exceptions if they not exist. -->
	<target name="checkDependencies">
		<available file="${application.path}" property="application.exists" />
		<available file="${ojdbc.path}" property="ojdbc.exists" />
		<fail unless="application.exists" message="The application file (${application.path}) does not exist." />
		<fail unless="ojdbc.exists" message="The ojdbc file (${ojdbc.path}) does not exist." />
	</target>
	<!-- Integrates all files of ojdbc.parent.path into the target jar. -->
	<target name="attachOJDBC" depends="checkDependencies">
		<jar update="true" destfile="${application.path}">
			<fileset dir="${ojdbc.parent.path}" />
		</jar>
	</target>
</project>

ExtJS 4 Updates

Ich bin gespannt.

SenchaCon

Sagte ich letztens, Sencha würde sich gut entwickeln? Die hauseigene SenchaConference ist gestartet, und die Firma hat erstmal kräftig auf den Putz gehauen. Es gibt nicht nur die finale Version SenchaTouch (quasi das ExtJS für mobile Plattformen inkl. UI), sondern direkt ein passendes Ext Designer Update zum entwickeln von Touch Anwendungen. Und auch einen Marktplatz für Entwickler/Kunden — den so genannten SenchaDev-Bereich. Ob der was taugen wird, das wird man später sehen.

Im Einzelnen: Ausgewählte Informationen per Copy-Paste aus dem @tdgi-Staccato:

  1. #SenchaCon ext designer to be moved to CSS, icon, template, theme and event mangers!
  2. #SenchaCon Web services: font, data image resizing and more, all from #senchainc.
  3. #SenchaCon #ExtJS 4has a brand new layout engine. Same API.
  4. #SenchaCon #ExtJS 4 has 4000 unit tests!
  5. #SenchaCon #ExtJS 4 is UI tested by a new tool called VisualQA. Awesome!
  6. #SenchaCon #ExtJS 4 most useful documentation ever. All classes documented.
  7. #SenchaCon #ExtJS 4 examples integrated into docs.
  8. #SenchaCon #ExtJS 4 upgrade guide available!
  9. #SenchaCon #ExtJS 4 API improvements, clears cruft. Standardizing naming, funcs conventions.
  10. #SenchaCon #ExtJS 4 new charting package. Bye bye flash!
  11. #SenchaCon #ExtJS 4: building complex forms are a lot easier!
  12. #SenchaCon #ExtJS 4: Record becomes Model. More complex data manipulation now possible.
  13. #SenchaCon #ExtJS 4: data associations are now going to empower a new level of application development!
  14. #SenchaCon #ExtJS 4: local and session storage APIs available.
  15. #SenchaCon Sencha Command is a way to start your apps.
  16. #SenchaCon #ExtJS 4: sencha command is automated by the model generator.
  17. #SenchaCon JSBuilder is tied into Sencha Command.
  18. #SenchaCon #ExtJS 4: that was beta in six weeks. Final is feb 28, 2011
  19. #SenchaCon #ExtJS 4: VisualQA will be open to end debs, release date unknown. Bye bye selenium, hellos new world of testing RIAs!

Eine neue Layoutengine hatte man bereits im Vorfeld leicht angekündigt; die Model-Neuerfindung ist auch nicht überraschend, da es bereits in SenchaTouch Einzug fand. Model Associations sind genial. Der Wegfall von Flash im Charting-Paket sollte auch nicht verwundern, schließlich hat man jetzt bereits zwei alternative Know-Hows in Form von Frameworks eingekauft.

Alles in allem hört sich das alles super an: Mehr UI-Testing ist speziell in einer RIA sehr schwierig und könnte durch geeignetes Framework-Hilfstool sicherlich um einiges besser machbar werden. Was sich genau hinter Sencha Command verbirgt bzw. welche Power es genau hat, wird man sehen.

Sencha [Update]

Es ist noch nicht so lange her, da schlossen sich die Firmen bzw. Entwickler von Ext JS, Raphaël und jQTouch zusammen und bildeten die Firma Sencha Inc. bzw. die Sencha Labs Foundation. Ext JS entwickelt ein gleichnamiges RIA-JavaScript-Framework sowie eine eigene Schnittstelle zu GWT (Ext GWT), während Raphaël ein JavaScript-Framework ist, welches mit generiertem SVG (auch IE-kompatibel) Charts und Graphen erzeugt. Mit Hilfe des jQTouch-Framework kann man Webanwendungen bauen, die nahezu wie native iPhone-Apps aussehen und sich auch ähnlich bedienen lassen.

Seitdem hat sich vieles getan: Sencha hat SenchTouch vorgestellt, welches aktuell als RC auf Version 1.0 zusteuert. Ähnlich wie jQTouch lässt sich mit diesem RIA-ähnlichen-JavaScript-Framework (stark verwandter Unterbau wie Ext JS) eine Applikation für mobile Endgeräte (typischerweise iPads und iPhones) bauen — inklusive mit den entsprechenden speziellen, optimierten UI-Elementen. Außerdem gibt es den Ext Designer: eine eigene grafische Oberfläche zum Entwickeln von Ext JS Komponenten. Super praktisch, und im professionellen Einsatz sicher sein Geld wert.

Dazugekommen sind außerdem:

  • Connect: ein node.js basierter Applicationserver
  • JavaScript InfoVis Toolkit: Ein JavaScript-Framework zur Darstellung von Graphen, etwa Bäumen oder anderer Strukturdiagramme.
  • CSS3PIE: macht neue CSS3-Attribute auch für die IE6-8 über JavaScript verfügbar.
  • Sencha Animator (Beta): Animationen erstellen mit Ausgabemodus “HTML5+CSS3″
  • RemoteJS: macht das (Remote-)Debuggen “on device” für Android-Entwickler einfacher

… und wahrscheinlich noch ein paar schöne Dinge. Wie etwa eine eigene Messe nächste Woche, die SenchaCon. Leider ist die San Francisco. :(

Der Sencha Verbund entwickelt sich so langsam zu einer richtig guten Sache, die auch schön viel in die Community bringt.

Update (01.12.2010): tinySrc ist jetzt auch dabei.

Links

{DEVELOPERS SHAME DAY}

Cem hat kürzlich den Developers Shame Day ins Leben gerufen.

Als Stichtag würde ich den 3.11.2010 vorschlagen. Ich stelle mir vor, dass an diesem Tag alle Entwickler, die ein Blog oder eine Seite betreiben, ein kleines Stück Code präsentieren, dass aus heutiger (oder vielleicht auch damaliger) Sicht total hirnverbrannt ist. Ein Stück Code, dass uns selbst die Schamröte ins Gesicht steigen lässt. Dabei ist egal, ob es sich um PHP, JavaScript, CSS, HTML, Java, C oder sonst etwas handelt. Es muss nur von euch sein und es darf nicht verändert werden (umeventuell doch als total verrückter Hund dazustehen ). Ein kleiner erläuternder Text sollte natürlich auch nicht fehlen.

Und das ist mein Beitrag, wohl einer meiner ersten Gehversuche in PHP. Der Quellcode entstammt einer Datei namens “functions.inc.php” [sic!]. Und es scheint so ;) , also wäre es eine größere Anwendung gewesen, ich habe jedoch echt keine Ahnung mehr welche — vielleicht die erste PHP-Homepage in Eigenentwicklung? Die Datei hatte sich irgendwie auf meine “Informatik-Diskette” [sic!] (Oberstufenkurs) verirrt, von der ich tatsächlich noch ein Abbild hatte. Der Rest der Programmiersünden muss entweder (m)einen Backup-Aufräumaktionen oder einem vor einigen Jahren aufgetreten Backupmediumfehler zum Opfen gefallen sein. Zu meiner Verteidigung kann ich wohl nur sagen hoffen, dass dies einer erste Spielversion war und nie “produktiv” wurde.

Listing

Bitte in voller Länge genießen. Jede Zeile ist ein Genuss. *ankoppfass*

Unverändert, nur Benutzername/Passwort habe ich ausgeixt.

Datei: functions.inc.php (von 2002 oder 2003)

<?php
//conf.inc.php
//please don't change this file manually - go to your admin-area to change settings!!!
$listname="Meine Linkliste";
$listname2="Downloads";
$linkwidth="100%";
$addpagewidth="50%";
$catorder="name";
$incatsort="Hits";
$perpage="5";
$max_search="10";
$adminpw="a";
$max_desc_leng="500";
$html="ON";
$language="german.lang";
$timeformat="1";
 @include("global/$language"); // language-file
 @include("../global/$language"); // language-file
//connect.inc.php
// DON'T CHANGE THIS FILE MANUALLY - EDIT ONLY VIA ADMIN-AREA
$server="localhost";
$user="xxx";
$pass="xxx";
$mydb="xxx";
$db_prefix="xl_";
$db_prefix2="dl_";
function JPDiv ($a,$b) {
  $i=0;
  $j=0;
  while($j==0) {
    if(($a/($b*($i+1)))>1) {
      $i++;
    } else {
      $j = 1;
    }
  }
return $i;
}
function JPDatumZeit ($a) {
  $JPTag = array("Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag");
  $JPMonat = array("Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember");
  $JPDatumTag = $JPTag[date("w",$a)];
  $JPDatumMonat = $JPMonat[date("n",$a)-1];
  $JPDatumJahr = date("Y",$a);
  $JPZeit = date("H:i:s",$a);
  $b = $JPDatumTag . ", " . date("j") . ". " . $JPDatumMonat . " " . $JPDatumJahr . " [" . $JPZeit . "]";
return $b;
}
function JPDatumZeit2 ($a) {
  $JPDatumJahr = date("Y",$a);
  $JPZeit = date("H:i:s",$a);
  $b = date("j") . "." . date("w",$a)+1 . "." . $JPDatumJahr . " [" . $JPZeit . "]";
return $b;
}
class my_zugriff{
//Variablen für Zugangsdaten
var $user="xxx";		//Benutzername für den MySQL-Zugang
var $password="xxx";		//Passwort
var $host="localhost";	//Name (IP-Adr.) des Rechners mit MySQL
var $dbname="xxx"; 	//Name der Datenbank
//Weitere Variablen
var $db_verbindung=false; //Speichert die Verbindungskennung
var $sql_result=false; //Speichert die Kennung eines ausgewerteten SQL-Befehls
//Konstruktor definieren
function my_zugriff(){
   //Funktion verbinden wird bei Aufruf der Klasse ausgeführt
	 $this->verbinden();
}
//Falls keine Verbindung besteht,
//Verbindung aufbauen und Datenbank als Standard definieren
function verbinden(){
if ($this->db_verbindung==false){
   $this->db_verbindung = @mysql_connect($this->host, $this->user, $this->password);
   if(empty($this->db_verbindung)){
      $this->fehler("Beim Verbinden");
   }
   $auswahl = @mysql_select_db($this->dbname, $this->db_verbindung);
   if(empty ($auswahl)){
      $this->fehler("Beim Ausw&auml;hlen der DB");
   }
   return $this->db_verbindung;
}
}
//Gibt Fehlermeldung aus und beendet das Skript
function fehler($fehlerpunkt){
    echo $fehlerpunkt . " ist ein Fehler aufgetreten!<br>";
		echo mysql_error() . "<br>"; //Fehlerbezeichnung
		echo mysql_errno();	 	 		//Fehlernummer
		echo "</body></html>";		//Html-Tags schließen
		exit;
}
//SQL-Befehl ausführen
function sql_befehl($sql){
$this->sql_result = @mysql_query($sql, $this->db_verbindung);
if (empty($this->sql_result)){
	 $this->fehler("Beim Senden der Abfrage");
}
return $this->sql_result;
}
//Falls zuvor ein SQL-Befehl ausgeführt wurde,
//wird hier das Array mit den Datensätzen ausgegeben
function sql_daten(){
if(!empty($this->sql_result)){
		$sql_array=@mysql_fetch_array($this->sql_result);
		return $sql_array;
}else{
		$this->fehler("Beim Ausgeben der Datens&auml;tze");
}
}
//eig. Fkt
function sql_num_rows($sql){
$this->sql_befehl($sql);
$rows = MYSQL_NUM_ROWS($this->sql_result);
return $rows;
}
}
$db=new my_zugriff();
$db->sql_befehl("SELECT elem_string FROM elem_global WHERE elem_name='JPmyVersion'");
$myVersion_now = $db->sql_daten();
 $JPmyVersion = $myVersion_now[0];
?>

Selbstreflexion

  • Struktur: globale Variablen
  • Struktur/Aufbau:Â als Script noch okay, aber als Include? Oweh..
  • Includes mittendrin
  • Variabel- und Funktionsnamen multilingual
  • Inhalt der Funktionen..
  • kein gängiger Codestyle (ja, der Blog zeigt’s richtig an)
  • Inline-SQL(!)

Kurzum: What the hell…?

Weitere via Google oder Twitter oder Facebook.

Apples Java-Support

Nur, falls das irgendjemand durch die ganzen Blogs, Techs & Co missverstanden hat:

The runtime provided by Apple (effectively everything in the .jdk bundle) is deprecated, but will continue to be supported throughout the service lifetimes of 10.5 and 10.6. The JavaVM.framework and it’s sub-frameworks are still supported API.

(Mike Swingler, Java Engineering, Apple Inc.) Quelle

Die Runtime ist “Java”, während das Framework quasi nur eine Schnittstelle ist. Und diese Schnittstelle ist *nicht* deprecated. Ganz im Gegenteil, sie wurde im letzten Update sogar aufgewertet (zugegeben, die Möglichkeit mehrere unterschiedlicher JVMs ist nur auf OSX ein Novum).