Fremdes Formular abschicken
Sebastian Becker
- php
Hallo,
ich möchte gerne die in ein Kontaktformular eingetragenen Daten beim Abschicken zusätzlich an ein Formular mit nahezu identischen Feldern (mit unterschiedlichen Namen) auf einem fremden Server (Partnerfirma) schicken.
Ich vermute mal, daß das mit "fsockopen" möglich ist, weiß aber nicht wie. Hat jemand mal ein praktisches Beispiel?
Danke für alle Hinweise,
Sebastian Becker
Hi!
Ich vermute mal, daß das mit "fsockopen" möglich ist, weiß aber nicht wie. Hat jemand mal ein praktisches Beispiel?
auf php-faq.de gibt es ein gutes Beispiel, das funktioniert zwar nicht mehr live, aber es sollte Dir helfen: http://www.dclp-faq.de/q/q-code-post.html
Grüße
Andreas
Hi, Andreas,
auf php-faq.de gibt es ein gutes Beispiel, das funktioniert zwar nicht mehr live, aber es sollte Dir helfen: http://www.dclp-faq.de/q/q-code-post.html
super, danke, ein erster Test hat geklappt. Ich hoffe, daß es auch noch funktioniert, wenn PHP nicht als CGI installiert ist und wenn ich die Variablen aus dem Originalformular verwende. Muß ich diese wohl noch mit urlencode behandeln?
Grüße,
Sebastian
Hi Sebastian!
super, danke, ein erster Test hat geklappt.
Auf diese Weise funktioniert es eigentlich immer, solange das Script an das die Daten gehen POST verarbeitet. Und Du kannst natürlich den Referer rausnehmen.
Ich hoffe, daß es auch noch funktioniert, wenn PHP nicht als CGI installiert ist
klar!
und wenn ich die Variablen aus dem Originalformular verwende. Muß ich diese wohl noch mit urlencode behandeln?
Solange Du die Daten wie im Beiliel per
Content-type: application/x-www-form-urlencoded
überträgst(was der Normalfall ist): ja. (aber nur die Variableninhalte)
Grüße
Andreas
Solange Du die Daten wie im Beiliel per
Content-type: application/x-www-form-urlencoded
Nur am Rande: [pref:t=40315&m=220961] wäre vielleicht interessant.
Gruß,
soenk.e
Hi!
Content-type: application/x-www-form-urlencoded
Nur am Rande: [pref:t=40315&m=220961] wäre vielleicht interessant.
Ich finde es erheblich komplizierter, von wegen Boundary..., warum sollte ich das an Stelle des obigen Content-type verwenden?
Oder wolltest Du die Möglichkeit nur aufzeigen?
Grüße
Andreas
Content-type: application/x-www-form-urlencoded
Nur am Rande: [pref:t=40315&m=220961] wäre vielleicht interessant.
Ich finde es erheblich komplizierter, von wegen Boundary..., warum sollte ich das an Stelle des obigen Content-type verwenden?
Vielleicht weil mulitpart/form-data erheblich mehr kann als x-www-form-urlencoded (Dateien und den kompletten Unicode-Zeichensatz).
Oder wolltest Du die Möglichkeit nur aufzeigen?
Du hast es erfasst. Um's genau zu sagen: Ich wollte lediglich darauf hinweisen, daß es RFCs gibt, in denen die Formate in allen erdenklichen Details erklärt sind - vielleicht interessiert es ja jemanden.
Gruß,
soenk.e
Hi!
Vielleicht weil mulitpart/form-data erheblich mehr kann als x-www-form-urlencoded (Dateien und den kompletten Unicode-Zeichensatz).
ich verwende es auch manchmal, aber nur wenn ich diese Komplexität auch wirklich brauche udn das ist eher selten.
Grüße
Andreas
Hi, Andreas,
[...] aha, danke!
Wozu dient denn eigentlich im Originalscript "return $res" - nur zum testen?
Und wie kann ich überprüfen, ob die Daten auch tatsächlich von dem externen Formular abgeschickt wurden? Eine kleine Fehlerbehandlung habe ich schon eingebaut - aber ich vermute, daß das noch nicht reicht:
function postToHost($host, $path, $referer, $data_to_send)
{
$fp=@fsockopen($host,80,$errorcode,$errortext,$timeout);
if($fp) {
fputs($fp, "POST $path HTTP/1.1\n");
fputs($fp, "Host: $host\n");
fputs($fp, "Referer: $referer\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
fputs($fp, "Content-length: ". strlen($data_to_send) ."\n");
fputs($fp, "Connection: close\n\n");
fputs($fp, "$data_to_send\n");
while(!feof($fp)) $res .= fgets($fp, 128);
fclose($fp);
return $res;
}
else {
return "$host: $errortext ($errorcode)\n<br>\n";
}
}
Was mich wundert ist, daß ein Absenden von Formularen auf einem fremden Server überhaupt möglich sein soll (was ich bislang noch nicht getestet habe) - das stellt doch eine Sicherheitslücke dar. Wer hindert mich z.B. daran, eine Firma mit gefaketer Post zu bombardieren, wenn ich ganz böse bin? ;-)
Grüße,
Sebastian
Hi!
Wozu dient denn eigentlich im Originalscript "return $res" - nur zum testen?
s.u.
Und wie kann ich überprüfen, ob die Daten auch tatsächlich von dem externen Formular abgeschickt wurden? Eine kleine Fehlerbehandlung habe ich schon eingebaut - aber ich vermute, daß das noch nicht reicht:
was genau willst/kannst Du kontrollieren?
function postToHost($host, $path, $referer, $data_to_send)
{
$fp=@fsockopen($host,80,$errorcode,$errortext,$timeout);
if($fp) {
fputs($fp, "POST $path HTTP/1.1\n");
fputs($fp, "Host: $host\n");
fputs($fp, "Referer: $referer\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
fputs($fp, "Content-length: ". strlen($data_to_send) ."\n");
fputs($fp, "Connection: close\n\n");
fputs($fp, "$data_to_send\n");
hier wird die Ausgabe des HTNL-Formulars per fgets eingelesen
und am Ende mit return als Rückgabewert der Funktion zurückgegeben.
-------------------------------------------------
while(!feof($fp)) $res .= fgets($fp, 128);
fclose($fp);
return $res;
}
-------------------------------------------------
das ist sicher von Dir ;-)
-------------------------------------------------
else {
return "$host: $errortext ($errorcode)\n<br>\n";
}
-------------------------------------------------
Ich wißt nicht ob es diese Schreibweise gibt:
while {} else {}, keie Ahnung. Habs noch nie gesehen.
Aber es würde nichst bringen. Entweder funktionmiert der Aufbau der Socket-Verbindung nicht, dann bekommst Du da einen Fehler, wenn das funktiniert gibt es den Server und er wird Dir antwotrten, Du bekommst also auf alle Fälle was zurück. Z.B. wenn die Seite nicht existiert wenigstens einen 404er HTTP-Fehler.
Bei Erfolg erhälst Du HTTP-Statuscode 200 und dahinter den Quelltext der html-Seite. Wenn darin jetzt steht "Abschicken war erfolgreich" könntest Du mit sowas wie
if(!stristr($res,"Abschicken war erfolgreich")){
echo "fehler!!!";
}
(http://php.net/stristr) prüfen ob es funkttioniert hat.
Du solltest Dir auch nochmal im Manual http://php.net/fsockopen durchlesen, auch die Kommentare, da stehen viele Beispiele.
}
Was mich wundert ist, daß ein Absenden von Formularen auf einem fremden Server überhaupt möglich sein soll (was ich bislang noch nicht getestet habe) - das stellt doch eine Sicherheitslücke dar.
Jeder Trottel könnte das auch von hand mißbrauchen! Vielleicht nicht ganz so efektiv, kommt drauf an wieviele Freunde er hat die da mitmachen ;-)
Wer hindert mich z.B. daran, eine Firma mit gefaketer Post zu bombardieren, wenn ich ganz böse bin? ;-)
Niemand, höchtens das StGB ;-)
Grüße
Andreas
Hi, Andreas,
was genau willst/kannst Du kontrollieren?
hier wird die Ausgabe des HTNL-Formulars per fgets eingelesen
und am Ende mit return als Rückgabewert der Funktion zurückgegeben.while(!feof($fp)) $res .= fgets($fp, 128);
fclose($fp);
return $res;
}
ja, aber wie wird dieser Rückgabewert an den fremden Server geschickt - das verstehe ich nicht ganz ...
das ist sicher von Dir ;-)
ja ...
while {} else {}, keie Ahnung. Habs noch nie gesehen.
das while ist doch im if-Zweig ...
Bei Erfolg erhälst Du HTTP-Statuscode 200 und dahinter den Quelltext der html-Seite.
Beim Auslesen von $res erhalte ich ...
HTTP/1.1 302 Found Date: Mon, 10 Mar 2003 22:08:02 GMT Server: Apache/1.3.19 (Unix) (SuSE/Linux) ApacheJServ/1.1.2 mod_ssl/2.8.3 OpenSSL/0.9.6a PHP/4.3.1 mod_perl/1.25 X-Powered-By: PHP/4.3.1 Location: mail_confirm_en.php?mailto=sebastian.becker%40berlin.de Expires: Mon, 10 Mar 2003 22:08:02 GMT Connection: close Transfer-Encoding: chunked Content-Type: text/html 0
Soll ich vielleicht besser HTTP/1.0 nehmen?
Grüße,
Sebastian
Hi!
while(!feof($fp)) $res .= fgets($fp, 128);
fclose($fp);
return $res;
}
ja, aber wie wird dieser Rückgabewert an den fremden Server geschickt - das verstehe ich nicht ganz ...
Nein. fgets liest auf Deinem Server das aus, was der fremde server auf Dein Request(fputs) antwortet, return sogt nur dafür das es der Rückgabewert der Funktion postToHost ist, also wird echo postToHost(...); die Ausgabe anzeigen.
while {} else {}, keie Ahnung. Habs noch nie gesehen.
das while ist doch im if-Zweig ...
ach so, ja, damit prüfst Du ob der Verbindungs-Aufbau funktioniert hat.
Bei Erfolg erhälst Du HTTP-Statuscode 200 und dahinter den Quelltext der html-Seite.
Beim Auslesen von $res erhalte ich ...
HTTP/1.1 302 Found Date: Mon, 10 Mar 2003 22:08:02 GMT Server: Apache/1.3.19 (Unix) (SuSE/Linux) ApacheJServ/1.1.2 mod_ssl/2.8.3 OpenSSL/0.9.6a PHP/4.3.1 mod_perl/1.25 X-Powered-By: PHP/4.3.1 Location: mail_confirm_en.php?mailto=sebastian.becker%40berlin.de Expires: Mon, 10 Mar 2003 22:08:02 GMT Connection: close Transfer-Encoding: chunked Content-Type: text/html 0
schön! es kann also nichts passieren, da Du umgeleitet wirst nach
mail_confirm_en.php?mailto=sebastian.becker%40berlin.de, d.h. Du solltest den Request _direkt_ an dieses Script schicken, sonst passiert nichts.
Soll ich vielleicht besser HTTP/1.0 nehmen?
auf jeden Fall, http 1.1 ist erheblich komplizierter.
Grüße
Andreas
Hi, Andreas,
return sogt nur dafür das es der Rückgabewert der Funktion postToHost ist, also wird echo postToHost(...); die Ausgabe anzeigen.
stimmt - diesen Rückgabewert brauche ich aber doch nur zu Kontrollzwecken, oder?
es kann also nichts passieren, da Du umgeleitet wirst nach
mail_confirm_en.php?mailto=sebastian.becker%40berlin.de, d.h. Du solltest den Request _direkt_ an dieses Script schicken, sonst passiert nichts.
stimmt nicht ganz - ich schicke das script (testweise) an mail.php und von dort wird normalerweise per Header die Bestätigungsseite mail_confirm_en.php?... aufgerufen.
Es funktioniert also im Prinzip schon - ich will nur sichergehen, daß die Daten auch tatsächlich an beide Server abgeschickt werden. Vielleicht mache ich es entsprechend Deinem Vorschlag durch Suchen in den Rückgabewerten.
Mit fsockopen hatte ich allerdings schon in einem anderen Fall Probleme - insbesondere konnte ich unter PHP 4.1xx die Timeoutzeit nicht beeinflussen und wenn zwar der Server erreichbar war, nicht aber die Seite, bekam ich keine Fehlermeldung ...
Danke nochmals für die freundliche Hilfe, Grüße
Sebastian
Hi!
stimmt - diesen Rückgabewert brauche ich aber doch nur zu Kontrollzwecken, oder?
kommt drauf an, damit kannst Du auch eien komplette html-Seite ausgeben. ,uß den HEader halt abtrennen - aber das willst ja nicht also brauchst Du kein return, höchtens für eine Fehlerbehandling und dann würde ich was aussagekräftigeres als due Ausgabe da rein schreiben.
stimmt nicht ganz - ich schicke das script (testweise) an mail.php und von dort wird normalerweise per Header die Bestätigungsseite mail_confirm_en.php?... aufgerufen.
ach so ist das, nur wenn es erfolgreich war wird weitergeleitet. Dann kannst Du ja prüfen ob in der Ausgabe mail_confirm_en.php vorkommt oder nicht denn in disem Fall hat es ja geklappt, oder?
Mit fsockopen hatte ich allerdings schon in einem anderen Fall Probleme - insbesondere konnte ich unter PHP 4.1xx die Timeoutzeit nicht beeinflussen und wenn zwar der Server erreichbar war, nicht aber die Seite, bekam ich keine Fehlermeldung ...
Die Fehlermeldung kommt als HTTP-Statuscode. Sende mal einen Request an den Server an die Seite "gibet_sicher_nich.html", und gucke Dir die Ausgabe($res) an, Du wirst einen 404er Fehler erhalten.
Mehr über HTTP-Statuscodes erfährst Du hier: http://selfhtml.teamone.de/diverses/httpstatuscodes.htm
Grüße
Andreas
Hi!
Um ein bisschen mit HTTP-Header rumzuspielen ist sicher folgendes Script ganz hilfreich: http://forum.de.selfhtml.org/cgi-bin/http_trace.pl
Grüße
Andreas
Hallo Sebastian,
Hat jemand mal ein praktisches Beispiel?
Das hat Andreas Dir ja schon geliefert. :)
Mich wundert nur, dass noch niemand den theoretischen Hintergrund verlinkt hat: http://www.w3.org/Protocols/rfc2616/rfc2616.html Das ist die offizielle Spezifikation des HTTP/1.1-Protokolls.
Ach ja, da Du Dich ja inzwischen etwas mit HTTP beschäftigt hast, ist vielleicht das hier ganz interessant: http://ppewww.ph.gla.ac.uk/~flavell/www/post-redirect.html (Du setzt ja auch eine Weiterleitung ein)
Christian