# Was sonst noch wichtig ist
Im Alltag siegt das Dringende über das Wichtige.
– Jean Remy von Matt, dt. Werbefachmann
Dieses Kapitel beschäftigt sich mit dem Sammeln der Informationen von Server und Browser. Aber auch die Netzwerkprogrammierung, reguläre Ausdrücke und das dynamische Erstellen von PDF-Dokumenten werden behandelt.
# Server-Informationen
Da leider alle Webserver unterschiedliche Informationen zur Verfügung stellen, ist es schwer zu sagen, welche Variablen Sie genau auslesen können. Das folgende Script soll dies jedoch erleichtern.
<?php
echo "<h1>Umgebungsvariablen</h1><table border=\"1\">";
echo "<tr><th>Schl�ssel</th><th>Wert</th></tr>";
foreach($_ENV as $key=>$value)
{
echo "<tr><td>$key</td><td>$value</td></tr>";
}
echo "</table>";
echo "<h1>Servervariablen</h1><table border=\"1\">";
echo "<tr><th>Schl�ssel</th><th>Wert</th></tr>";
foreach($_SERVER as $key=>$value)
{
echo "<tr><td>$key</td><td>$value</td></tr>";
}
echo "</table>";
?>
Listing 9.1: Ausgabe der Server-Informationen
Die beiden assoziativen Arrays $_ENV
und $_SERVER
stellen die unterschiedlichsten Informationen bereit. Dabei finden Sie in $_ENV
die Umgebungsvariablen und in $_SERVER
die vom Server zur Verfügung gestellten Daten.
Außerdem können Sie mit der Funktion phpinfo
unterschiedlichste Daten im Browser ausgeben.
void phpinfo(void)
Ein Beispiel:
<?php
phpinfo();
?>
Listing 9.2: Ausgabe der unterschiedlichsten Informationen mit phpinfo
# Netzwerkfunktionen
In Bezug auf Netzwerke sind in PHP einige Funktionen sehr hilfreich, auch wenn sie eher selten verwendet werden.
# IP-Adressen und DNS
Die Funktion gethostbyaddr
ermittelt den Hostnamen eines Rechners im Internet anhand seiner IP-Adresse. Die IP-Adresse wird als Parameter erwartet. Bei einem Fehler wird die übergebene IP-Adresse zurückgegeben, ansonsten der entsprechende Hostname.
string gethostbyaddr(string ipaddress)
Sie können die IP-Adresse jedoch auch anhand eines Hostnamens ermitteln. Der Hostname wird als Parameter übergeben, und die IP-Adresse wird zurückgegeben.
string gethostbyname(string hostname)
Alternativ können Sie jedoch auch eine Liste von passenden IP-Adressen zu einem Hostname als Array erhalten. Die IP-Adresse muss als Parameter übergeben werden. Das Array wird zurückgegeben.
array gethostbynamel(string hostname)
# Verbindungen zu anderen Servern
Mit der Funktion fsockopen
können Sie eine Verbindung zu einem anderen Server aufbauen.
int fsockopen([string udp://hostname, int port [, int errno
[, string errstr [, double timeout]]]])
Die Funktion gibt bei Erfolg ein Handle zurück, das einem Dateihandle entspricht. Dadurch ist es möglich, Dateifunktionen wie z. B. fgets
, fputs
, feof
oder fclose
zu verwenden. Wenn die Verbindungsanforderung scheitert, gibt die Funktion FALSE
zurück und speichert in den Parametern errno
und errstr
die Fehlernummer sowie eine entsprechende Meldung.
<?php
$connection = fsockopen("www.google.de",80);
if($connection)
{
fputs($connection,"GET / HTTP/1.0\r\n\r\n");
while(!feof($connection))
{
echo fgets($connection,128);
}
fclose($connection);
}
else
{
echo "Verbindung zu www.google.de fehlgeschlagen.";
}
?>
Listing 9.3: Verbindungsaufbau zum Server www.google.de über den Port 80
Das Script aus Listing 9.3 baut eine Verbindung zum Server www.google.de auf; und zwar über den Port 80. Dies ist der Standard-Port für HTTP-Verbindungen. Aus diesem Grund müssen und dürfen Sie das Protokoll nicht in der URI mit angeben, da das zu verwendende Protokoll aus dem angesprochenen Port resultiert. Wurde die Verbindung erfolgreich hergestellt, wird in der Variablen $connection
ein Dateihandle gespeichert, über das im if
-Anweisungsblock die Kommunikation mit dem Server erfolgt. Zuerst wird dem Server per HTTP-Kommando mitgeteilt, welche Methode und welche Protokollversion bei der Kommunikation verwendet werden soll. In der nachfolgenden while
-Schleife werden so lange Zeichen eingelesen, bis der Server nichts mehr sendet.
Alternativ können Sie anstelle des while
-Konstrukts auch die Funktion fpassthru
verwenden. Diese Funktion liest alle Zeichen ein, die über eine Verbindung empfangen werden können.
if($connection)
{
fputs($connection,"GET / HTTP/1.0\\r\n\\r\n");
fpassthru($connection);
fclose($connection);
}
Neben HTTP-Verbindungen können Sie auch andere POP3- oder FTP-Verbindungen herstellen.
Die entsprechenden Ports können Sie der Tabelle 9.1 entnehmen.
Port | Dienst bzw. Protokoll |
---|---|
13 | Daytime |
21 | FTP |
23 | Telnet |
25 | Mailto / SMTP |
37 | Time |
42 | DNS |
43 | WhoIs |
69 | Trivial File Transfer Protocol (TFTP) |
70 | Gopher |
79 | Finger |
80 | HTTP |
110 | Mailfrom / POP3 |
119 | News/NNTP |
Tabelle 9.1: Ports für verschiedene Verbindungen
# HTTP-Verbindungen
Auf die gleiche Art und Weise wie in Listing 9.3 kommuniziert auch ein Browser mit einem Webserver. Er sendet unterschiedliche HTTP-Kommandos und wartet die Reaktion des Servers ab. Ein solches HTTP-Kommando ist folgendermaßen aufgebaut:
- Kommando (Methode ID Protokoll-Version)
- Header
- Content-Length-Feld
- Daten (ggf. zwei Leerzeilen)
Das Kommando in Listing 9.3 besteht aus der Methode GET
der ID /
und der Protokoll-Version HTTP/1.0
.
Anstelle der Methode GET
können Sie auch eine der anderen, in Tabelle 9.2 enthaltenen Methoden verwenden.
Für ID können Sie auch eine Domain oder einen Dateinamen angeben, und als Protokollversion ist auch die Angabe HTTP/1.1
möglich. Wenn Sie keine Daten an den Server übergeben möchten, müssen Sie das Kommando mit zwei Leerzeilen abschließen. In Abschnitt 47.4, PDF-Dokumente erzeugen, finden Sie das Beispiel eines HTTP-Kommandos, das sowohl den Header als auch das Content-Length-Feld als auch Daten an den Browser sendet.
Methode | Erklärung |
---|---|
DELETE | Ressource löschen |
GET | Ressource anfordern |
HEAD | Header anfordern |
LINK | Verknüpfung anlegen |
OPTIONS | Optionen ermitteln |
POST | Daten senden |
PUT | Ressource ablegen |
TRACE | Rückverfolgung des Kommandos |
UNLINK | Verknüpfung löschen |
Tabelle 9.2: Kommando-Methoden
# POP3-Verbindung
Verbindungen, bei denen das POP3-Protokoll verwendet wird, sind Verbindungen, um E‑Mails von einem Server abzurufen. Das Listing 9.4 enthält hierfür ein Beispiel. Der Port für eine solche Verbindung lautet 110.
<?php
$connection = fsockopen('pop.server.tld',110);
if($connection)
{
echo fgets($connection,1024);
fputs($connection,'USER username\r\n');
echo fgets($connection,1024);
fputs($connection,'PASS passwort\r\n');
echo fgets($connection,1024);
fputs($connection,'STAT\r\n');
echo fgets($connection,1024);
fputs($connection,'QUIT\r\n');
echo fgets($connection,1024);
fclose($connection);
}
?>
Listing 9.4: Verbindung zu einem POP3-Server mit PHP
Anstelle von USER
, PASS
oder STAT
können Sie auch eines der in Tabelle 9.3 aufgeführten Kommandos verwenden.
Kommando | Erklärung |
---|---|
DELE | E‑Mail löschen |
LIST | E‑Mails auflisten |
NOOP | Verbindungsstatus abfragen |
PASS | Passwort |
QUIT | Verbindung beenden |
RETR | E‑Mail öffnen bzw. empfangen |
RSET | Löschmarkierung entfernen |
STAT | E‑Mails mit entsprechender Größe auflisten |
USER | Benutzername |
Tabelle 9.3: Kommandos für POP3-Verbindungen
Die in Listing 9.4 angegebenen Platzhalter username
und password
müssen durch die entsprechenden Daten ersetzt werden. Außerdem sollten Sie jedes Kommando mit \\r\n
(carriage return und line feed) abschließen.
# Perl-kompatible reguläre Ausdrücke in PHP
Reguläre Ausdrücke, wie sie in Perl typisch sind, lassen sich mit ein wenig Mehraufwand auch in PHP einsetzen. So können Sie einen String auf einen regulären Ausdruck überprüfen, Treffer durch eine andere Zeichenkette ersetzen oder Strings anhand eines regulären Ausdrucks in ein Array zerlegen.
Während Sie in Perl einfach den Bindungsoperator =\
~ verwenden konnten, müssen Sie in PHP hierfür eine Funktion bemühen: preg_match
. Sie erwartet als ersten Parameter den regulären Ausdruck und als zweiten die Zeichenkette, die durch den regulären Ausdruck überprüft werden soll.
int preg_match(string regexp, string str)
Ein Beispiel:
if(preg_match("/aus/","Haus"))
{
echo "Treffer!";
}
else
{
echo "Kein Treffer!";
}
Dieses Beispiel wird Treffer!
im Browser ausgeben, da aus
in Haus
vorkommt. Beachten Sie, dass ein regulärer Ausdruck, anders als in Perl, in doppelten Anführungsstrichen notiert werden muss. Mit einer foreach
-Schleife lässt sich ein regulärer Ausdruck auch auf ein Array anwenden.
$strings = Array("Maus","Haus","Haut","Laus");
foreach($strings as $value)
{
if(preg_match("/aus/",$value))
{
echo "Treffer in $value<br>\n";
}
else
{
echo "Kein Treffer in $value<br>\n";
}
}
Ausgabe:
Treffer in Maus
Treffer in Haus
Kein Treffer in Haut
Treffer in Laus
Leider kann PHP das Flag g
nicht interpretieren, das in einer Zeichenkette nach allen Vorkommen des regulären Ausdrucks sucht. Daher müssen Sie in solchen Fällen eine andere Funktion verwenden: preg_match_all
.
int preg_match_all(string regexp, string str, array matches)
Wenn Sie als dritten Parameter nun ein Array angeben, werden alle Treffer in diesem Array gespeichert. Beachten Sie dabei, dass das angegebene Array danach mehrdimensional ist und die Treffer im Unter-Array $matches[0]
gespeichert werden.
Mit der Funktion preg_replace
können Sie Zeichenketten mit Hilfe regulärer Ausdrücke ersetzen.
mixed preg_replace(mixed regexp, mixed replacewith, mixed replacein)
Anstelle des Parameters regexp
können Sie einen regulären Ausdruck als String oder mehrere als Array übergeben. Der Parameter replacewith
nimmt entweder einen String oder ein Array von Strings entgegen, mit denen ersetzt werden soll. Die Zeichenkette bzw. die Zeichenketten, in denen ersetzt werden soll, werden als Parameter replacein
übergeben. Wurde eine Ersetzung vorgenommen, wird/werden die überarbeitete(n) Zeichenkette(n) zurückgegeben, andernfalls die unbearbeitete(n) Zeichenkette(n).
echo preg_replace("/[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}/",
strftime("%d.%m.%Y"),
"Heute ist der 04.10.2002");
Dieses Beispiel ersetzt jedes Datum, das gefunden wird, durch das aktuelle Datum.
Die Funktion preg_split
ermöglicht das Zerlegen eines String in mehrere Teilstrings anhand eines regulären Ausdrucks. Als Parameter erwartet die Funktion den regulären Ausdruck als String und die Zeichenkette, die zerlegt werden soll. Der Rückgabewert der Funktion ist ein Array.
array preg_split(string regexp, string string_to_split)
Ein Beispiel:
$splitted = preg_split("/[\\s]/","Dies ist eine normale Zeichenkette");
foreach($splitted as $value)
{
echo "$value<br>\n";
}
In diesem Beispiel wird eine Zeichenkette anhand aller gefundenen nicht druckbaren Zeichen zerlegt (z. B. \n
, \\r
oder \\t
) und im Array $splitted
gespeichert. Anschließend wird das Array in einer foreach
-Schleife ausgegeben.
# PDF-Dokumente erzeugen
Seit geraumer Zeit ist in PHP eine Erweiterung verfügbar, mit der Sie zur Laufzeit eines Scripts ein PDF-Dokument erzeugen können. Sie können dabei beliebige Texte und Bilder in das Dokument einfügen und verschiedene Formatierungen vornehmen.
<?php
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf,'Creator','pdf.php');
pdf_set_info($pdf,'Author','pdf.php');
pdf_set_info($pdf,'Title','Hallo Welt');
pdf_begin_page($pdf,595,842);
$font = pdf_findfont($pdf,'Times New Roman','host',0);
pdf_setfont($pdf,$font,20.0);
pdf_show_xy($pdf,'Hallo Welt!',50,842-20-50);
pdf_end_page($pdf);
pdf_set_parameter($pdf,"openaction","fitpage");
pdf_close($pdf);
$buffer = pdf_get_buffer($pdf);
$size = strlen($buffer);
header('Content-Type: application/pdf');
header("Content-Length: $size");
header('Content-Disposition: inline; filename=pdf.pdf');
echo $buffer;
pdf_delete($pdf);
?>
Listing 9.5: Erzeugen eines PDF-Dokuments zur Laufzeit
Es gibt verschiedene Erweiterungen, mit denen PHP ein PDF-Dokument zur Laufzeit erzeugen kann. PHP liefert bereits eine dieser Erweiterungen mit: die PDFLIB. Für private Zwecke ist diese Bibliothek kostenfrei und dadurch für die meisten Personen verwendbar. Wollen Sie die Bibliothek kommerziell verwenden, müssen Sie zuerst eine Lizenz erwerben. Aufgrund ihrer weiten Verbreitung werde ich mich in diesem Kapitel auf diese Bibliothek beziehen.
Zuallererst muss mit der Funktion pdf_new
eine neue Datenstruktur erzeugt werden. Die Funktion liefert anschließend ein Handle auf diese Struktur zurück. Die Funktion pdf_open_file
öffnet ein neues Dokument. Als erster Parameter wird das Datenstruktur-Handle erwartet und optional ein Dateiname, unter dem das Dokument gespeichert wird.
$pdf = pdf_new();
pdf_open_file($pdf);
Spezielle Informationen, die im Dokument gespeichert werden sollen, wie z. B. der Name des Autors, der Ersteller oder der Titel des Dokuments werden »Metadaten« genannt. Metadaten werden mit der Funktion pdf_set_info
angegeben. Auch diese Funktion erwartet wieder als ersten Parameter das Handle4; der zweite Parameter identifiziert den Feldnamen und der dritte den einzufügenden Wert.
pdf_set_info($pdf,'Creator','pdf.php');
pdf_set_info($pdf,'Author','pdf.php');
pdf_set_info($pdf,'Title','Hallo Welt');
Nach diesen Vorbereitungen wird mit der Funktion pdf_begin_page
eine neue Seite in das Dokument eingefügt. Zuerst wird wieder das Handle übergeben, gefolgt von den Abmessungen der Seite in der Reihenfolge Breite und dann Höhe. Eine Seite wird in Punkt angegeben. Ein Punkt entspricht 1/72 Zoll.
pdf_begin_page($pdf,595,842);
Die Maße 595 × 842 entsprechen einer DIN-A4-Seite.
# Dokument mit Inhalt füllen
Für die Ausgabe eines Textes im Dokument müssen Sie zuerst eine Schriftart auswählen. Dabei hilft Ihnen die Funktion pdf_findfont
. Dieser Funktion können Sie den Namen einer Schriftart übergeben und festlegen, wo sie suchen soll. Anschließend gibt sie den Font zurück. Diesen übergeben Sie der Funktion pdf_setfont
, zusammen mit der Schriftgröße in Punkt.
$font = pdf_findfont($pdf,'Times New Roman','host',0);
pdf_setfont($pdf,$font,20.0);
Nun können Sie mit der Funktion pdf_show_xy
eine Zeichenkette in das Dokument einfügen. Dabei erwartet die Funktion die Zeichenkette und anschließend die x- und die y-Position. Beachten Sie dabei, dass der Ausgangspunkt (0,0) in der linken unteren Ecke liegt. In Listing 9.5 wird der Text Hallo Welt!
an der x-Position 50 und der y‑Position 772 (842 – 20 – 50 = 772) ausgegeben.
pdf_show_xy($pdf,'Hallo Welt!',50,842–20–50);
Jede angefangene Seite muss mit der Funktion pdf_end_page
beendet werden. Anschließend können Sie noch Parameter festlegen, die keinen informativen Gehalt besitzen. Sie werden vom öffnenden Programm interpretiert und führen z. B. dazu, dass eine Seite des PDF-Dokuments an die Fenstergröße angepasst wird (openaction
und fitpage
). Die hierfür zu verwendende Funktion lautet pdf_set_parameter
. Zum Schluss können Sie das PDF-Dokument mit pdf_close
schließen.
pdf_end_page($pdf);
pdf_set_parameter($pdf,"openaction","fitpage");
pdf_close($pdf);
Die PDF-Datenstruktur muss nun in einer Variable gespeichert werden. Dies erfolgt mit der Funktion pdf_get_buffer
. Die Funktion liefert die Datenstruktur als String zurück. Die Länge dieses Strings wird ebenfalls benötigt. Aus diesem Grund wird in der Variablen $size
die mit strlen
ermittelte Zeichenzahl gespeichert.
$buffer = pdf_get_buffer($pdf);
$size = strlen($buffer);
Anstatt nun einfach eine Ausgabe im Browser zu erzeugen, wird dem Browser zuerst der MIME-Typ der nun folgenden Daten mitgeteilt. Zusätzlich wird dabei auch die Größe des folgenden Datenstroms übergeben.
header('Content-Type: application/pdf');
header("Content-Length: $size");
header('Content-Disposition: inline; filename=pdf.pdf');
Abschließend wird die PDF-Datenstruktur ausgegeben und der auf dem Server belegte Speicher wieder freigeräumt.
echo $buffer;
pdf_delete($pdf);
Weitere Informationen zum Erzeugen von PDF-Dokumenten finden Sie unter der Adresse http://www.pdflib.com/.
# Zusammenfassung
- In den assoziativen Arrays
$_ENV
und$_SERVER
stehen die verschiedenen Umgebungs- und Servervariablen zur Verfügung. - Mit der Funktion
fsockopen
können Verbindungen zu Servern aufgebaut werden. Zum Kommunizieren mit dem Server können die Funktionenfgets
undfputs
verwendet werden. - Mit speziellen Funktionen, wie z. B.
gethostbyaddr
, kann der Hostname eines Computers im Internet anhand seiner IP-Adresse ermittelt werden. Dies ist auch umgekehrt möglich. - Perl-kompatible reguläre Ausdrücke können mit den Funktionen
preg_match
,preg_repacle
undpreg_split
auch in PHP verwendet werden. - Die Bibliothek PDFLIB wird mit PHP ausgeliefert und ermöglicht das Erzeugen von PDF-Dokumenten zur Laufzeit.
# Fragen und Übungen
- Mit welcher Anweisung können Sie die Servervariable
DOCUMENT_ROOT
ausgeben? - Schreiben Sie ein PHP-Script, das die IP-Adresse eines Host ausgibt, dessen Name durch ein HTML-Formular übergeben wurde
- Schreiben Sie ein PHP-Script, das alle Ende-Tags in einer HTML-Datei ermittelt und die Zahl im Browser ausgibt.
- Schreiben Sie ein PHP-Script, das ein PDF-Dokument ausgibt. In das PDF-Dokument soll der Inhalt eines HTML-Dokuments eingefügt werden.