diff -u -x .orig -x ~ curl-7.8.orig/lib/escape.c curl-7.8/lib/escape.c --- curl-7.8.orig/lib/escape.c Sat Apr 7 20:37:50 2001 +++ curl-7.8/lib/escape.c Mon Jul 16 15:28:40 2001 @@ -37,7 +37,7 @@ #include "memdebug.h" #endif -char *curl_escape(char *string, int length) +char *curl_escape(const char *string, int length) { int alloc = (length?length:strlen(string))+1; char *ns = malloc(alloc); @@ -88,7 +88,7 @@ return ns; } -char *curl_unescape(char *string, int length) +char *curl_unescape(const char *string, int length) { int alloc = (length?length:strlen(string))+1; char *ns = malloc(alloc); diff -u -x .orig -x ~ curl-7.8.orig/lib/escape.h curl-7.8/lib/escape.h --- curl-7.8.orig/lib/escape.h Thu Mar 22 12:40:58 2001 +++ curl-7.8/lib/escape.h Mon Jul 16 15:28:31 2001 @@ -26,7 +26,7 @@ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ -char *curl_escape(char *string, int length); -char *curl_unescape(char *string, int length); +char *curl_escape(const char *string, int length); +char *curl_unescape(const char *string, int length); #endif diff -u -x .orig -x ~ curl-7.8.orig/lib/formdata.c curl-7.8/lib/formdata.c --- curl-7.8.orig/lib/formdata.c Tue Jun 5 13:27:40 2001 +++ curl-7.8/lib/formdata.c Tue Jul 17 10:21:01 2001 @@ -64,7 +64,7 @@ /* This is a silly duplicate of the function in main.c to enable this source to compile stand-alone for better debugging */ static void GetStr(char **string, - char *value) + const char *value) { if(*string) free(*string); @@ -299,6 +299,50 @@ return FormParse(input, httppost, last_post); } +/*************************************************************************** + * + * FormAdd() + * + * Stores the name, value paramters and builds the appropriate linked list. + * + ***************************************************************************/ + +static +int FormAdd(const char *name, + const char *value, + struct HttpPost **httppost, + struct HttpPost **last_post) +{ + struct HttpPost *post; + post = (struct HttpPost *)malloc(sizeof(struct HttpPost)); + if(post) { + memset(post, 0, sizeof(struct HttpPost)); + GetStr(&post->name, name); /* get the name */ + GetStr(&post->contents, value); /* get the contents */ + post->flags = 0; + } + else + return 1; + + /* make the previous point to this */ + if(*last_post) + (*last_post)->next = post; + else + (*httppost) = post; + + (*last_post) = post; + + return 0; +} + +int curl_formadd(const char *name, + const char *value, + struct HttpPost **httppost, + struct HttpPost **last_post) +{ + return FormAdd(name, value, httppost, last_post); +} + static int AddFormData(struct FormData **formp, void *line, long length) @@ -584,12 +628,58 @@ memcpy(buffer, form->data->line + form->sent, gotsize = (form->data->length - form->sent) ); + + form->sent = 0; + + form->data = form->data->next; /* advance */ + + } while(!gotsize && form->data); + /* If we got an empty line and we have more data, we proceed to the next + line immediately to avoid returning zero before we've reached the end. + This is the bug reported November 22 1999 on curl 6.3. (Daniel) */ + + return gotsize; +} +/* fread() emulation */ +int Curl_FastFormReader(char *buffer, + size_t size, + size_t nitems, + FILE *mydata) +{ + struct Form *form; + int wantedsize; + int gotsize = 0; + + form=(struct Form *)mydata; + + wantedsize = size * nitems; + + if(!form->data) + return -1; /* nothing, error, empty */ + + do { + + if( (form->data->length - form->sent ) > wantedsize - gotsize) { + + memcpy(buffer + gotsize , form->data->line + form->sent, + wantedsize - gotsize); + + form->sent += wantedsize-gotsize; + + return wantedsize; + } + + memcpy(buffer+gotsize, + form->data->line + form->sent, + (form->data->length - form->sent) ); + gotsize += form->data->length - form->sent; + form->sent = 0; form->data = form->data->next; /* advance */ - } while(!gotsize && form->data); + } while(form->data); /* If we got an empty line and we have more data, we proceed to the next line immediately to avoid returning zero before we've reached the end. This is the bug reported November 22 1999 on curl 6.3. (Daniel) */ diff -u -x .orig -x ~ curl-7.8.orig/lib/formdata.h curl-7.8/lib/formdata.h --- curl-7.8.orig/lib/formdata.h Fri Jan 5 11:11:42 2001 +++ curl-7.8/lib/formdata.h Tue Jul 17 09:11:58 2001 @@ -47,6 +47,12 @@ size_t nitems, FILE *mydata); +/* fread() emulation */ +int Curl_FastFormReader(char *buffer, + size_t size, + size_t nitems, + FILE *mydata); + char *Curl_FormBoundary(void); void Curl_FormFree(struct FormData *); diff -u -x .orig -x ~ curl-7.8.orig/lib/http.c curl-7.8/lib/http.c --- curl-7.8.orig/lib/http.c Thu May 31 12:55:59 2001 +++ curl-7.8/lib/http.c Tue Jul 17 09:24:52 2001 @@ -704,6 +704,8 @@ } if(data->bits.http_formpost) { + char contentType[256]; + int written1 = 0; if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!\n"); return CURLE_HTTP_POST_ERROR; @@ -712,13 +714,36 @@ http->storefread = data->fread; /* backup */ http->in = data->in; /* backup */ - data->fread = (curl_read_callback) - Curl_FormReader; /* set the read function to read from the - generated form data */ + /* set the read function to read from the + generated form data */ + if (data->bits.http_post_fast_form_reader) { + data->fread = (curl_read_callback) + Curl_FastFormReader; + } + else { + data->fread = (curl_read_callback) + Curl_FormReader; + } data->in = (FILE *)&http->form; add_bufferf(req_buffer, "Content-Length: %d\r\n", http->postsize-2); + if (data->bits.http_post_use_continue) { + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + /* Get Content-Type: line from FormReader */ + if ( (written1 = Curl_FormReader (contentType, 256, 1, &http->form)) + == -1) { + failf(data, "Could not get Content-Type header line!\n"); + return CURLE_HTTP_POST_ERROR; + } + /* Add newline to tell HTTP server header is done */ + contentType[written1] = '\r'; + contentType[written1+1] = '\n'; + contentType[written1+2] = '\0'; + add_bufferf(req_buffer, + contentType); + } /* set upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); diff -u -x .orig -x ~ curl-7.8.orig/lib/transfer.c curl-7.8/lib/transfer.c --- curl-7.8.orig/lib/transfer.c Tue May 22 23:09:09 2001 +++ curl-7.8/lib/transfer.c Tue Jul 17 10:24:50 2001 @@ -265,6 +265,18 @@ keepon |= KEEP_WRITE; } + if (data->bits.http_formpost && data->bits.http_post_use_continue) { + /* read 100 continue if we asked for it should be 25 bytes + * but we have got a problem when there are more than 1024 bytes! */ + char tmpBuffer[1024]; + int tmpRead, tmpRet; + if ((tmpRet = Curl_read(conn, conn->sockfd, tmpBuffer, 1024, &tmpRead)) + == -1) { + failf(data, "Failed reading 100 continue"); + return CURLE_WRITE_ERROR; + } + } + /* get these in backup variables to be able to restore them on each lap in the select() loop */ rkeepfd = readfd; @@ -758,6 +770,8 @@ if ((signed int)nread<=0) { /* done */ keepon &= ~KEEP_WRITE; /* we're done writing */ + FD_CLR(conn->writesockfd, &wkeepfd); /* prevent select from + * awakening us with wkeepfd*/ break; } writebytecount += nread; diff -u -x .orig -x ~ curl-7.8.orig/lib/url.c curl-7.8/lib/url.c --- curl-7.8.orig/lib/url.c Thu Jun 7 07:59:20 2001 +++ curl-7.8/lib/url.c Tue Jul 17 09:29:56 2001 @@ -792,6 +792,20 @@ */ data->telnet_options = va_arg(param, struct curl_slist *); break; + case CURLOPT_HTTPPOST_USE_CONTINUE: + /* + * Do use a Expect: 100-continue in the header and read the answer + * => Use 100-continue handshake for CURLOPT_HTTPPOST + */ + data->bits.http_post_use_continue = va_arg(param, long)?TRUE:FALSE; + break; + case CURLOPT_HTTPPOST_FASTFORMREADER: + /* + * Do use CurlFastFormReader instead of Curl_FormReader when + * performing a CURLOPT_HTTPPOST + */ + data->bits.http_post_fast_form_reader = va_arg(param, long)?TRUE:FALSE; + break; default: /* unknown tag and its companion, just ignore: */ return CURLE_READ_ERROR; /* correct this */ diff -u -x .orig -x ~ curl-7.8.orig/lib/urldata.h curl-7.8/lib/urldata.h --- curl-7.8.orig/lib/urldata.h Thu May 31 15:50:28 2001 +++ curl-7.8/lib/urldata.h Tue Jul 17 09:11:06 2001 @@ -415,6 +415,10 @@ after use */ bool reuse_fresh; /* do not re-use an existing connection for this transfer */ + bool http_post_use_continue; /* do use Expect: 100-continue + for CURLOPT_HTTPPOST */ + bool http_post_fast_form_reader; /* do use Curl_FastFormReader for + CURLOPT_HTTPPOST */ }; /* diff -u -x .orig -x ~ curl-7.8.orig/include/curl/curl.h curl-7.8/include/curl/curl.h --- curl-7.8.orig/include/curl/curl.h Thu Jun 7 11:33:36 2001 +++ curl-7.8/include/curl/curl.h Tue Jul 17 09:16:28 2001 @@ -443,6 +443,13 @@ * parameters will use fwrite() syntax, make sure to follow them. */ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + /* Whether CURLOPT_HTTPPOST will use 100-continue handshake */ + CINIT(HTTPPOST_USE_CONTINUE, LONG, 80), + + /* Whether CURLOPT_HTTPPOST will use fast Curl_FastFormReader + * (instead of Curl_FormReader) */ + CINIT(HTTPPOST_FASTFORMREADER, LONG, 81), + CURLOPT_LASTENTRY /* the last unusued */ } CURLoption; @@ -478,6 +485,12 @@ struct HttpPost **httppost, struct HttpPost **last_post); +/* add name value pair for form */ +int curl_formadd(const char *name, + const char *value, + struct HttpPost **httppost, + struct HttpPost **last_post); + /* cleanup a form: */ void curl_formfree(struct HttpPost *form); @@ -490,8 +503,8 @@ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ -char *curl_escape(char *string, int length); -char *curl_unescape(char *string, int length); +char *curl_escape(const char *string, int length); +char *curl_unescape(const char *string, int length); /* curl_global_init() should be invoked exactly once for each application that uses libcurl */ diff -u -P -x .orig -X curl-7.8/docs/Makefile curl-7.8.orig/docs/Makefile.am curl-7.8/docs/Makefile.am --- curl-7.8.orig/docs/Makefile.am Tue May 29 14:09:47 2001 +++ curl-7.8/docs/Makefile.am Tue Jul 17 09:59:58 2001 @@ -13,6 +13,7 @@ curl_easy_perform.3 \ curl_easy_setopt.3 \ curl_formparse.3 \ + curl_formadd.3 \ curl_formfree.3 \ curl_getdate.3 \ curl_getenv.3 \ diff -u -P -x .orig -X curl-7.8/docs/Makefile curl-7.8.orig/docs/curl_easy_setopt.3 curl-7.8/docs/curl_easy_setopt.3 --- curl-7.8.orig/docs/curl_easy_setopt.3 Fri Jun 1 09:33:38 2001 +++ curl-7.8/docs/curl_easy_setopt.3 Tue Jul 17 09:51:36 2001 @@ -274,8 +274,22 @@ list of 'struct HttpPost' structs properly filled in. The best and most elegant way to do this, is to use .I curl_formparse(3) +or +.I curl_formadd(3) as documented. The data in this list must remained intact until you close this curl handle again with curl_easy_cleanup(). +.B CURLOPT_HTTPPOST_USECONTINUE +A non-zero parameter tells the library you want to use a 100-continue +handshake with the HTTP server for a multipart/formdata HTTP +POST. This might decrease network delays (especially in LAN environments). +.TP +.B CURLOPT_HTTPPOST_FASTFORMREADER +A non-zero parameter tells the library you want to use an alternative +read function for the multipart/formdata HTTP POST form that provides +libcurl always with as much bytes as are available/requested (taking +the smaller amount of the two values) instead of providing the next +line if it fits into the provided buffer (and possibly much less +bytes). This minimizes the calls to the write/... functions. .TP .B CURLOPT_SSLCERT Pass a pointer to a zero terminated string as parameter. The string should be diff -u -P -x .orig -X curl-7.8/docs/Makefile curl-7.8.orig/docs/curl_formadd.3 curl-7.8/docs/curl_formadd.3 --- curl-7.8.orig/docs/curl_formadd.3 Thu Jan 1 01:00:00 1970 +++ curl-7.8/docs/curl_formadd.3 Tue Jul 17 09:58:03 2001 @@ -0,0 +1,60 @@ +.\" You can view this file with: +.\" nroff -man [file] +.\" $Id: curl_formadd.3,v 1.12 2001/07/17 08:41:42 bagder Exp $ +.\" +.TH curl_formparse 3 "17 July 2001" "libcurl 7.8" "libcurl Manual" +.SH NAME +curl_formparse - add a section to a multipart/formdata HTTP POST +.SH SYNOPSIS +.B #include +.sp +.BI "CURLcode curl_formadd(const char * " name, "const char * " value, +.BI " struct HttpPost ** " firstitem, "struct HttpPost ** " lastitem ");" +.ad +.SH DESCRIPTION +curl_formadd() is used to append sections when building a multipart/formdata +HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at +a time until you've added all the sections you want included and then you pass +the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP. +\fIlastitem\fP is set after each call and on repeated invokes it should be +left as set to allow repeated invokes to find the end of the list in a faster +way. \fIstring\fP must be a zero terminated string abiding to the syntax +described in a section below + +The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to +NULL in the first call to this function. All list-data will be allocated by +the function itself. You must call \fIcurl_formfree\fP after the form post has +been done to free the resources again. + +This function will copy all input data and keep its own version of it +allocated until you call \fIcurl_formfree\fP. When you've passed the pointer +to \fIcurl_easy_setopt\fP, you must not free the list until after you've +called \fIcurl_easy_cleanup\fP for the curl handle. + +You may mix calls to \fIcurl_formparse\fP and \fIcurl_formadd\fP as +you like. + +See example below. +.SH RETURN VALUE +Returns non-zero if an error occurs. +.SH EXAMPLE + + HttpPost* post = NULL; + HttpPost* last = NULL; + + /* Add an image section */ + curl_formparse("picture=@my-face.jpg", &post, &last); + /* Add a normal text section */ + curl_formadd("name", "FooBar", &post, &last); + /* Add a normal text section */ + curl_formparse("name=FooBar", &post, &last); + /* Set the form info */ + curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); + +.SH "SEE ALSO" +.BR curl_easy_setopt "(3), " +.BR curl_formparse "(3), " +.BR curl_formfree "(3) +.SH BUGS +Surely there are some, you tell me! + diff -u -P -x .orig -X curl-7.8/docs/Makefile curl-7.8.orig/docs/curl_formparse.3 curl-7.8/docs/curl_formparse.3 --- curl-7.8.orig/docs/curl_formparse.3 Thu May 31 10:41:42 2001 +++ curl-7.8/docs/curl_formparse.3 Tue Jul 17 09:58:22 2001 @@ -79,6 +79,7 @@ .SH "SEE ALSO" .BR curl_easy_setopt "(3), " +.BR curl_formadd "(3), " .BR curl_formfree "(3) .SH BUGS Surely there are some, you tell me! Common subdirectories: curl-7.8.orig/docs/examples and curl-7.8/docs/examples