Hallo liebe HTML'ler!
Ich versuchte seit längerem, einen File-Upload mit einem
in C++ geschriebenen CGI-Skript zum laufen zu bringen, was
mir jetzt ENDLICH gelungen ist ;-)
Damit andere nicht in die gleiche Falle laufen, poste ich
das Problem vorbeugend mal ins Forum...
Ich hatte ein Formular mittels
<form action="http://...." method="post" enctype="multipart/form-data">
an mein CGI-prog geschickt, in dem sich u.a. auch ein
File-Button befindet, mit dem ein ASCII-File ge-uploadet
werden soll.
Mit folgendem C-Code Fragment wollte ich nun die geposteten
Daten aus der Standard-Eingabe stdin in den String 'post'
einlesen (um sie später weiterzuverarbeiten):
char *s, *post;
int postlen=0;
s=getenv("CONTENT_LENGTH");
// die Anzahl der ge-post-eten Zeichen in postlen speichern...
if (s!=NULL) postlen=atoi(s);
if (postlen>0) {
post = new char[postlen+1];
// postlen Zeichen aus stdin in post einlesen
fread(post, sizeof(char), postlen, stdin);
}
Funktionierte zunächst ohne Probleme, zumindest unter Win95 mit
dem Xitami-Server und dem OmniHTTPd.
Allerdings hat das Prog unter dem Personal Web Server und IIS von Microsoft
an dieser Stelle grundsätzlich gestreikt und verharrte in einer Art Endlosschleife.
Grund:
Die Funktion "fread(post, sizeof(char), postlen, stdin); " liest eigentlich
"postlen" Elemente der Größe "sizeof(char)" aus dem Eingabestrom "stdin"
in die Variable "post" ein - sollte man meinen...
Allerdings hat diese Funktion den Haken, daß sie bei Zeilenumbrüchen,
- bestehend aus Carriage-Return (CR) und Line-Feed (LF) - das Carriage-Return
wegläßt, also an dieser Stelle statt 2 Bytes nur eines zurückgibt.
Will man nun aus stdin eine 1000 byte lange ASCII-Datei mit 50 Zeilenumbrüchen
lesen, so liefert fread(...) sämtliche Zeilen bereits nach 950 bytes
zurück (die fehlenden 50 bytes wurden ja durch die verkürzten Zeilenumbrüche
geschluckt).
Nun wurden aber 1000 Zeichen angefordert, aber "stdin" ist schon
nach 950 Zeichen mit seinem Latein am Ende!!
Als Resultat bleibt das Programm stehen und wartet endlos auf weitere Eingaben aus stdin,
bis der Web-Server sein Timeout erreicht und dem Programm den Gnadenstoß verpaßt.
Nachdem man dies weiß ($@§$%!!), kann man sich z.B. mit folgender Routine behelfen:
char *s, *post, *tmp;
int postlen=0;
s=getenv("CONTENT_LENGTH");
// die Anzahl der ge-post-eten Zeichen in postlen speichern...
if (s!=NULL) postlen=atoi(s);
// postlen Zeichen aus stdin in post einlesen
if (postlen>0) {
post = new char[postlen+1];
tmp = new char[postlen+1];
strcpy(post, "");
while(postlen>0) {
strcpy(tmp, "");
fgets(tmp, postlen+1, stdin);
postlen -= strlen(tmp)+1; // man beachte die +1 !!!
strcat(post, tmp);
}
}
die Funktion fgets(buffer, laenge, stream) liest dabei bis zum nächsten Zeilenumbruch
aber höchstens soviele Zeichen, wie in "laenge" angegeben wurde.
Viele Grüße!
Andreas