aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/http.c142
-rw-r--r--lib/sendf.c90
-rw-r--r--lib/sendf.h14
3 files changed, 175 insertions, 71 deletions
diff --git a/lib/http.c b/lib/http.c
index 4e3471b36..7e2089496 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -340,35 +340,41 @@ CURLcode http(struct connectdata *conn)
http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
do {
+ send_buffer *req_buffer;
struct curl_slist *headers=data->headers;
- sendf(data->firstsocket, data,
- "%s " /* GET/HEAD/POST/PUT */
- "%s HTTP/1.0\r\n" /* path */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- "%s" /* range */
- "%s" /* user agent */
- "%s" /* cookie */
- "%s" /* host */
- "%s" /* pragma */
- "%s" /* accept */
- "%s", /* referer */
-
- data->customrequest?data->customrequest:
- (data->bits.no_body?"HEAD":
- (data->bits.http_post || data->bits.http_formpost)?"POST":
- (data->bits.http_put)?"PUT":"GET"),
- ppath,
- (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
- (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
- (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
- (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
- (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
- (data->ptr_host?data->ptr_host:""), /* Host: host */
- http->p_pragma?http->p_pragma:"",
- http->p_accept?http->p_accept:"",
- (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
- );
+
+ /* initialize a dynamic send-buffer */
+ req_buffer = add_buffer_init();
+
+ /* add the main request stuff */
+ add_bufferf(req_buffer,
+ "%s " /* GET/HEAD/POST/PUT */
+ "%s HTTP/1.0\r\n" /* path */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* cookie */
+ "%s" /* host */
+ "%s" /* pragma */
+ "%s" /* accept */
+ "%s", /* referer */
+
+ data->customrequest?data->customrequest:
+ (data->bits.no_body?"HEAD":
+ (data->bits.http_post || data->bits.http_formpost)?"POST":
+ (data->bits.http_put)?"PUT":"GET"),
+ ppath,
+ (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
+ (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
+ (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
+ (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
+ (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
+ (data->ptr_host?data->ptr_host:""), /* Host: host */
+ http->p_pragma?http->p_pragma:"",
+ http->p_accept?http->p_accept:"",
+ (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
+ );
if(co) {
int count=0;
@@ -376,19 +382,16 @@ CURLcode http(struct connectdata *conn)
while(co) {
if(co->value && strlen(co->value)) {
if(0 == count) {
- sendf(data->firstsocket, data,
- "Cookie:");
+ add_bufferf(req_buffer, "Cookie:");
}
- sendf(data->firstsocket, data,
- "%s%s=%s", count?"; ":"", co->name,
- co->value);
+ add_bufferf(req_buffer,
+ "%s%s=%s", count?"; ":"", co->name, co->value);
count++;
}
co = co->next; /* next cookie please */
}
if(count) {
- sendf(data->firstsocket, data,
- "\r\n");
+ add_buffer(req_buffer, "\r\n", 2);
}
cookie_freelist(co); /* free the cookie list */
co=NULL;
@@ -419,16 +422,16 @@ CURLcode http(struct connectdata *conn)
switch(data->timecondition) {
case TIMECOND_IFMODSINCE:
default:
- sendf(data->firstsocket, data,
- "If-Modified-Since: %s\r\n", buf);
+ add_bufferf(req_buffer,
+ "If-Modified-Since: %s\r\n", buf);
break;
case TIMECOND_IFUNMODSINCE:
- sendf(data->firstsocket, data,
- "If-Unmodified-Since: %s\r\n", buf);
+ add_bufferf(req_buffer,
+ "If-Unmodified-Since: %s\r\n", buf);
break;
case TIMECOND_LASTMOD:
- sendf(data->firstsocket, data,
- "Last-Modified: %s\r\n", buf);
+ add_bufferf(req_buffer,
+ "Last-Modified: %s\r\n", buf);
break;
}
}
@@ -445,9 +448,7 @@ CURLcode http(struct connectdata *conn)
if(*ptr) {
/* only send this if the contents was non-blank */
- sendf(data->firstsocket, data,
- "%s\015\012",
- headers->data);
+ add_bufferf(req_buffer, "%s\r\n", headers->data);
}
}
headers = headers->next;
@@ -468,12 +469,13 @@ CURLcode http(struct connectdata *conn)
generated form data */
data->in = (FILE *)&http->form;
- sendf(data->firstsocket, data,
- "Content-Length: %d\r\n",
- http->postsize-2);
+ add_bufferf(req_buffer,
+ "Content-Length: %d\r\n", http->postsize-2);
+ /* set upload size to the progress meter */
pgrsSetUploadSize(data, http->postsize);
+ add_buffer_send(data->firstsocket, conn, req_buffer);
result = Transfer(conn, data->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
@@ -487,16 +489,20 @@ CURLcode http(struct connectdata *conn)
/* Let's PUT the data to the server! */
if(data->infilesize>0) {
- sendf(data->firstsocket, data,
- "Content-Length: %d\r\n\r\n", /* file size */
- data->infilesize );
+ add_bufferf(req_buffer,
+ "Content-Length: %d\r\n\r\n", /* file size */
+ data->infilesize );
}
else
- sendf(data->firstsocket, data,
- "\015\012");
+ add_bufferf(req_buffer, "\015\012");
+ /* set the upload size to the progress meter */
pgrsSetUploadSize(data, data->infilesize);
+ /* this sends the buffer and frees all the buffer resources */
+ add_buffer_send(data->firstsocket, conn, req_buffer);
+
+ /* prepare for transfer */
result = Transfer(conn, data->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
@@ -512,30 +518,34 @@ CURLcode http(struct connectdata *conn)
if(!checkheaders(data, "Content-Length:"))
/* we allow replacing this header, although it isn't very wise to
actually set your own */
- sendf(data->firstsocket, data,
- "Content-Length: %d\r\n",
- (data->postfieldsize?data->postfieldsize:
- strlen(data->postfields)) );
+ add_bufferf(req_buffer,
+ "Content-Length: %d\r\n",
+ (data->postfieldsize?data->postfieldsize:
+ strlen(data->postfields)) );
if(!checkheaders(data, "Content-Type:"))
- sendf(data->firstsocket, data,
- "Content-Type: application/x-www-form-urlencoded\r\n");
+ add_bufferf(req_buffer,
+ "Content-Type: application/x-www-form-urlencoded\r\n");
/* and here comes the actual data */
if(data->postfieldsize) {
- ssend(data->firstsocket, conn, "\r\n", 2);
- ssend(data->firstsocket, conn, data->postfields, data->postfieldsize);
- ssend(data->firstsocket, conn, "\r\n", 2);
+ add_buffer(req_buffer, "\r\n", 2);
+ add_buffer(req_buffer, data->postfields,
+ data->postfieldsize);
+ add_buffer(req_buffer, "\r\n", 2);
+ }
+ else {
+ add_bufferf(req_buffer,
+ "\r\n"
+ "%s\r\n",
+ data->postfields );
}
- sendf(data->firstsocket, data,
- "\r\n"
- "%s\r\n",
- data->postfields );
}
else
- sendf(data->firstsocket, data, "\r\n");
+ add_buffer(req_buffer, "\r\n", 2);
/* HTTP GET/HEAD download: */
+ add_buffer_send(data->firstsocket, conn, req_buffer);
result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */
}
diff --git a/lib/sendf.c b/lib/sendf.c
index 77f403d70..8042ac8b9 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -53,6 +53,7 @@
#include <curl/curl.h>
#include "urldata.h"
+#include "sendf.h"
#include <curl/mprintf.h>
@@ -89,7 +90,7 @@ void failf(struct UrlData *data, char *fmt, ...)
}
/* sendf() sends the formated data to the server */
-int sendf(int fd, struct UrlData *data, char *fmt, ...)
+size_t sendf(int fd, struct UrlData *data, char *fmt, ...)
{
size_t bytes_written;
char *s;
@@ -118,7 +119,7 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
/*
* ftpsendf() sends the formated string as a ftp command to a ftp server
*/
-int ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
+size_t ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
{
size_t bytes_written;
char *s;
@@ -154,9 +155,6 @@ size_t ssend(int fd, struct connectdata *conn, void *mem, size_t len)
size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
- if(data->bits.verbose)
- fprintf(data->err, "> [binary output]\n");
-
#ifdef USE_SSLEAY
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, mem, len);
@@ -177,6 +175,88 @@ size_t ssend(int fd, struct connectdata *conn, void *mem, size_t len)
return bytes_written;
}
+/*
+ * add_buffer_init() returns a fine buffer struct
+ */
+send_buffer *add_buffer_init(void)
+{
+ send_buffer *blonk;
+ blonk=(send_buffer *)malloc(sizeof(send_buffer));
+ if(blonk) {
+ memset(blonk, 0, sizeof(send_buffer));
+ return blonk;
+ }
+ return NULL; /* failed, go home */
+}
+
+/*
+ * add_buffer_send() sends a buffer and frees all associated memory.
+ */
+size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in)
+{
+ if(in->buffer)
+ free(in->buffer);
+ free(in);
+
+ if(conn->data->bits.verbose) {
+ fputs("> ", conn->data->err);
+ /* this data _may_ contain binary stuff */
+ fwrite(in->buffer, in->size_used, 1, conn->data->err);
+ }
+ return ssend(sockfd, conn, in->buffer, in->size_used);
+}
+/*
+ * add_bufferf() builds a buffer from the formatted input
+ */
+CURLcode add_bufferf(send_buffer *in, char *fmt, ...)
+{
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ char *s;
+ va_list ap;
+ va_start(ap, fmt);
+ s = mvaprintf(fmt, ap); /* this allocs a new string to append */
+ va_end(ap);
+
+ if(s) {
+ result = add_buffer(in, s, strlen(s));
+ free(s);
+ }
+ return result;
+}
+
+/*
+ * add_buffer() appends a memory chunk to the existing one
+ */
+CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
+{
+ char *new_rb;
+ int new_size;
+
+ if(size > 0) {
+ if(!in->buffer ||
+ ((in->size_used + size) > (in->size_max - 1))) {
+ new_size = (in->size_used+size)*2;
+ if(in->buffer)
+ /* we have a buffer, enlarge the existing one */
+ new_rb = (char *)realloc(in->buffer, new_size);
+ else
+ /* create a new buffer */
+ new_rb = (char *)malloc(new_size);
+
+ if(!new_rb)
+ return CURLE_OUT_OF_MEMORY;
+
+ in->buffer = new_rb;
+ in->size_max = new_size;
+ }
+ memcpy(&in->buffer[in->size_used], inptr, size);
+
+ in->size_used += size;
+ }
+
+ return CURLE_OK;
+}
+
diff --git a/lib/sendf.h b/lib/sendf.h
index 91af88f99..0ff305ec2 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -46,4 +46,18 @@ size_t ssend(int fd, struct connectdata *, void *fmt, size_t len);
void infof(struct UrlData *, char *fmt, ...);
void failf(struct UrlData *, char *fmt, ...);
+struct send_buffer {
+ char *buffer;
+ long size_max;
+ long size_used;
+};
+typedef struct send_buffer send_buffer;
+
+
+send_buffer *add_buffer_init(void);
+CURLcode add_buffer(send_buffer *in, void *inptr, size_t size);
+CURLcode add_bufferf(send_buffer *in, char *fmt, ...);
+size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in);
+
+
#endif