XHTML SVG CSS PHP

Dr. O. Hoffmann

CSS-Layout

Immer lernt der Kluge vom Dummen mehr als der Dumme vom Klugen.
Peter Rosegger

browser-Weiche mit PHP

Wegen der unterschiedlichen Fähigkeiten in der Interpretation von XHTML und CSS bei verschiedenen Darstellungsprogrammen besteht oft der Wunsch, Stilvorlagen oder gar XHTML-Elemente an diese Fähigkeiten anzupassen. Der ideale und gerade Weg dabei ist nicht zu bestimmen, welches Darstellungsprogramm gerade verwendet wird, sondern welche Fähigkeiten es wirklich hat. Teilweise können Mängel durch geschickte Konstruktionen abgefangen werden, ohne überhaupt zu wissen, ob das Programm einen Fehler hat oder um welches Programm es sich handelt.
Ein anders gelagertes Problem liegt indessen vor, wenn man nur abhängig von der Größe des Darstellungsbereiches eine andere Stilvorlage anbieten will, dies geht recht einfach mit einem Modul von CSS 3 für Medienanfragen (englisch: media queries).

Hinsichtlich der Fehler und Mängel soll ein Darstellungsprogramm CSS-Eigenschaften komplett ignorieren, wenn es sie nicht beherrscht, statt zu improvisieren. Das kann dann zu Konstruktionen wie folgenden führen:


.irgendwas
{
position: absolute;
position: fixed;
top: 1em;
left: 1em;
}

Dies bedeutet, daß ein Programm, welches position: fixed nicht beherrscht, position: absolute verwenden muß. So weit die Theorie. Praktisch hat in diesem Falle der MSIE in alten Versionen einen Fehler, so daß er position: static verwendet, womit diese Idee bei diesem Programm eher ausscheidet. Oft ist diese Methode ansonsten aber nützlicher als eine browser-Weiche, denn bei Darstellungsprogrammen wie Opera, Konqueror und den Geckos werden im Gegensatz zum MSIE derartige Fehler recht schnell behoben, wodurch es wenig effektiv ist, für jede Version solcher Programme andere Stilvorlagen anzubieten.

Recht vielversprechend ist in dem Zusammenhang auch die Untersuchung mit PHP folgender Information des Darstellungsprogrammes an den server:
$_SERVER["HTTP_ACCEPT"]
Dort bekennt sich das Darstellungsprogramm zu Inhaltstypen (ehemals auch MIME-Typen genannt) von Formaten, die es interpretieren kann. Oft ist die Liste allerdings nicht vollständig und die angegebene Gewichtung ist nicht zwangsläufig korreliert mit der Qualität der Unterstützung des Formates, sondern wohl eher mit der Vorliebe der Entwickler.
Relevant ist dies etwa, um zu entscheiden, ob ein Programm XHTML versteht oder zumindest kennt oder nur HTML. Auch kann es sinnvoll sein festzustellen, ob das Programm ein PNG-Bild oder nur ein GIF-Bild bekommen soll. Leider listen einige Programme in dieser Variable noch nicht alle Inhaltstypen auf, die sie interpretieren können, aber es kann schon mal eine wertvolle Ergänzung für den Autor eines Projektes sein, die hilfreicher ist als eine browser-Weiche. Gern wird auch das vertrauenserweckende */* verwendet, was wohl so viel heißen soll, daß das Programm alles verarbeiten kann. Das ist natürlich eine freche Lüge und sollte ignoriert werden.

Ist die Entwicklung eines Darstellungsprogrammes abgeschlossen, wie bei Netscape 4, oder stagniert über viele Jahre wie beim MSIE 5/6, so kann es sich lohnen zu versuchen, dieses Programm zu identifizieren, um dessen Fehler zu kompensieren, um dem Nutzer eines solchen Programmes die angebotenen Inhalte zugänglich zu halten.
Schauen wir uns mal ein einfaches Beispiel für solch eine einfache PHP-Weiche an:

<?php 
# Fehlerbericht anschalten:
error_reporting(E_ALL);

# user-agent ermitteln:
if(isset($_SERVER['HTTP_USER_AGENT'])) {
  $agent=$_SERVER['HTTP_USER_AGENT'];
} else {
  $agent="noagent";
}

# Gucken, ob der sich fuer mozilla4 kompatibel haelt,
# also schon aelteren Datums ist.
# Darunter fallen vor allem netscape4, msie5/6,
# aber auch neuere browser, falls die sich als
# netscape4 oder msie tarnen.
$ok=substr_count(substr($agent, 0, 15), "Mozilla/4.");
if($ok != "0") {
   # Sparversion fuer alte browser
$typ="0";
} else {
   # das ist der Stil fuer normale browser, 
   # wenn keine manuelle Auswahl erfolgt
$typ="1";
}
# maximale Anzahl der Stile
# vorgeben (von 0 bis stylemax):
$stylemax=3;

# Manuelle Anwahl des Stils:
# Ist nur fair, wenn der Stil auch manuell anwaehlbar ist -
# dazu ist dann ein entsprechender Verweis auf die Seite
# zu setzen...
if(isset($_GET['style'])) {
  $type=$_GET['style'];
  # Groesse begrenzen:
  if (($type >= 0) AND ($type <=$stylemax)) {
    # die Anzahl der verfuegbaren Stile ist natuerlich
    # anzupassen
    $typ=$type;
  } else {
    # bei sonstigen Angaben wird einfach eine leere
    # Datei als style sheet verwendet
    $typ="no";
  } 
}
?>

Im Bereich head des Dokumentes wird dann ein entsprechender Stil abhängig von der Variable $typ mit dem Element link auf eine entsprechende CSS-Datei eingebunden. Wenn $typ = 0, so sollte also ein Stil für alte Programme angeboten werden, sofern nicht manuell ein Stil ausgewählt wird. Für $typ = 1 sollte ein vorausgewählter Stil angeboten werden, sofern keiner manuell ausgewählt worden ist.
Falls $typ = no, so sollte eine leere CSS-Datei oder gar kein link zu einer CSS-Datei ausgegeben werden.

Um genauer auf browser-Weichen in dem Beispiel zum Layout mit CSS und PHP einzugehen, sei hier darauf hingewiesen, daß die eingebaute Weiche den user-agent des Darstellungsprogrammes ausließt. Die Weiche sollte übrigens nur auf das Layout wirken, nicht auf den Inhalt. Es wäre eine bodenlose Frechheit, eine solche Weiche zu nutzen, um anderen Inhalt anzuzeigen, das wäre ein versteckter Manipulationsversuch am Nutzer, keine Hilfestellung für alte Programme. Die Angabe des user-agent ist freiwillig und kann teilweise vom Nutzer des Darstellungsprogrammes oder vom verwendeten Betriebssystem manipuliert werden. Bei der vorhandenen Weiche werden Darstellungsprogramme der vierten Generation separiert. Typisch für diese ist, daß der user-agent beginnt mit der Bezeichnung 'Mozilla/4.'.
Ältere Opera-Programme tarnen sich ebenfalls mit dieser Bezeichnung, wie auch msie 5 oder 6.
Wenn sich neue Programme wie Opera7/8/9 oder auch Konqueror jedoch als Mozilla4 tarnen, bekommen sie auch dessen Stilvorlage zu sehen, das ist nur fair, wenn wer sich als ein anderes Programm tarnt, kann nicht erwarten, daß er eine andere Behandlung bekommt. Natürlich kann auch das durch eine verfeinerte Analyse noch optimiert werden. Wegen der potentiellen Beliebigkeit der Angabe ist es aber schlichtweg unmöglich, über diesen Parameter wirklich spezifisch zu selektieren.
Weder das 'Mozilla/4.' reicht also zur Identifizierung aus, noch das typische MSIE für den microsoft internet explorer.
Auch nicht überall, wo Gecko im user-agent steht, ist der auch wirklich drin - siehe Safari und Konqueror3.2. Hinsichtlich CSS muß man allerdings die verschiedenen echten Gecko-Programme gar nicht namentlich unterscheiden, sondern eher nach ihrer Version (rev:.. , bei neueren Varianten ist die Version auch direkt angegeben).
Gemäß der Philosophie der Konqueror-Entwickler ist es das Ziel, daß sich dieses Programm letztlich gar nicht mehr von anderen Darstellungsprogrammen unterscheiden läßt. Demgemäß lassen sich an diesem Programm exakt die user-agents anderer Anbieter einstellen. Wegen ständiger Diskriminierungen der Nutzer hat auch Opera ab der Version 9 eine Möglichkeit eingebaut, sich komplett für einzelne Seiten als ein anderes Programm zu tarnen, ist somit auch durch aufwendige Analysen nicht eindeutig identifizierbar. Das ist im Grunde das Ende aller browser-Weichen, die den user-agent auswerten. Im Grunde ist das auch gut so und ohnehin wie oben angedeutet besser, über die Fähigkeiten zu separieren als über den Namen.

Für alte Darstellungsprogramme der vierten Generation kann es dennoch sinnvoll sein, zu selektieren, weil man deren Fähigkeiten im Grunde kennt, weil sie nicht mehr verändert werden, also auch keine falschen Angaben für den user-agent machen.
Wer also feiner vorgehen möchte, muß derzeit etwa in folgender Reihenfolge gucken:

  1. Wird im user-agent Safari oder WebKit erwähnt?
  2. Wird im user-agent Konqueror oder KHTML erwähnt?
  3. Wird im user-agent Opera erwähnt, Version entweder mit Schrägstrich oder mit Leerzeichen abgetrennt? (Versionen größer als 10 geben sich vorne übrigens als 9.80 aus und geben erst weiter hinten in der Zeichenkette die richtige Version an, was daran liegen soll, daß mangelhafte browser-Weichen Version 10 mit Version 1 verwechselt haben...)
  4. Wird im user-agent Mozilla5, Gecko und 'rev:' erwähnt?
  5. 'Mozilla/4.xy' weist auf Netscape4 hin, falls x und y Ziffern sind.
  6. Folgt auf 'Mozilla/4.0' hingegen ' (compatible;' , so handelt es sich vermutlich um Opera oder MSIE oder um ein anderes als Netscape4 getarntes Programm.
  7. Ist weiterhin kein Opera oder sonstiges Programm zu finden, aber MSIE mit Versionsnummer, kann es sich um einen msie handeln, muß es aber nicht. Insgesamt ist der msie somit am schwierigsten automatisch zu identifizieren, dazu muß immer kontrolliert werden, ob im user-agent nicht irgendwo noch ein Indiz für ein getarntes Programm oder eine Suchmaschine auftaucht.
    Ich vermute in dieser Schwierigkeit liegt auch ein Grund, warum Statistiken von browser-Häufigkeiten oft einfach falsch sind. Viele getarnte Programme werden als Netscape4 oder als msie gezählt. Vermutlich gibt es kaum noch Leute, die diese Programme noch nutzen, trotzdem kommt besonders der MSIE noch sehr häufig in Statistiken vor.
Beispiele für Angaben zum user-agent:
user-agent Kommentar
user-agent Kommentar
Mozilla/4.75 [en] (X11; U; AIX 4.3) Netscape4 auf aix-unix-Rechner
Mozilla/4.77 [en] (X11; U; Linux 2.4.4-4GB i686)Netscape4 auf Linux
Mozilla/4.78 [de]C-CCK-MCD DT (WinNT; U) Netscape4 auf Windows
Mozilla/4.5 [de] (Macintosh; I; PPC) Netscape4 auf Macintosh
Lynx/2.8.4rel.1 libwww-FM/2.14Lynx
amaya/8.2 libwww/5.4.0Amaya
Dillo/0.6.4Dillo
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) msie 6 getarnt als Netscape4
Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt) msie 5 getarnt als Netscape4
Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera9 auf Linux, maskiert als msie 6, der sich als Netscape4 tarnt
Mozilla/5.0 (X11; Linux i686; U; en; rv:1.7.5) Gecko/20041110 Opera9 auf Linux, maskiert als Mozilla, Gecko Version 1.7.5
Opera/9.00 (X11; Linux i686; U; en) Opera9 auf Linux
Opera/8.5 (X11; Linux i686; U; en) Opera8.5 auf Linux
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [de] Opera 7 getarnt als msie6, der sich als Netscape4 tarnt
Opera/7.11 (Windows NT 5.1; U) [de] Opera 7
Opera/7.54 (X11; Linux i686; U) [en]Opera 7
Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 6.01 [de] Opera 6 getarnt als msie5, der sich als Netscape4 tarnt
Opera/6.05 (Windows 2000; U) [de] Opera 6 auf windows
Opera/5.0 (Linux 2.4.13 i686; U) [en] Opera 5 auf Linux
Mozilla/5.0 (Linux 2.4.2 i686; U) Opera 6.11 [en] Opera 6 auf Linux
Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3 Netscape 6 auf Macintosh, weitgehend identisch mit Mozilla, Gecko Version 0.9.4.1
Mozilla/5.0 (... rv:1.0.2) Gecko/... Netscape/7.01 Netscape 7, weitgehend identisch mit Mozilla, Gecko Version 1.0.2
Mozilla/5.0 Galeon/1.2.0 (X11; Linux i686; U;) Gecko/20020408 Galeon auf Linux, weitgehend identisch mit Mozilla, Gecko Version 1.2.0
Mozilla/5.0 (... rv:1.2.1) Gecko/...Mozilla, Gecko Version 1.2.1
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0Mozilla, Gecko Version 1.7.5, Firefox 1.0 auf windows
Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)Mozilla, Gecko Version 1.7.5, Firefox 1.0 auf Debian-Linux
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050202 Firefox/1.0+ (PowerBook)Mozilla, Gecko Version 1.8b, Firefox 1.0+ auf Macintosh
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041201 Camino/0.8.2Mozilla, Gecko Version 1.7.5, Camino auf Macintosh
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616 MultiZilla/1.6.4.0bMozilla, Gecko Version 1.7, mit Multizilla-Erweiterung auf Linux
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.1) Gecko/20060130 SeaMonkey/1.0SeaMonkey1.0, Gecko Version 1.8.0.1 auf Linux
Mozilla/5.0 (compatible; Konqueror/3.1; Linux) Konqueror 3.1
Mozilla/5.0 (compatible; Konqueror/3.2; Linux; de, de_DE@euro) (KHTML, like Gecko) Konqueror 3.2
Mozilla/5.0 (compatible; Konqueror/2.1.2; X11) Konqueror 2
Lynx/2.8.3dev.6 libwww-FM/2.14 Konqueror 3.2, der sich als Lynx tarnt
Mozilla/5.0 (Windows; U; WinNT5.0; en-US; 1.2.1) Gecko/20021130 Konqueror 3.2 auf Linux, der sich als Mozilla/Gecko tarnt
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Konqueror 3.2 auf Linux, der sich als msie6 tarnt, der sich als Netscape4 tarnt
Wget/1.5.3 Konqueror 3.2 auf Linux, der sich als Wget tarnt
Opera/4.03 (Windows NT 4.0; U) Konqueror 3.2 auf Linux, der sich als Opera4 auf windows NT tarnt
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/51 (like Gecko) Safari/51 Safari auf Macintosh, basierend auf dem Konqueror, gibt sich als ähnlich zum Gecko aus
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12 Safari auf Macintosh, basierend auf dem Konqueror, gibt sich als ähnlich zum Gecko aus
\"Mozilla/4.0\"schlecht getarnter Roboter einer Suchmaschine
Mozilla/4.0 (compatible;)schlecht getarnter Roboter einer Suchmaschine
Mozilla/3.0 (compatible; Indy Library)als Netscape3 getarnter Roboter einer Suchmaschine
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; H010818)gut getarnter Roboter einer Suchmaschine, tarnt sich als msie, der sich als netscape4 tarnt
Googlebot/2.1 (+http://www.google.com/bot.html)ein Roboter der Suchmaschine Google
msnbot/1.0 (+http://search.msn.com/msnbot.htm)ein Roboter von microsoft
W3C_Validator/1.305.2.148 libwww-perl/5.803W3C-Validator - jemand hat nachgeguckt, ob (X)HTML-Fehler auf der Seite drauf sind
Jigsaw/2.2.3 W3C_CSS_Validator_JFouffa/2.0W3C-CSS-Validator - jemand hat nachgeguckt, ob CSS-Fehler auf der Seite drauf sind
CCBot/2.0 (http://commoncrawl.org/faq/)Dein derzeitiger eigener user-agent
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Dein derzeitiges HTTP_ACCEPT