Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 23 CGI mit C
Pfeil 23.1 Was ist CGI?
Pfeil 23.2 Vorteile von CGIs in C
Pfeil 23.3 Andere Techniken der Webprogrammierung
Pfeil 23.4 Das dreistufige Webanwendungsdesign
Pfeil 23.4.1 Darstellungsschicht
Pfeil 23.4.2 Verarbeitungsschicht
Pfeil 23.4.3 Speicherschicht
Pfeil 23.5 Clientseitige Programmierung
Pfeil 23.5.1 JavaScript
Pfeil 23.5.2 Java-Applets
Pfeil 23.6 Serverseitige Programmierung
Pfeil 23.7 Der Webserver
Pfeil 23.7.1 Das Client/Server-Modell des Internets
Pfeil 23.7.2 Serverimplementierung
Pfeil 23.7.3 Hosting-Services
Pfeil 23.7.4 Schlüsselfertige Lösung
Pfeil 23.7.5 Weitere Möglichkeiten
Pfeil 23.7.6 Apache
Pfeil 23.8 Das HTTP-Protokoll
Pfeil 23.8.1 Web-Protokolle
Pfeil 23.8.2 Wozu dienen Protokolle?
Pfeil 23.8.3 Was ist ein Protokoll?
Pfeil 23.8.4 Normen für die Netzwerktechnik
Pfeil 23.8.5 Das OSI-Schichtenmodell
Pfeil 23.8.6 Die Elemente einer URL
Pfeil 23.8.7 Client-Anfrage – HTTP-Request (Browser-Request)
Pfeil 23.8.8 Serverantwort (Server-Response)
Pfeil 23.8.9 Zusammenfassung
Pfeil 23.9 Das Common Gateway Interface (CGI)
Pfeil 23.9.1 Filehandles
Pfeil 23.9.2 CGI-Umgebungsvariablen
Pfeil 23.9.3 CGI-Ausgabe
Pfeil 23.10 HTML-Formulare
Pfeil 23.10.1 Die Tags und ihre Bedeutung
Pfeil 23.11 CGI-Eingabe
Pfeil 23.11.1 Die Anfrage des Clients an den Server
Pfeil 23.11.2 Eingabe parsen
Pfeil 23.12 Ein Gästebuch
Pfeil 23.12.1 Das HTML-Formular (»guestbook.html«)
Pfeil 23.12.2 Das CGI-Programm (»auswert.cgi«)
Pfeil 23.12.3 Das HTML-Gästebuch (»gaeste.html«)
Pfeil 23.13 Ausblick


Rheinwerk Computing - Zum Seitenanfang

23.9 Das Common Gateway Interface (CGI) Zur nächsten ÜberschriftZur vorigen Überschrift

Damit Sie CGI-Anwendungen auf einem Server ausführen können, muss dafür eine bestimmte Umgebung erzeugt werden. CGI erzeugt diese Umgebung. In diesem Abschnitt geht es darum, welche Umgebung Ihnen CGI zur Verfügung stellt und wie Sie damit arbeiten können.


Rheinwerk Computing - Zum Seitenanfang

23.9.1 Filehandles Zur nächsten ÜberschriftZur vorigen Überschrift

Den Standard-Filehandles stdin und stdout fällt bei CGI-Anwendungen eine besondere Rolle zu:

  • stdin – Erhält der Webserver eine Anfrage (HTTP-Request) mit der POST-Methode vom Webbrowser, eine CGI-Anwendung zu starten, wird der Nachrichten-Body über stdin an die CGI-Anwendung weitergeleitet. Über die Standardeingabe können Sie nun Content-Length-Bytes einlesen. Diese eingelesenen Daten liegen allerdings noch in kodierter Form vor und müssen erst noch dekodiert werden.
  • stdout – Auf stdout geben CGI-Anwendungen ihre Daten aus. Die Ausgabe beim Apache-Webserver ist dabei ungepuffert.

Einfacher geht es eigentlich kaum. Daten vom Webbrowser für die CGI-Anwendung werden einfach über die Standardeingabe (stdin) eingelesen, und Daten für den Webbrowser (z. B. die Darstellung einer Webseite) werden über die Standardausgabe (stdout) ausgegeben. Und hier greifen Sie ein. Sie sind mit einer dazwischenliegenden CGI-Anwendung für den Datenfluss verantwortlich.

Was die Standardfehlerausgabe (stderr) bei CGI-Anwendungen macht, ist nicht festgelegt und hängt somit von den einzelnen Webservern ab. Zumindest beim Apache werden Ausgaben in das in der httpd.conf angegebene error.log geleitet.


Rheinwerk Computing - Zum Seitenanfang

23.9.2 CGI-Umgebungsvariablen Zur nächsten ÜberschriftZur vorigen Überschrift

In den sogenannten Umgebungsvariablen befinden sich Informationen zum Webserver und zum Client (Browser). Die CGI-Umgebungsvariablen werden aus drei verschiedenen Quellen erzeugt:

  • dem HTTP-Anfrage-Paket
  • dem Webserver
  • dem HTTP-Anfrage-Header des Webbrowsers

Einige der Umgebungsvariablen werden dabei aus einer Kombination dieser drei Quellen gesetzt. Hier folgt ein Überblick zu einigen Standard-Umgebungsvariablen auf dem Webserver:


Tabelle 23.8 CGI-Umgebungsvariablen und deren Bedeutung

CGI-Umgebungsvariable Bedeutung
AUTH_TYPE

Authentifizierungsmethode zur Überprüfung des Benutzers (falls angefordert)

CONTENT_LENGTH

Größe der Daten in Bytes, die an die Standardeingabe (stdin) der CGI-Anwendung übergeben wurden

CONTENT_TYPE

die Art des Dokuments des Nachrichten-Body

DOCUMENT_ROOT

Verzeichnis, aus dem statische Webseiten gelesen werden

GATEWAY_INTERFACE

Version der CGI-Spezifikation des Webservers

PATH_INFO

zusätzliche Pfadinformationen, die beispielsweise vom Webbrowser übergeben wurden

PATH_TRANSLATED

die übersetzte Version von PATH_INFO, die als Systempfad angegeben wird

QUERY_STRING

die Information, die mit einem ? an die URL gehängt wird

REMOTE_ADDR

die IP-Adresse des Clients, der den Request geschickt hat

REMOTE_HOST

der DNS-Name des Clients, der den Request geschickt hat

REMOTE_IDENT

Der Name des Remote-Benutzers, der vom Server ermittelt wurde. Funktioniert nur, wenn Server und Client die RFC-931-Identifikation unterstützen.

REMOTE_USER

Unterstützt Ihr Server Benutzer-Authentifizierung, dann ist dies der Benutzername, mit dem Sie sich authentifiziert haben.

REQUEST_METHOD

die Methode der verwendeten HTTP-Anfrage (meist GET oder POST)

SCRIPT_NAME

der URL-Pfad des ausgeführten Skripts

SERVER_NAME

der Hostname, der DNS-Alias oder die IP-Adresse des Serverrechners

SERVER_PORT

Die Portnummer, an die die HTTP-Anfrage gesendet wurde. Meistens ist das Port 80.

SERVER_PROTOCOL

der Name und die Versionsnummer des Protokolls, mit dem die Anfrage gesendet wurde

SERVER_SOFTWARE

der Name und die Versionsnummer des verwendeten Webservers


Weitere Header-Variablen, die Ihnen Apache zur Verfügung stellt, sind die vom Client (Webbrowser) bei der Anfrage gesendeten Variablen. Alle diese Header-Variablen sind gleich aufgebaut: HTTP_Name_des_Headers. Tabelle 23.9 zeigt einige dieser Variablen im Überblick:


Tabelle 23.9 HTTP-Header-Variablen

Header-Variablen Bedeutung
HTTP_ACCEPT

Liste der akzeptierten Medientypen

HTTP_ACCEPT_CHARSET

Liste der akzeptierten Zeichensätze

HTTP_ACCEPT_LANGUAGE

Liste der akzeptierten Sprachen

HTTP_COOKIE

das Cookie, das vom Server gesetzt wurde

HTTP_FROM

die E-Mail-Adresse des Benutzers, der den Request gesendet hat (ist meistens nicht gesetzt)

HTTP_REFERER

Die URL, die der Benutzer zuletzt besucht hat. Ausnahme: eine direkt eingetippte URL oder ein Bookmark

HTTP_USER_AGENT

Name und Versionen des Betriebssystems und des Webbrowsers, der den Request gesendet hat


Um jetzt auf die Umgebungsvariablen zuzugreifen, wird die ANSI-C-Funktion getenv() verwendet:

#include <stdlib.h>

char *getenv(const char *str);

Ist die Umgebungsvariable str vorhanden, wird ein Zeiger auf den Inhalt dieser Umgebungsvariable zurückgegeben. Wenn die Umgebungsvariable nicht vorhanden ist, wird NULL zurückgegeben. Wollen Sie beispielsweise abfragen, von welchem Betriebssystem und welchem Webbrowser die Anfrage gestellt wurde, können Sie wie folgt vorgehen:

/* browser.c */
#include <stdio.h>
#include <stdlib.h>

/* die Kopfzeile eines Standard-HTML-Dokuments;
 * titel: String, der als Titel erscheinen soll
 */
void print_html_header(char *titel) {
   printf("<html><head>\n");
   printf("<title>%s</title>\n",titel);
   printf("</head><body><pre>\n");
}

/* das Ende eines HTML-Dokuments */
void print_html_end(void) {
   printf("</pre></body></html>\n");
}

/* damit überhaupt ein HTML-Dokument ausgegeben wird */
void print_header(void) {
   printf("Content-Type: text/html\n\n");
}
int main(void) {
   char *p;

   print_header();
   print_html_header("Wer bin ich?");
   p = getenv("HTTP_USER_AGENT");
   if(p!=NULL)
      printf("Sie browsen mit : %s\n",p);
   else
      printf("Konnte HTTP_USER_AGENT nicht ermitteln!\n");
   print_html_end();
   return EXIT_SUCCESS;
}

Wenn Sie diese CGI-Anwendung wieder aufrufen (der Name sei browser.cgi), und zwar mit http://localhost/cgi-bin/browser.cgi, dann sollten Sie im Browser einen String vorfinden wie z. B.:

Sie browsen mit :
Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.0.8)
Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729)

oder:

Sie browsen mit :
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5

Die Abfrage aller Umgebungsvariablen soll jetzt in eine Funktion gepackt werden. Das folgende Listing gibt alle vorhandenen Umgebungsvariablen auf dem Browser aus:

/* env.c */
#include <stdio.h>
#include <stdlib.h>

/* Listing gibt alle vorhandenen Environment-Variablen aus. */

char *env[] =  {
   "AUTH_TYPE", "CONTENT_LENGTH", "CONTENT_TYPE",
   "GATEWAY_INTERFACE", "HTTP_ACCEPT", "HTTP_CONNECTION",
   "HTTP_HOST", "HTTP_REFERER", "HTTP_USER_AGENT",
   "PATH_INFO", "PATH_TRANSLATET", "QUERY_STRING",
   "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_IDENT",
   "REMOTE_USER", "REQUEST_METHOD", "SCRIPT_NAME",
   "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL",
   "SERVER_SOFTWARE" , NULL
};
/* die Kopfzeile eines Standard-HTML-Dokuments;
 * titel: String, der als Titel erscheinen soll
 */
void print_html_header(char *titel) {
   printf("<html><head>\n");
   printf("<title>%s</title>\n",titel);
   printf("</head><body><pre>\n");
}

/* das Ende eines HTML-Dokuments */
void print_html_end(void) {
   printf("</pre></body></html>\n");
}

/* damit überhaupt ein HTML-Dokument ausgegeben wird */
void print_header(void) {
   printf("Content-Type: text/html\n\n");
}

/* Inhalt der Environment-Variable ausgeben */
void environment(const char *s) {
   char *p;

   p = getenv(s);
   printf ("%s", s);
   if(p!=NULL)
      printf (" = %s", p);
   else
      printf(" = (<i>keine Angaben</i>)");
   printf ("<BR>\n");
}

int main(void) {
   int i;

   print_header();
   print_html_header("CGI-Umgebungsvariablen ausgeben - 2\n");
   for(i=0; env[i] != NULL; i++)
      environment(env[i]);
   print_html_end();
   return EXIT_SUCCESS;
}

Abbildung 23.11 Ausgabe der Umgebungsvariablen

Dreh- und Angelpunkt ist die Funktion environment(), die mit einem entsprechenden String als Argument aufgerufen wird. Die Strings wurden in diesem Beispiel alle in eine Stringtabelle verpackt. In environment() werden in einer Schleife alle Umgebungsvariablen abgefragt und ausgegeben.


Rheinwerk Computing - Zum Seitenanfang

23.9.3 CGI-Ausgabe topZur vorigen Überschrift

Wenn Ihre CGI-Anwendung etwas ausgeben soll, müssen Sie mindestens eine Headerzeile ausgeben. Der Webserver erledigt dann den Rest, wie zum Beispiel die Ausgabe weiterer Header. Von den drei folgenden Headern muss mindestens einer angegeben werden.

Content-Type-Dokumente ausgeben

Wollen Sie, dass Ihre CGI-Anwendung ein bestimmtes Dokument ausgibt, müssen Sie dem Webserver erst mitteilen, um was für ein Dokument es sich handelt. Meistens werden Sie ein HTML-Dokument ausgeben wollen. Dies wird mit folgender Angabe erledigt:

printf("Content-Type: text/html\n\n");

Die beiden Newline-Zeichen am Ende sind enorm wichtig. Damit wird dem Webserver angezeigt, dass es sich um die letzte Headerzeile handelt. Wenn der Webserver diese Leerzeile erhält, kann er dem Webbrowser seine Daten schicken. Meistens ist dies das Anzeigen einer HTML-Webseite. Natürlich lassen sich mit dem Content-Type-Header noch unzählig viele andere Dokumente neben den HTML-Dokumenten ausgeben.

»Status« – Statuscode ausgeben

Damit können Sie angeben, welchen Statuscode der Webserver an den Webbrowser als Response schicken soll. Welche unterschiedlichen Statuscodes Sie verwenden können, wissen Sie bereits. Wollen Sie zum Beispiel den Statuscode 403 (Forbidden) an den Webbrowser senden, und zwar derart, dass der Surfer keinen Zugriff auf diese Seite hat, können Sie so vorgehen:

printf("Status: 403");

»Location« – Weiterleiten an ein anderes Dokument

Wollen Sie mithilfe einer CGI-Anwendung nicht ein Dokument ausgeben, sondern zu einem anderen Dokument weiterleiten, können Sie dazu den Location-Header verwenden. Dieser lässt sich beispielsweise ideal einsetzen, wenn sich die URL eines Dokuments geändert hat. Anwenden können Sie den Header so:

printf("Location: umleitungs_ziel.html\n\n");

Bitte bedenken Sie auch, dass es immer noch Surfer mit älteren Browsern gibt, die eine automatische Weiterleitung nicht unterstützen. Schreiben Sie dafür ein paar extra Zeilen HTML-Code mit einem Link zum Weiterklicken.

Hierzu folgt jetzt ein Programmbeispiel, das Surfern mit bestimmten IP-Adressen (REMOTE_ADDR) den Zugang auf die Webseite verweigert. Falls aber die IP-Adresse Zugang hat, wird der Surfer zu einer entsprechenden URL weitergeleitet.

/* location.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Listing fragt REMOTE_ADDR ab. Lässt sich der Wert nicht
 * auslesen, gibt das CGI-Programm den Statuscode 500 zurück.
 * Ansonsten werden die verbotenen IP-Adressen in forbidden mit
 * REMOTE_ADDR überprüft und entsprechende Maßnahmen getroffen. */

/* die Liste der IP-Adressen, die keinen Zugriff auf die Seite
 * haben sollen */
char *forbidden[] = {
   "127.0.0.1", "168.123.6.1", NULL
};

/* Weiterleitung zu einer URL;
 * url ist die URL, zu der Sie den User weiterleiten.
 */
void print_location(char *url) {
   printf("Location: %s\n\n", url);
   /* für den Fall, dass ein alter Browser keine
    * automatische Weiterleitung unterstützt */
   printf("Content-Type: text/html\n\n");
   printf("<html><head>\n");
   printf("<title>Weiterleitung zu %s</title>\n",url);
   printf("</head><body><pre>\n");
   printf("Weiter gehts <a href=\"%s\">hier</a>",url);
   printf("</pre></body></html>\n");
}

/* Statuscode zurückgeben */
void print_status(char *status) {
   printf("Status: %s", status);
}

int main(void) {
   char *p;
   int i;

   /* IP-Adresse ermitteln */
   p = getenv("REMOTE_ADDR");
   if( p == NULL) { /* Fehler bei getenv-Abfrage */
      print_status("500");
      return EXIT_FAILURE;
   }
   for(i=0; forbidden[i] != NULL; i++)
      if(strcmp(p, forbidden[i]) == 0) {
         /* Diese IP hat keinen Zutritt */
         print_status("403");
         return EXIT_FAILURE;
      }
   /* Ok, der User wird auf die Willkommen-Seite weitergeleitet.
    * Die URL an Ihre Bedürfnisse anpassen */
   print_location("http://localhost/welcome.html");
   return EXIT_SUCCESS;
}

Zuerst überprüft die CGI-Anwendung die IP-Adresse des Surfers. Sollte es dabei schon zu Problemen kommen, wird der Fehlercode 500 zurückgegeben, ein Serverfehler also. Ansonsten wird die Stringtabelle forbidden durchlaufen und mit strcmp() und dem Rückgabewert von getenv() verglichen. Bei der IP-Adresse 127.0.0.1 handelt es sich um die Adresse des localhost. Wenn Sie die Anwendung auf Ihrem System testen wollen, handelt es sich um Ihre eigene IP-Adresse. In diesem Fall sollten Sie den Statuscode 403 (Forbidden) vom Browser zurückbekommen. Der letzte Fall leitet Sie an die URL http://localhost/welcome.html weiter, die sich im Beispiel im htdocs-Verzeichnis befindet.

Außerdem empfehle ich Ihnen, die Daten der Stringtabelle forbidden in einer extra Datei zu speichern. Diese Datei können Sie dann beim Ausführen der CGI-Anwendung zum Lesen öffnen, auslesen und mit REMOTE_ADDR überprüfen. Eine extra Datei ist deshalb sinnvoller, weil Sie beim Hinzufügen von weiteren IP-Adressen nicht das komplette Listing neu übersetzen müssen.


Hinweis

In der Praxis empfiehlt es sich, die Zugriffe auf bestimmte Seiten mit der Datei .htaccess zu regeln. Dies ist wesentlich einfacher, als eine CGI-Anwendung dafür zu schreiben.




Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: C/C++






 C/C++


Zum Rheinwerk-Shop: Einstieg in C






 Einstieg in C


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern