if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form);
data->req.p.http = http;
connkeep(conn, "HTTP default");
return CURLE_OK;
Curl_dyn_free(&http->send_buffer);
- Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
Curl_hyper_done(data);
Curl_ws_done(data);
switch(httpreq) {
case HTTPREQ_POST_MIME:
- http->sendit = &data->set.mimepost;
+ data->state.mimepost = &data->set.mimepost;
break;
#ifndef CURL_DISABLE_FORM_API
case HTTPREQ_POST_FORM:
- /* Convert the form structure into a mime structure. */
- Curl_mime_cleanpart(&http->form);
- result = Curl_getformdata(data, &http->form, data->set.httppost,
- data->state.fread_func);
- if(result)
- return result;
- http->sendit = &http->form;
+ /* Convert the form structure into a mime structure, then keep
+ the conversion */
+ if(!data->state.formp) {
+ data->state.formp = calloc(sizeof(curl_mimepart), 1);
+ if(!data->state.formp)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_mime_cleanpart(data->state.formp);
+ result = Curl_getformdata(data, data->state.formp, data->set.httppost,
+ data->state.fread_func);
+ if(result)
+ return result;
+ data->state.mimepost = data->state.formp;
+ }
break;
#endif
default:
- http->sendit = NULL;
+ data->state.mimepost = NULL;
}
#ifndef CURL_DISABLE_MIME
- if(http->sendit) {
+ if(data->state.mimepost) {
const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
/* Read and seek body only. */
- http->sendit->flags |= MIME_BODY_ONLY;
+ data->state.mimepost->flags |= MIME_BODY_ONLY;
/* Prepare the mime structure headers & set content type. */
if(cthdr)
for(cthdr += 13; *cthdr == ' '; cthdr++)
;
- else if(http->sendit->kind == MIMEKIND_MULTIPART)
+ else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
cthdr = "multipart/form-data";
- curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
+ curl_mime_headers(data->state.mimepost, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
NULL, MIMESTRATEGY_FORM);
- curl_mime_headers(http->sendit, NULL, 0);
+ curl_mime_headers(data->state.mimepost, NULL, 0);
if(!result)
- result = Curl_mime_rewind(http->sendit);
+ result = Curl_mime_rewind(data->state.mimepost);
if(result)
return result;
- http->postsize = Curl_mime_size(http->sendit);
+ http->postsize = Curl_mime_size(data->state.mimepost);
}
#endif
{
struct curl_slist *hdr;
- for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
+ for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
if(result)
return result;
/* Read from mime structure. */
data->state.fread_func = (curl_read_callback) Curl_mime_read;
- data->state.in = (void *) http->sendit;
+ data->state.in = (void *) data->state.mimepost;
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
* HTTP unique setup
***************************************************************************/
struct HTTP {
- curl_mimepart *sendit;
curl_off_t postsize; /* off_t to handle large file sizes */
const char *postdata;
-
- /* For FORM posting */
- curl_mimepart form;
-
struct back {
curl_read_callback fread_func; /* backup storage for fread pointer */
void *fread_in; /* backup storage for fread_in pointer */
void Curl_mime_cleanpart(curl_mimepart *part)
{
- cleanup_part_content(part);
- curl_slist_free_all(part->curlheaders);
- if(part->flags & MIME_USERHEADERS_OWNER)
- curl_slist_free_all(part->userheaders);
- Curl_safefree(part->mimetype);
- Curl_safefree(part->name);
- Curl_safefree(part->filename);
- Curl_mime_initpart(part);
+ if(part) {
+ cleanup_part_content(part);
+ curl_slist_free_all(part->curlheaders);
+ if(part->flags & MIME_USERHEADERS_OWNER)
+ curl_slist_free_all(part->userheaders);
+ Curl_safefree(part->mimetype);
+ Curl_safefree(part->name);
+ Curl_safefree(part->filename);
+ Curl_mime_initpart(part);
+ }
}
/* Recursively delete a mime handle and its parts. */
*/
static CURLcode readrewind(struct Curl_easy *data)
{
- struct connectdata *conn = data->conn;
curl_mimepart *mimepart = &data->set.mimepost;
- DEBUGASSERT(conn);
+ DEBUGASSERT(data->conn);
data->state.rewindbeforesend = FALSE; /* we rewind now */
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
CURLOPT_HTTPPOST, call app to rewind
*/
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.p.http;
-
- if(http->sendit)
- mimepart = http->sendit;
+#ifndef CURL_DISABLE_HTTP
+ if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ if(data->state.mimepost)
+ mimepart = data->state.mimepost;
}
+#endif
if(data->set.postfields ||
(data->state.httpreq == HTTPREQ_GET) ||
(data->state.httpreq == HTTPREQ_HEAD))
#ifndef CURL_DISABLE_FORM_API
case CURLOPT_HTTPPOST:
/*
- * Set to make us do HTTP POST
+ * Set to make us do HTTP POST. Legacy API-style.
*/
data->set.httppost = va_arg(param, struct curl_httppost *);
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
+ Curl_mime_cleanpart(data->state.formp);
+ Curl_safefree(data->state.formp);
break;
#endif
if(!result) {
data->set.method = HTTPREQ_POST_MIME;
data->set.opt_no_body = FALSE; /* this is implied */
+#ifndef CURL_DISABLE_FORM_API
+ Curl_mime_cleanpart(data->state.formp);
+ Curl_safefree(data->state.formp);
+#endif
}
break;
}
#endif
+ Curl_mime_cleanpart(data->state.formp);
+#ifndef CURL_DISABLE_HTTP
+ Curl_safefree(data->state.formp);
+#endif
+
/* destruct wildcard structures if it is needed */
Curl_wildcard_dtor(&data->wildcard);
Curl_freeset(data);
struct curl_slist *resolve; /* set to point to the set.resolve list when
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
+ curl_mimepart *mimepost;
+ curl_mimepart *formp; /* storage for old API form-posting, alloced on
+ demand */
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
headers */
#
# Server-side
<reply>
-<data>
-HTTP/1.1 200 OK\r
+<data nocheck="yes">
+HTTP/1.1 301 OK\r
Date: Tue, 09 Nov 2010 14:49:00 GMT\r
Server: test-server/fake swsclose\r
Connection: close\r
Content-Type: text/html\r
+Location: /%TESTNUMBER0002
\r
hello
</data>
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
+-foo-
+</data>
</reply>
# Client-side
</tool>
<name>
-HTTP formpost using form API
+HTTP formpost using form API - with redirect and re-POST
</name>
<stdin>
Some data from stdin
Content-Type: application/octet-stream\r
\r
\r
+16\r
+ Some data from stdin
+\r
+30\r
+\r
+--------------------------------\r
+\r
+0\r
+\r
+POST /%TESTNUMBER0002 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+Transfer-Encoding: chunked\r
+Content-Type: multipart/form-data; boundary=----------------------------\r
+Expect: 100-continue\r
+\r
+361\r
+------------------------------\r
+Content-Disposition: form-data; name="fieldname"\r
+Content-Type: text/plain\r
+X-customheader-1: Header 1 data\r
+X-customheader-2: Header 2 data\r
+\r
+this is what we post to the silly web server\r
+------------------------------\r
+Content-Disposition: form-data; name="fieldnam"\r
+\r
+uhis is what we post to the silly web serve\r
+------------------------------\r
+Content-Disposition: form-data; name="multifile"\r
+Content-Type: multipart/mixed; boundary=----------------------------\r
+\r
+------------------------------\r
+Content-Disposition: attachment; filename="test%TESTNUMBER.filedata"\r
+Content-Type: application/octet-stream\r
+\r
+This is data from a file.
+\r
+------------------------------\r
+Content-Disposition: attachment; filename="test%TESTNUMBER.filedata"\r
+Content-Type: text/whatever\r
+\r
+\r
+%if hyper
+A5\r
+%else
+a5\r
+%endif
+This is data from a file.
+\r
+------------------------------\r
+Content-Disposition: attachment; filename="test%TESTNUMBER.filedata"\r
+Content-Type: text/whatever\r
+\r
+\r
+%if hyper
+AF\r
+%else
+af\r
+%endif
+This is data from a file.
+\r
+--------------------------------\r
+\r
+------------------------------\r
+Content-Disposition: form-data; name="filecontents"\r
+\r
+\r
+%if hyper
+10F\r
+%else
+10f\r
+%endif
+This is data from a file.
+\r
+------------------------------\r
+Content-Disposition: form-data; name="formlength"\r
+\r
+1367\r
+------------------------------\r
+Content-Disposition: form-data; name="standardinput"\r
+Content-Type: application/octet-stream\r
+\r
+\r
16\r
Some data from stdin
\r
/* get verbose debug output please */
test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ test_setopt(curl, CURLOPT_POSTREDIR, (long)CURL_REDIR_POST_301);
+
/* include headers in the output */
test_setopt(curl, CURLOPT_HEADER, 1L);