[C++] libCurl FORM Data (HTTP POST) Problem

DasIrrlicht

Grünschnabel
Servus!

Hab wieder ein kleine Problem mit libCurl. Ich rufe in meinem Programm diverse Seiten auf, auch als POST mit Daten im Anhang. Nun habe ich das Problem, dass wohl (laut Wireshark) immer wieder die gleichen FORM Daten (also von einem HTML Form) mit geschickt werden. So wird bei einem Aufruf irgendeiner Seite noch immer der Benutzername und das Kennwort mit geschickt.

So setze ich ein Feld:
C:
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "fieldname", CURLFORM_COPYCONTENTS, "fieldvalue", CURLFORM_END);
Vor jedem Aufruf einer Seite mache ich folgende Funktionsaufrufe:
C:
// Reset the formpost chain
curl_formfree(formpost); // Ein Versuch, funktioniert leider nicht
// Reset curl_handle
curl_easy_reset(curl_handle);

Mein eigentliches Problem ist jedoch, dass ich eine Seite habe, die anders ist als die anderen und hier der POST Aufruf nicht funktioniert. Sprich alle anderen Seite interessiert das gar nicht, dass die Daten da noch drin sind.

Der Unterschied zu den anderen Seiten ist:
- Es ist eine URL mit GET Daten zusaetzlich (http://www.example.com/blah.php?getvar=data).
- Das Form hat kein Submit Feld, sonder wird per <a href='#'' onCLick='document.formname.submit()'> "gesubmitted".

Also ich rufe die Seite so:
C:
curl_formfree(formpost);
curl_easy_reset(curl_handle);
curl_easy_setopt(curl_handle, CURLOPT_URL, "www.example.com/blah.php?getvar=data");
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "post_field", CURLFORM_COPYCONTENTS, "post_data", CURLFORM_END);
curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, formpost);

Das Ergebnis ist dann eben nicht das gewuenschte, sonder ich bin immer noch im selben Zustand wie zuvor.

Eine Sache koennte ich mir noch vorstelle, wuesste aber nicht wie ich das umsetzen soll (google schweigt sich aus). Wenn ich als CURLOPT_URL die URL mit # aufrufe (HREF vom Submit). Aber wie geb ich dann die GET Daten mit? :confused:

Hoffe ihr koennt mir weiterhelfen!
Danke,
Daniel
 
Hi.

Mehr Informationen wären nicht schlecht. Wie sehen die Anfragen normalerweise aus? Was wird von curl übermittelt? Wie sieht das Forumular aus? Hat das Forumular einen onsubmit Eventhandler? Wenn ja, was passiert da?

Eigentlich ist es eher ungewöhnlich, dass eine Anfrage nicht klappt wenn irgendwelche Daten zusätzlich übermittelt werden, meistens liegt es eher daran, dass irgendwelche Daten fehlen.

Gruß
 
Servus!

Danke fuer deine Antwort!

So schaut mein POST Request per Wireshark aus:
Code:
POST /create.php?open=new HTTP/1.1
#####################
EgxC@
#XPF,'W{Py------------------------------5428f0bf75ba
Content-Disposition: form-data; name="username"

blahuser
------------------------------5428f0bf75ba
Content-Disposition: form-data; name="password"

blahpassword
------------------------------5428f0bf75ba
Content-Disposition: form-data; name="agbcheck"

agbchecked
------------------------------5428f0bf75ba
Content-Disposition: form-data; name="submit"

Login
------------------------------5428f0bf75ba
Content-Disposition: form-data; name="randomval"

1094043805
------------------------------5428f0bf75ba--
Das einzige Feld welches ich mitgeben _will_ ist "randomval". Die anderen Felder (inklusive dem Submit Feld) kommen von einem ganz anderen POST Request, naemlich dem Login. Der ist da aber schon lange vorbei. Kann es sein, dass das Submit Feld das ganze versaut? Eben weil es nicht da sein sollte?

Ich habe gerade kein Paket von einem original Request, aber ich weiss, dass da wirklich nur das Feld "randomval" drin steht, sonst nichts.

Das Formular sieht wie folgt aus:
HTML:
<form method='post' name='doaction' action='create.php?open=new'>
            <input type='hidden' name='randomval' value='831856300'>
            <a href='#'' onCLick='document.kontoerf.submit()'>Do it now!</a><br /><br />

Das </form> fehlt im ganzen Quelltext. Ein OnSubmit Event gibt es auch nicht.

Hoffe das hilft weiter, wenn noch mehr Info fehlt, einfach kurz sagen :)

Danke!
Daniel
 
Hi!

Danke für deine Antwort! Das hab ich schon probiert. Sorry, hab ich vergessen zu sagen.

Zuerst hab ich überprüft ob formpost != NULL ist und wollte es dann auf NULL setzen. Da aber formpost und lastptr immer schon NULL waren, hab ich es einfach noch einmal auf NULL gesetzt, also ohne vorherige Abfrage. Hat leider gar nichts geändert. Scheinbar werden die beiden schon von libCurl nach Verwendung wieder auf NULL gesetzt. Ich habe es auf jeden Fall nicht getan, zumal ich sowohl curl_formfree(formpost); und curl_easy_reset(curl_handle); erst danach aufgerufen habe. Ich debugge jetzt noch einmal alles durch und hoffe mir fällt doch noch etwas auf. Wenn dir (euch) noch etwas einfällt, nur zu! :)

Danke!
Daniel
 
So, hier jetzt noch mal der momentane Stand.

Ein original Browser Request:
Code:
G``En@@HXP7c
b'EPOST /job.php?open=new HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.04 (jaunty) Firefox/3.0.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://www.example.com/job.php
Cookie: sess=1247833826; sessid=e68b03d6156c17643686174746544654c456e666572
Content-Type: application/x-www-form-urlencoded
Content-Length: 16

randomval=712964474

Dazu das Paket das von libCurl verschickt wird:
Code:
G``Ec@@XTPjb/w9.
{_,dPOST /job.php?open=new HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: www.example.com
Accept: */*
Cookie: sessid=66e01d8a0f61b5043686174746544654c456e666572; sess=1247834669
Content-Length: 575
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------0d9e3a7f10cc

G``Ese@@XTPjcwR.
{{,------------------------------0d9e3a7f10cc
Content-Disposition: form-data; name="username"

myusername
------------------------------0d9e3a7f10cc
Content-Disposition: form-data; name="password"

mypassword
------------------------------0d9e3a7f10cc
Content-Disposition: form-data; name="agbcheck"

agbchecked
------------------------------0d9e3a7f10cc
Content-Disposition: form-data; name="submit"

Login
------------------------------0d9e3a7f10cc
Content-Disposition: form-data; name="randomval"

1199661318
------------------------------0d9e3a7f10cc--

Ich frage mich wirklich wie libCurl darauf kommt, gerade diese Daten zu übermitteln. Schließlich wird nach dem Login und vor diesem Request noch häufig ein POST Request ausgeführt. Dabei ist mir übrigens aufgefallen, dass es sogar soweit kommen kann, dass aus einem Request drei Pakete werden, weil die gleichen Daten 20 mal aufgeführt werden. ich führe aber vor jedem Request curl_formfree(formpost); und curl_easy_reset(curl_handle); aus.

So nun noch wie ich den Request mache:
C++:
// Reset the formpost chain
curl_formfree(formpost);
// Reset curl_handle
curl_easy_reset(curl_handle);
// what URL
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.example.com/job.php?open=new");
// send all data to this function
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
// we pass our 'chunk' struct to the callback function
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
//curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "randomval", CURLFORM_COPYCONTENTS, rand_val.c_str(), CURLFORM_END);
// make this a post call
curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, formpost);
if(curl_easy_perform(curl_handle) != CURLE_OK){
  cout << endl << "Error: Could not receive job.php?open=new" << endl;
  return 0;
}

Ich suche weiter...


EDIT:

Ich habe nun versucht das ganze mit einem neuen formpost und lastptr (einfach noch zwei curl_httppost pointer namens formpost2 und lastptr2) durchzuspielen. Das Paket sieht nun frei von alten Form-Daten aus, funktionieren tut es trotzdem nicht. Was stimmt mit meinem Paket/Request nicht :( Ich werd schon ganz verwirrt...
 
Zuletzt bearbeitet von einem Moderator:
Als kleines Workaroud wollte ich versuchen statt mit curl_formadd() mit curl_easy_setopt und CURLOPT_POSTFIELDS zu arbeiten. Es scheint zumindest bei manchen Versuchen, dass keine Alt-Daten mehr vorhanden sind. Leider scheint libCurl keine gute Laune zu haben und schneidet meine POST Daten einfach ab. Hier mal ein Beispiel Paket:

Code:
G``E#%@@XPd"A
&POST /login.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: www.example.com
Accept: */*
Cookie: sess=1248003067
Content-Length: 17
Content-Type: application/x-www-form-urlencoded

username=testnaQ

hier fehlt der halbe Benutzername, das Passwort, eine randomvalue und das Submit Feld. Das das nicht funktioniert ist ja irgendwie klar. Hier der Code den ich verwende:

C++:
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.example.com/login.php");
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, 0);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, "username=testname&password=secret&randomval=123456&submit=Login";
curl_easy_perform(curl_handle);

Kann das normal sein oder ist die libCurl einfach buggy? Bin ich zu blöd? Ich weiß nicht was ich da falsch machen kann...

EDIT:
Noch ein belustigendes Beispiel:
Code:
G``EK>@@XPPi
4WPOST /job.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: www.example.com
Accept: */*
Cookie: sessid=8523f3b0cd9f9e94972726c69636874; sess=1248006197
Content-Length: 14
Content-Type: application/x-www-form-urlencoded

n/x-www-form-u

Ups, wo kommt denn das her?
 
Zuletzt bearbeitet von einem Moderator:
Hat sich erledigt, es war gar kein libCurl Problem und auch kein Fehler meinerseits. Die Seite die ich versucht habe zu benutzen hat einen Bug. Ich versuche hier eine bestimmte Aktion "freizuschalten" mit dem POST. Das Problem ist, wenn man nicht ueber einen Browser auf die Seite zugreift, kann man die Aktion auch ohne das Freischalten ausfuehren. Wenn man dies tut ist aber das Freischalten (was ich die ganze Zeit versuche) nicht mehr moeglich.

Nach dem erstellen eines neuen Account funktioniert es nun einwandfrei... ;-)

Danke trotzdem fuer die Unterstuetzung!

Daniel
 
Zurück