From ae1912cb0d494b48d514d937826c9fe83ec96c4d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 29 Dec 1999 14:20:26 +0000 Subject: Initial revision --- lib/http.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 lib/http.c (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c new file mode 100644 index 000000000..2dd380214 --- /dev/null +++ b/lib/http.c @@ -0,0 +1,381 @@ +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Curl. + * + * The Initial Developer of the Original Code is Daniel Stenberg. + * + * Portions created by the Initial Developer are Copyright (C) 1998. + * All Rights Reserved. + * + * ------------------------------------------------------------ + * Main author: + * - Daniel Stenberg + * + * http://curl.haxx.nu + * + * $Source$ + * $Revision$ + * $Date$ + * $Author$ + * $State$ + * $Locker$ + * + * ------------------------------------------------------------ + ****************************************************************************/ + +/* -- WIN32 approved -- */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "setup.h" + +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#include +#include +#include +#else +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#include +#include + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + + +#endif + +#include "urldata.h" +#include +#include "download.h" +#include "sendf.h" +#include "formdata.h" +#include "progress.h" +#include "base64.h" +#include "upload.h" +#include "cookie.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +/* + * This function checks the linked list of custom HTTP headers for a particular + * header (prefix). + */ +bool static checkheaders(struct UrlData *data, char *thisheader) +{ + struct HttpHeader *head; + size_t thislen = strlen(thisheader); + + for(head = data->headers; head; head=head->next) { + if(strnequal(head->header, thisheader, thislen)) { + return TRUE; + } + } + return FALSE; +} + +UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) +{ + /* Send the GET line to the HTTP server */ + + struct FormData *sendit=NULL; + int postsize=0; + UrgError result; + char *buf; + struct Cookie *co = NULL; + char *p_pragma = NULL; + char *p_accept = NULL; + + buf = data->buffer; /* this is our buffer */ + + if ( (data->conf&(CONF_HTTP|CONF_FTP)) && + (data->conf&CONF_UPLOAD)) { + data->conf |= CONF_PUT; + } +#if 0 /* old version */ + if((data->conf&(CONF_HTTP|CONF_UPLOAD)) == + (CONF_HTTP|CONF_UPLOAD)) { + /* enable PUT! */ + data->conf |= CONF_PUT; + } +#endif + + /* The User-Agent string has been built in url.c already, because it might + have been used in the proxy connect, but if we have got a header with + the user-agent string specified, we erase the previosly made string + here. */ + if(checkheaders(data, "User-Agent:") && data->ptr_uagent) { + free(data->ptr_uagent); + data->ptr_uagent=NULL; + } + + if((data->conf & CONF_USERPWD) && !checkheaders(data, "Authorization:")) { + char authorization[512]; + sprintf(data->buffer, "%s:%s", data->user, data->passwd); + base64Encode(data->buffer, authorization); + data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", + authorization); + } + if((data->conf & CONF_RANGE) && !checkheaders(data, "Range:")) { + data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); + } + if((data->conf & CONF_REFERER) && !checkheaders(data, "Referer:")) { + data->ptr_ref = maprintf("Referer: %s\015\012", data->referer); + } + if(data->cookie && !checkheaders(data, "Cookie:")) { + data->ptr_cookie = maprintf("Cookie: %s\015\012", data->cookie); + } + + if(data->cookies) { + co = cookie_getlist(data->cookies, + host, + ppath, + data->conf&CONF_HTTPS?TRUE:FALSE); + } + if ((data->conf & CONF_PROXY) && (!(data->conf & CONF_HTTPS))) { + /* The path sent to the proxy is in fact the entire URL */ + strncpy(ppath, data->url, URL_MAX_LENGTH-1); + } + if(data->conf & CONF_HTTPPOST) { + /* we must build the whole darned post sequence first, so that we have + a size of the whole shebang before we start to send it */ + sendit = getFormData(data->httppost, &postsize); + } + + if(!checkheaders(data, "Host:")) + data->ptr_host = maprintf("Host: %s\r\n", host); + + + if(!checkheaders(data, "Pragma:")) + p_pragma = "Pragma: no-cache\r\n"; + + if(!checkheaders(data, "Accept:")) + p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; + + do { + 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->conf&CONF_NOBODY?"HEAD": + (data->conf&(CONF_POST|CONF_HTTPPOST))?"POST": + (data->conf&CONF_PUT)?"PUT":"GET"), + ppath, + (data->conf&CONF_PROXYUSERPWD && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", + (data->conf&CONF_USERPWD && data->ptr_userpwd)?data->ptr_userpwd:"", + (data->conf&CONF_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->ptr_host?data->ptr_host:""), /* Host: host */ + p_pragma?p_pragma:"", + p_accept?p_accept:"", + (data->conf&CONF_REFERER && data->ptr_ref)?data->ptr_ref:"" /* Referer: */ + ); + + if(co) { + int count=0; + /* now loop through all cookies that matched */ + while(co) { + if(0 == count) { + sendf(data->firstsocket, data, + "Cookie: "); + } + count++; + sendf(data->firstsocket, data, + "%s=%s;", co->name, co->value); + co = co->next; /* next cookie please */ + } + if(count) { + sendf(data->firstsocket, data, + "\r\n"); + } + cookie_freelist(co); /* free the cookie list */ + co=NULL; + } + + if(data->timecondition) { + struct tm *thistime; + + thistime = localtime(&data->timevalue); + +#if defined(HAVE_STRFTIME) || defined(WIN32) + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S %Z", thistime); +#else + /* Right, we *could* write a replacement here */ + strcpy(buf, "no strftime() support"); +#endif + switch(data->timecondition) { + case TIMECOND_IFMODSINCE: + default: + sendf(data->firstsocket, data, + "If-Modified-Since: %s\r\n", buf); + break; + case TIMECOND_IFUNMODSINCE: + sendf(data->firstsocket, data, + "If-Unmodified-Since: %s\r\n", buf); + break; + case TIMECOND_LASTMOD: + sendf(data->firstsocket, data, + "Last-Modified: %s\r\n", buf); + break; + } + } + + while(data->headers) { + sendf(data->firstsocket, data, + "%s\015\012", + data->headers->header); + data->headers = data->headers->next; + } + + if(data->conf&(CONF_POST|CONF_HTTPPOST)) { + if(data->conf & CONF_POST) { + /* this is the simple x-www-form-urlencoded style */ + sendf(data->firstsocket, data, + "Content-Length: %d\015\012" + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + "%s\015\012", + strlen(data->postfields), + data->postfields ); + } + else { + struct Form form; + size_t (*storefread)(char *, size_t , size_t , FILE *); + FILE *in; + long conf; + + if(FormInit(&form, sendit)) { + failf(data, "Internal HTTP POST error!\n"); + return URG_HTTP_POST_ERROR; + } + + storefread = data->fread; /* backup */ + in = data->in; /* backup */ + + data->fread = + (size_t (*)(char *, size_t, size_t, FILE *)) + FormReader; /* set the read function to read from the + generated form data */ + data->in = (FILE *)&form; + + sendf(data->firstsocket, data, + "Content-Length: %d\r\n", + postsize-2); + + conf = data->conf; + data->conf &= ~CONF_NOPROGRESS; /* enable progress meter */ + ProgressInit(data, postsize); + + result = Upload(data, data->firstsocket, bytecount); + + FormFree(sendit); /* Now free that whole lot */ + + data->conf = conf; /* restore conf values for the download */ + + if(result) + return result; + + data->fread = storefread; /* restore */ + data->in = in; /* restore */ + + sendf(data->firstsocket, data, + "\r\n\r\n"); + } + } + else if(data->conf&CONF_PUT) { + /* Let's PUT the data to the server! */ + long conf; + + if(data->infilesize>0) { + sendf(data->firstsocket, data, + "Content-Length: %d\r\n\r\n", /* file size */ + data->infilesize ); + } + else + sendf(data->firstsocket, data, + "\015\012"); + + conf = data->conf; + data->conf &= ~CONF_NOPROGRESS; /* enable progress meter */ + + ProgressInit(data, data->infilesize); + + result = Upload(data, data->firstsocket, bytecount); + + data->conf = conf; + + if(result) + return result; + + /* reset the byte counter */ + *bytecount=0; + } + else { + sendf(data->firstsocket, data, "\r\n"); + } + /* HTTP GET/HEAD download: */ + result = Download(data, data->firstsocket, -1, TRUE, bytecount); + + if(result) + return result; + + ProgressEnd(data); + } while (0); /* this is just a left-over from the multiple document download + attempts */ + + return URG_OK; +} + -- cgit v1.2.1 From 63aefdb50b3af26321da2d1cde31e4530e2c1c66 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 16 Jan 2000 18:52:24 +0000 Subject: changed a tiny comment --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2dd380214..2dd41c0fa 100644 --- a/lib/http.c +++ b/lib/http.c @@ -254,7 +254,7 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S %Z", thistime); #else - /* Right, we *could* write a replacement here */ + /* TODO: Right, we *could* write a replacement here */ strcpy(buf, "no strftime() support"); #endif switch(data->timecondition) { -- cgit v1.2.1 From 15755b3fd8744e1ff7d2cda5f2db9477a84e5c88 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 1 Feb 2000 23:52:11 +0000 Subject: Adjusted to use the new Transfer() instead of the old Download() --- lib/http.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2dd41c0fa..49d47b3a5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -127,6 +127,8 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) struct Cookie *co = NULL; char *p_pragma = NULL; char *p_accept = NULL; + long readbytecount; + long writebytecount; buf = data->buffer; /* this is our buffer */ @@ -144,7 +146,7 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) /* The User-Agent string has been built in url.c already, because it might have been used in the proxy connect, but if we have got a header with - the user-agent string specified, we erase the previosly made string + the user-agent string specified, we erase the previously made string here. */ if(checkheaders(data, "User-Agent:") && data->ptr_uagent) { free(data->ptr_uagent); @@ -315,16 +317,14 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) "Content-Length: %d\r\n", postsize-2); - conf = data->conf; - data->conf &= ~CONF_NOPROGRESS; /* enable progress meter */ ProgressInit(data, postsize); - result = Upload(data, data->firstsocket, bytecount); + result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, + data->firstsocket, writebytecount); + *bytecount = readbytecount + writebytecount; FormFree(sendit); /* Now free that whole lot */ - data->conf = conf; /* restore conf values for the download */ - if(result) return result; @@ -348,27 +348,25 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) sendf(data->firstsocket, data, "\015\012"); - conf = data->conf; - data->conf &= ~CONF_NOPROGRESS; /* enable progress meter */ - ProgressInit(data, data->infilesize); - result = Upload(data, data->firstsocket, bytecount); - - data->conf = conf; + result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, + data->firstsocket, &writebytecount); + + *bytecount = readbytecount + writebytecount; if(result) return result; - /* reset the byte counter */ - *bytecount=0; } else { sendf(data->firstsocket, data, "\r\n"); } - /* HTTP GET/HEAD download: */ - result = Download(data, data->firstsocket, -1, TRUE, bytecount); - + if(0 == *bytecount) { + /* HTTP GET/HEAD download: */ + result = Transfer(data, data->firstsocket, -1, TRUE, bytecount, + -1, NULL); /* nothing to upload */ + } if(result) return result; -- cgit v1.2.1 From c758744e7e5a33e9372eff0c995c0739bdbc23b9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 1 Feb 2000 23:56:28 +0000 Subject: removed #include "upload.h" --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 49d47b3a5..38b07b6ad 100644 --- a/lib/http.c +++ b/lib/http.c @@ -93,7 +93,6 @@ #include "formdata.h" #include "progress.h" #include "base64.h" -#include "upload.h" #include "cookie.h" #define _MPRINTF_REPLACE /* use our functions only */ @@ -320,7 +319,7 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) ProgressInit(data, postsize); result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, - data->firstsocket, writebytecount); + data->firstsocket, &writebytecount); *bytecount = readbytecount + writebytecount; FormFree(sendit); /* Now free that whole lot */ -- cgit v1.2.1 From 9ef5f5ef5ae01355f9006b0f9fbaacd3b9ca1cee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Feb 2000 23:15:33 +0000 Subject: This should no longer send empty cookies to the server --- lib/http.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 38b07b6ad..c37318d8f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -229,13 +229,15 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) int count=0; /* now loop through all cookies that matched */ while(co) { - if(0 == count) { + if(co->value && strlen(co->value)) { + if(0 == count) { + sendf(data->firstsocket, data, + "Cookie: "); + } + count++; sendf(data->firstsocket, data, - "Cookie: "); + "%s=%s;", co->name, co->value); } - count++; - sendf(data->firstsocket, data, - "%s=%s;", co->name, co->value); co = co->next; /* next cookie please */ } if(count) { -- cgit v1.2.1 From 5a99be254566758d8ff42d905cad98b1ee7a2e87 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Feb 2000 22:57:42 +0000 Subject: updated to use the new set of progress-functions --- lib/http.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c37318d8f..bf89d97b0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -317,8 +317,11 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) sendf(data->firstsocket, data, "Content-Length: %d\r\n", postsize-2); - + + pgrsSetUploadSize(data, postsize); +#if 0 ProgressInit(data, postsize); +#endif result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, data->firstsocket, &writebytecount); @@ -348,8 +351,11 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) else sendf(data->firstsocket, data, "\015\012"); - + +#if 0 ProgressInit(data, data->infilesize); +#endif + pgrsSetUploadSize(data, data->infilesize); result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, data->firstsocket, &writebytecount); @@ -370,8 +376,12 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) } if(result) return result; - + +#if 0 ProgressEnd(data); +#endif + pgrsDone(data); + } while (0); /* this is just a left-over from the multiple document download attempts */ -- cgit v1.2.1 From 2ad8ed777138834202a7cad9336b60bb50d026cc Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Mar 2000 09:11:54 +0000 Subject: now sends cookies space separated to better work with IIS4.0 servers --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bf89d97b0..7bbf13b7a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -232,11 +232,11 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) if(co->value && strlen(co->value)) { if(0 == count) { sendf(data->firstsocket, data, - "Cookie: "); + "Cookie:"); } count++; sendf(data->firstsocket, data, - "%s=%s;", co->name, co->value); + " %s=%s;", co->name, co->value); } co = co->next; /* next cookie please */ } -- cgit v1.2.1 From 0aa3f705c21a49d43ce5f2e7bdd7a8686c1ee418 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Mar 2000 11:40:48 +0000 Subject: removed an unnecessary #ifdef WIN32 --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7bbf13b7a..3f030b4a1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -253,7 +253,7 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) thistime = localtime(&data->timevalue); -#if defined(HAVE_STRFTIME) || defined(WIN32) +#ifdef HAVE_STRFTIME /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S %Z", thistime); #else -- cgit v1.2.1 From 96dde76b99897352aa3d0877a0b621a9e605733e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 May 2000 14:12:12 +0000 Subject: moved here from the newlib branch --- lib/http.c | 246 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 153 insertions(+), 93 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3f030b4a1..0f41e7c09 100644 --- a/lib/http.c +++ b/lib/http.c @@ -94,6 +94,9 @@ #include "progress.h" #include "base64.h" #include "cookie.h" +#include "strequal.h" +#include "url.h" +#include "ssluse.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -115,33 +118,114 @@ bool static checkheaders(struct UrlData *data, char *thisheader) return FALSE; } -UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) +CURLcode http_connect(struct connectdata *conn) { - /* Send the GET line to the HTTP server */ - - struct FormData *sendit=NULL; - int postsize=0; - UrgError result; - char *buf; - struct Cookie *co = NULL; - char *p_pragma = NULL; - char *p_accept = NULL; - long readbytecount; - long writebytecount; - - buf = data->buffer; /* this is our buffer */ - - if ( (data->conf&(CONF_HTTP|CONF_FTP)) && - (data->conf&CONF_UPLOAD)) { - data->conf |= CONF_PUT; + struct UrlData *data; + + data=conn->data; + + /* If we are not using a proxy and we want a secure connection, + * perform SSL initialization & connection now. + * If using a proxy with https, then we must tell the proxy to CONNECT + * us to the host we want to talk to. Only after the connect + * has occured, can we start talking SSL + */ + if (conn->protocol & PROT_HTTPS) { + if (data->bits.httpproxy) { + + /* OK, now send the connect statment */ + sendf(data->firstsocket, data, + "CONNECT %s:%d HTTP/1.0\015\012" + "%s" + "%s" + "\r\n", + data->hostname, data->remote_port, + (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", + (data->useragent?data->ptr_uagent:"") + ); + + /* wait for the proxy to send us a HTTP/1.0 200 OK header */ + /* Daniel rewrote this part Nov 5 1998 to make it more obvious */ + { + int httperror=0; + int subversion=0; + while(GetLine(data->firstsocket, data->buffer, data)) { + if('\r' == data->buffer[0]) + break; /* end of headers */ + if(2 == sscanf(data->buffer, "HTTP/1.%d %d", + &subversion, + &httperror)) { + ; + } + } + if(200 != httperror) { + if(407 == httperror) + /* Added Nov 6 1998 */ + failf(data, "Proxy requires authorization!"); + else + failf(data, "Received error code %d from proxy", httperror); + return CURLE_READ_ERROR; + } + } + infof (data, "Proxy has replied to CONNECT request\n"); + } + + /* now, perform the SSL initialization for this socket */ + if(UrgSSLConnect (data)) { + return CURLE_SSL_CONNECT_ERROR; + } + } + + return CURLE_OK; +} +CURLcode http_done(struct connectdata *conn) +{ + struct UrlData *data; + long *bytecount = &conn->bytecount; + struct HTTP *http; + + data=conn->data; + http=data->proto.http; + + if(data->bits.http_formpost) { + *bytecount = http->readbytecount + http->writebytecount; + + FormFree(http->sendit); /* Now free that whole lot */ + + data->fread = http->storefread; /* restore */ + data->in = http->in; /* restore */ } -#if 0 /* old version */ - if((data->conf&(CONF_HTTP|CONF_UPLOAD)) == - (CONF_HTTP|CONF_UPLOAD)) { - /* enable PUT! */ - data->conf |= CONF_PUT; + else if(data->bits.http_put) { + *bytecount = http->readbytecount + http->writebytecount; + } + + /* TBD: the HTTP struct remains allocated here */ + + return CURLE_OK; +} + + +CURLcode http(struct connectdata *conn) +{ + struct UrlData *data=conn->data; + char *buf = data->buffer; /* this is a short cut to the buffer */ + CURLcode result; + struct HTTP *http; + struct Cookie *co=NULL; /* no cookies from start */ + char *ppath = conn->ppath; /* three previous function arguments */ + char *host = conn->name; + long *bytecount = &conn->bytecount; + + http = (struct HTTP *)malloc(sizeof(struct HTTP)); + if(!http) + return CURLE_OUT_OF_MEMORY; + memset(http, 0, sizeof(struct HTTP)); + data->proto.http = http; + + if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && + data->bits.upload) { + data->bits.http_put=1; } -#endif /* The User-Agent string has been built in url.c already, because it might have been used in the proxy connect, but if we have got a header with @@ -152,17 +236,17 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) data->ptr_uagent=NULL; } - if((data->conf & CONF_USERPWD) && !checkheaders(data, "Authorization:")) { + if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { char authorization[512]; sprintf(data->buffer, "%s:%s", data->user, data->passwd); base64Encode(data->buffer, authorization); data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", authorization); } - if((data->conf & CONF_RANGE) && !checkheaders(data, "Range:")) { + if((data->bits.set_range) && !checkheaders(data, "Range:")) { data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); } - if((data->conf & CONF_REFERER) && !checkheaders(data, "Referer:")) { + if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { data->ptr_ref = maprintf("Referer: %s\015\012", data->referer); } if(data->cookie && !checkheaders(data, "Cookie:")) { @@ -173,16 +257,16 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) co = cookie_getlist(data->cookies, host, ppath, - data->conf&CONF_HTTPS?TRUE:FALSE); + conn->protocol&PROT_HTTPS?TRUE:FALSE); } - if ((data->conf & CONF_PROXY) && (!(data->conf & CONF_HTTPS))) { + if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ strncpy(ppath, data->url, URL_MAX_LENGTH-1); } - if(data->conf & CONF_HTTPPOST) { + if(data->bits.http_formpost) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ - sendit = getFormData(data->httppost, &postsize); + http->sendit = getFormData(data->httppost, &http->postsize); } if(!checkheaders(data, "Host:")) @@ -190,10 +274,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) if(!checkheaders(data, "Pragma:")) - p_pragma = "Pragma: no-cache\r\n"; + http->p_pragma = "Pragma: no-cache\r\n"; if(!checkheaders(data, "Accept:")) - p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; + http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; do { sendf(data->firstsocket, data, @@ -210,19 +294,19 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) "%s", /* referer */ data->customrequest?data->customrequest: - (data->conf&CONF_NOBODY?"HEAD": - (data->conf&(CONF_POST|CONF_HTTPPOST))?"POST": - (data->conf&CONF_PUT)?"PUT":"GET"), + (data->bits.no_body?"HEAD": + (data->bits.http_post || data->bits.http_formpost)?"POST": + (data->bits.http_put)?"PUT":"GET"), ppath, - (data->conf&CONF_PROXYUSERPWD && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", - (data->conf&CONF_USERPWD && data->ptr_userpwd)?data->ptr_userpwd:"", - (data->conf&CONF_RANGE && data->ptr_rangeline)?data->ptr_rangeline:"", + (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->ptr_host?data->ptr_host:""), /* Host: host */ - p_pragma?p_pragma:"", - p_accept?p_accept:"", - (data->conf&CONF_REFERER && data->ptr_ref)?data->ptr_ref:"" /* Referer: */ + http->p_pragma?http->p_pragma:"", + http->p_accept?http->p_accept:"", + (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: */ ); if(co) { @@ -234,9 +318,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) sendf(data->firstsocket, data, "Cookie:"); } - count++; sendf(data->firstsocket, data, - " %s=%s;", co->name, co->value); + "%s%s=%s", count?"; ":"", co->name, + co->value); + count++; } co = co->next; /* next cookie please */ } @@ -284,8 +369,8 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) data->headers = data->headers->next; } - if(data->conf&(CONF_POST|CONF_HTTPPOST)) { - if(data->conf & CONF_POST) { + if(data->bits.http_post || data->bits.http_formpost) { + if(data->bits.http_post) { /* this is the simple x-www-form-urlencoded style */ sendf(data->firstsocket, data, "Content-Length: %d\015\012" @@ -295,53 +380,39 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) data->postfields ); } else { - struct Form form; - size_t (*storefread)(char *, size_t , size_t , FILE *); - FILE *in; - long conf; - if(FormInit(&form, sendit)) { + if(FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!\n"); - return URG_HTTP_POST_ERROR; + return CURLE_HTTP_POST_ERROR; } - storefread = data->fread; /* backup */ - in = data->in; /* backup */ + http->storefread = data->fread; /* backup */ + http->in = data->in; /* backup */ data->fread = (size_t (*)(char *, size_t, size_t, FILE *)) FormReader; /* set the read function to read from the generated form data */ - data->in = (FILE *)&form; + data->in = (FILE *)&http->form; sendf(data->firstsocket, data, "Content-Length: %d\r\n", - postsize-2); + http->postsize-2); - pgrsSetUploadSize(data, postsize); -#if 0 - ProgressInit(data, postsize); -#endif + pgrsSetUploadSize(data, http->postsize); - result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, - data->firstsocket, &writebytecount); - *bytecount = readbytecount + writebytecount; - - FormFree(sendit); /* Now free that whole lot */ - - if(result) + result = Transfer(conn, data->firstsocket, -1, TRUE, + &http->readbytecount, + data->firstsocket, + &http->writebytecount); + if(result) { + FormFree(http->sendit); /* free that whole lot */ return result; - - data->fread = storefread; /* restore */ - data->in = in; /* restore */ - - sendf(data->firstsocket, data, - "\r\n\r\n"); + } } } - else if(data->conf&CONF_PUT) { + else if(data->bits.http_put) { /* Let's PUT the data to the server! */ - long conf; if(data->infilesize>0) { sendf(data->firstsocket, data, @@ -352,39 +423,28 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) sendf(data->firstsocket, data, "\015\012"); -#if 0 - ProgressInit(data, data->infilesize); -#endif pgrsSetUploadSize(data, data->infilesize); - result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, - data->firstsocket, &writebytecount); - - *bytecount = readbytecount + writebytecount; - + result = Transfer(conn, data->firstsocket, -1, TRUE, + &http->readbytecount, + data->firstsocket, + &http->writebytecount); if(result) return result; } else { sendf(data->firstsocket, data, "\r\n"); - } - if(0 == *bytecount) { + /* HTTP GET/HEAD download: */ - result = Transfer(data, data->firstsocket, -1, TRUE, bytecount, + result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount, -1, NULL); /* nothing to upload */ } if(result) return result; - -#if 0 - ProgressEnd(data); -#endif - pgrsDone(data); - } while (0); /* this is just a left-over from the multiple document download attempts */ - return URG_OK; + return CURLE_OK; } -- cgit v1.2.1 From ecb2b95b1cef4c913fcf2b19e79e474c299f5a20 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Jun 2000 08:23:50 +0000 Subject: struct HttpHeader changed to struct curl_slist --- lib/http.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0f41e7c09..b6b87f905 100644 --- a/lib/http.c +++ b/lib/http.c @@ -107,11 +107,11 @@ */ bool static checkheaders(struct UrlData *data, char *thisheader) { - struct HttpHeader *head; + struct curl_slist *head; size_t thislen = strlen(thisheader); for(head = data->headers; head; head=head->next) { - if(strnequal(head->header, thisheader, thislen)) { + if(strnequal(head->data, thisheader, thislen)) { return TRUE; } } @@ -280,6 +280,7 @@ CURLcode http(struct connectdata *conn) http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; do { + struct curl_slist *headers=data->headers; sendf(data->firstsocket, data, "%s " /* GET/HEAD/POST/PUT */ "%s HTTP/1.0\r\n" /* path */ @@ -362,11 +363,11 @@ CURLcode http(struct connectdata *conn) } } - while(data->headers) { + while(headers) { sendf(data->firstsocket, data, "%s\015\012", - data->headers->header); - data->headers = data->headers->next; + headers->data); + headers = headers->next; } if(data->bits.http_post || data->bits.http_formpost) { -- cgit v1.2.1 From 94ec5ff44a78921a11803d33b3065d2d5322cf6d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 14 Jun 2000 17:15:07 +0000 Subject: correct the POST workings. Tim Tassonis reported. --- lib/http.c | 70 ++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b6b87f905..60869d6d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -209,7 +209,7 @@ CURLcode http(struct connectdata *conn) { struct UrlData *data=conn->data; char *buf = data->buffer; /* this is a short cut to the buffer */ - CURLcode result; + CURLcode result=CURLE_OK; struct HTTP *http; struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->ppath; /* three previous function arguments */ @@ -370,46 +370,34 @@ CURLcode http(struct connectdata *conn) headers = headers->next; } - if(data->bits.http_post || data->bits.http_formpost) { - if(data->bits.http_post) { - /* this is the simple x-www-form-urlencoded style */ - sendf(data->firstsocket, data, - "Content-Length: %d\015\012" - "Content-Type: application/x-www-form-urlencoded\r\n\r\n" - "%s\015\012", - strlen(data->postfields), - data->postfields ); + if(data->bits.http_formpost) { + if(FormInit(&http->form, http->sendit)) { + failf(data, "Internal HTTP POST error!\n"); + return CURLE_HTTP_POST_ERROR; } - else { - if(FormInit(&http->form, http->sendit)) { - failf(data, "Internal HTTP POST error!\n"); - return CURLE_HTTP_POST_ERROR; - } - - http->storefread = data->fread; /* backup */ - http->in = data->in; /* backup */ + http->storefread = data->fread; /* backup */ + http->in = data->in; /* backup */ - data->fread = - (size_t (*)(char *, size_t, size_t, FILE *)) - FormReader; /* set the read function to read from the - generated form data */ - data->in = (FILE *)&http->form; + data->fread = + (size_t (*)(char *, size_t, size_t, FILE *)) + FormReader; /* set the read function to read from the + generated form data */ + data->in = (FILE *)&http->form; - sendf(data->firstsocket, data, - "Content-Length: %d\r\n", - http->postsize-2); + sendf(data->firstsocket, data, + "Content-Length: %d\r\n", + http->postsize-2); - pgrsSetUploadSize(data, http->postsize); + pgrsSetUploadSize(data, http->postsize); - result = Transfer(conn, data->firstsocket, -1, TRUE, - &http->readbytecount, + result = Transfer(conn, data->firstsocket, -1, TRUE, + &http->readbytecount, data->firstsocket, - &http->writebytecount); - if(result) { - FormFree(http->sendit); /* free that whole lot */ - return result; - } + &http->writebytecount); + if(result) { + FormFree(http->sendit); /* free that whole lot */ + return result; } } else if(data->bits.http_put) { @@ -432,10 +420,20 @@ CURLcode http(struct connectdata *conn) &http->writebytecount); if(result) return result; - + } else { - sendf(data->firstsocket, data, "\r\n"); + if(data->bits.http_post) { + /* this is the simple x-www-form-urlencoded style */ + sendf(data->firstsocket, data, + "Content-Length: %d\015\012" + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + "%s\r\n", + strlen(data->postfields), + data->postfields ); + } + else + sendf(data->firstsocket, data, "\r\n"); /* HTTP GET/HEAD download: */ result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount, -- cgit v1.2.1 From 1ef3600a0731fef8f59563a1e49981f1b64b9746 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Jun 2000 15:31:26 +0000 Subject: haxx.nu => haxx.se --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 60869d6d8..d83942d1d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -24,9 +24,9 @@ * * ------------------------------------------------------------ * Main author: - * - Daniel Stenberg + * - Daniel Stenberg * - * http://curl.haxx.nu + * http://curl.haxx.se * * $Source$ * $Revision$ -- cgit v1.2.1 From e999182758f809fb8a173c0caec2283d4bbfe280 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 25 Jul 2000 07:28:28 +0000 Subject: The Host: header now includes the port number if not default HTTP --- lib/http.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d83942d1d..c3fb857d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -269,9 +269,12 @@ CURLcode http(struct connectdata *conn) http->sendit = getFormData(data->httppost, &http->postsize); } - if(!checkheaders(data, "Host:")) - data->ptr_host = maprintf("Host: %s\r\n", host); - + if(!checkheaders(data, "Host:")) { + if(data->port != PORT_HTTP) + data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->port); + else + data->ptr_host = maprintf("Host: %s\r\n", host); + } if(!checkheaders(data, "Pragma:")) http->p_pragma = "Pragma: no-cache\r\n"; -- cgit v1.2.1 From 29eda80f9669f5469f4cbe06269ad7a0da844495 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 25 Jul 2000 21:16:32 +0000 Subject: uses auth_host to only send user+password to that particular site, usable if Location: following takes "us" to other servers that should not get the user and password --- lib/http.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c3fb857d8..9372e488e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -176,8 +176,24 @@ CURLcode http_connect(struct connectdata *conn) } } + if(data->bits.user_passwd && !data->bits.this_is_a_follow) { + /* Authorization: is requested, this is not a followed location, get the + original host name */ + data->auth_host = strdup(data->hostname); + } + return CURLE_OK; } + +/* called from curl_close() when this struct is about to get wasted, free + protocol-specific resources */ +CURLcode http_close(struct connectdata *conn) +{ + if(conn->data->auth_host) + free(conn->data->auth_host); + return CURLE_OK; +} + CURLcode http_done(struct connectdata *conn) { struct UrlData *data; @@ -238,10 +254,17 @@ CURLcode http(struct connectdata *conn) if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { char authorization[512]; - sprintf(data->buffer, "%s:%s", data->user, data->passwd); - base64Encode(data->buffer, authorization); - data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", - authorization); + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->bits.this_is_a_follow || + !data->auth_host || + strequal(data->auth_host, data->hostname)) { + sprintf(data->buffer, "%s:%s", data->user, data->passwd); + base64Encode(data->buffer, authorization); + data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", + authorization); + } } if((data->bits.set_range) && !checkheaders(data, "Range:")) { data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); -- cgit v1.2.1 From f50fd062e9552a0f98dd962c66f2a475b4994d78 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 28 Jul 2000 07:55:21 +0000 Subject: corrected the Host: header's port number --- lib/http.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9372e488e..711775bbd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -293,10 +293,7 @@ CURLcode http(struct connectdata *conn) } if(!checkheaders(data, "Host:")) { - if(data->port != PORT_HTTP) - data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->port); - else - data->ptr_host = maprintf("Host: %s\r\n", host); + data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->remote_port); } if(!checkheaders(data, "Pragma:")) -- cgit v1.2.1 From 9d5c6df788c8eaa3986aa78c27c896255f6dc1e9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 29 Jul 2000 22:21:10 +0000 Subject: added localtime_r() --- lib/http.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 711775bbd..c8be1e35d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -61,6 +61,7 @@ #endif #include #include + #include #ifdef HAVE_UNISTD_H #include @@ -360,7 +361,18 @@ CURLcode http(struct connectdata *conn) if(data->timecondition) { struct tm *thistime; +#ifdef HAVE_LOCALTIME_R + extern struct tm *localtime_r(time_t *, struct tm *); + /* thread-safe version */ + struct tm keeptime; + thistime = localtime_r(&data->timevalue, &keeptime); +#else thistime = localtime(&data->timevalue); +#endif + if(NULL == thistime) { + failf(data, "localtime() failed!"); + return CURLE_OUT_OF_MEMORY; + } #ifdef HAVE_STRFTIME /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ -- cgit v1.2.1 From 1cf13c825fa9e45a3dc8f7abf5aa43d8446b89ab Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Jul 2000 21:30:19 +0000 Subject: Replacing one of the internal headers with one that has no contents will now completely disable that header to get sent. --- lib/http.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c8be1e35d..f6b626606 100644 --- a/lib/http.c +++ b/lib/http.c @@ -399,9 +399,22 @@ CURLcode http(struct connectdata *conn) } while(headers) { - sendf(data->firstsocket, data, - "%s\015\012", - headers->data); + char *ptr = strchr(headers->data, ':'); + if(ptr) { + /* we require a colon for this to be a true header */ + + ptr++; /* pass the colon */ + while(*ptr && isspace(*ptr)) + ptr++; + + if(*ptr) { + /* only send this if the contents was non-blank */ + + sendf(data->firstsocket, data, + "%s\015\012", + headers->data); + } + } headers = headers->next; } -- cgit v1.2.1 From c3c7739811fc2231182d2b46f5fd42e44007dd2c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Jul 2000 22:42:34 +0000 Subject: big last-beta (?) cleanup commit --- lib/http.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f6b626606..d05e73cf0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -38,6 +38,10 @@ * ------------------------------------------------------------ ****************************************************************************/ +#define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun + made the localtime_r() prototype dependent on it (or + _POSIX_C_SOURCE or _POSIX_PTHREAD_SEMANTICS). */ + /* -- WIN32 approved -- */ #include #include @@ -62,6 +66,12 @@ #include #include +#ifdef HAVE_TIME_H +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#endif + #include #ifdef HAVE_UNISTD_H #include @@ -362,7 +372,6 @@ CURLcode http(struct connectdata *conn) struct tm *thistime; #ifdef HAVE_LOCALTIME_R - extern struct tm *localtime_r(time_t *, struct tm *); /* thread-safe version */ struct tm keeptime; thistime = localtime_r(&data->timevalue, &keeptime); -- cgit v1.2.1 From 349a3aaf5b33406445d394922813cf60b5d3264d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 11 Aug 2000 06:39:53 +0000 Subject: Made it possible to replace the Content-Type: and Content-Length: headers curl issues when doing a regular HTTP post. This should not be taken light- heartedly though. Replacing them might get you into trouble! --- lib/http.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d05e73cf0..fae22816f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -481,12 +481,23 @@ CURLcode http(struct connectdata *conn) } else { if(data->bits.http_post) { - /* this is the simple x-www-form-urlencoded style */ + /* this is the simple POST, using x-www-form-urlencoded style */ + + 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", + strlen(data->postfields)); + + if(!checkheaders(data, "Content-Type:")) + sendf(data->firstsocket, data, + "Content-Type: application/x-www-form-urlencoded\r\n"); + + /* and here comes the actual data */ sendf(data->firstsocket, data, - "Content-Length: %d\015\012" - "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + "\r\n" "%s\r\n", - strlen(data->postfields), data->postfields ); } else -- cgit v1.2.1 From d4731b70505d308064e85bfa1ea1f88904442af2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 23 Aug 2000 07:23:42 +0000 Subject: Albert Chin-A-Young's fixes --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fae22816f..0632f6084 100644 --- a/lib/http.c +++ b/lib/http.c @@ -38,9 +38,11 @@ * ------------------------------------------------------------ ****************************************************************************/ +#ifdef NEED_REENTRANT #define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun made the localtime_r() prototype dependent on it (or _POSIX_C_SOURCE or _POSIX_PTHREAD_SEMANTICS). */ +#endif /* -- WIN32 approved -- */ #include @@ -63,7 +65,9 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_NETINET_IN_H #include +#endif #include #ifdef HAVE_TIME_H -- cgit v1.2.1 From 1b1f143cd65cb86138e3083790d89f959e3ecc87 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Aug 2000 12:33:16 +0000 Subject: hostname and large file support added --- lib/http.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0632f6084..5e3f1b10c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -38,12 +38,6 @@ * ------------------------------------------------------------ ****************************************************************************/ -#ifdef NEED_REENTRANT -#define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun - made the localtime_r() prototype dependent on it (or - _POSIX_C_SOURCE or _POSIX_PTHREAD_SEMANTICS). */ -#endif - /* -- WIN32 approved -- */ #include #include @@ -57,6 +51,12 @@ #include "setup.h" +#ifdef NEED_REENTRANT +#define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun + made the localtime_r() prototype dependent on it (or + _POSIX_C_SOURCE or _POSIX_PTHREAD_SEMANTICS). */ +#endif + #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #include #include @@ -378,7 +378,7 @@ CURLcode http(struct connectdata *conn) #ifdef HAVE_LOCALTIME_R /* thread-safe version */ struct tm keeptime; - thistime = localtime_r(&data->timevalue, &keeptime); + thistime = (struct tm *)localtime_r(&data->timevalue, &keeptime); #else thistime = localtime(&data->timevalue); #endif @@ -492,13 +492,19 @@ CURLcode http(struct connectdata *conn) actually set your own */ sendf(data->firstsocket, data, "Content-Length: %d\r\n", - strlen(data->postfields)); + (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"); /* and here comes the actual data */ + if(data->postfieldsize) { + ssend(data->firstsocket, data, "\r\n", 2); + ssend(data->firstsocket, data, data->postfields, data->postfieldsize); + ssend(data->firstsocket, data, "\r\n", 2); + } sendf(data->firstsocket, data, "\r\n" "%s\r\n", -- cgit v1.2.1 From b6e18f2f665f16910c04cb52bdc7b90270ab7c9b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Aug 2000 14:26:33 +0000 Subject: #include "setup.h" moved first of all includes --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5e3f1b10c..1ee8b4519 100644 --- a/lib/http.c +++ b/lib/http.c @@ -38,6 +38,8 @@ * ------------------------------------------------------------ ****************************************************************************/ +#include "setup.h" + /* -- WIN32 approved -- */ #include #include @@ -49,7 +51,6 @@ #include -#include "setup.h" #ifdef NEED_REENTRANT #define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun -- cgit v1.2.1 From 86ff2c46b73a2bbcd25edaf6a3c1d62c8a85f29d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 14 Sep 2000 14:05:01 +0000 Subject: introduced 'tunnel through http proxy' for ftp --- lib/http.c | 114 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 65 insertions(+), 49 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1ee8b4519..7d3507ce4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -134,9 +134,57 @@ bool static checkheaders(struct UrlData *data, char *thisheader) return FALSE; } +/* + * GetHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. + */ + +CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket) +{ + int httperror=0; + int subversion=0; + + infof(data, "Establish HTTP proxy tunnel\n"); + + /* OK, now send the connect statment */ + sendf(tunnelsocket, data, + "CONNECT %s:%d HTTP/1.0\015\012" + "%s" + "%s" + "\r\n", + data->hostname, data->remote_port, + (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", + (data->useragent?data->ptr_uagent:"") + ); + + /* wait for the proxy to send us a HTTP/1.0 200 OK header */ + while(GetLine(tunnelsocket, data->buffer, data)) { + if('\r' == data->buffer[0]) + break; /* end of headers */ + if(2 == sscanf(data->buffer, "HTTP/1.%d %d", + &subversion, + &httperror)) { + ; + } + } + if(200 != httperror) { + if(407 == httperror) + /* Added Nov 6 1998 */ + failf(data, "Proxy requires authorization!"); + else + failf(data, "Received error code %d from proxy", httperror); + return CURLE_READ_ERROR; + } + + infof (data, "Proxy replied to CONNECT request\n"); + return CURLE_OK; +} + CURLcode http_connect(struct connectdata *conn) { struct UrlData *data; + CURLcode result; data=conn->data; @@ -146,59 +194,27 @@ CURLcode http_connect(struct connectdata *conn) * us to the host we want to talk to. Only after the connect * has occured, can we start talking SSL */ - if (conn->protocol & PROT_HTTPS) { - if (data->bits.httpproxy) { + if (conn->protocol & PROT_HTTPS) { + if (data->bits.httpproxy) { + /* HTTPS through a proxy can only be done with a tunnel */ + result = GetHTTPProxyTunnel(data, data->firstsocket); + if(CURLE_OK != result) + return result; + } - /* OK, now send the connect statment */ - sendf(data->firstsocket, data, - "CONNECT %s:%d HTTP/1.0\015\012" - "%s" - "%s" - "\r\n", - data->hostname, data->remote_port, - (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", - (data->useragent?data->ptr_uagent:"") - ); - - /* wait for the proxy to send us a HTTP/1.0 200 OK header */ - /* Daniel rewrote this part Nov 5 1998 to make it more obvious */ - { - int httperror=0; - int subversion=0; - while(GetLine(data->firstsocket, data->buffer, data)) { - if('\r' == data->buffer[0]) - break; /* end of headers */ - if(2 == sscanf(data->buffer, "HTTP/1.%d %d", - &subversion, - &httperror)) { - ; - } - } - if(200 != httperror) { - if(407 == httperror) - /* Added Nov 6 1998 */ - failf(data, "Proxy requires authorization!"); - else - failf(data, "Received error code %d from proxy", httperror); - return CURLE_READ_ERROR; - } - } - infof (data, "Proxy has replied to CONNECT request\n"); - } - - /* now, perform the SSL initialization for this socket */ - if(UrgSSLConnect (data)) { - return CURLE_SSL_CONNECT_ERROR; - } + /* now, perform the SSL initialization for this socket */ + if(UrgSSLConnect (data)) { + return CURLE_SSL_CONNECT_ERROR; + } } - if(data->bits.user_passwd && !data->bits.this_is_a_follow) { - /* Authorization: is requested, this is not a followed location, get the - original host name */ - data->auth_host = strdup(data->hostname); - } + if(data->bits.user_passwd && !data->bits.this_is_a_follow) { + /* Authorization: is requested, this is not a followed location, get the + original host name */ + data->auth_host = strdup(data->hostname); + } - return CURLE_OK; + return CURLE_OK; } /* called from curl_close() when this struct is about to get wasted, free -- cgit v1.2.1 From 0da7057591609d98f3e0820a13730d97abb2083a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 15 Sep 2000 06:10:52 +0000 Subject: more "anything through http proxy tunnel" fixes --- lib/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7d3507ce4..fba4b80cb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -140,7 +140,8 @@ bool static checkheaders(struct UrlData *data, char *thisheader) * this proxy. After that, the socket can be used just as a normal socket. */ -CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket) +CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, + char *hostname, int remote_port) { int httperror=0; int subversion=0; @@ -153,7 +154,7 @@ CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket) "%s" "%s" "\r\n", - data->hostname, data->remote_port, + hostname, remote_port, (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", (data->useragent?data->ptr_uagent:"") ); @@ -197,7 +198,8 @@ CURLcode http_connect(struct connectdata *conn) if (conn->protocol & PROT_HTTPS) { if (data->bits.httpproxy) { /* HTTPS through a proxy can only be done with a tunnel */ - result = GetHTTPProxyTunnel(data, data->firstsocket); + result = GetHTTPProxyTunnel(data, data->firstsocket, + data->hostname, data->remote_port); if(CURLE_OK != result) return result; } -- cgit v1.2.1 From 00eaf202988bc36d235bbecb1facc72372ea14f9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 15 Sep 2000 12:55:38 +0000 Subject: bugfixed the proxytunnel --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fba4b80cb..c835b1313 100644 --- a/lib/http.c +++ b/lib/http.c @@ -146,7 +146,7 @@ CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, int httperror=0; int subversion=0; - infof(data, "Establish HTTP proxy tunnel\n"); + infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); /* OK, now send the connect statment */ sendf(tunnelsocket, data, -- cgit v1.2.1 From 6f6dfa97a80cb1da3ea82d02cc855000e7b5ea95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 21 Sep 2000 08:48:48 +0000 Subject: Uses the new interface to ssend() and the base64 encoder --- lib/http.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c835b1313..d4a3da1c0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -287,7 +287,7 @@ CURLcode http(struct connectdata *conn) } if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { - char authorization[512]; + char *authorization; /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ @@ -295,9 +295,12 @@ CURLcode http(struct connectdata *conn) !data->auth_host || strequal(data->auth_host, data->hostname)) { sprintf(data->buffer, "%s:%s", data->user, data->passwd); - base64Encode(data->buffer, authorization); - data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", - authorization); + if(base64Encode(data->buffer, 0, /* size zero makes it do strlen() */ + &authorization) >= 0) { + data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", + authorization); + free(authorization); + } } } if((data->bits.set_range) && !checkheaders(data, "Range:")) { @@ -520,9 +523,9 @@ CURLcode http(struct connectdata *conn) /* and here comes the actual data */ if(data->postfieldsize) { - ssend(data->firstsocket, data, "\r\n", 2); - ssend(data->firstsocket, data, data->postfields, data->postfieldsize); - ssend(data->firstsocket, data, "\r\n", 2); + ssend(data->firstsocket, conn, "\r\n", 2); + ssend(data->firstsocket, conn, data->postfields, data->postfieldsize); + ssend(data->firstsocket, conn, "\r\n", 2); } sendf(data->firstsocket, data, "\r\n" -- cgit v1.2.1 From 13962adcb55a676b0b47925680b2e17b3e4815f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 28 Sep 2000 10:26:44 +0000 Subject: 7.3 commit --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d4a3da1c0..4e3471b36 100644 --- a/lib/http.c +++ b/lib/http.c @@ -295,7 +295,7 @@ CURLcode http(struct connectdata *conn) !data->auth_host || strequal(data->auth_host, data->hostname)) { sprintf(data->buffer, "%s:%s", data->user, data->passwd); - if(base64Encode(data->buffer, 0, /* size zero makes it do strlen() */ + if(base64_encode(data->buffer, strlen(data->buffer), &authorization) >= 0) { data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", authorization); -- cgit v1.2.1 From d3f9b2a49051e512c0daa8fccdee7231fadff015 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Oct 2000 11:01:32 +0000 Subject: introduced the new add_buffer() concept that makes the HTTP request to get sent in only one shot --- lib/http.c | 142 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 66 deletions(-) (limited to 'lib/http.c') 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->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: */ - ); + + /* 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->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: */ + ); 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 */ } -- cgit v1.2.1 From 5865860ad6b9f02dba6ed389d554458930d47d07 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 4 Oct 2000 13:07:43 +0000 Subject: counts header and request size --- lib/http.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7e2089496..4b9da418b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -475,7 +475,8 @@ CURLcode http(struct connectdata *conn) /* set upload size to the progress meter */ pgrsSetUploadSize(data, http->postsize); - add_buffer_send(data->firstsocket, conn, req_buffer); + data->request_size = + add_buffer_send(data->firstsocket, conn, req_buffer); result = Transfer(conn, data->firstsocket, -1, TRUE, &http->readbytecount, data->firstsocket, @@ -500,7 +501,8 @@ CURLcode http(struct connectdata *conn) pgrsSetUploadSize(data, data->infilesize); /* this sends the buffer and frees all the buffer resources */ - add_buffer_send(data->firstsocket, conn, req_buffer); + data->request_size = + add_buffer_send(data->firstsocket, conn, req_buffer); /* prepare for transfer */ result = Transfer(conn, data->firstsocket, -1, TRUE, @@ -544,8 +546,11 @@ CURLcode http(struct connectdata *conn) else add_buffer(req_buffer, "\r\n", 2); + /* issue the request */ + data->request_size = + add_buffer_send(data->firstsocket, conn, req_buffer); + /* 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 */ } -- cgit v1.2.1 From 0f8facb49b45a711fa7832c68260a5b45b362922 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Oct 2000 11:12:34 +0000 Subject: added memory debugging include file --- lib/http.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4b9da418b..6c247792c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -117,6 +117,11 @@ #define _MPRINTF_REPLACE /* use our functions only */ #include +/* The last #include file should be: */ +#ifdef MALLOCDEBUG +#include "memdebug.h" +#endif + /* * This function checks the linked list of custom HTTP headers for a particular * header (prefix). -- cgit v1.2.1 From 85174ed358307a611dfa796315ab3485b2a38c3d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Oct 2000 10:29:25 +0000 Subject: memory leak adjusts --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6c247792c..551fac339 100644 --- a/lib/http.c +++ b/lib/http.c @@ -254,7 +254,8 @@ CURLcode http_done(struct connectdata *conn) *bytecount = http->readbytecount + http->writebytecount; } - /* TBD: the HTTP struct remains allocated here */ + free(http); + data->proto.http=NULL; /* it is gone */ return CURLE_OK; } -- cgit v1.2.1 From c44b10de41ffca204acf11f36093c24521119239 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 20 Oct 2000 13:48:38 +0000 Subject: remote_port used in Host: headers only when non-default --- lib/http.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 551fac339..1e6bd24b2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -336,7 +336,13 @@ CURLcode http(struct connectdata *conn) } if(!checkheaders(data, "Host:")) { - data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->remote_port); + if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) || + (!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) + /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include + the port number in the host string */ + data->ptr_host = maprintf("Host: %s\r\n", host); + else + data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->remote_port); } if(!checkheaders(data, "Pragma:")) -- cgit v1.2.1 From bfb118e42ae0785de1106938d3566039e801b925 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Nov 2000 11:29:32 +0000 Subject: Added space after the Cookie: header keyword --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1e6bd24b2..70870f7b2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -394,7 +394,7 @@ CURLcode http(struct connectdata *conn) while(co) { if(co->value && strlen(co->value)) { if(0 == count) { - add_bufferf(req_buffer, "Cookie:"); + add_bufferf(req_buffer, "Cookie: "); } add_bufferf(req_buffer, "%s%s=%s", count?"; ":"", co->name, co->value); -- cgit v1.2.1 From 868488b518706a7eba8e380eeb51d71066a73df8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Nov 2000 14:03:58 +0000 Subject: memory leak cleanup campaign --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 70870f7b2..d5241acec 100644 --- a/lib/http.c +++ b/lib/http.c @@ -390,6 +390,7 @@ CURLcode http(struct connectdata *conn) if(co) { int count=0; + struct Cookie *store=co; /* now loop through all cookies that matched */ while(co) { if(co->value && strlen(co->value)) { @@ -405,7 +406,7 @@ CURLcode http(struct connectdata *conn) if(count) { add_buffer(req_buffer, "\r\n", 2); } - cookie_freelist(co); /* free the cookie list */ + cookie_freelist(store); /* free the cookie list */ co=NULL; } -- cgit v1.2.1 From 42280e95bf159c4db89e3d9ea3d2e77f32cf800f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 20 Nov 2000 08:53:21 +0000 Subject: removed URL size restrictions --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d5241acec..2ff643248 100644 --- a/lib/http.c +++ b/lib/http.c @@ -327,7 +327,7 @@ CURLcode http(struct connectdata *conn) } if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ - strncpy(ppath, data->url, URL_MAX_LENGTH-1); + ppath = data->url; } if(data->bits.http_formpost) { /* we must build the whole darned post sequence first, so that we have -- cgit v1.2.1 From 9a9013ac25206b98d67efa1d833c7aecd541c1ef Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 Nov 2000 09:31:03 +0000 Subject: typecasted the argument to isspace() to int, to remove a pedantic compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2ff643248..d55916e11 100644 --- a/lib/http.c +++ b/lib/http.c @@ -455,7 +455,7 @@ CURLcode http(struct connectdata *conn) /* we require a colon for this to be a true header */ ptr++; /* pass the colon */ - while(*ptr && isspace(*ptr)) + while(*ptr && isspace((int)*ptr)) ptr++; if(*ptr) { -- cgit v1.2.1 From 24dee483e9e925c2ab79dd582f70c9a55ab9ba4d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Jan 2001 09:29:33 +0000 Subject: dual-license fix --- lib/http.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d55916e11..b97213d8f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,38 +5,21 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * The contents of this file are subject to the Mozilla Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ + * Copyright (C) 2000, Daniel Stenberg, , et al. * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. + * In order to be useful for every potential user, curl and libcurl are + * dual-licensed under the MPL and the MIT/X-derivate licenses. * - * The Original Code is Curl. + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the MPL or the MIT/X-derivate + * licenses. You may pick one of these licenses. * - * The Initial Developer of the Original Code is Daniel Stenberg. + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. * - * Portions created by the Initial Developer are Copyright (C) 1998. - * All Rights Reserved. - * - * ------------------------------------------------------------ - * Main author: - * - Daniel Stenberg - * - * http://curl.haxx.se - * - * $Source$ - * $Revision$ - * $Date$ - * $Author$ - * $State$ - * $Locker$ - * - * ------------------------------------------------------------ - ****************************************************************************/ + * $Id$ + *****************************************************************************/ #include "setup.h" -- cgit v1.2.1 From 4031104404c6ceed5e57134125dcdb6cac51c564 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Jan 2001 10:11:41 +0000 Subject: Internal symbols that aren't static are now prefixed with 'Curl_' --- lib/http.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 176 insertions(+), 33 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b97213d8f..555845abb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -105,6 +105,150 @@ #include "memdebug.h" #endif +/* + * The add_buffer series of functions are used to build one large memory chunk + * from repeated function invokes. Used so that the entire HTTP request can + * be sent in one go. + */ +static CURLcode + add_buffer(send_buffer *in, void *inptr, size_t size); + +/* + * add_buffer_init() returns a fine buffer struct + */ +static +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. + */ +static +size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in) +{ + size_t amount; + 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); + } + + amount = ssend(sockfd, conn, in->buffer, in->size_used); + + if(in->buffer) + free(in->buffer); + free(in); + + return amount; +} + + +/* + * add_bufferf() builds a buffer from the formatted input + */ +static +CURLcode add_bufferf(send_buffer *in, char *fmt, ...) +{ + CURLcode result = CURLE_OUT_OF_MEMORY; + char *s; + va_list ap; + va_start(ap, fmt); + s = Curl_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 + */ +static +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; +} + +/* end of the add_buffer functions */ +/*****************************************************************************/ + +/* + * Read everything until a newline. + */ + +static +int GetLine(int sockfd, char *buf, struct UrlData *data) +{ + int nread; + int read_rc=1; + char *ptr; + ptr=buf; + + /* get us a full line, terminated with a newline */ + for(nread=0; + (nreadssl.use) { + read_rc = SSL_read(data->ssl.handle, ptr, 1); + } + else { +#endif + read_rc = sread(sockfd, ptr, 1); +#ifdef USE_SSLEAY + } +#endif /* USE_SSLEAY */ + if (*ptr == '\n') + break; + } + *ptr=0; /* zero terminate */ + + if(data->bits.verbose) { + fputs("< ", data->err); + fwrite(buf, 1, nread, data->err); + fputs("\n", data->err); + } + return nread; +} + + + /* * This function checks the linked list of custom HTTP headers for a particular * header (prefix). @@ -123,13 +267,13 @@ bool static checkheaders(struct UrlData *data, char *thisheader) } /* - * GetHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This + * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This * function will issue the necessary commands to get a seamless tunnel through * this proxy. After that, the socket can be used just as a normal socket. */ -CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, - char *hostname, int remote_port) +CURLcode Curl_ConnectHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, + char *hostname, int remote_port) { int httperror=0; int subversion=0; @@ -170,7 +314,7 @@ CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, return CURLE_OK; } -CURLcode http_connect(struct connectdata *conn) +CURLcode Curl_http_connect(struct connectdata *conn) { struct UrlData *data; CURLcode result; @@ -186,16 +330,15 @@ CURLcode http_connect(struct connectdata *conn) if (conn->protocol & PROT_HTTPS) { if (data->bits.httpproxy) { /* HTTPS through a proxy can only be done with a tunnel */ - result = GetHTTPProxyTunnel(data, data->firstsocket, - data->hostname, data->remote_port); + result = Curl_ConnectHTTPProxyTunnel(data, data->firstsocket, + data->hostname, data->remote_port); if(CURLE_OK != result) return result; } /* now, perform the SSL initialization for this socket */ - if(UrgSSLConnect (data)) { + if(Curl_SSLConnect(data)) return CURLE_SSL_CONNECT_ERROR; - } } if(data->bits.user_passwd && !data->bits.this_is_a_follow) { @@ -209,14 +352,14 @@ CURLcode http_connect(struct connectdata *conn) /* called from curl_close() when this struct is about to get wasted, free protocol-specific resources */ -CURLcode http_close(struct connectdata *conn) +CURLcode Curl_http_close(struct connectdata *conn) { if(conn->data->auth_host) free(conn->data->auth_host); return CURLE_OK; } -CURLcode http_done(struct connectdata *conn) +CURLcode Curl_http_done(struct connectdata *conn) { struct UrlData *data; long *bytecount = &conn->bytecount; @@ -228,7 +371,7 @@ CURLcode http_done(struct connectdata *conn) if(data->bits.http_formpost) { *bytecount = http->readbytecount + http->writebytecount; - FormFree(http->sendit); /* Now free that whole lot */ + Curl_FormFree(http->sendit); /* Now free that whole lot */ data->fread = http->storefread; /* restore */ data->in = http->in; /* restore */ @@ -244,7 +387,7 @@ CURLcode http_done(struct connectdata *conn) } -CURLcode http(struct connectdata *conn) +CURLcode Curl_http(struct connectdata *conn) { struct UrlData *data=conn->data; char *buf = data->buffer; /* this is a short cut to the buffer */ @@ -284,29 +427,29 @@ CURLcode http(struct connectdata *conn) !data->auth_host || strequal(data->auth_host, data->hostname)) { sprintf(data->buffer, "%s:%s", data->user, data->passwd); - if(base64_encode(data->buffer, strlen(data->buffer), - &authorization) >= 0) { - data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", - authorization); + if(Curl_base64_encode(data->buffer, strlen(data->buffer), + &authorization) >= 0) { + data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012", + authorization); free(authorization); } } } if((data->bits.set_range) && !checkheaders(data, "Range:")) { - data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); + data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range); } if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { - data->ptr_ref = maprintf("Referer: %s\015\012", data->referer); + data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); } if(data->cookie && !checkheaders(data, "Cookie:")) { - data->ptr_cookie = maprintf("Cookie: %s\015\012", data->cookie); + data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie); } if(data->cookies) { - co = cookie_getlist(data->cookies, - host, - ppath, - conn->protocol&PROT_HTTPS?TRUE:FALSE); + co = Curl_cookie_getlist(data->cookies, + host, + ppath, + conn->protocol&PROT_HTTPS?TRUE:FALSE); } if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ @@ -315,7 +458,7 @@ CURLcode http(struct connectdata *conn) if(data->bits.http_formpost) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ - http->sendit = getFormData(data->httppost, &http->postsize); + http->sendit = Curl_getFormData(data->httppost, &http->postsize); } if(!checkheaders(data, "Host:")) { @@ -323,9 +466,9 @@ CURLcode http(struct connectdata *conn) (!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ - data->ptr_host = maprintf("Host: %s\r\n", host); + data->ptr_host = aprintf("Host: %s\r\n", host); else - data->ptr_host = maprintf("Host: %s:%d\r\n", host, data->remote_port); + data->ptr_host = aprintf("Host: %s:%d\r\n", host, data->remote_port); } if(!checkheaders(data, "Pragma:")) @@ -389,7 +532,7 @@ CURLcode http(struct connectdata *conn) if(count) { add_buffer(req_buffer, "\r\n", 2); } - cookie_freelist(store); /* free the cookie list */ + Curl_cookie_freelist(store); /* free the cookie list */ co=NULL; } @@ -451,7 +594,7 @@ CURLcode http(struct connectdata *conn) } if(data->bits.http_formpost) { - if(FormInit(&http->form, http->sendit)) { + if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!\n"); return CURLE_HTTP_POST_ERROR; } @@ -461,15 +604,15 @@ CURLcode http(struct connectdata *conn) data->fread = (size_t (*)(char *, size_t, size_t, FILE *)) - FormReader; /* set the read function to read from the - generated form data */ + Curl_FormReader; /* set the read function to read from the + generated form data */ data->in = (FILE *)&http->form; add_bufferf(req_buffer, "Content-Length: %d\r\n", http->postsize-2); /* set upload size to the progress meter */ - pgrsSetUploadSize(data, http->postsize); + Curl_pgrsSetUploadSize(data, http->postsize); data->request_size = add_buffer_send(data->firstsocket, conn, req_buffer); @@ -478,7 +621,7 @@ CURLcode http(struct connectdata *conn) data->firstsocket, &http->writebytecount); if(result) { - FormFree(http->sendit); /* free that whole lot */ + Curl_FormFree(http->sendit); /* free that whole lot */ return result; } } @@ -494,7 +637,7 @@ CURLcode http(struct connectdata *conn) add_bufferf(req_buffer, "\015\012"); /* set the upload size to the progress meter */ - pgrsSetUploadSize(data, data->infilesize); + Curl_pgrsSetUploadSize(data, data->infilesize); /* this sends the buffer and frees all the buffer resources */ data->request_size = -- cgit v1.2.1 From 6403257886fffe9d320099dfa019620c6c1f8dee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Jan 2001 12:19:42 +0000 Subject: renamed Curl_ to curl_ for the printf() prefixes --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 555845abb..aa96ed0af 100644 --- a/lib/http.c +++ b/lib/http.c @@ -161,7 +161,7 @@ CURLcode add_bufferf(send_buffer *in, char *fmt, ...) char *s; va_list ap; va_start(ap, fmt); - s = Curl_mvaprintf(fmt, ap); /* this allocs a new string to append */ + s = vaprintf(fmt, ap); /* this allocs a new string to append */ va_end(ap); if(s) { -- cgit v1.2.1 From ae0a6835bdd6c54e56ce16b7a2727ada3adcccaf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 17 Jan 2001 13:23:01 +0000 Subject: Transfer is now Curl_Tranfer() and transfer.h is used instead of highlevel.h and download.h --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index aa96ed0af..c80fda551 100644 --- a/lib/http.c +++ b/lib/http.c @@ -87,7 +87,7 @@ #include "urldata.h" #include -#include "download.h" +#include "transfer.h" #include "sendf.h" #include "formdata.h" #include "progress.h" @@ -616,7 +616,7 @@ CURLcode Curl_http(struct connectdata *conn) data->request_size = add_buffer_send(data->firstsocket, conn, req_buffer); - result = Transfer(conn, data->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, &http->readbytecount, data->firstsocket, &http->writebytecount); @@ -644,7 +644,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer_send(data->firstsocket, conn, req_buffer); /* prepare for transfer */ - result = Transfer(conn, data->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, &http->readbytecount, data->firstsocket, &http->writebytecount); @@ -690,7 +690,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer_send(data->firstsocket, conn, req_buffer); /* HTTP GET/HEAD download: */ - result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount, + result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount, -1, NULL); /* nothing to upload */ } if(result) -- cgit v1.2.1 From f0b9aefd2e62c389de485e26de2f736ed8043803 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 25 Jan 2001 12:19:02 +0000 Subject: Curl_read() and Curl_write() are now used for reading/writing sockets. Some functions changed prototype due to this change as well. --- lib/http.c | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c80fda551..5fff27bc4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -94,7 +94,6 @@ #include "base64.h" #include "cookie.h" #include "strequal.h" -#include "url.h" #include "ssluse.h" #define _MPRINTF_REPLACE /* use our functions only */ @@ -141,7 +140,7 @@ size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in) fwrite(in->buffer, in->size_used, 1, conn->data->err); } - amount = ssend(sockfd, conn, in->buffer, in->size_used); + Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); if(in->buffer) free(in->buffer); @@ -213,28 +212,21 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size) */ static -int GetLine(int sockfd, char *buf, struct UrlData *data) +int GetLine(int sockfd, char *buf, struct connectdata *conn) { - int nread; + size_t nread; int read_rc=1; char *ptr; + struct UrlData *data=conn->data; + ptr=buf; /* get us a full line, terminated with a newline */ for(nread=0; (nreadssl.use) { - read_rc = SSL_read(data->ssl.handle, ptr, 1); - } - else { -#endif - read_rc = sread(sockfd, ptr, 1); -#ifdef USE_SSLEAY - } -#endif /* USE_SSLEAY */ - if (*ptr == '\n') + if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) || + (*ptr == '\n')) break; } *ptr=0; /* zero terminate */ @@ -272,27 +264,29 @@ bool static checkheaders(struct UrlData *data, char *thisheader) * this proxy. After that, the socket can be used just as a normal socket. */ -CURLcode Curl_ConnectHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, +CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, + int tunnelsocket, char *hostname, int remote_port) { int httperror=0; int subversion=0; + struct UrlData *data=conn->data; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); - /* OK, now send the connect statment */ - sendf(tunnelsocket, data, - "CONNECT %s:%d HTTP/1.0\015\012" - "%s" - "%s" - "\r\n", - hostname, remote_port, - (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", - (data->useragent?data->ptr_uagent:"") - ); + /* OK, now send the connect request to the proxy */ + Curl_sendf(tunnelsocket, conn, + "CONNECT %s:%d HTTP/1.0\015\012" + "%s" + "%s" + "\r\n", + hostname, remote_port, + (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", + (data->useragent?data->ptr_uagent:"") + ); /* wait for the proxy to send us a HTTP/1.0 200 OK header */ - while(GetLine(tunnelsocket, data->buffer, data)) { + while(GetLine(tunnelsocket, data->buffer, conn)) { if('\r' == data->buffer[0]) break; /* end of headers */ if(2 == sscanf(data->buffer, "HTTP/1.%d %d", @@ -330,7 +324,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) if (conn->protocol & PROT_HTTPS) { if (data->bits.httpproxy) { /* HTTPS through a proxy can only be done with a tunnel */ - result = Curl_ConnectHTTPProxyTunnel(data, data->firstsocket, + result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket, data->hostname, data->remote_port); if(CURLE_OK != result) return result; -- cgit v1.2.1 From 3a3f632bf0e1d65a2bd5ab4ff47c6bd7f5e0e474 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 26 Jan 2001 15:49:39 +0000 Subject: Made it possible to do "upload resume" over HTTP --- lib/http.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5fff27bc4..a9b9c5d97 100644 --- a/lib/http.c +++ b/lib/http.c @@ -471,6 +471,64 @@ CURLcode Curl_http(struct connectdata *conn) if(!checkheaders(data, "Accept:")) http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; + if((data->bits.http_post || + data->bits.http_formpost || + data->bits.http_put) && + data->resume_from) { + /********************************************************************** + * Resuming upload in HTTP means that we PUT or POST and that we have + * got a resume_from value set. The resume value has already created + * a Range: header that will be passed along. We need to "fast forward" + * the file the given number of bytes and decrease the assume upload + * file size before we continue this venture in the dark lands of HTTP. + *********************************************************************/ + + if(data->resume_from < 0 ) { + /* + * This is meant to get the size of the present remote-file by itself. + * We don't support this now. Bail out! + */ + data->resume_from = 0; + } + + if(data->resume_from) { + /* do we still game? */ + int passed=0; + + /* Now, let's read off the proper amount of bytes from the + input. If we knew it was a proper file we could've just + fseek()ed but we only have a stream here */ + do { + int readthisamountnow = (data->resume_from - passed); + int actuallyread; + + if(readthisamountnow > BUFSIZE) + readthisamountnow = BUFSIZE; + + actuallyread = + data->fread(data->buffer, 1, readthisamountnow, data->in); + + passed += actuallyread; + if(actuallyread != readthisamountnow) { + failf(data, "Could only read %d bytes from the input\n", + passed); + return CURLE_READ_ERROR; + } + } while(passed != data->resume_from); /* loop until done */ + + /* now, decrease the size of the read */ + if(data->infilesize>0) { + data->infilesize -= data->resume_from; + + if(data->infilesize <= 0) { + failf(data, "File already completely uploaded\n"); + return CURLE_PARTIAL_FILE; + } + } + /* we've passed, proceed as normal */ + } + } + do { send_buffer *req_buffer; struct curl_slist *headers=data->headers; -- cgit v1.2.1 From 3a8210c975fd829f00e43f87974d51e3d6b12410 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 27 Jan 2001 18:57:07 +0000 Subject: Resume is now done with a Content-Range header instead of a Range header if the request isn't GET. Presumably, this is how it should be made. --- lib/http.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a9b9c5d97..7553b613b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -429,8 +429,21 @@ CURLcode Curl_http(struct connectdata *conn) } } } - if((data->bits.set_range) && !checkheaders(data, "Range:")) { - data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range); + if(data->bits.set_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if((data->httpreq == HTTPREQ_GET) && + !checkheaders(data, "Range:")) { + data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range); + } + else if((data->httpreq != HTTPREQ_GET) && + !checkheaders(data, "Content-Range:")) { + data->ptr_rangeline = aprintf("Content-Range: bytes=%s\015\012", + data->range); + } } if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); -- cgit v1.2.1 From 513bc444218f5ac0c942b07abc7c9b94787858ec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Jan 2001 07:24:20 +0000 Subject: HTTP PUT resume now sends Content-Range: headers as I believe the RFC2616 describes, Bob Schader's research seems to agree. --- lib/http.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7553b613b..41e5e87bf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -429,22 +429,6 @@ CURLcode Curl_http(struct connectdata *conn) } } } - if(data->bits.set_range) { - /* - * A range is selected. We use different headers whether we're downloading - * or uploading and we always let customized headers override our internal - * ones if any such are specified. - */ - if((data->httpreq == HTTPREQ_GET) && - !checkheaders(data, "Range:")) { - data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range); - } - else if((data->httpreq != HTTPREQ_GET) && - !checkheaders(data, "Content-Range:")) { - data->ptr_rangeline = aprintf("Content-Range: bytes=%s\015\012", - data->range); - } - } if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); } @@ -541,6 +525,34 @@ CURLcode Curl_http(struct connectdata *conn) /* we've passed, proceed as normal */ } } + if(data->bits.set_range) { + /* + * A range is selected. We use different headers whether we're downloading + * or uploading and we always let customized headers override our internal + * ones if any such are specified. + */ + if((data->httpreq == HTTPREQ_GET) && + !checkheaders(data, "Range:")) { + data->ptr_rangeline = aprintf("Range: bytes=%s\r\n", data->range); + } + else if((data->httpreq != HTTPREQ_GET) && + !checkheaders(data, "Content-Range:")) { + + if(data->resume_from) { + /* This is because "resume" was selected */ + long total_expected_size= data->resume_from + data->infilesize; + data->ptr_rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", + data->range, total_expected_size-1, + total_expected_size); + } + else { + /* Range was selected and then we just pass the incoming range and + append total size */ + data->ptr_rangeline = aprintf("Content-Range: bytes %s/%d\r\n", + data->range, data->infilesize); + } + } + } do { send_buffer *req_buffer; -- cgit v1.2.1 From c41c5a0ef236f1eb1a973eeb25f47e848c9e68db Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 31 Jan 2001 13:54:12 +0000 Subject: curl_read() and Curl_read() now have ssize_t in the last argument --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 41e5e87bf..9fe056c5f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -214,7 +214,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size) static int GetLine(int sockfd, char *buf, struct connectdata *conn) { - size_t nread; + ssize_t nread; int read_rc=1; char *ptr; struct UrlData *data=conn->data; -- cgit v1.2.1 From abb14de7e05505d4159e6ffbb75f6135d21b3f6e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Feb 2001 09:31:03 +0000 Subject: GetLine() didn't properly act on -1 lengths returned from Curl_read() --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9fe056c5f..54623ec6b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -226,17 +226,18 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn) (nreadbits.verbose) { fputs("< ", data->err); fwrite(buf, 1, nread, data->err); fputs("\n", data->err); } - return nread; + return nread>0?nread:0; } -- cgit v1.2.1 From a140e5311d4cc2dd72a172443643839723b30bde Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 Feb 2001 13:34:16 +0000 Subject: moved the protocol-specific free to allow easier multiple transfers --- lib/http.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 54623ec6b..93ae049b1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -375,9 +375,6 @@ CURLcode Curl_http_done(struct connectdata *conn) *bytecount = http->readbytecount + http->writebytecount; } - free(http); - data->proto.http=NULL; /* it is gone */ - return CURLE_OK; } -- cgit v1.2.1 From a1d6ad26100bc493c7b04f1301b1634b7f5aa8b4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Feb 2001 17:35:51 +0000 Subject: multiple connection support initial commit --- lib/http.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 93ae049b1..836a16622 100644 --- a/lib/http.c +++ b/lib/http.c @@ -325,21 +325,21 @@ CURLcode Curl_http_connect(struct connectdata *conn) if (conn->protocol & PROT_HTTPS) { if (data->bits.httpproxy) { /* HTTPS through a proxy can only be done with a tunnel */ - result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket, - data->hostname, data->remote_port); + result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, + conn->hostname, conn->remote_port); if(CURLE_OK != result) return result; } /* now, perform the SSL initialization for this socket */ - if(Curl_SSLConnect(data)) + if(Curl_SSLConnect(conn)) return CURLE_SSL_CONNECT_ERROR; } if(data->bits.user_passwd && !data->bits.this_is_a_follow) { /* Authorization: is requested, this is not a followed location, get the original host name */ - data->auth_host = strdup(data->hostname); + data->auth_host = strdup(conn->hostname); } return CURLE_OK; @@ -361,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn) struct HTTP *http; data=conn->data; - http=data->proto.http; + http=conn->proto.http; if(data->bits.http_formpost) { *bytecount = http->readbytecount + http->writebytecount; @@ -394,7 +394,7 @@ CURLcode Curl_http(struct connectdata *conn) if(!http) return CURLE_OUT_OF_MEMORY; memset(http, 0, sizeof(struct HTTP)); - data->proto.http = http; + conn->proto.http = http; if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->bits.upload) { @@ -417,7 +417,7 @@ CURLcode Curl_http(struct connectdata *conn) host due to a location-follow, we do some weirdo checks here */ if(!data->bits.this_is_a_follow || !data->auth_host || - strequal(data->auth_host, data->hostname)) { + strequal(data->auth_host, conn->hostname)) { sprintf(data->buffer, "%s:%s", data->user, data->passwd); if(Curl_base64_encode(data->buffer, strlen(data->buffer), &authorization) >= 0) { @@ -690,10 +690,10 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); data->request_size = - add_buffer_send(data->firstsocket, conn, req_buffer); - result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, + add_buffer_send(conn->firstsocket, conn, req_buffer); + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &http->readbytecount, - data->firstsocket, + conn->firstsocket, &http->writebytecount); if(result) { Curl_FormFree(http->sendit); /* free that whole lot */ @@ -716,12 +716,12 @@ CURLcode Curl_http(struct connectdata *conn) /* this sends the buffer and frees all the buffer resources */ data->request_size = - add_buffer_send(data->firstsocket, conn, req_buffer); + add_buffer_send(conn->firstsocket, conn, req_buffer); /* prepare for transfer */ - result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &http->readbytecount, - data->firstsocket, + conn->firstsocket, &http->writebytecount); if(result) return result; @@ -762,10 +762,10 @@ CURLcode Curl_http(struct connectdata *conn) /* issue the request */ data->request_size = - add_buffer_send(data->firstsocket, conn, req_buffer); + add_buffer_send(conn->firstsocket, conn, req_buffer); /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount, + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, -1, NULL); /* nothing to upload */ } if(result) -- cgit v1.2.1 From 46e0937263df22f091cb7367182ff6095f73b82e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Feb 2001 17:46:35 +0000 Subject: corrected memory leaks when re-using connections --- lib/http.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 836a16622..897e0a1fb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -421,6 +421,8 @@ CURLcode Curl_http(struct connectdata *conn) sprintf(data->buffer, "%s:%s", data->user, data->passwd); if(Curl_base64_encode(data->buffer, strlen(data->buffer), &authorization) >= 0) { + if(data->ptr_userpwd) + free(data->ptr_userpwd); data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012", authorization); free(authorization); @@ -428,9 +430,13 @@ CURLcode Curl_http(struct connectdata *conn) } } if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { + if(data->ptr_ref) + free(data->ptr_ref); data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); } if(data->cookie && !checkheaders(data, "Cookie:")) { + if(data->ptr_cookie) + free(data->ptr_cookie); data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie); } @@ -450,7 +456,11 @@ CURLcode Curl_http(struct connectdata *conn) http->sendit = Curl_getFormData(data->httppost, &http->postsize); } - if(!checkheaders(data, "Host:")) { + if(!checkheaders(data, "Host:") && + !data->ptr_host) { + /* if ptr_host is already set, it is OK since we only re-use connections + to the very same host and port */ + if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include -- cgit v1.2.1 From 584dbffe601f823e5d3a3ced0d035b499f1bc903 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Feb 2001 23:32:02 +0000 Subject: moved the dynamicly set pointers to the connectdata struct --- lib/http.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 897e0a1fb..3184c7f5f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -282,8 +282,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, "%s" "\r\n", hostname, remote_port, - (data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", - (data->useragent?data->ptr_uagent:"") + (data->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", + (data->useragent?conn->allocptr.uagent:"") ); /* wait for the proxy to send us a HTTP/1.0 200 OK header */ @@ -405,9 +405,9 @@ CURLcode Curl_http(struct connectdata *conn) have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ - if(checkheaders(data, "User-Agent:") && data->ptr_uagent) { - free(data->ptr_uagent); - data->ptr_uagent=NULL; + if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { + free(conn->allocptr.uagent); + conn->allocptr.uagent=NULL; } if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { @@ -421,23 +421,23 @@ CURLcode Curl_http(struct connectdata *conn) sprintf(data->buffer, "%s:%s", data->user, data->passwd); if(Curl_base64_encode(data->buffer, strlen(data->buffer), &authorization) >= 0) { - if(data->ptr_userpwd) - free(data->ptr_userpwd); - data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012", + if(conn->allocptr.userpwd) + free(conn->allocptr.userpwd); + conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", authorization); free(authorization); } } } if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { - if(data->ptr_ref) - free(data->ptr_ref); - data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); + if(conn->allocptr.ref) + free(conn->allocptr.ref); + conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer); } if(data->cookie && !checkheaders(data, "Cookie:")) { - if(data->ptr_cookie) - free(data->ptr_cookie); - data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie); + if(conn->allocptr.cookie) + free(conn->allocptr.cookie); + conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie); } if(data->cookies) { @@ -457,7 +457,7 @@ CURLcode Curl_http(struct connectdata *conn) } if(!checkheaders(data, "Host:") && - !data->ptr_host) { + !conn->allocptr.host) { /* if ptr_host is already set, it is OK since we only re-use connections to the very same host and port */ @@ -465,9 +465,10 @@ CURLcode Curl_http(struct connectdata *conn) (!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ - data->ptr_host = aprintf("Host: %s\r\n", host); + conn->allocptr.host = aprintf("Host: %s\r\n", host); else - data->ptr_host = aprintf("Host: %s:%d\r\n", host, data->remote_port); + conn->allocptr.host = aprintf("Host: %s:%d\r\n", host, + data->remote_port); } if(!checkheaders(data, "Pragma:")) @@ -541,7 +542,7 @@ CURLcode Curl_http(struct connectdata *conn) */ if((data->httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { - data->ptr_rangeline = aprintf("Range: bytes=%s\r\n", data->range); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range); } else if((data->httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { @@ -549,14 +550,14 @@ CURLcode Curl_http(struct connectdata *conn) if(data->resume_from) { /* This is because "resume" was selected */ long total_expected_size= data->resume_from + data->infilesize; - data->ptr_rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", + conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", data->range, total_expected_size-1, total_expected_size); } else { /* Range was selected and then we just pass the incoming range and append total size */ - data->ptr_rangeline = aprintf("Content-Range: bytes %s/%d\r\n", + conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", data->range, data->infilesize); } } @@ -572,7 +573,7 @@ CURLcode Curl_http(struct connectdata *conn) /* add the main request stuff */ add_bufferf(req_buffer, "%s " /* GET/HEAD/POST/PUT */ - "%s HTTP/1.0\r\n" /* path */ + "%s HTTP/1.1\r\n" /* path */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ @@ -588,15 +589,15 @@ CURLcode Curl_http(struct connectdata *conn) (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->ptr_host?data->ptr_host:""), /* Host: host */ + (data->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", + (data->bits.user_passwd && conn->allocptr.userpwd)?conn->allocptr.userpwd:"", + (data->bits.set_range && conn->allocptr.rangeline)?conn->allocptr.rangeline:"", + (data->useragent && *data->useragent && conn->allocptr.uagent)?conn->allocptr.uagent:"", + (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: */ + (conn->allocptr.host?conn->allocptr.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->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */ ); if(co) { -- cgit v1.2.1 From 9c63fcf21002256c338f2fe8dde34a5dc43d9a4e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Feb 2001 23:41:15 +0000 Subject: we only allocate the HTTP struct if we need to --- lib/http.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3184c7f5f..641373ae2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -390,11 +390,15 @@ CURLcode Curl_http(struct connectdata *conn) char *host = conn->name; long *bytecount = &conn->bytecount; - http = (struct HTTP *)malloc(sizeof(struct HTTP)); - if(!http) - return CURLE_OUT_OF_MEMORY; - memset(http, 0, sizeof(struct HTTP)); - conn->proto.http = http; + if(!conn->proto.http) { + /* Only allocate this struct if we don't already have it! */ + + http = (struct HTTP *)malloc(sizeof(struct HTTP)); + if(!http) + return CURLE_OUT_OF_MEMORY; + memset(http, 0, sizeof(struct HTTP)); + conn->proto.http = http; + } if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->bits.upload) { -- cgit v1.2.1 From d1cfbd51b5f6e4246cec86ce3c9b7b1cde2f860a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 2 Mar 2001 15:34:15 +0000 Subject: remade the port number stuff so that following locations work and doing intermixed HTTP and FTP persistant connections also work! --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 641373ae2..a77cc0e45 100644 --- a/lib/http.c +++ b/lib/http.c @@ -465,14 +465,14 @@ CURLcode Curl_http(struct connectdata *conn) /* if ptr_host is already set, it is OK since we only re-use connections to the very same host and port */ - if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) || - (!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) + if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || + (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ conn->allocptr.host = aprintf("Host: %s\r\n", host); else conn->allocptr.host = aprintf("Host: %s:%d\r\n", host, - data->remote_port); + conn->remote_port); } if(!checkheaders(data, "Pragma:")) -- cgit v1.2.1 From 90ac37a683820850e50d189cae0ee1b99c29d11b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 4 Mar 2001 15:25:54 +0000 Subject: Curl_http() could crash on connection re-use --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a77cc0e45..589501450 100644 --- a/lib/http.c +++ b/lib/http.c @@ -399,6 +399,8 @@ CURLcode Curl_http(struct connectdata *conn) memset(http, 0, sizeof(struct HTTP)); conn->proto.http = http; } + else + http = conn->proto.http; if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->bits.upload) { -- cgit v1.2.1 From c21f848c1c54b10e6d0f99baf520789803437a4e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Mar 2001 13:40:08 +0000 Subject: enable persistant connections by default --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 589501450..71ef7aa35 100644 --- a/lib/http.c +++ b/lib/http.c @@ -402,6 +402,9 @@ CURLcode Curl_http(struct connectdata *conn) else http = conn->proto.http; + /* We default to persistant connections */ + conn->bits.close = FALSE; + if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->bits.upload) { data->bits.http_put=1; -- cgit v1.2.1 From a23db7b7c7a183cbab8eadc59d73aaa159d301de Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Mar 2001 23:51:41 +0000 Subject: "Transfer-Encoding: chunked" support added --- lib/http.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 71ef7aa35..2da7cbf72 100644 --- a/lib/http.c +++ b/lib/http.c @@ -104,6 +104,7 @@ #include "memdebug.h" #endif +/* ------------------------------------------------------------------------- */ /* * The add_buffer series of functions are used to build one large memory chunk * from repeated function invokes. Used so that the entire HTTP request can @@ -205,7 +206,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size) } /* end of the add_buffer functions */ -/*****************************************************************************/ +/* ------------------------------------------------------------------------- */ /* * Read everything until a newline. @@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OK; } +/* + * HTTP stuff to do at connect-time. + */ CURLcode Curl_http_connect(struct connectdata *conn) { struct UrlData *data; -- cgit v1.2.1 From ac0bad2433a35c274cf8ad14e158251b88817b33 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 9 Mar 2001 16:48:18 +0000 Subject: remake Host: for each connection and it'll work with proxies too --- lib/http.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2da7cbf72..52b009d3e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -469,10 +469,14 @@ CURLcode Curl_http(struct connectdata *conn) http->sendit = Curl_getFormData(data->httppost, &http->postsize); } - if(!checkheaders(data, "Host:") && - !conn->allocptr.host) { - /* if ptr_host is already set, it is OK since we only re-use connections - to the very same host and port */ + if(!checkheaders(data, "Host:")) { + /* if ptr_host is already set, it is almost OK since we only re-use + connections to the very same host and port, but when we use a HTTP + proxy we have a persistant connect and yet we must change the Host: + header! */ + + if(conn->allocptr.host) + free(conn->allocptr.host); if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) -- cgit v1.2.1 From f8e1fc32de60c5f4c30d20d2bc8c55ac13405752 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 14 Mar 2001 14:11:11 +0000 Subject: Edin Kadribaic's bug report #408488 forced a rearrange of two struct fields from urldata to connectdata, quite correctly. --- lib/http.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 52b009d3e..a701e2a46 100644 --- a/lib/http.c +++ b/lib/http.c @@ -283,7 +283,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, "%s" "\r\n", hostname, remote_port, - (data->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", + (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", (data->useragent?conn->allocptr.uagent:"") ); @@ -340,7 +340,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) return CURLE_SSL_CONNECT_ERROR; } - if(data->bits.user_passwd && !data->bits.this_is_a_follow) { + if(conn->bits.user_passwd && !data->bits.this_is_a_follow) { /* Authorization: is requested, this is not a followed location, get the original host name */ data->auth_host = strdup(conn->hostname); @@ -423,7 +423,7 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.uagent=NULL; } - if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { + if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) { char *authorization; /* To prevent the user+password to get sent to other than the original @@ -606,10 +606,14 @@ CURLcode Curl_http(struct connectdata *conn) (data->bits.http_post || data->bits.http_formpost)?"POST": (data->bits.http_put)?"PUT":"GET"), ppath, - (data->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", - (data->bits.user_passwd && conn->allocptr.userpwd)?conn->allocptr.userpwd:"", - (data->bits.set_range && conn->allocptr.rangeline)?conn->allocptr.rangeline:"", - (data->useragent && *data->useragent && conn->allocptr.uagent)?conn->allocptr.uagent:"", + (conn->bits.proxy_user_passwd && + conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", + (conn->bits.user_passwd && conn->allocptr.userpwd)? + conn->allocptr.userpwd:"", + (data->bits.set_range && conn->allocptr.rangeline)? + conn->allocptr.rangeline:"", + (data->useragent && *data->useragent && conn->allocptr.uagent)? + conn->allocptr.uagent:"", (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: */ (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", -- cgit v1.2.1 From fd8ea204c0faec613a43166af578bff95e724f79 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 Apr 2001 07:28:49 +0000 Subject: use GMT for the conditional timed gets (reported by Phil Karn) --- lib/http.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a701e2a46..58d03ac65 100644 --- a/lib/http.c +++ b/lib/http.c @@ -646,12 +646,21 @@ CURLcode Curl_http(struct connectdata *conn) if(data->timecondition) { struct tm *thistime; + /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since + * header family should have their times set in GMT as RFC2616 defines: + * "All HTTP date/time stamps MUST be represented in Greenwich Mean Time + * (GMT), without exception. For the purposes of HTTP, GMT is exactly + * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). + */ + #ifdef HAVE_LOCALTIME_R /* thread-safe version */ + /* We assume that the presense of localtime_r() proves the presense + of gmtime_r() which is a bit ugly but might work */ struct tm keeptime; - thistime = (struct tm *)localtime_r(&data->timevalue, &keeptime); + thistime = (struct tm *)gmtime_r(&data->timevalue, &keeptime); #else - thistime = localtime(&data->timevalue); + thistime = gmtime(&data->timevalue); #endif if(NULL == thistime) { failf(data, "localtime() failed!"); -- cgit v1.2.1 From 3fd65fb7d83a8e3e6acd1a40c48b46088ebd536f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 18 Apr 2001 07:25:11 +0000 Subject: Remade resume stuff to keep data in the connectdata struct instead of the main handle struct to work with persistant connections --- lib/http.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 58d03ac65..1f17b9c00 100644 --- a/lib/http.c +++ b/lib/http.c @@ -497,7 +497,7 @@ CURLcode Curl_http(struct connectdata *conn) if((data->bits.http_post || data->bits.http_formpost || data->bits.http_put) && - data->resume_from) { + conn->resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have * got a resume_from value set. The resume value has already created @@ -506,15 +506,15 @@ CURLcode Curl_http(struct connectdata *conn) * file size before we continue this venture in the dark lands of HTTP. *********************************************************************/ - if(data->resume_from < 0 ) { + if(conn->resume_from < 0 ) { /* * This is meant to get the size of the present remote-file by itself. * We don't support this now. Bail out! */ - data->resume_from = 0; + conn->resume_from = 0; } - if(data->resume_from) { + if(conn->resume_from) { /* do we still game? */ int passed=0; @@ -522,7 +522,7 @@ CURLcode Curl_http(struct connectdata *conn) input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - int readthisamountnow = (data->resume_from - passed); + int readthisamountnow = (conn->resume_from - passed); int actuallyread; if(readthisamountnow > BUFSIZE) @@ -537,11 +537,11 @@ CURLcode Curl_http(struct connectdata *conn) passed); return CURLE_READ_ERROR; } - } while(passed != data->resume_from); /* loop until done */ + } while(passed != conn->resume_from); /* loop until done */ /* now, decrease the size of the read */ if(data->infilesize>0) { - data->infilesize -= data->resume_from; + data->infilesize -= conn->resume_from; if(data->infilesize <= 0) { failf(data, "File already completely uploaded\n"); @@ -551,7 +551,7 @@ CURLcode Curl_http(struct connectdata *conn) /* we've passed, proceed as normal */ } } - if(data->bits.set_range) { + if(conn->bits.use_range) { /* * A range is selected. We use different headers whether we're downloading * or uploading and we always let customized headers override our internal @@ -559,23 +559,23 @@ CURLcode Curl_http(struct connectdata *conn) */ if((data->httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { - conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); } else if((data->httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { - if(data->resume_from) { + if(conn->resume_from) { /* This is because "resume" was selected */ - long total_expected_size= data->resume_from + data->infilesize; + long total_expected_size= conn->resume_from + data->infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", - data->range, total_expected_size-1, + conn->range, total_expected_size-1, total_expected_size); } else { /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", - data->range, data->infilesize); + conn->range, data->infilesize); } } } @@ -610,7 +610,7 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", (conn->bits.user_passwd && conn->allocptr.userpwd)? conn->allocptr.userpwd:"", - (data->bits.set_range && conn->allocptr.rangeline)? + (conn->bits.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", (data->useragent && *data->useragent && conn->allocptr.uagent)? conn->allocptr.uagent:"", -- cgit v1.2.1 From 89ba66e071ba23d6cd20a714217432e6c3845eda Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 May 2001 12:38:28 +0000 Subject: corrected the read-callback typecase since FILE * was replaced with void * --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1f17b9c00..4984d684d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -718,8 +718,7 @@ CURLcode Curl_http(struct connectdata *conn) http->storefread = data->fread; /* backup */ http->in = data->in; /* backup */ - data->fread = - (size_t (*)(char *, size_t, size_t, FILE *)) + data->fread = (curl_read_callback) Curl_FormReader; /* set the read function to read from the generated form data */ data->in = (FILE *)&http->form; -- cgit v1.2.1 From c7dbde9f3f0a3dd8e3b04106c2d8dba90d89c994 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 12 May 2001 09:30:42 +0000 Subject: Uses the Curl_SSLConnect() according to the new return type --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4984d684d..3aba7aadd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -336,8 +336,9 @@ CURLcode Curl_http_connect(struct connectdata *conn) } /* now, perform the SSL initialization for this socket */ - if(Curl_SSLConnect(conn)) - return CURLE_SSL_CONNECT_ERROR; + result = Curl_SSLConnect(conn); + if(result) + return result; } if(conn->bits.user_passwd && !data->bits.this_is_a_follow) { -- cgit v1.2.1 From 77f34915ce25a22b2f2742ba69ac76093376dc94 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 31 May 2001 07:03:04 +0000 Subject: removed _REENTRANT define --- lib/http.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3aba7aadd..73d13a6dc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -34,13 +34,6 @@ #include - -#ifdef NEED_REENTRANT -#define _REENTRANT /* Necessary to use in Solaris, since the silly guys at Sun - made the localtime_r() prototype dependent on it (or - _POSIX_C_SOURCE or _POSIX_PTHREAD_SEMANTICS). */ -#endif - #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #include #include -- cgit v1.2.1 From 89872447585d6d279bb9cb23fda30855932143a2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 3 Aug 2001 11:52:53 +0000 Subject: httpreq cleanup fix --- lib/http.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 73d13a6dc..28292384e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -361,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn) data=conn->data; http=conn->proto.http; - if(data->bits.http_formpost) { + if(HTTPREQ_POST_FORM == data->httpreq) { *bytecount = http->readbytecount + http->writebytecount; Curl_FormFree(http->sendit); /* Now free that whole lot */ @@ -369,7 +369,7 @@ CURLcode Curl_http_done(struct connectdata *conn) data->fread = http->storefread; /* restore */ data->in = http->in; /* restore */ } - else if(data->bits.http_put) { + else if(HTTPREQ_PUT == data->httpreq) { *bytecount = http->readbytecount + http->writebytecount; } @@ -405,7 +405,7 @@ CURLcode Curl_http(struct connectdata *conn) if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->bits.upload) { - data->bits.http_put=1; + data->httpreq = HTTPREQ_PUT; } /* The User-Agent string has been built in url.c already, because it might @@ -457,7 +457,7 @@ CURLcode Curl_http(struct connectdata *conn) /* The path sent to the proxy is in fact the entire URL */ ppath = data->url; } - if(data->bits.http_formpost) { + if(HTTPREQ_POST_FORM == data->httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ http->sendit = Curl_getFormData(data->httppost, &http->postsize); @@ -488,9 +488,9 @@ CURLcode Curl_http(struct connectdata *conn) if(!checkheaders(data, "Accept:")) http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; - if((data->bits.http_post || - data->bits.http_formpost || - data->bits.http_put) && + if(( (HTTPREQ_POST == data->httpreq) || + (HTTPREQ_POST_FORM == data->httpreq) || + (HTTPREQ_PUT == data->httpreq) ) && conn->resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have @@ -597,8 +597,9 @@ CURLcode Curl_http(struct connectdata *conn) data->customrequest?data->customrequest: (data->bits.no_body?"HEAD": - (data->bits.http_post || data->bits.http_formpost)?"POST": - (data->bits.http_put)?"PUT":"GET"), + ((HTTPREQ_POST == data->httpreq) || + (HTTPREQ_POST_FORM == data->httpreq))?"POST": + (HTTPREQ_PUT == data->httpreq)?"PUT":"GET"), ppath, (conn->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", @@ -703,7 +704,7 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } - if(data->bits.http_formpost) { + if(HTTPREQ_POST_FORM == data->httpreq) { if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!\n"); return CURLE_HTTP_POST_ERROR; @@ -734,7 +735,7 @@ CURLcode Curl_http(struct connectdata *conn) return result; } } - else if(data->bits.http_put) { + else if(HTTPREQ_PUT == data->httpreq) { /* Let's PUT the data to the server! */ if(data->infilesize>0) { @@ -762,7 +763,7 @@ CURLcode Curl_http(struct connectdata *conn) } else { - if(data->bits.http_post) { + if(HTTPREQ_POST == data->httpreq) { /* this is the simple POST, using x-www-form-urlencoded style */ if(!checkheaders(data, "Content-Length:")) -- cgit v1.2.1 From 2cf45f68b095f478a8a80a2acb5e0ea54e49db70 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 6 Aug 2001 12:36:18 +0000 Subject: Curl_FormFree renamed to Curl_formclean, as it turns out VMS for example requires all global symbols to be *case insentively* unique! curl_formfree is a global function we shouldn't touch. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 28292384e..42947749e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -364,7 +364,7 @@ CURLcode Curl_http_done(struct connectdata *conn) if(HTTPREQ_POST_FORM == data->httpreq) { *bytecount = http->readbytecount + http->writebytecount; - Curl_FormFree(http->sendit); /* Now free that whole lot */ + Curl_formclean(http->sendit); /* Now free that whole lot */ data->fread = http->storefread; /* restore */ data->in = http->in; /* restore */ @@ -731,7 +731,7 @@ CURLcode Curl_http(struct connectdata *conn) conn->firstsocket, &http->writebytecount); if(result) { - Curl_FormFree(http->sendit); /* free that whole lot */ + Curl_formclean(http->sendit); /* free that whole lot */ return result; } } -- cgit v1.2.1 From c11a1bf72a23ab0fc4d55aaac46425fdef92657b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Aug 2001 08:28:15 +0000 Subject: made some char * into const char * and I removed the check for size > 0 in the add_buffer function. --- lib/http.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 42947749e..16c03b123 100644 --- a/lib/http.c +++ b/lib/http.c @@ -104,7 +104,7 @@ * be sent in one go. */ static CURLcode - add_buffer(send_buffer *in, void *inptr, size_t size); + add_buffer(send_buffer *in, const void *inptr, size_t size); /* * add_buffer_init() returns a fine buffer struct @@ -148,7 +148,7 @@ size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in) * add_bufferf() builds a buffer from the formatted input */ static -CURLcode add_bufferf(send_buffer *in, char *fmt, ...) +CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) { CURLcode result = CURLE_OUT_OF_MEMORY; char *s; @@ -168,32 +168,30 @@ CURLcode add_bufferf(send_buffer *in, char *fmt, ...) * add_buffer() appends a memory chunk to the existing one */ static -CURLcode add_buffer(send_buffer *in, void *inptr, size_t size) +CURLcode add_buffer(send_buffer *in, const 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(!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; + 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; + in->buffer = new_rb; + in->size_max = new_size; } + memcpy(&in->buffer[in->size_used], inptr, size); + + in->size_used += size; return CURLE_OK; } @@ -240,7 +238,7 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn) * This function checks the linked list of custom HTTP headers for a particular * header (prefix). */ -bool static checkheaders(struct UrlData *data, char *thisheader) +static bool checkheaders(struct UrlData *data, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); -- cgit v1.2.1 From 70ad8a0b2be173a71a0e55263da55c78fcd505b6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Aug 2001 13:38:36 +0000 Subject: Using CURLOPT_POST without using CURLOPT_POSTFIELDS caused us to strlen() a NULL pointer. Now, we treat a missing CURLOPT_POSTFIELDS as if there is no data to send. --- lib/http.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 16c03b123..ba9685642 100644 --- a/lib/http.c +++ b/lib/http.c @@ -764,6 +764,17 @@ CURLcode Curl_http(struct connectdata *conn) if(HTTPREQ_POST == data->httpreq) { /* this is the simple POST, using x-www-form-urlencoded style */ + if(!data->postfields) { + /* + * This is an attempt to do a POST without having anything to + * actually send. Let's make a NULL pointer equal "" here. Good/bad + * ? + */ + data->postfields = ""; + data->postfieldsize = 0; /* it might been set to something illegal, + anything > 0 would be! */ + } + if(!checkheaders(data, "Content-Length:")) /* we allow replacing this header, although it isn't very wise to actually set your own */ -- cgit v1.2.1 From 1b00298b52a2d66126ddec8688001e46b4f45f5b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Aug 2001 10:14:06 +0000 Subject: modified to use the renamed kerberos functions with Curl_ prefix --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ba9685642..5dd1e49d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -770,7 +770,7 @@ CURLcode Curl_http(struct connectdata *conn) * actually send. Let's make a NULL pointer equal "" here. Good/bad * ? */ - data->postfields = ""; + data->postfields = (char *)""; data->postfieldsize = 0; /* it might been set to something illegal, anything > 0 would be! */ } -- cgit v1.2.1 From 08655d8d5d0ea980227096366c231693198e61d6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 Aug 2001 13:18:07 +0000 Subject: Georg Huettenegger's patch curl-7.8.1-pre5-patch-20010819 --- lib/http.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5dd1e49d8..df5e58557 100644 --- a/lib/http.c +++ b/lib/http.c @@ -703,6 +703,8 @@ CURLcode Curl_http(struct connectdata *conn) } if(HTTPREQ_POST_FORM == data->httpreq) { + char contentType[256]; + int linelength=0; if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!\n"); return CURLE_HTTP_POST_ERROR; @@ -719,15 +721,40 @@ CURLcode Curl_http(struct connectdata *conn) add_bufferf(req_buffer, "Content-Length: %d\r\n", http->postsize-2); + if(!checkheaders(data, "Expect:")) { + /* if not disabled explicitly we add a Expect: 100-continue + to the headers which actually speeds up post operations (as + there is one packet coming back from the web server) */ + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + data->bits.expect100header = TRUE; + + /* Get Content-Type: line from Curl_FormReadOneLine, which happens + to always be the first line. We can know this for sure since + we always build the formpost linked list the same way! */ + linelength = Curl_FormReadOneLine (contentType, + sizeof(contentType), + 1, + (FILE *)&http->form); + if(linelength == -1) { + failf(data, "Could not get Content-Type header line!\n"); + return CURLE_HTTP_POST_ERROR; + } + add_buffer(req_buffer, contentType, linelength); + } + /* set upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); + /* fire away the whole request to the server */ data->request_size = add_buffer_send(conn->firstsocket, conn, req_buffer); + + /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, - &http->readbytecount, - conn->firstsocket, - &http->writebytecount); + &http->readbytecount, + conn->firstsocket, + &http->writebytecount); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; -- cgit v1.2.1 From 0ece1b5c34c049a3226f7dd793cf75e470c46e4d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 30 Aug 2001 22:48:34 +0000 Subject: Major rename and redesign of the internal "backbone" structs. Details will be posted in a minute to the libcurl list. --- lib/http.c | 185 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 93 insertions(+), 92 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index df5e58557..a1ab24b86 100644 --- a/lib/http.c +++ b/lib/http.c @@ -128,10 +128,10 @@ static size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in) { size_t amount; - if(conn->data->bits.verbose) { - fputs("> ", conn->data->err); + if(conn->data->set.verbose) { + fputs("> ", conn->data->set.err); /* this data _may_ contain binary stuff */ - fwrite(in->buffer, in->size_used, 1, conn->data->err); + fwrite(in->buffer, in->size_used, 1, conn->data->set.err); } Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); @@ -209,7 +209,7 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn) ssize_t nread; int read_rc=1; char *ptr; - struct UrlData *data=conn->data; + struct SessionHandle *data=conn->data; ptr=buf; @@ -224,10 +224,10 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn) } *ptr=0; /* zero terminate */ - if(data->bits.verbose) { - fputs("< ", data->err); - fwrite(buf, 1, nread, data->err); - fputs("\n", data->err); + if(data->set.verbose) { + fputs("< ", data->set.err); + fwrite(buf, 1, nread, data->set.err); + fputs("\n", data->set.err); } return nread>0?nread:0; } @@ -238,12 +238,12 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn) * This function checks the linked list of custom HTTP headers for a particular * header (prefix). */ -static bool checkheaders(struct UrlData *data, const char *thisheader) +static bool checkheaders(struct SessionHandle *data, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); - for(head = data->headers; head; head=head->next) { + for(head = data->set.headers; head; head=head->next) { if(strnequal(head->data, thisheader, thislen)) { return TRUE; } @@ -263,7 +263,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, { int httperror=0; int subversion=0; - struct UrlData *data=conn->data; + struct SessionHandle *data=conn->data; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); @@ -275,14 +275,14 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, "\r\n", hostname, remote_port, (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", - (data->useragent?conn->allocptr.uagent:"") + (data->set.useragent?conn->allocptr.uagent:"") ); /* wait for the proxy to send us a HTTP/1.0 200 OK header */ - while(GetLine(tunnelsocket, data->buffer, conn)) { - if('\r' == data->buffer[0]) + while(GetLine(tunnelsocket, data->state.buffer, conn)) { + if('\r' == data->state.buffer[0]) break; /* end of headers */ - if(2 == sscanf(data->buffer, "HTTP/1.%d %d", + if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d", &subversion, &httperror)) { ; @@ -306,7 +306,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, */ CURLcode Curl_http_connect(struct connectdata *conn) { - struct UrlData *data; + struct SessionHandle *data; CURLcode result; data=conn->data; @@ -318,7 +318,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has occured, can we start talking SSL */ if (conn->protocol & PROT_HTTPS) { - if (data->bits.httpproxy) { + if (data->change.proxy) { /* HTTPS through a proxy can only be done with a tunnel */ result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, conn->hostname, conn->remote_port); @@ -332,10 +332,10 @@ CURLcode Curl_http_connect(struct connectdata *conn) return result; } - if(conn->bits.user_passwd && !data->bits.this_is_a_follow) { + if(conn->bits.user_passwd && !data->state.this_is_a_follow) { /* Authorization: is requested, this is not a followed location, get the original host name */ - data->auth_host = strdup(conn->hostname); + data->state.auth_host = strdup(conn->hostname); } return CURLE_OK; @@ -345,29 +345,29 @@ CURLcode Curl_http_connect(struct connectdata *conn) protocol-specific resources */ CURLcode Curl_http_close(struct connectdata *conn) { - if(conn->data->auth_host) - free(conn->data->auth_host); + if(conn->data->state.auth_host) + free(conn->data->state.auth_host); return CURLE_OK; } CURLcode Curl_http_done(struct connectdata *conn) { - struct UrlData *data; + struct SessionHandle *data; long *bytecount = &conn->bytecount; struct HTTP *http; data=conn->data; http=conn->proto.http; - if(HTTPREQ_POST_FORM == data->httpreq) { + if(HTTPREQ_POST_FORM == data->set.httpreq) { *bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ - data->fread = http->storefread; /* restore */ - data->in = http->in; /* restore */ + data->set.fread = http->storefread; /* restore */ + data->set.in = http->in; /* restore */ } - else if(HTTPREQ_PUT == data->httpreq) { + else if(HTTPREQ_PUT == data->set.httpreq) { *bytecount = http->readbytecount + http->writebytecount; } @@ -377,8 +377,8 @@ CURLcode Curl_http_done(struct connectdata *conn) CURLcode Curl_http(struct connectdata *conn) { - struct UrlData *data=conn->data; - char *buf = data->buffer; /* this is a short cut to the buffer */ + struct SessionHandle *data=conn->data; + char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; struct Cookie *co=NULL; /* no cookies from start */ @@ -402,8 +402,8 @@ CURLcode Curl_http(struct connectdata *conn) conn->bits.close = FALSE; if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && - data->bits.upload) { - data->httpreq = HTTPREQ_PUT; + data->set.upload) { + data->set.httpreq = HTTPREQ_PUT; } /* The User-Agent string has been built in url.c already, because it might @@ -420,45 +420,45 @@ CURLcode Curl_http(struct connectdata *conn) /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ - if(!data->bits.this_is_a_follow || - !data->auth_host || - strequal(data->auth_host, conn->hostname)) { - sprintf(data->buffer, "%s:%s", data->user, data->passwd); - if(Curl_base64_encode(data->buffer, strlen(data->buffer), + if(!data->state.this_is_a_follow || + !data->state.auth_host || + strequal(data->state.auth_host, conn->hostname)) { + sprintf(data->state.buffer, "%s:%s", + data->state.user, data->state.passwd); + if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { if(conn->allocptr.userpwd) free(conn->allocptr.userpwd); conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", - authorization); + authorization); free(authorization); } } } - if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { + if((data->change.referer) && !checkheaders(data, "Referer:")) { if(conn->allocptr.ref) free(conn->allocptr.ref); - conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer); + conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer); } - if(data->cookie && !checkheaders(data, "Cookie:")) { + if(data->set.cookie && !checkheaders(data, "Cookie:")) { if(conn->allocptr.cookie) free(conn->allocptr.cookie); - conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie); + conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); } if(data->cookies) { co = Curl_cookie_getlist(data->cookies, - host, - ppath, + host, ppath, conn->protocol&PROT_HTTPS?TRUE:FALSE); } - if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) { + if ((data->change.proxy) && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ - ppath = data->url; + ppath = data->change.url; } - if(HTTPREQ_POST_FORM == data->httpreq) { + if(HTTPREQ_POST_FORM == data->set.httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ - http->sendit = Curl_getFormData(data->httppost, &http->postsize); + http->sendit = Curl_getFormData(data->set.httppost, &http->postsize); } if(!checkheaders(data, "Host:")) { @@ -486,9 +486,9 @@ CURLcode Curl_http(struct connectdata *conn) if(!checkheaders(data, "Accept:")) http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; - if(( (HTTPREQ_POST == data->httpreq) || - (HTTPREQ_POST_FORM == data->httpreq) || - (HTTPREQ_PUT == data->httpreq) ) && + if(( (HTTPREQ_POST == data->set.httpreq) || + (HTTPREQ_POST_FORM == data->set.httpreq) || + (HTTPREQ_PUT == data->set.httpreq) ) && conn->resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have @@ -521,7 +521,8 @@ CURLcode Curl_http(struct connectdata *conn) readthisamountnow = BUFSIZE; actuallyread = - data->fread(data->buffer, 1, readthisamountnow, data->in); + data->set.fread(data->state.buffer, 1, readthisamountnow, + data->set.in); passed += actuallyread; if(actuallyread != readthisamountnow) { @@ -532,10 +533,10 @@ CURLcode Curl_http(struct connectdata *conn) } while(passed != conn->resume_from); /* loop until done */ /* now, decrease the size of the read */ - if(data->infilesize>0) { - data->infilesize -= conn->resume_from; + if(data->set.infilesize>0) { + data->set.infilesize -= conn->resume_from; - if(data->infilesize <= 0) { + if(data->set.infilesize <= 0) { failf(data, "File already completely uploaded\n"); return CURLE_PARTIAL_FILE; } @@ -549,16 +550,16 @@ CURLcode Curl_http(struct connectdata *conn) * or uploading and we always let customized headers override our internal * ones if any such are specified. */ - if((data->httpreq == HTTPREQ_GET) && + if((data->set.httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); } - else if((data->httpreq != HTTPREQ_GET) && + else if((data->set.httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { if(conn->resume_from) { /* This is because "resume" was selected */ - long total_expected_size= conn->resume_from + data->infilesize; + long total_expected_size= conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", conn->range, total_expected_size-1, total_expected_size); @@ -567,14 +568,14 @@ CURLcode Curl_http(struct connectdata *conn) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", - conn->range, data->infilesize); + conn->range, data->set.infilesize); } } } do { send_buffer *req_buffer; - struct curl_slist *headers=data->headers; + struct curl_slist *headers=data->set.headers; /* initialize a dynamic send-buffer */ req_buffer = add_buffer_init(); @@ -593,11 +594,11 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* accept */ "%s", /* referer */ - data->customrequest?data->customrequest: - (data->bits.no_body?"HEAD": - ((HTTPREQ_POST == data->httpreq) || - (HTTPREQ_POST_FORM == data->httpreq))?"POST": - (HTTPREQ_PUT == data->httpreq)?"PUT":"GET"), + data->set.customrequest?data->set.customrequest: + (data->set.no_body?"HEAD": + ((HTTPREQ_POST == data->set.httpreq) || + (HTTPREQ_POST_FORM == data->set.httpreq))?"POST": + (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"), ppath, (conn->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", @@ -605,13 +606,13 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.userpwd:"", (conn->bits.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", - (data->useragent && *data->useragent && conn->allocptr.uagent)? + (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? conn->allocptr.uagent:"", (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: */ (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", - (data->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */ + (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */ ); if(co) { @@ -636,7 +637,7 @@ CURLcode Curl_http(struct connectdata *conn) co=NULL; } - if(data->timecondition) { + if(data->set.timecondition) { struct tm *thistime; /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since @@ -651,9 +652,9 @@ CURLcode Curl_http(struct connectdata *conn) /* We assume that the presense of localtime_r() proves the presense of gmtime_r() which is a bit ugly but might work */ struct tm keeptime; - thistime = (struct tm *)gmtime_r(&data->timevalue, &keeptime); + thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); #else - thistime = gmtime(&data->timevalue); + thistime = gmtime(&data->set.timevalue); #endif if(NULL == thistime) { failf(data, "localtime() failed!"); @@ -667,7 +668,7 @@ CURLcode Curl_http(struct connectdata *conn) /* TODO: Right, we *could* write a replacement here */ strcpy(buf, "no strftime() support"); #endif - switch(data->timecondition) { + switch(data->set.timecondition) { case TIMECOND_IFMODSINCE: default: add_bufferf(req_buffer, @@ -702,7 +703,7 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } - if(HTTPREQ_POST_FORM == data->httpreq) { + if(HTTPREQ_POST_FORM == data->set.httpreq) { char contentType[256]; int linelength=0; if(Curl_FormInit(&http->form, http->sendit)) { @@ -710,13 +711,13 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_HTTP_POST_ERROR; } - http->storefread = data->fread; /* backup */ - http->in = data->in; /* backup */ + http->storefread = data->set.fread; /* backup */ + http->in = data->set.in; /* backup */ - data->fread = (curl_read_callback) + data->set.fread = (curl_read_callback) Curl_FormReader; /* set the read function to read from the generated form data */ - data->in = (FILE *)&http->form; + data->set.in = (FILE *)&http->form; add_bufferf(req_buffer, "Content-Length: %d\r\n", http->postsize-2); @@ -727,7 +728,7 @@ CURLcode Curl_http(struct connectdata *conn) there is one packet coming back from the web server) */ add_bufferf(req_buffer, "Expect: 100-continue\r\n"); - data->bits.expect100header = TRUE; + data->set.expect100header = TRUE; /* Get Content-Type: line from Curl_FormReadOneLine, which happens to always be the first line. We can know this for sure since @@ -747,7 +748,7 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - data->request_size = + data->info.request_size = add_buffer_send(conn->firstsocket, conn, req_buffer); /* setup variables for the upcoming transfer */ @@ -760,22 +761,22 @@ CURLcode Curl_http(struct connectdata *conn) return result; } } - else if(HTTPREQ_PUT == data->httpreq) { + else if(HTTPREQ_PUT == data->set.httpreq) { /* Let's PUT the data to the server! */ - if(data->infilesize>0) { + if(data->set.infilesize>0) { add_bufferf(req_buffer, "Content-Length: %d\r\n\r\n", /* file size */ - data->infilesize ); + data->set.infilesize ); } else add_bufferf(req_buffer, "\015\012"); /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, data->infilesize); + Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ - data->request_size = + data->info.request_size = add_buffer_send(conn->firstsocket, conn, req_buffer); /* prepare for transfer */ @@ -788,17 +789,17 @@ CURLcode Curl_http(struct connectdata *conn) } else { - if(HTTPREQ_POST == data->httpreq) { + if(HTTPREQ_POST == data->set.httpreq) { /* this is the simple POST, using x-www-form-urlencoded style */ - if(!data->postfields) { + if(!data->set.postfields) { /* * This is an attempt to do a POST without having anything to * actually send. Let's make a NULL pointer equal "" here. Good/bad * ? */ - data->postfields = (char *)""; - data->postfieldsize = 0; /* it might been set to something illegal, + data->set.postfields = (char *)""; + data->set.postfieldsize = 0; /* it might been set to something illegal, anything > 0 would be! */ } @@ -807,32 +808,32 @@ CURLcode Curl_http(struct connectdata *conn) actually set your own */ add_bufferf(req_buffer, "Content-Length: %d\r\n", - (data->postfieldsize?data->postfieldsize: - strlen(data->postfields)) ); + (data->set.postfieldsize?data->set.postfieldsize: + strlen(data->set.postfields)) ); if(!checkheaders(data, "Content-Type:")) add_bufferf(req_buffer, "Content-Type: application/x-www-form-urlencoded\r\n"); /* and here comes the actual data */ - if(data->postfieldsize) { + if(data->set.postfieldsize) { add_buffer(req_buffer, "\r\n", 2); - add_buffer(req_buffer, data->postfields, - data->postfieldsize); + add_buffer(req_buffer, data->set.postfields, + data->set.postfieldsize); add_buffer(req_buffer, "\r\n", 2); } else { add_bufferf(req_buffer, "\r\n" "%s\r\n", - data->postfields ); + data->set.postfields ); } } else add_buffer(req_buffer, "\r\n", 2); /* issue the request */ - data->request_size = + data->info.request_size = add_buffer_send(conn->firstsocket, conn, req_buffer); /* HTTP GET/HEAD download: */ -- cgit v1.2.1 From 6147879837a53d22c9be04e7a4fc315a297ba2b3 Mon Sep 17 00:00:00 2001 From: Sterling Hughes Date: Fri, 7 Sep 2001 04:01:32 +0000 Subject: Added formatting sections for emacs and vim --- lib/http.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a1ab24b86..6ba4d235a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -848,3 +848,11 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_OK; } + +/* + * local variables: + * eval: (load-file "../curl-mode.el") + * end: + * vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker + * vim<600: et sw=2 ts=2 sts=2 tw=78 + */ -- cgit v1.2.1 From 437fd064c9b294de81b15972c40e8a1c5c0191d7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 18 Sep 2001 15:29:57 +0000 Subject: modified GetLine(), removed Curl_http_close() --- lib/http.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6ba4d235a..353ab5c7c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -204,31 +204,18 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) */ static -int GetLine(int sockfd, char *buf, struct connectdata *conn) +int GetLine(int sockfd, char *ptr, struct connectdata *conn) { ssize_t nread; - int read_rc=1; - char *ptr; - struct SessionHandle *data=conn->data; - - ptr=buf; /* get us a full line, terminated with a newline */ - for(nread=0; - (nreadset.verbose) { - fputs("< ", data->set.err); - fwrite(buf, 1, nread, data->set.err); - fputs("\n", data->set.err); - } return nread>0?nread:0; } @@ -282,6 +269,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, while(GetLine(tunnelsocket, data->state.buffer, conn)) { if('\r' == data->state.buffer[0]) break; /* end of headers */ + if(data->set.verbose) + fprintf(data->set.err, "< %s\n", data->state.buffer); + if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d", &subversion, &httperror)) { @@ -341,15 +331,6 @@ CURLcode Curl_http_connect(struct connectdata *conn) return CURLE_OK; } -/* called from curl_close() when this struct is about to get wasted, free - protocol-specific resources */ -CURLcode Curl_http_close(struct connectdata *conn) -{ - if(conn->data->state.auth_host) - free(conn->data->state.auth_host); - return CURLE_OK; -} - CURLcode Curl_http_done(struct connectdata *conn) { struct SessionHandle *data; -- cgit v1.2.1 From a9181f8f00d5bdfda39e227ed2ec4076ee4d2baa Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Oct 2001 06:52:37 +0000 Subject: added the option CURLOPT_HTTP_VERSION that can specify which HTTP version libcurl should use in its request --- lib/http.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 353ab5c7c..ea1e4b6c0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -555,6 +555,10 @@ CURLcode Curl_http(struct connectdata *conn) } do { + /* Use 1.1 unless the use specificly asked for 1.0 */ + const char *httpstring= + data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; + send_buffer *req_buffer; struct curl_slist *headers=data->set.headers; @@ -564,7 +568,7 @@ CURLcode Curl_http(struct connectdata *conn) /* add the main request stuff */ add_bufferf(req_buffer, "%s " /* GET/HEAD/POST/PUT */ - "%s HTTP/1.1\r\n" /* path */ + "%s HTTP/%s\r\n" /* path */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ @@ -580,7 +584,7 @@ CURLcode Curl_http(struct connectdata *conn) ((HTTPREQ_POST == data->set.httpreq) || (HTTPREQ_POST_FORM == data->set.httpreq))?"POST": (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"), - ppath, + ppath, httpstring, (conn->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", (conn->bits.user_passwd && conn->allocptr.userpwd)? -- cgit v1.2.1 From 8e91d5de8e4e17ce3d4936cc91171d09726e7bb3 Mon Sep 17 00:00:00 2001 From: Sterling Hughes Date: Thu, 11 Oct 2001 09:32:19 +0000 Subject: looks nicer and is better compatible with older vim versions --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ea1e4b6c0..d12db0c8c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -838,6 +838,6 @@ CURLcode Curl_http(struct connectdata *conn) * local variables: * eval: (load-file "../curl-mode.el") * end: - * vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker - * vim<600: et sw=2 ts=2 sts=2 tw=78 + * vim600: fdm=marker + * vim: et sw=2 ts=2 sts=2 tw=78 */ -- cgit v1.2.1 From 4e37187e44b85aa11fee92eca4d87b3839cd435f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Oct 2001 11:58:32 +0000 Subject: now counts header size return from server and if nothing is returned from a HTTP server we return error --- lib/http.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d12db0c8c..b3074ec65 100644 --- a/lib/http.c +++ b/lib/http.c @@ -352,6 +352,13 @@ CURLcode Curl_http_done(struct connectdata *conn) *bytecount = http->readbytecount + http->writebytecount; } + if(0 == (http->readbytecount + conn->headerbytecount)) { + /* nothing was read from the HTTP server, this can't be right + so we return an error here */ + failf(data, "Empty reply from server\n"); + return CURLE_GOT_NOTHING; + } + return CURLE_OK; } -- cgit v1.2.1 From 69d5d88259e1542ac2a9da8f17e67c59602159cf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 31 Oct 2001 14:57:00 +0000 Subject: Added better checking of return codes when we send data to sockets/connections --- lib/http.c | 84 ++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 33 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b3074ec65..9526e5188 100644 --- a/lib/http.c +++ b/lib/http.c @@ -125,22 +125,27 @@ send_buffer *add_buffer_init(void) * add_buffer_send() sends a buffer and frees all associated memory. */ static -size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in) +CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, + long *bytes_written) { size_t amount; + CURLcode result; + if(conn->data->set.verbose) { fputs("> ", conn->data->set.err); /* this data _may_ contain binary stuff */ fwrite(in->buffer, in->size_used, 1, conn->data->set.err); } - Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); + result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); if(in->buffer) free(in->buffer); free(in); - return amount; + *bytes_written = amount; + + return result; } @@ -251,19 +256,25 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int httperror=0; int subversion=0; struct SessionHandle *data=conn->data; + CURLcode result; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); /* OK, now send the connect request to the proxy */ - Curl_sendf(tunnelsocket, conn, - "CONNECT %s:%d HTTP/1.0\015\012" - "%s" - "%s" - "\r\n", - hostname, remote_port, - (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", - (data->set.useragent?conn->allocptr.uagent:"") - ); + result = + Curl_sendf(tunnelsocket, conn, + "CONNECT %s:%d HTTP/1.0\015\012" + "%s" + "%s" + "\r\n", + hostname, remote_port, + (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", + (data->set.useragent?conn->allocptr.uagent:"") + ); + if(result) { + failf(data, "Failed sending CONNECT to proxy"); + return result; + } /* wait for the proxy to send us a HTTP/1.0 200 OK header */ while(GetLine(tunnelsocket, data->state.buffer, conn)) { @@ -740,14 +751,16 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - data->info.request_size = - add_buffer_send(conn->firstsocket, conn, req_buffer); - - /* setup variables for the upcoming transfer */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, - &http->readbytecount, - conn->firstsocket, - &http->writebytecount); + result = add_buffer_send(conn->firstsocket, conn, req_buffer, + &data->info.request_size); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, + conn->firstsocket, + &http->writebytecount); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -768,14 +781,16 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ - data->info.request_size = - add_buffer_send(conn->firstsocket, conn, req_buffer); - - /* prepare for transfer */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, - &http->readbytecount, - conn->firstsocket, - &http->writebytecount); + result = add_buffer_send(conn->firstsocket, conn, req_buffer, + &data->info.request_size); + if(result) + failf(data, "Faied sending POST request"); + else + /* prepare for transfer */ + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, + conn->firstsocket, + &http->writebytecount); if(result) return result; @@ -825,12 +840,15 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* issue the request */ - data->info.request_size = - add_buffer_send(conn->firstsocket, conn, req_buffer); + result = add_buffer_send(conn->firstsocket, conn, req_buffer, + &data->info.request_size); - /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, - -1, NULL); /* nothing to upload */ + if(result) + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, + -1, NULL); /* nothing to upload */ } if(result) return result; -- cgit v1.2.1 From 1affbff8f92b98ca01d42ff3b9a1606ef3b51c82 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 Nov 2001 09:47:09 +0000 Subject: new Curl_ConnectHTTPProxyTunnel() function, needs a **lot** of testing!!! --- lib/http.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 33 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9526e5188..2fe8e08dd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -204,28 +204,6 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) /* end of the add_buffer functions */ /* ------------------------------------------------------------------------- */ -/* - * Read everything until a newline. - */ - -static -int GetLine(int sockfd, char *ptr, struct connectdata *conn) -{ - ssize_t nread; - - /* get us a full line, terminated with a newline */ - for(nread=0; (nread0?nread:0; -} - - - /* * This function checks the linked list of custom HTTP headers for a particular * header (prefix). @@ -258,6 +236,22 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, struct SessionHandle *data=conn->data; CURLcode result; + int nread; /* total size read */ + int perline; /* count bytes per line */ + bool keepon=TRUE; + ssize_t gotbytes; + char *ptr; + int timeout = 3600; /* default timeout in seconds */ + struct timeval interval; + fd_set rkeepfd; + fd_set readfd; + char *line_start; + +#define SELECT_OK 0 +#define SELECT_ERROR 1 +#define SELECT_TIMEOUT 2 + int error = SELECT_OK; + infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); /* OK, now send the connect request to the proxy */ @@ -276,19 +270,105 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return result; } - /* wait for the proxy to send us a HTTP/1.0 200 OK header */ - while(GetLine(tunnelsocket, data->state.buffer, conn)) { - if('\r' == data->state.buffer[0]) - break; /* end of headers */ - if(data->set.verbose) - fprintf(data->set.err, "< %s\n", data->state.buffer); - - if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d", - &subversion, - &httperror)) { - ; + /* Now, read the full reply we get from the proxy */ + + + if(data->set.timeout) { + /* if timeout is requested, find out how much remaining time we have */ + timeout = data->set.timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ + if(timeout <=0 ) { + failf(data, "Transfer aborted due to timeout"); + return -SELECT_TIMEOUT; /* already too little time */ } } + + FD_ZERO (&readfd); /* clear it */ + FD_SET (tunnelsocket, &readfd); /* read socket */ + + /* get this in a backup variable to be able to restore it on each lap in the + select() loop */ + rkeepfd = readfd; + + ptr=data->state.buffer; + line_start = ptr; + + nread=0; + perline=0; + keepon=TRUE; + + while((nreadset.verbose) { + fputs("< ", data->set.err); + fwrite(line_start, perline, 1, data->set.err); + /* no need to output LF here, it is part of the data */ + } + + if('\r' == line_start[0]) { + /* end of headers */ + keepon=FALSE; + break; /* breaks out of loop, not switch */ + } + + if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &httperror)) { + ; + } + + perline=0; /* line starts over here */ + line_start = ptr+1; + } + } + } + break; + } /* switch */ + } /* while there's buffer left and loop is requested */ + + if(error) + return CURLE_READ_ERROR; + if(200 != httperror) { if(407 == httperror) /* Added Nov 6 1998 */ -- cgit v1.2.1 From 05f3ca880fa092e4fd8684d39cb52401fedc9db7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 Nov 2001 14:08:41 +0000 Subject: made CURLOPT_HTTPPROXYTUNNEL work for plain HTTP as well --- lib/http.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2fe8e08dd..6d1330c25 100644 --- a/lib/http.c +++ b/lib/http.c @@ -398,19 +398,22 @@ CURLcode Curl_http_connect(struct connectdata *conn) * us to the host we want to talk to. Only after the connect * has occured, can we start talking SSL */ - if (conn->protocol & PROT_HTTPS) { - if (data->change.proxy) { - /* HTTPS through a proxy can only be done with a tunnel */ - result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, - conn->hostname, conn->remote_port); - if(CURLE_OK != result) - return result; - } - /* now, perform the SSL initialization for this socket */ - result = Curl_SSLConnect(conn); - if(result) + if(data->change.proxy && + ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { + + /* either HTTPS over proxy, OR explicitly asked for a tunnel */ + result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, + conn->hostname, conn->remote_port); + if(CURLE_OK != result) return result; + + if(conn->protocol & PROT_HTTPS) { + /* now, perform the SSL initialization for this socket */ + result = Curl_SSLConnect(conn); + if(result) + return result; + } } if(conn->bits.user_passwd && !data->state.this_is_a_follow) { @@ -530,7 +533,9 @@ CURLcode Curl_http(struct connectdata *conn) host, ppath, conn->protocol&PROT_HTTPS?TRUE:FALSE); } - if ((data->change.proxy) && !(conn->protocol&PROT_HTTPS)) { + if (data->change.proxy && + !data->set.tunnel_thru_httpproxy && + !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ ppath = data->change.url; } -- cgit v1.2.1 From c2479ccb7a73db4b8c3071ed4cc92e27d30dabf2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 Nov 2001 08:34:24 +0000 Subject: my proxytunnel fix accidentally ruined the normal https connects --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6d1330c25..bb0c26e72 100644 --- a/lib/http.c +++ b/lib/http.c @@ -407,13 +407,13 @@ CURLcode Curl_http_connect(struct connectdata *conn) conn->hostname, conn->remote_port); if(CURLE_OK != result) return result; - - if(conn->protocol & PROT_HTTPS) { - /* now, perform the SSL initialization for this socket */ - result = Curl_SSLConnect(conn); - if(result) - return result; - } + } + + if(conn->protocol & PROT_HTTPS) { + /* now, perform the SSL initialization for this socket */ + result = Curl_SSLConnect(conn); + if(result) + return result; } if(conn->bits.user_passwd && !data->state.this_is_a_follow) { -- cgit v1.2.1 From e6dd4a6456bee374800aaf7dd58a77cd52ef7a88 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 16 Nov 2001 11:21:50 +0000 Subject: Klevtsov Vadim's time condition fix --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bb0c26e72..1573f4456 100644 --- a/lib/http.c +++ b/lib/http.c @@ -751,7 +751,7 @@ CURLcode Curl_http(struct connectdata *conn) #ifdef HAVE_STRFTIME /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S %Z", thistime); + strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S GMT", thistime); #else /* TODO: Right, we *could* write a replacement here */ strcpy(buf, "no strftime() support"); -- cgit v1.2.1 From 650b95045d0b02e1b53dcad3414d1dfde77f4e6b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 7 Dec 2001 15:51:59 +0000 Subject: added gmtime_r check --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1573f4456..c0b9ce1d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -735,7 +735,7 @@ CURLcode Curl_http(struct connectdata *conn) * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). */ -#ifdef HAVE_LOCALTIME_R +#ifdef HAVE_GMTIME_R /* thread-safe version */ /* We assume that the presense of localtime_r() proves the presense of gmtime_r() which is a bit ugly but might work */ -- cgit v1.2.1 From 47e67eab26c8d2702d254dcc7e7fa2c69228c32a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 7 Dec 2001 15:56:57 +0000 Subject: corrected the comment above gmtime_r --- lib/http.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c0b9ce1d3..f1d3fb326 100644 --- a/lib/http.c +++ b/lib/http.c @@ -737,8 +737,6 @@ CURLcode Curl_http(struct connectdata *conn) #ifdef HAVE_GMTIME_R /* thread-safe version */ - /* We assume that the presense of localtime_r() proves the presense - of gmtime_r() which is a bit ugly but might work */ struct tm keeptime; thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); #else -- cgit v1.2.1 From e1922617883d5a70a282ed0e9e756a27eeed6bba Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Dec 2001 13:13:01 +0000 Subject: failf() calls should not have newlines in the message string! --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f1d3fb326..ffb442089 100644 --- a/lib/http.c +++ b/lib/http.c @@ -449,7 +449,7 @@ CURLcode Curl_http_done(struct connectdata *conn) if(0 == (http->readbytecount + conn->headerbytecount)) { /* nothing was read from the HTTP server, this can't be right so we return an error here */ - failf(data, "Empty reply from server\n"); + failf(data, "Empty reply from server"); return CURLE_GOT_NOTHING; } @@ -610,7 +610,7 @@ CURLcode Curl_http(struct connectdata *conn) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read %d bytes from the input\n", + failf(data, "Could only read %d bytes from the input", passed); return CURLE_READ_ERROR; } @@ -621,7 +621,7 @@ CURLcode Curl_http(struct connectdata *conn) data->set.infilesize -= conn->resume_from; if(data->set.infilesize <= 0) { - failf(data, "File already completely uploaded\n"); + failf(data, "File already completely uploaded"); return CURLE_PARTIAL_FILE; } } @@ -793,7 +793,7 @@ CURLcode Curl_http(struct connectdata *conn) char contentType[256]; int linelength=0; if(Curl_FormInit(&http->form, http->sendit)) { - failf(data, "Internal HTTP POST error!\n"); + failf(data, "Internal HTTP POST error!"); return CURLE_HTTP_POST_ERROR; } @@ -824,7 +824,7 @@ CURLcode Curl_http(struct connectdata *conn) 1, (FILE *)&http->form); if(linelength == -1) { - failf(data, "Could not get Content-Type header line!\n"); + failf(data, "Could not get Content-Type header line!"); return CURLE_HTTP_POST_ERROR; } add_buffer(req_buffer, contentType, linelength); -- cgit v1.2.1 From 4931fbce49887f7d4022c39ea7d94c4294b5f479 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Jan 2002 23:14:59 +0000 Subject: Curl_read() now returns a negative return code if EWOULDBLOCK or similar --- lib/http.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ffb442089..795a6f79c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -235,6 +235,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int subversion=0; struct SessionHandle *data=conn->data; CURLcode result; + int res; int nread; /* total size read */ int perline; /* count bytes per line */ @@ -317,8 +318,12 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, * to read, but when we use Curl_read() it may do so. Do confirm * that this is still ok and then remove this comment! */ - if(CURLE_OK != Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, - &gotbytes)) + res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, + &gotbytes); + if(res< 0) + /* EWOULDBLOCK */ + continue; /* go loop yourself */ + else if(res) keepon = FALSE; else if(gotbytes <= 0) { keepon = FALSE; -- cgit v1.2.1 From cba9838e8fcfdd653a60f7b01edacdb3a31214a2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 16 Jan 2002 14:47:00 +0000 Subject: Somewhat ugly fix to deal with non-blocking sockets. We just loop and try again. THIS IS NOT A NICE FIX. --- lib/http.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 795a6f79c..42668b398 100644 --- a/lib/http.c +++ b/lib/http.c @@ -128,8 +128,10 @@ static CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, long *bytes_written) { - size_t amount; - CURLcode result; + ssize_t amount; + CURLcode res; + char *ptr; + int size; if(conn->data->set.verbose) { fputs("> ", conn->data->set.err); @@ -137,7 +139,25 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, fwrite(in->buffer, in->size_used, 1, conn->data->set.err); } - result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); + /* The looping below is required since we use non-blocking sockets, but due + to the circumstances we will just loop and try again and again etc */ + + ptr = in->buffer; + size = in->size_used; + do { + res = Curl_write(conn, sockfd, ptr, size, &amount); + + if(CURLE_OK != res) + break; + + if(amount != size) { + size += amount; + ptr += amount; + } + else + break; + + } while(1); if(in->buffer) free(in->buffer); @@ -145,7 +165,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, *bytes_written = amount; - return result; + return res; } -- cgit v1.2.1 From e3f10eb825974c4071ad17ead97190a5c7fe8f15 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 27 Jan 2002 11:51:11 +0000 Subject: no longer add CRLF _after_ POST data, it should not be needed. Pedro Neves pointed out this ugliness. --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 42668b398..1113e38e4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -935,12 +935,11 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); add_buffer(req_buffer, data->set.postfields, data->set.postfieldsize); - add_buffer(req_buffer, "\r\n", 2); } else { add_bufferf(req_buffer, "\r\n" - "%s\r\n", + "%s", data->set.postfields ); } } -- cgit v1.2.1 From 85dbf82d9316df3b33290eca17a41d0d5ea8e671 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Jan 2002 20:32:10 +0000 Subject: append a CRLF pair after the content-type line --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1113e38e4..9ceeb0fbf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -853,6 +853,9 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_HTTP_POST_ERROR; } add_buffer(req_buffer, contentType, linelength); + + /* make the request end in a true CRLF */ + add_buffer(req_buffer, "\r\n", 2); } /* set upload size to the progress meter */ -- cgit v1.2.1 From c40b4f6c3977497bc4b2d248554f13ea82354b76 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2002 09:32:40 +0000 Subject: don't add 2 to the post size, that was a previous mistake because there was an extra CRLF added to the post data --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9ceeb0fbf..07a202b96 100644 --- a/lib/http.c +++ b/lib/http.c @@ -831,7 +831,7 @@ CURLcode Curl_http(struct connectdata *conn) data->set.in = (FILE *)&http->form; add_bufferf(req_buffer, - "Content-Length: %d\r\n", http->postsize-2); + "Content-Length: %d\r\n", http->postsize); if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue -- cgit v1.2.1 From dfda7ba456f72576142d1dd3065d7c1a9a9858f3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 17 Feb 2002 14:42:44 +0000 Subject: corrected the Expect: ignore, made Content-Type: possible to skip --- lib/http.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 07a202b96..e0d3cda9b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -815,8 +815,6 @@ CURLcode Curl_http(struct connectdata *conn) } if(HTTPREQ_POST_FORM == data->set.httpreq) { - char contentType[256]; - int linelength=0; if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!"); return CURLE_HTTP_POST_ERROR; @@ -840,10 +838,19 @@ CURLcode Curl_http(struct connectdata *conn) add_bufferf(req_buffer, "Expect: 100-continue\r\n"); data->set.expect100header = TRUE; + } + if(!checkheaders(data, "Content-Type:")) { /* Get Content-Type: line from Curl_FormReadOneLine, which happens to always be the first line. We can know this for sure since - we always build the formpost linked list the same way! */ + we always build the formpost linked list the same way! + + The Content-Type header line also contains the MIME boundary + string etc why disabling this header is likely to not make things + work, but we support it anyway. + */ + char contentType[256]; + int linelength=0; linelength = Curl_FormReadOneLine (contentType, sizeof(contentType), 1, @@ -853,11 +860,11 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_HTTP_POST_ERROR; } add_buffer(req_buffer, contentType, linelength); - - /* make the request end in a true CRLF */ - add_buffer(req_buffer, "\r\n", 2); } + /* make the request end in a true CRLF */ + add_buffer(req_buffer, "\r\n", 2); + /* set upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); -- cgit v1.2.1 From 535258ffe4cd770615828b1cda85bc094c9074fd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 18 Feb 2002 22:41:52 +0000 Subject: Philip Gladstone's size problem in add_buffer_send() --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e0d3cda9b..c4d44b47c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -151,7 +151,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, break; if(amount != size) { - size += amount; + size -= amount; ptr += amount; } else -- cgit v1.2.1 From 468b7872725237d538a219273532150e86ce239f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 14 Mar 2002 14:39:23 +0000 Subject: if CURLOPT_POSTFIELDS isn't set, but CURLOPT_POST is, we will assume that we should read the POST-data from the read callback --- lib/http.c | 88 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c4d44b47c..a7d8098fe 100644 --- a/lib/http.c +++ b/lib/http.c @@ -814,7 +814,9 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } - if(HTTPREQ_POST_FORM == data->set.httpreq) { + switch(data->set.httpreq) { + + case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!"); return CURLE_HTTP_POST_ERROR; @@ -883,9 +885,9 @@ CURLcode Curl_http(struct connectdata *conn) Curl_formclean(http->sendit); /* free that whole lot */ return result; } - } - else if(HTTPREQ_PUT == data->set.httpreq) { - /* Let's PUT the data to the server! */ + break; + + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ if(data->set.infilesize>0) { add_bufferf(req_buffer, @@ -911,51 +913,51 @@ CURLcode Curl_http(struct connectdata *conn) &http->writebytecount); if(result) return result; - - } - else { - if(HTTPREQ_POST == data->set.httpreq) { - /* this is the simple POST, using x-www-form-urlencoded style */ - - if(!data->set.postfields) { - /* - * This is an attempt to do a POST without having anything to - * actually send. Let's make a NULL pointer equal "" here. Good/bad - * ? - */ - data->set.postfields = (char *)""; - data->set.postfieldsize = 0; /* it might been set to something illegal, - anything > 0 would be! */ - } + break; - if(!checkheaders(data, "Content-Length:")) - /* we allow replacing this header, although it isn't very wise to - actually set your own */ - add_bufferf(req_buffer, - "Content-Length: %d\r\n", - (data->set.postfieldsize?data->set.postfieldsize: - strlen(data->set.postfields)) ); + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ - if(!checkheaders(data, "Content-Type:")) - add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); + if(!checkheaders(data, "Content-Length:")) + /* we allow replacing this header, although it isn't very wise to + actually set your own */ + add_bufferf(req_buffer, + "Content-Length: %d\r\n", + (data->set.postfieldsize?data->set.postfieldsize: + strlen(data->set.postfields)) ); - /* and here comes the actual data */ - if(data->set.postfieldsize) { - add_buffer(req_buffer, "\r\n", 2); - add_buffer(req_buffer, data->set.postfields, - data->set.postfieldsize); - } - else { - add_bufferf(req_buffer, - "\r\n" - "%s", - data->set.postfields ); - } + if(!checkheaders(data, "Content-Type:")) + add_bufferf(req_buffer, + "Content-Type: application/x-www-form-urlencoded\r\n"); + + add_buffer(req_buffer, "\r\n", 2); + + /* and here comes the actual data */ + if(data->set.postfieldsize && data->set.postfields) { + add_buffer(req_buffer, data->set.postfields, + data->set.postfieldsize); } + else if(data->set.postfields) + add_bufferf(req_buffer, + "%s", + data->set.postfields ); + + /* issue the request */ + result = add_buffer_send(conn->firstsocket, conn, req_buffer, + &data->info.request_size); + + if(result) + failf(data, "Failed sending HTTP POST request"); else - add_buffer(req_buffer, "\r\n", 2); + result = + Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, + data->set.postfields?-1:conn->firstsocket, + data->set.postfields?NULL:&http->writebytecount); + break; + default: + add_buffer(req_buffer, "\r\n", 2); + /* issue the request */ result = add_buffer_send(conn->firstsocket, conn, req_buffer, &data->info.request_size); -- cgit v1.2.1 From 974f314f5785156af6983675aeb28313cc8ba2ea Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Mar 2002 07:54:55 +0000 Subject: copyright string (year) update --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a7d8098fe..da3815269 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. * * In order to be useful for every potential user, curl and libcurl are * dual-licensed under the MPL and the MIT/X-derivate licenses. -- cgit v1.2.1 From e8109b09b117749dc9b7e2ab7d51bd100e254d7e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Apr 2002 13:44:42 +0000 Subject: error code cleanup, use the new SEND/RECV errors --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index da3815269..9e0275f70 100644 --- a/lib/http.c +++ b/lib/http.c @@ -392,7 +392,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } /* while there's buffer left and loop is requested */ if(error) - return CURLE_READ_ERROR; + return CURLE_RECV_ERROR; if(200 != httperror) { if(407 == httperror) @@ -400,7 +400,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, failf(data, "Proxy requires authorization!"); else failf(data, "Received error code %d from proxy", httperror); - return CURLE_READ_ERROR; + return CURLE_RECV_ERROR; } infof (data, "Proxy replied to CONNECT request\n"); -- cgit v1.2.1 From 3f6133be2735936631c4bfe5aedd28ae9b084f3f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Apr 2002 07:21:11 +0000 Subject: Jean-Philippe Barrette-LaPierre provided his patch that introduces CURLOPT_DEBUGFUNCTION and CURLOPT_DEBUGDATA. --- lib/http.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9e0275f70..42c167275 100644 --- a/lib/http.c +++ b/lib/http.c @@ -133,12 +133,6 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, char *ptr; int size; - if(conn->data->set.verbose) { - fputs("> ", conn->data->set.err); - /* this data _may_ contain binary stuff */ - fwrite(in->buffer, in->size_used, 1, conn->data->set.err); - } - /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ @@ -150,6 +144,10 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, if(CURLE_OK != res) break; + if(conn->data->set.verbose) + /* this data _may_ contain binary stuff */ + Curl_debug(conn->data, CURLINFO_DATA_OUT, ptr, amount); + if(amount != size) { size -= amount; ptr += amount; @@ -364,11 +362,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, the line isn't really terminated until the LF comes */ /* output debug output if that is requested */ - if(data->set.verbose) { - fputs("< ", data->set.err); - fwrite(line_start, perline, 1, data->set.err); - /* no need to output LF here, it is part of the data */ - } + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_IN, line_start, perline); if('\r' == line_start[0]) { /* end of headers */ -- cgit v1.2.1 From 93516effe4112ca98a430d8b603fb03179cb7cb6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Apr 2002 07:53:12 +0000 Subject: the HTTP request is a CURLINFO_HEADER_OUT --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 42c167275..758433509 100644 --- a/lib/http.c +++ b/lib/http.c @@ -146,7 +146,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, if(conn->data->set.verbose) /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_DATA_OUT, ptr, amount); + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); if(amount != size) { size -= amount; -- cgit v1.2.1 From 95f78080abd4a07f95e1aa06737e1faa854614c7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 15 Apr 2002 11:19:03 +0000 Subject: This makes formposting with a specified file missing fail. curl_easy_perform will then return CURLE_READ_ERROR. --- lib/http.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 758433509..dc074aced 100644 --- a/lib/http.c +++ b/lib/http.c @@ -562,7 +562,13 @@ CURLcode Curl_http(struct connectdata *conn) if(HTTPREQ_POST_FORM == data->set.httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ - http->sendit = Curl_getFormData(data->set.httppost, &http->postsize); + result = Curl_getFormData(&http->sendit, data->set.httppost, + &http->postsize); + if(CURLE_OK != result) { + /* Curl_getFormData() doesn't use failf() */ + failf(data, "failed creating formpost data"); + return result; + } } if(!checkheaders(data, "Host:")) { -- cgit v1.2.1 From ef436bdbe8a28626e11462d77b66f6b4bb36d737 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Apr 2002 23:53:15 +0000 Subject: renamed the TIMECOND defines to be CURL_ prefixed --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dc074aced..a4deeb14b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -781,16 +781,16 @@ CURLcode Curl_http(struct connectdata *conn) strcpy(buf, "no strftime() support"); #endif switch(data->set.timecondition) { - case TIMECOND_IFMODSINCE: + case CURL_TIMECOND_IFMODSINCE: default: add_bufferf(req_buffer, "If-Modified-Since: %s\r\n", buf); break; - case TIMECOND_IFUNMODSINCE: + case CURL_TIMECOND_IFUNMODSINCE: add_bufferf(req_buffer, "If-Unmodified-Since: %s\r\n", buf); break; - case TIMECOND_LASTMOD: + case CURL_TIMECOND_LASTMOD: add_bufferf(req_buffer, "Last-Modified: %s\r\n", buf); break; -- cgit v1.2.1 From c0257c672180586e7d8bd3125dee398d06f42d19 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 3 Jun 2002 12:47:08 +0000 Subject: T. Bharath made the request size add up as it is documented to do. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a4deeb14b..cc4ac8fe1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -161,7 +161,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, free(in->buffer); free(in); - *bytes_written = amount; + *bytes_written += amount; return res; } -- cgit v1.2.1 From fc37ef9e4b9cd4a385d9d6104ba144da334f67b6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Jun 2002 07:20:21 +0000 Subject: make sure data->set.postfields is non-NULL before doing strlen() on the pointer. Bugs item #566835. --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cc4ac8fe1..b135912bb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -924,8 +924,9 @@ CURLcode Curl_http(struct connectdata *conn) actually set your own */ add_bufferf(req_buffer, "Content-Length: %d\r\n", - (data->set.postfieldsize?data->set.postfieldsize: - strlen(data->set.postfields)) ); + data->set.postfieldsize? + data->set.postfieldsize: + (data->set.postfields?strlen(data->set.postfields):0) ); if(!checkheaders(data, "Content-Type:")) add_bufferf(req_buffer, -- cgit v1.2.1 From 08ef208fb78fb2eabc5cec08c23e74e251eac898 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Jun 2002 11:13:01 +0000 Subject: added disable-[protocol] support, largely provided by Miklos Nemeth --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b135912bb..763b90a3a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -23,6 +23,7 @@ #include "setup.h" +#ifndef CURL_DISABLE_HTTP /* -- WIN32 approved -- */ #include #include @@ -987,3 +988,4 @@ CURLcode Curl_http(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif -- cgit v1.2.1 From 982c5460f0eb521ce4f9526535e9d122fe8755bd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Aug 2002 17:20:29 +0000 Subject: Andrew Francis removed the need for/use of MSVC pragmas --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 763b90a3a..66fa234ec 100644 --- a/lib/http.c +++ b/lib/http.c @@ -552,7 +552,7 @@ CURLcode Curl_http(struct connectdata *conn) if(data->cookies) { co = Curl_cookie_getlist(data->cookies, host, ppath, - conn->protocol&PROT_HTTPS?TRUE:FALSE); + (conn->protocol&PROT_HTTPS?TRUE:FALSE)); } if (data->change.proxy && !data->set.tunnel_thru_httpproxy && -- cgit v1.2.1 From 8aa3f143035ad982acb6e596a8653ac41a7860cc Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 30 Aug 2002 09:20:11 +0000 Subject: SOCKS5 support added (contributed by a still unnamed person). Not properly working for "IPv6 enabled" libcurls yet, but should be pretty easy for someone to adjust. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 66fa234ec..08a5536dc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -420,7 +420,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has occured, can we start talking SSL */ - if(data->change.proxy && + if(data->change.proxy && (data->set.proxytype == CURLPROXY_HTTP) && ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { /* either HTTPS over proxy, OR explicitly asked for a tunnel */ -- cgit v1.2.1 From 64bbe9dfafc6693a96b742f3133c636385835a19 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Sep 2002 22:31:18 +0000 Subject: James Gallagher's Content-Encoding work --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 08a5536dc..8957968d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -707,6 +707,7 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* host */ "%s" /* pragma */ "%s" /* accept */ + "%s" /* accept-encoding */ "%s", /* referer */ data->set.customrequest?data->set.customrequest: @@ -727,6 +728,8 @@ CURLcode Curl_http(struct connectdata *conn) (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", + (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", /* 08/28/02 jhrg */ (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */ ); -- cgit v1.2.1 From ba4e69bebc8f7f32f3bc7faa1e13e7580754075b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Sep 2002 11:52:59 +0000 Subject: updated source code boilerplate/header --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8957968d8..788309d76 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1,4 +1,4 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | @@ -7,19 +7,19 @@ * * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. - * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" -- cgit v1.2.1 From cac5251a98165bf5b6069f5276fd9d1d7331a11a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Sep 2002 10:32:37 +0000 Subject: Lukasz Czekierda correctly pointed out that curl used a bad Host: header when talking to a IPv6-server using IPv6 IP address only. --- lib/http.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 788309d76..6a71e47b1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -581,13 +581,22 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->allocptr.host) free(conn->allocptr.host); + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ - conn->allocptr.host = aprintf("Host: %s\r\n", host); + conn->allocptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); else - conn->allocptr.host = aprintf("Host: %s:%d\r\n", host, + conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", conn->remote_port); } -- cgit v1.2.1 From c19844a0a3d7f7d1c7351de65605d13d422f2600 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Sep 2002 12:40:36 +0000 Subject: better deal with HTTP(S) servers that respond with no headers at all, test case 306 added to verify that we do right --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6a71e47b1..177d61100 100644 --- a/lib/http.c +++ b/lib/http.c @@ -965,7 +965,8 @@ CURLcode Curl_http(struct connectdata *conn) failf(data, "Failed sending HTTP POST request"); else result = - Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, + Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, data->set.postfields?-1:conn->firstsocket, data->set.postfields?NULL:&http->writebytecount); break; @@ -981,7 +982,8 @@ CURLcode Curl_http(struct connectdata *conn) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, -1, NULL); /* nothing to upload */ } if(result) -- cgit v1.2.1 From b466924717163bb034139eb74376294ca085dbc1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 23 Sep 2002 12:47:18 +0000 Subject: removed use of extra unneeded variable --- lib/http.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 177d61100..855d74733 100644 --- a/lib/http.c +++ b/lib/http.c @@ -449,23 +449,21 @@ CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_done(struct connectdata *conn) { struct SessionHandle *data; - long *bytecount = &conn->bytecount; struct HTTP *http; data=conn->data; http=conn->proto.http; if(HTTPREQ_POST_FORM == data->set.httpreq) { - *bytecount = http->readbytecount + http->writebytecount; + conn->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ data->set.fread = http->storefread; /* restore */ data->set.in = http->in; /* restore */ } - else if(HTTPREQ_PUT == data->set.httpreq) { - *bytecount = http->readbytecount + http->writebytecount; - } + else if(HTTPREQ_PUT == data->set.httpreq) + conn->bytecount = http->readbytecount + http->writebytecount; if(0 == (http->readbytecount + conn->headerbytecount)) { /* nothing was read from the HTTP server, this can't be right @@ -487,7 +485,6 @@ CURLcode Curl_http(struct connectdata *conn) struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->ppath; /* three previous function arguments */ char *host = conn->name; - long *bytecount = &conn->bytecount; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ -- cgit v1.2.1 From 969217c9d9a25cb75d26f815e43f5748b9891f2c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 25 Sep 2002 12:47:38 +0000 Subject: make sure we free rangeline before we re-assign it to a new allocated memory as otherwise we (might) leak memory --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 855d74733..6bba43dda 100644 --- a/lib/http.c +++ b/lib/http.c @@ -669,6 +669,9 @@ CURLcode Curl_http(struct connectdata *conn) */ if((data->set.httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { + /* if a line like this was already allocated, free the previous one */ + if(conn->allocptr.rangeline) + free(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); } else if((data->set.httpreq != HTTPREQ_GET) && -- cgit v1.2.1 From 701509d32237da51bd5b4e6c5bcbd145541259a1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Oct 2002 08:00:49 +0000 Subject: Jeff Lawson fixed a few problems with connection re-use that remained when you set CURLOPT_PROXY to "". --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6bba43dda..35cae48e8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -420,7 +420,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has occured, can we start talking SSL */ - if(data->change.proxy && (data->set.proxytype == CURLPROXY_HTTP) && + if(conn->bits.httpproxy && ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { /* either HTTPS over proxy, OR explicitly asked for a tunnel */ @@ -551,7 +551,7 @@ CURLcode Curl_http(struct connectdata *conn) host, ppath, (conn->protocol&PROT_HTTPS?TRUE:FALSE)); } - if (data->change.proxy && + if (data->change.proxy && *data->change.proxy && !data->set.tunnel_thru_httpproxy && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ -- cgit v1.2.1 From 03c22b4576e99abf6385f64f54e3fb85c782cf0f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Nov 2002 08:40:37 +0000 Subject: Now supports "Transfer-Encoding: chunked" for HTTP PUT operations where the size of the uploaded file is unknown. --- lib/http.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 35cae48e8..460ce0a86 100644 --- a/lib/http.c +++ b/lib/http.c @@ -485,6 +485,7 @@ CURLcode Curl_http(struct connectdata *conn) struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->ppath; /* three previous function arguments */ char *host = conn->name; + const char *te = ""; /* tranfer-encoding */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -546,6 +547,14 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); } + if(conn->upload_chunky) { + if(!checkheaders(data, "Transfer-Encoding:")) { + te = "Transfer-Encoding: chunked\r\n"; + } + /* else + our header was already added, what to do now? */ + } + if(data->cookies) { co = Curl_cookie_getlist(data->cookies, host, ppath, @@ -717,7 +726,8 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* pragma */ "%s" /* accept */ "%s" /* accept-encoding */ - "%s", /* referer */ + "%s" /* referer */ + "%s",/* transfer-encoding */ data->set.customrequest?data->set.customrequest: (data->set.no_body?"HEAD": @@ -739,7 +749,8 @@ CURLcode Curl_http(struct connectdata *conn) http->p_accept?http->p_accept:"", (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? conn->allocptr.accept_encoding:"", /* 08/28/02 jhrg */ - (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */ + (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, + te ); if(co) { -- cgit v1.2.1 From 42acb00c815f2cca5bd1e3653c9f3a47e9256572 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Nov 2002 23:03:03 +0000 Subject: moved the bools in the connectdata struct into the substruct named ConnectBits where the other bools already are --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 460ce0a86..903deb229 100644 --- a/lib/http.c +++ b/lib/http.c @@ -547,7 +547,7 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); } - if(conn->upload_chunky) { + if(conn->bits.upload_chunky) { if(!checkheaders(data, "Transfer-Encoding:")) { te = "Transfer-Encoding: chunked\r\n"; } -- cgit v1.2.1 From e5e2fb82744daa7f9db77bd6a7168af30ff74330 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 26 Nov 2002 17:32:15 +0000 Subject: Dan Becker fixed a minor memory leak on persistent connnections using FOLLOWLOCATION and CURLOPT_USERPWD. --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 903deb229..92143c4a7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -440,6 +440,10 @@ CURLcode Curl_http_connect(struct connectdata *conn) if(conn->bits.user_passwd && !data->state.this_is_a_follow) { /* Authorization: is requested, this is not a followed location, get the original host name */ + if (data->state.auth_host) + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.auth_host); + data->state.auth_host = strdup(conn->hostname); } -- cgit v1.2.1 From eef6c835032cb4eb7bb6140b17263593ff0ad29e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 28 Nov 2002 15:45:06 +0000 Subject: Moved the compareheader function into this file and added Curl_ prefix We now check if the chunked transfer-encoding header has been added "by force" and if so, we enabled the chunky upload! --- lib/http.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 92143c4a7..6b60f66db 100644 --- a/lib/http.c +++ b/lib/http.c @@ -223,21 +223,75 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) /* end of the add_buffer functions */ /* ------------------------------------------------------------------------- */ +/* + * Curl_compareheader() + * + * Returns TRUE if 'headerline' contains the 'header' with given 'content'. + * Pass headers WITH the colon. + */ +bool +Curl_compareheader(char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content) /* content string to find */ +{ + /* RFC2616, section 4.2 says: "Each header field consists of a name followed + * by a colon (":") and the field value. Field names are case-insensitive. + * The field value MAY be preceded by any amount of LWS, though a single SP + * is preferred." */ + + size_t hlen = strlen(header); + size_t clen; + size_t len; + char *start; + char *end; + + if(!strnequal(headerline, header, hlen)) + return FALSE; /* doesn't start with header */ + + /* pass the header */ + start = &headerline[hlen]; + + /* pass all white spaces */ + while(*start && isspace((int)*start)) + start++; + + /* find the end of the header line */ + end = strchr(start, '\r'); /* lines end with CRLF */ + if(!end) { + /* in case there's a non-standard compliant line here */ + end = strchr(start, '\n'); + + if(!end) + /* hm, there's no line ending here, use the zero byte! */ + end = strchr(start, '\0'); + } + + len = end-start; /* length of the content part of the input line */ + clen = strlen(content); /* length of the word to find */ + + /* find the content string in the rest of the line */ + for(;len>=clen;len--, start++) { + if(strnequal(start, content, clen)) + return TRUE; /* match! */ + } + + return FALSE; /* no match */ +} + /* * This function checks the linked list of custom HTTP headers for a particular * header (prefix). */ -static bool checkheaders(struct SessionHandle *data, const char *thisheader) +static char *checkheaders(struct SessionHandle *data, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); for(head = data->set.headers; head; head=head->next) { - if(strnequal(head->data, thisheader, thislen)) { - return TRUE; - } + if(strnequal(head->data, thisheader, thislen)) + return head->data; } - return FALSE; + return NULL; } /* @@ -527,7 +581,7 @@ CURLcode Curl_http(struct connectdata *conn) host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || !data->state.auth_host || - strequal(data->state.auth_host, conn->hostname)) { + curl_strequal(data->state.auth_host, conn->hostname)) { sprintf(data->state.buffer, "%s:%s", data->state.user, data->state.passwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), @@ -551,12 +605,25 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); } + if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { + /* not a chunky transfer but data is to be sent */ + char *ptr = checkheaders(data, "Transfer-Encoding:"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + if(Curl_compareheader(ptr, "Transfer-Encoding:", "chunked")) + /* we have been told explicitly to upload chunky so deal with it! */ + conn->bits.upload_chunky = TRUE; + } + } + if(conn->bits.upload_chunky) { if(!checkheaders(data, "Transfer-Encoding:")) { te = "Transfer-Encoding: chunked\r\n"; } - /* else - our header was already added, what to do now? */ + else { + /* The "Transfer-Encoding:" header was already added. */ + te = ""; + } } if(data->cookies) { -- cgit v1.2.1 From bf678a1ca92112f51e1156e55e3868b2cd34499d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 1 Dec 2002 11:20:41 +0000 Subject: only use Content-Length: header if not transfering data chunked --- lib/http.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6b60f66db..645d11200 100644 --- a/lib/http.c +++ b/lib/http.c @@ -617,6 +617,11 @@ CURLcode Curl_http(struct connectdata *conn) } if(conn->bits.upload_chunky) { + /* RFC2616 section 4.4: + Messages MUST NOT include both a Content-Length header field and a + non-identity transfer-coding. If the message does include a non- + identity transfer-coding, the Content-Length MUST be ignored. */ + if(!checkheaders(data, "Transfer-Encoding:")) { te = "Transfer-Encoding: chunked\r\n"; } @@ -926,8 +931,10 @@ CURLcode Curl_http(struct connectdata *conn) generated form data */ data->set.in = (FILE *)&http->form; - add_bufferf(req_buffer, - "Content-Length: %d\r\n", http->postsize); + if(!conn->bits.upload_chunky) + /* only add Content-Length if not uploading chunked */ + add_bufferf(req_buffer, + "Content-Length: %d\r\n", http->postsize); if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue @@ -985,13 +992,13 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - if(data->set.infilesize>0) { + if((data->set.infilesize>0) && !conn->bits.upload_chunky) + /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: %d\r\n\r\n", /* file size */ + "Content-Length: %d\r\n", /* file size */ data->set.infilesize ); - } - else - add_bufferf(req_buffer, "\015\012"); + + add_bufferf(req_buffer, "\r\n"); /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, data->set.infilesize); @@ -1014,14 +1021,20 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_POST: /* this is the simple POST, using x-www-form-urlencoded style */ - if(!checkheaders(data, "Content-Length:")) - /* we allow replacing this header, although it isn't very wise to - actually set your own */ - add_bufferf(req_buffer, - "Content-Length: %d\r\n", - data->set.postfieldsize? - data->set.postfieldsize: - (data->set.postfields?strlen(data->set.postfields):0) ); + if(!conn->bits.upload_chunky) { + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + + if(!checkheaders(data, "Content-Length:")) + /* we allow replacing this header, although it isn't very wise to + actually set your own */ + add_bufferf(req_buffer, + "Content-Length: %d\r\n", + data->set.postfieldsize? + data->set.postfieldsize: + (data->set.postfields?strlen(data->set.postfields):0) ); + } if(!checkheaders(data, "Content-Type:")) add_bufferf(req_buffer, -- cgit v1.2.1 From 4bcc866c52d5d5eaae18bda4b2afad8014b23683 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Dec 2002 15:37:54 +0000 Subject: The fread() callback pointer and associated pointer is now stored in the connectdata struct instead, and is no longer modified within the 'set' struct as previously (which was a really BAAAD thing). --- lib/http.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 645d11200..82cd664ee 100644 --- a/lib/http.c +++ b/lib/http.c @@ -126,8 +126,11 @@ send_buffer *add_buffer_init(void) * add_buffer_send() sends a buffer and frees all associated memory. */ static -CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, - long *bytes_written) +CURLcode add_buffer_send(send_buffer *in, + int sockfd, + struct connectdata *conn, + long *bytes_written) /* add the number of sent + bytes to this counter */ { ssize_t amount; CURLcode res; @@ -149,6 +152,8 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); + *bytes_written += amount; + if(amount != size) { size -= amount; ptr += amount; @@ -162,8 +167,6 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, free(in->buffer); free(in); - *bytes_written += amount; - return res; } @@ -517,8 +520,9 @@ CURLcode Curl_http_done(struct connectdata *conn) Curl_formclean(http->sendit); /* Now free that whole lot */ - data->set.fread = http->storefread; /* restore */ - data->set.in = http->in; /* restore */ + /* set the proper values */ + conn->fread = data->set.fread; /* restore */ + conn->fread_in = data->set.in; /* restore */ } else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; @@ -923,13 +927,9 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_HTTP_POST_ERROR; } - http->storefread = data->set.fread; /* backup */ - http->in = data->set.in; /* backup */ - - data->set.fread = (curl_read_callback) - Curl_FormReader; /* set the read function to read from the - generated form data */ - data->set.in = (FILE *)&http->form; + /* set the read function to read from the generated form data */ + conn->fread = (curl_read_callback)Curl_FormReader; + conn->fread_in = &http->form; if(!conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ @@ -974,7 +974,7 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) failf(data, "Failed sending POST request"); @@ -1004,10 +1004,10 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) - failf(data, "Faied sending POST request"); + failf(data, "Failed sending POST request"); else /* prepare for transfer */ result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, @@ -1053,7 +1053,7 @@ CURLcode Curl_http(struct connectdata *conn) data->set.postfields ); /* issue the request */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) @@ -1070,7 +1070,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* issue the request */ - result = add_buffer_send(conn->firstsocket, conn, req_buffer, + result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); if(result) -- cgit v1.2.1 From 49f75ee8ce690c3397b5ff01e313629ca89e9235 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Dec 2002 16:05:57 +0000 Subject: A normal POST now provides data to the main transfer loop via the usual read callback, and thus won't put a lot of stress on the request sending code (which currently does an ugly loop). --- lib/http.c | 58 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 82cd664ee..f9f0a819b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -515,14 +515,14 @@ CURLcode Curl_http_done(struct connectdata *conn) data=conn->data; http=conn->proto.http; + /* set the proper values (possibly modified on POST) */ + conn->fread = data->set.fread; /* restore */ + conn->fread_in = data->set.in; /* restore */ + if(HTTPREQ_POST_FORM == data->set.httpreq) { conn->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ - - /* set the proper values */ - conn->fread = data->set.fread; /* restore */ - conn->fread_in = data->set.in; /* restore */ } else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; @@ -537,6 +537,32 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } +/* fread() emulation to provide POST data */ +static int POSTReader(char *buffer, + size_t size, + size_t nitems, + void *userp) +{ + struct HTTP *http = (struct HTTP *)userp; + int fullsize = size * nitems; + + if(0 == http->postsize) + /* nothing to return */ + return 0; + + if(http->postsize <= fullsize) { + memcpy(buffer, http->postdata, http->postsize); + fullsize = http->postsize; + http->postsize = 0; + return fullsize; + } + + memcpy(buffer, http->postdata, fullsize); + http->postdata += fullsize; + http->postsize -= fullsize; + + return fullsize; +} CURLcode Curl_http(struct connectdata *conn) { @@ -1042,17 +1068,19 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); - /* and here comes the actual data */ - if(data->set.postfieldsize && data->set.postfields) { - add_buffer(req_buffer, data->set.postfields, - data->set.postfieldsize); + /* and here we setup the pointers to the actual data */ + if(data->set.postfields) { + if(data->set.postfieldsize) + http->postsize = data->set.postfieldsize; + else + http->postsize = strlen(data->set.postfields); + http->postdata = data->set.postfields; + + conn->fread = (curl_read_callback)POSTReader; + conn->fread_in = (void *)http; } - else if(data->set.postfields) - add_bufferf(req_buffer, - "%s", - data->set.postfields ); - /* issue the request */ + /* issue the request, headers-only */ result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); @@ -1062,8 +1090,8 @@ CURLcode Curl_http(struct connectdata *conn) result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &http->readbytecount, - data->set.postfields?-1:conn->firstsocket, - data->set.postfields?NULL:&http->writebytecount); + conn->firstsocket, + &http->writebytecount); break; default: -- cgit v1.2.1 From db6ff224f8ac1ffb0c99ad6ce17e32d30e463e9c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Dec 2002 13:10:00 +0000 Subject: The initial HTTP request can now be sent in multiple parts, as part of the regular transfer process. This required some new tweaks, like for example we need to be able to tell the tranfer loop to not chunky-encode uploads while we're transferring the rest of the request... --- lib/http.c | 141 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 102 insertions(+), 39 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f9f0a819b..49ba70f36 100644 --- a/lib/http.c +++ b/lib/http.c @@ -98,12 +98,65 @@ #include "memdebug.h" #endif +/* fread() emulation to provide POST and/or request data */ +static int readmoredata(char *buffer, + size_t size, + size_t nitems, + void *userp) +{ + struct connectdata *conn = (struct connectdata *)userp; + struct HTTP *http = conn->proto.http; + int fullsize = size * nitems; + + if(0 == http->postsize) + /* nothing to return */ + return 0; + + /* make sure that a HTTP request is never sent away chunked! */ + conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + + if(http->postsize <= fullsize) { + memcpy(buffer, http->postdata, http->postsize); + fullsize = http->postsize; + + if(http->backup.postsize) { + /* move backup data into focus and continue on that */ + http->postdata = http->backup.postdata; + http->postsize = http->backup.postsize; + conn->fread = http->backup.fread; + conn->fread_in = http->backup.fread_in; + + http->sending++; /* move one step up */ + + http->backup.postsize=0; + } + else + http->postsize = 0; + + return fullsize; + } + + memcpy(buffer, http->postdata, fullsize); + http->postdata += fullsize; + http->postsize -= fullsize; + + return fullsize; +} + /* ------------------------------------------------------------------------- */ /* * The add_buffer series of functions are used to build one large memory chunk * from repeated function invokes. Used so that the entire HTTP request can * be sent in one go. */ + +struct send_buffer { + char *buffer; + size_t size_max; + size_t size_used; +}; +typedef struct send_buffer send_buffer; + static CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size); @@ -136,33 +189,52 @@ CURLcode add_buffer_send(send_buffer *in, CURLcode res; char *ptr; int size; + struct HTTP *http = conn->proto.http; /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ ptr = in->buffer; size = in->size_used; - do { - res = Curl_write(conn, sockfd, ptr, size, &amount); - if(CURLE_OK != res) - break; + res = Curl_write(conn, sockfd, ptr, size, &amount); + + if(CURLE_OK == res) { if(conn->data->set.verbose) /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); *bytes_written += amount; - + if(amount != size) { + /* The whole request could not be sent in one system call. We must queue + it up and send it later when we get the chance. We must not loop here + and wait until it might work again. */ + size -= amount; ptr += amount; + + /* backup the currently set pointers */ + http->backup.fread = conn->fread; + http->backup.fread_in = conn->fread_in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; + + /* set the new pointers for the request-sending */ + conn->fread = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + http->postdata = ptr; + http->postsize = size; + + http->send_buffer = in; + http->sending = HTTPSEND_REQUEST; + + return CURLE_OK; } - else - break; - - } while(1); + /* the full buffer was sent, clean up and return */ + } if(in->buffer) free(in->buffer); free(in); @@ -519,6 +591,13 @@ CURLcode Curl_http_done(struct connectdata *conn) conn->fread = data->set.fread; /* restore */ conn->fread_in = data->set.in; /* restore */ + if(http->send_buffer) { + send_buffer *buff = http->send_buffer; + + free(buff->buffer); + free(buff); + } + if(HTTPREQ_POST_FORM == data->set.httpreq) { conn->bytecount = http->readbytecount + http->writebytecount; @@ -537,33 +616,6 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } -/* fread() emulation to provide POST data */ -static int POSTReader(char *buffer, - size_t size, - size_t nitems, - void *userp) -{ - struct HTTP *http = (struct HTTP *)userp; - int fullsize = size * nitems; - - if(0 == http->postsize) - /* nothing to return */ - return 0; - - if(http->postsize <= fullsize) { - memcpy(buffer, http->postdata, http->postsize); - fullsize = http->postsize; - http->postsize = 0; - return fullsize; - } - - memcpy(buffer, http->postdata, fullsize); - http->postdata += fullsize; - http->postsize -= fullsize; - - return fullsize; -} - CURLcode Curl_http(struct connectdata *conn) { struct SessionHandle *data=conn->data; @@ -957,6 +1009,8 @@ CURLcode Curl_http(struct connectdata *conn) conn->fread = (curl_read_callback)Curl_FormReader; conn->fread_in = &http->form; + http->sending = HTTPSEND_BODY; + if(!conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, @@ -1076,9 +1130,17 @@ CURLcode Curl_http(struct connectdata *conn) http->postsize = strlen(data->set.postfields); http->postdata = data->set.postfields; - conn->fread = (curl_read_callback)POSTReader; - conn->fread_in = (void *)http; + http->sending = HTTPSEND_BODY; + + conn->fread = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); } + else + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, data->set.infilesize); /* issue the request, headers-only */ result = add_buffer_send(req_buffer, conn->firstsocket, conn, @@ -1107,7 +1169,8 @@ CURLcode Curl_http(struct connectdata *conn) /* HTTP GET/HEAD download: */ result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &http->readbytecount, - -1, NULL); /* nothing to upload */ + http->postdata?conn->firstsocket:-1, + http->postdata?&http->writebytecount:NULL); } if(result) return result; -- cgit v1.2.1 From f26a338a54e04d0a6907f5d2479d8b0fa9daf297 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Jan 2003 21:08:12 +0000 Subject: copyright year update in the source header --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 49ba70f36..21ca98b40 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From a7c72b7abf1213c471f3fd11e6b8e3a37d526f60 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 29 Jan 2003 10:14:20 +0000 Subject: removed the local variables for emacs and vim, use the new sample.emacs way for emacs, and vim users should provide a similar non-polluting style --- lib/http.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 21ca98b40..03f7b91d6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1179,13 +1179,4 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_OK; } - - -/* - * local variables: - * eval: (load-file "../curl-mode.el") - * end: - * vim600: fdm=marker - * vim: et sw=2 ts=2 sts=2 tw=78 - */ #endif -- cgit v1.2.1 From a6206a3aefa2814959dad1bc84ef96b5bf24d60f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 Feb 2003 16:53:53 +0000 Subject: Fixes to bring back the the "Expect: 100-continue" functionality. If the header is used, we must wait for a 100-code (or timeout), before we send the data. The timeout is merely 1000 ms at this point. We may have reason to set a longer timeout in the future. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 03f7b91d6..699df5361 100644 --- a/lib/http.c +++ b/lib/http.c @@ -232,7 +232,7 @@ CURLcode add_buffer_send(send_buffer *in, return CURLE_OK; } - + http->sending = HTTPSEND_BODY; /* the full buffer was sent, clean up and return */ } if(in->buffer) -- cgit v1.2.1 From 3242ea5f66d7e5714538a11832009cc23762b174 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 2 Mar 2003 17:43:42 +0000 Subject: Init postdata properly before issuing a request, so that there isn't any lingering POST-stuff that confuses GET requests. Juan F. Codagnone reported this problem in bug report #653859. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 699df5361..94f36c96a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -997,6 +997,8 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } + http->postdata = NULL; /* nothing to post at this point */ + switch(data->set.httpreq) { case HTTPREQ_POST_FORM: -- cgit v1.2.1 From 17962b3d2eb8b99b45709cc65ed346b63394ec22 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 3 Mar 2003 06:45:27 +0000 Subject: Added typecast to please the MSVC compiler. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 94f36c96a..876dbac2e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -716,7 +716,7 @@ CURLcode Curl_http(struct connectdata *conn) if(data->cookies) { co = Curl_cookie_getlist(data->cookies, host, ppath, - (conn->protocol&PROT_HTTPS?TRUE:FALSE)); + (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); } if (data->change.proxy && *data->change.proxy && !data->set.tunnel_thru_httpproxy && -- cgit v1.2.1 From d349eb3d43085a0d35fd4810d9bb295e9152d41e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 16 Mar 2003 16:15:24 +0000 Subject: Juan F. Codagnone pointed out a missing thing from the march 2 fix --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 876dbac2e..850731ce3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -997,7 +997,8 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } - http->postdata = NULL; /* nothing to post at this point */ + http->postdata = NULL; /* nothing to post at this point */ + Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ switch(data->set.httpreq) { -- cgit v1.2.1 From 25f611ca4279927d38327b3c8b4a9f81702cd127 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Mar 2003 04:41:05 +0000 Subject: Guillaume Cottenceau's patch that adds CURLOPT_UNRESTRICTED_AUTH that disables the host name check in the FOLLOWLOCATION code. With that option set, libcurl will send user+password to all hosts. --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 850731ce3..1a9bd2a1d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -663,7 +663,8 @@ CURLcode Curl_http(struct connectdata *conn) host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || !data->state.auth_host || - curl_strequal(data->state.auth_host, conn->hostname)) { + curl_strequal(data->state.auth_host, conn->hostname) || + data->set.http_disable_hostname_check_before_authentication) { sprintf(data->state.buffer, "%s:%s", data->state.user, data->state.passwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), -- cgit v1.2.1 From 7c96c5a39b00f0ed1f1eb436154a5e92bc7637ed Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 30 Apr 2003 17:04:53 +0000 Subject: extract host name from custom Host: headers to use for cookies --- lib/http.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1a9bd2a1d..d736dfdfa 100644 --- a/lib/http.c +++ b/lib/http.c @@ -626,6 +626,7 @@ CURLcode Curl_http(struct connectdata *conn) char *ppath = conn->ppath; /* three previous function arguments */ char *host = conn->name; const char *te = ""; /* tranfer-encoding */ + char *ptr; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -737,7 +738,30 @@ CURLcode Curl_http(struct connectdata *conn) } } - if(!checkheaders(data, "Host:")) { + ptr = checkheaders(data, "Host:"); + if(ptr) { + /* If we have a given custom Host: header, we extract the host name + in order to possibly use it for cookie reasons later on. */ + char *start = ptr+strlen("Host:"); + char *ptr; + while(*start && isspace((int)*start )) + start++; + ptr = start; /* start host-scanning here */ + + /* scan through the string to find the end */ + while(*ptr && !isspace((int)*ptr)) + ptr++; + + if(ptr != start) { + int len=ptr-start; + conn->allocptr.cookiehost = malloc(len+1); + if(!conn->allocptr.cookiehost) + return CURLE_OUT_OF_MEMORY; + memcpy(conn->allocptr.cookiehost, start, len); + conn->allocptr.cookiehost[len]=0; + } + } + else { /* if ptr_host is already set, it is almost OK since we only re-use connections to the very same host and port, but when we use a HTTP proxy we have a persistant connect and yet we must change the Host: -- cgit v1.2.1 From bea02ddebec7b49cd087ccde78cba0cd0eaf1882 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 30 Apr 2003 17:12:29 +0000 Subject: stop parsing Host: host names at colons too --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d736dfdfa..bfef5cecf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -748,8 +748,8 @@ CURLcode Curl_http(struct connectdata *conn) start++; ptr = start; /* start host-scanning here */ - /* scan through the string to find the end */ - while(*ptr && !isspace((int)*ptr)) + /* scan through the string to find the end (space or colon) */ + while(*ptr && !isspace((int)*ptr) && !(':'==*ptr)) ptr++; if(ptr != start) { -- cgit v1.2.1 From 1752d809152da83425a5a9e4bbc74536cf1ee445 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 2 May 2003 09:13:19 +0000 Subject: If there is a custom Host: header specified, we use that host name to extract the correct set of cookies to send. This functionality is verified by test case 62. --- lib/http.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bfef5cecf..40fa54949 100644 --- a/lib/http.c +++ b/lib/http.c @@ -715,29 +715,6 @@ CURLcode Curl_http(struct connectdata *conn) } } - if(data->cookies) { - co = Curl_cookie_getlist(data->cookies, - host, ppath, - (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); - } - if (data->change.proxy && *data->change.proxy && - !data->set.tunnel_thru_httpproxy && - !(conn->protocol&PROT_HTTPS)) { - /* The path sent to the proxy is in fact the entire URL */ - ppath = data->change.url; - } - if(HTTPREQ_POST_FORM == data->set.httpreq) { - /* we must build the whole darned post sequence first, so that we have - a size of the whole shebang before we start to send it */ - result = Curl_getFormData(&http->sendit, data->set.httppost, - &http->postsize); - if(CURLE_OK != result) { - /* Curl_getFormData() doesn't use failf() */ - failf(data, "failed creating formpost data"); - return result; - } - } - ptr = checkheaders(data, "Host:"); if(ptr) { /* If we have a given custom Host: header, we extract the host name @@ -789,6 +766,32 @@ CURLcode Curl_http(struct connectdata *conn) conn->remote_port); } + if(data->cookies) { + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, ppath, + (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + } + + if (data->change.proxy && *data->change.proxy && + !data->set.tunnel_thru_httpproxy && + !(conn->protocol&PROT_HTTPS)) { + /* The path sent to the proxy is in fact the entire URL */ + ppath = data->change.url; + } + if(HTTPREQ_POST_FORM == data->set.httpreq) { + /* we must build the whole darned post sequence first, so that we have + a size of the whole shebang before we start to send it */ + result = Curl_getFormData(&http->sendit, data->set.httppost, + &http->postsize); + if(CURLE_OK != result) { + /* Curl_getFormData() doesn't use failf() */ + failf(data, "failed creating formpost data"); + return result; + } + } + + if(!checkheaders(data, "Pragma:")) http->p_pragma = "Pragma: no-cache\r\n"; -- cgit v1.2.1 From 940707ad6632fa557f2ac28685afa153a3883f19 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 May 2003 12:29:00 +0000 Subject: incoming proxy headers shall be sent to the debug function has HEADERs not DATA --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 40fa54949..a41d0b048 100644 --- a/lib/http.c +++ b/lib/http.c @@ -491,16 +491,16 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* a newline is CRLF in ftp-talk, so the CR is ignored as the line isn't really terminated until the LF comes */ - /* output debug output if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_DATA_IN, line_start, perline); - if('\r' == line_start[0]) { /* end of headers */ keepon=FALSE; break; /* breaks out of loop, not switch */ } + /* output debug output if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); + if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &httperror)) { -- cgit v1.2.1 From 334d78cd18a7310144383929bdcef34ffbf6159b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 May 2003 16:09:54 +0000 Subject: Initial Digest support. At least partly working. --- lib/http.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a41d0b048..a7ad947e1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -89,6 +89,7 @@ #include "cookie.h" #include "strequal.h" #include "ssluse.h" +#include "http_digest.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -627,6 +628,7 @@ CURLcode Curl_http(struct connectdata *conn) char *host = conn->name; const char *te = ""; /* tranfer-encoding */ char *ptr; + unsigned char *request; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -647,6 +649,12 @@ CURLcode Curl_http(struct connectdata *conn) data->set.upload) { data->set.httpreq = HTTPREQ_PUT; } + + request = data->set.customrequest?data->set.customrequest: + (data->set.no_body?"HEAD": + ((HTTPREQ_POST == data->set.httpreq) || + (HTTPREQ_POST_FORM == data->set.httpreq))?"POST": + (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"); /* The User-Agent string has been built in url.c already, because it might have been used in the proxy connect, but if we have got a header with @@ -657,7 +665,12 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.uagent=NULL; } - if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) { + if(data->state.digest.nonce) { + result = Curl_output_digest(conn, request, (unsigned char *)ppath); + if(result) + return result; + } + else if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) { char *authorization; /* To prevent the user+password to get sent to other than the original @@ -902,7 +915,7 @@ CURLcode Curl_http(struct connectdata *conn) /* add the main request stuff */ add_bufferf(req_buffer, "%s " /* GET/HEAD/POST/PUT */ - "%s HTTP/%s\r\n" /* path */ + "%s HTTP/%s\r\n" /* path + HTTP version */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ @@ -915,16 +928,12 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* referer */ "%s",/* transfer-encoding */ - data->set.customrequest?data->set.customrequest: - (data->set.no_body?"HEAD": - ((HTTPREQ_POST == data->set.httpreq) || - (HTTPREQ_POST_FORM == data->set.httpreq))?"POST": - (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"), - ppath, httpstring, + request, + ppath, + httpstring, (conn->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", - (conn->bits.user_passwd && conn->allocptr.userpwd)? - conn->allocptr.userpwd:"", + conn->allocptr.userpwd?conn->allocptr.userpwd:"", (conn->bits.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? -- cgit v1.2.1 From a39d77227fe9d74db74fee259329e4b4a086fcce Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 May 2003 22:39:38 +0000 Subject: Better Digest stuff --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a7ad947e1..44ef29e8f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -670,7 +670,9 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; } - else if((conn->bits.user_passwd) && !checkheaders(data, "Authorization:")) { + else if(!data->set.httpdigest && /* not if Digest is enabled */ + conn->bits.user_passwd && + !checkheaders(data, "Authorization:")) { char *authorization; /* To prevent the user+password to get sent to other than the original -- cgit v1.2.1 From 01108e3a632c5fdb6a789d0c82375fd24ebf7474 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 May 2003 22:45:38 +0000 Subject: warning-free is better --- lib/http.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 44ef29e8f..0d2996c03 100644 --- a/lib/http.c +++ b/lib/http.c @@ -628,7 +628,7 @@ CURLcode Curl_http(struct connectdata *conn) char *host = conn->name; const char *te = ""; /* tranfer-encoding */ char *ptr; - unsigned char *request; + char *request; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -650,11 +650,12 @@ CURLcode Curl_http(struct connectdata *conn) data->set.httpreq = HTTPREQ_PUT; } - request = data->set.customrequest?data->set.customrequest: - (data->set.no_body?"HEAD": + request = data->set.customrequest? + data->set.customrequest: + (data->set.no_body?(char *)"HEAD": ((HTTPREQ_POST == data->set.httpreq) || - (HTTPREQ_POST_FORM == data->set.httpreq))?"POST": - (HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"); + (HTTPREQ_POST_FORM == data->set.httpreq))?(char *)"POST": + (HTTPREQ_PUT == data->set.httpreq)?(char *)"PUT":(char *)"GET"); /* The User-Agent string has been built in url.c already, because it might have been used in the proxy connect, but if we have got a header with @@ -666,7 +667,9 @@ CURLcode Curl_http(struct connectdata *conn) } if(data->state.digest.nonce) { - result = Curl_output_digest(conn, request, (unsigned char *)ppath); + result = Curl_output_digest(conn, + (unsigned char *)request, + (unsigned char *)ppath); if(result) return result; } -- cgit v1.2.1 From 90b0f38316ce59d24d254e4f46d46bc08174b854 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 May 2003 06:28:25 +0000 Subject: Another socks5-fix. Make sure that when we use a socks-proxy, it is not the same as using a httpproxy so we must make sure to better check for http proxies before we do HTTP proxy stuff. This included authorization and URI usage in the request etc. --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0d2996c03..d63eb6b55 100644 --- a/lib/http.c +++ b/lib/http.c @@ -791,7 +791,7 @@ CURLcode Curl_http(struct connectdata *conn) (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); } - if (data->change.proxy && *data->change.proxy && + if (conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ @@ -936,8 +936,8 @@ CURLcode Curl_http(struct connectdata *conn) request, ppath, httpstring, - (conn->bits.proxy_user_passwd && - conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", + (conn->bits.httpproxy && conn->allocptr.proxyuserpwd)? + conn->allocptr.proxyuserpwd:"", conn->allocptr.userpwd?conn->allocptr.userpwd:"", (conn->bits.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", -- cgit v1.2.1 From 5bd8d60e41ad4c9304f0a5210ead7cfa4543d15e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 May 2003 08:33:08 +0000 Subject: Rudy Koento experienced problems with curl's recent habit of POSTing data in two separate send() calls, first the headers and then the data. I've now made a fix that for static and known content that isn't to be chunked-encoded, everything is now sent in one single system call again. This is also better for network performance reasons. --- lib/http.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d63eb6b55..7be5eb902 100644 --- a/lib/http.c +++ b/lib/http.c @@ -906,13 +906,14 @@ CURLcode Curl_http(struct connectdata *conn) } } - do { + { /* Use 1.1 unless the use specificly asked for 1.0 */ const char *httpstring= data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; send_buffer *req_buffer; struct curl_slist *headers=data->set.headers; + size_t postsize; /* initialize a dynamic send-buffer */ req_buffer = add_buffer_init(); @@ -1146,6 +1147,11 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_POST: /* this is the simple POST, using x-www-form-urlencoded style */ + /* store the size of the postfields */ + postsize = data->set.postfieldsize? + data->set.postfieldsize: + (data->set.postfields?strlen(data->set.postfields):0); + if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both @@ -1154,11 +1160,7 @@ CURLcode Curl_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 */ - add_bufferf(req_buffer, - "Content-Length: %d\r\n", - data->set.postfieldsize? - data->set.postfieldsize: - (data->set.postfields?strlen(data->set.postfields):0) ); + add_bufferf(req_buffer, "Content-Length: %d\r\n", postsize); } if(!checkheaders(data, "Content-Type:")) @@ -1169,19 +1171,25 @@ CURLcode Curl_http(struct connectdata *conn) /* and here we setup the pointers to the actual data */ if(data->set.postfields) { - if(data->set.postfieldsize) - http->postsize = data->set.postfieldsize; - else - http->postsize = strlen(data->set.postfields); - http->postdata = data->set.postfields; - http->sending = HTTPSEND_BODY; + if(!conn->bits.upload_chunky) { + /* We have a static chunk of data to POST, and we're not sending + it 'chunked', then we can just as well append it to the request + already now to reduce the number if send() calls */ + add_buffer(req_buffer, data->set.postfields, postsize); + } + else { + http->postsize = postsize; + http->postdata = data->set.postfields; - conn->fread = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; + http->sending = HTTPSEND_BODY; - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); + conn->fread = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + } } else /* set the upload size to the progress meter */ @@ -1197,8 +1205,8 @@ CURLcode Curl_http(struct connectdata *conn) result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, &http->readbytecount, - conn->firstsocket, - &http->writebytecount); + http->postdata?conn->firstsocket:-1, + http->postdata?&http->writebytecount:NULL); break; default: @@ -1219,8 +1227,7 @@ CURLcode Curl_http(struct connectdata *conn) } if(result) return result; - } while (0); /* this is just a left-over from the multiple document download - attempts */ + } return CURLE_OK; } -- cgit v1.2.1 From 4e410111dbc8f953560e3616e084517360c59533 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 28 May 2003 07:54:33 +0000 Subject: Posting static data using POST and chunked encoded now also appends the data to the initial request buffer, if the total post data is less than 100K. --- lib/http.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7be5eb902..408cbafc5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1169,16 +1169,27 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); - /* and here we setup the pointers to the actual data */ if(data->set.postfields) { - if(!conn->bits.upload_chunky) { - /* We have a static chunk of data to POST, and we're not sending - it 'chunked', then we can just as well append it to the request - already now to reduce the number if send() calls */ - add_buffer(req_buffer, data->set.postfields, postsize); + if(postsize < (100*1024)) { + /* The post data is less than 100K, then append it to the header. + This limit is no magic limit but only set to prevent really huge + POSTs to get the data duplicated with malloc() and family. */ + + if(!conn->bits.upload_chunky) + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + add_buffer(req_buffer, data->set.postfields, postsize); + else { + /* Append the POST data chunky-style */ + add_bufferf(req_buffer, "%x\r\n", postsize); + add_buffer(req_buffer, data->set.postfields, postsize); + add_buffer(req_buffer, "\r\n0\r\n", 5); /* end of a chunked + transfer stream */ + } } else { + /* A huge POST coming up, do data separate from the request */ http->postsize = postsize; http->postdata = data->set.postfields; -- cgit v1.2.1 From 8d30d34e0cc45376bb95de46d42a786c2c362e8a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Jun 2003 14:58:26 +0000 Subject: When doing very big GET requests over HTTPS, we need to add some extra funky logic in order to make re-tries work fine with OpenSSL. This corrects the problem David Orrell noticed. --- lib/http.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 408cbafc5..16a87d937 100644 --- a/lib/http.c +++ b/lib/http.c @@ -191,6 +191,7 @@ CURLcode add_buffer_send(send_buffer *in, char *ptr; int size; struct HTTP *http = conn->proto.http; + int sendsize; /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ @@ -198,7 +199,28 @@ CURLcode add_buffer_send(send_buffer *in, ptr = in->buffer; size = in->size_used; - res = Curl_write(conn, sockfd, ptr, size, &amount); + if(conn->protocol & PROT_HTTPS) { + /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + + sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size; + + /* OpenSSL is very picky and we must send the SAME buffer pointer to the + library when we attempt to re-send this buffer. Sending the same data + is not enough, we must use the exact same address. For this reason, we + must copy the data to the uploadbuffer first, since that is the buffer + we will be using if this send is retried later. + */ + memcpy(conn->data->state.uploadbuffer, ptr, sendsize); + ptr = conn->data->state.uploadbuffer; + } + else + sendsize = size; + + res = Curl_write(conn, sockfd, ptr, sendsize, &amount); if(CURLE_OK == res) { -- cgit v1.2.1 From e56ae1426cb7a0a4a427cf8d6099a821fdaae428 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Jun 2003 12:22:19 +0000 Subject: Daniel Kouril's patch that adds HTTP negotiation support to libcurl was added. --- lib/http.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 16a87d937..e5d2b49d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -688,6 +688,14 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.uagent=NULL; } +#ifdef GSSAPI + if (data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + result = Curl_output_negotiate(conn); + if (result) + return result; + } else +#endif if(data->state.digest.nonce) { result = Curl_output_digest(conn, (unsigned char *)request, -- cgit v1.2.1 From 73c5f24fa40460f41d6cd9114827383edc57e287 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Jun 2003 13:38:55 +0000 Subject: Initial take at NTLM authentication. It doesn't really work at this point but the infrastructure is there. --- lib/http.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e5d2b49d3..b06de06a8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -90,6 +90,7 @@ #include "strequal.h" #include "ssluse.h" #include "http_digest.h" +#include "http_ntlm.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -696,7 +697,12 @@ CURLcode Curl_http(struct connectdata *conn) return result; } else #endif - if(data->state.digest.nonce) { + if(data->state.ntlm.state) { + result = Curl_output_ntlm(conn); + if(result) + return result; + } + else if(data->state.digest.nonce) { result = Curl_output_digest(conn, (unsigned char *)request, (unsigned char *)ppath); -- cgit v1.2.1 From ecf32c964aa1f45285d26c91f2cad5513075aa45 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 12 Jun 2003 17:34:27 +0000 Subject: CURLHTTP* renamed to CURLAUTH* and NEGOTIATE is now GSSNEGOTIATE as there's a "plain" Negotiate as well. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b06de06a8..2c1bb292f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -709,7 +709,7 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; } - else if(!data->set.httpdigest && /* not if Digest is enabled */ + else if((data->set.httpauth == CURLAUTH_BASIC) && /* if Basic is desired */ conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { char *authorization; -- cgit v1.2.1 From 12859e345fceaa1599188e2a56419401687d1718 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 26 Jun 2003 11:24:55 +0000 Subject: major adjustments to the new authentication support --- lib/http.c | 101 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 39 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2c1bb292f..aa5a64dc0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -91,12 +91,13 @@ #include "ssluse.h" #include "http_digest.h" #include "http_ntlm.h" +#include "http_negotiate.h" #define _MPRINTF_REPLACE /* use our functions only */ #include /* The last #include file should be: */ -#ifdef MALLOCDEBUG +#ifdef CURLDEBUG #include "memdebug.h" #endif @@ -237,7 +238,8 @@ CURLcode add_buffer_send(send_buffer *in, and wait until it might work again. */ size -= amount; - ptr += amount; + + ptr = in->buffer + amount; /* backup the currently set pointers */ http->backup.fread = conn->fread; @@ -640,6 +642,26 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } +static CURLcode Curl_output_basic(struct connectdata *conn) +{ + char *authorization; + struct SessionHandle *data=conn->data; + + sprintf(data->state.buffer, "%s:%s", + data->state.user, data->state.passwd); + if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), + &authorization) >= 0) { + if(conn->allocptr.userpwd) + free(conn->allocptr.userpwd); + conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", + authorization); + free(authorization); + } + else + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + CURLcode Curl_http(struct connectdata *conn) { struct SessionHandle *data=conn->data; @@ -689,49 +711,50 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.uagent=NULL; } + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + !data->state.auth_host || + curl_strequal(data->state.auth_host, conn->hostname) || + data->set.http_disable_hostname_check_before_authentication) { + #ifdef GSSAPI - if (data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { - result = Curl_output_negotiate(conn); - if (result) + if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && + data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + result = Curl_output_negotiate(conn); + if (result) return result; - } else + } + else #endif - if(data->state.ntlm.state) { - result = Curl_output_ntlm(conn); - if(result) - return result; - } - else if(data->state.digest.nonce) { - result = Curl_output_digest(conn, - (unsigned char *)request, - (unsigned char *)ppath); - if(result) - return result; - } - else if((data->set.httpauth == CURLAUTH_BASIC) && /* if Basic is desired */ - conn->bits.user_passwd && - !checkheaders(data, "Authorization:")) { - char *authorization; - - /* To prevent the user+password to get sent to other than the original - host due to a location-follow, we do some weirdo checks here */ - if(!data->state.this_is_a_follow || - !data->state.auth_host || - curl_strequal(data->state.auth_host, conn->hostname) || - data->set.http_disable_hostname_check_before_authentication) { - sprintf(data->state.buffer, "%s:%s", - data->state.user, data->state.passwd); - if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) >= 0) { - if(conn->allocptr.userpwd) - free(conn->allocptr.userpwd); - conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", - authorization); - free(authorization); +#ifdef USE_SSLEAY + if(data->state.authwant == CURLAUTH_NTLM) { + result = Curl_output_ntlm(conn); + if(result) + return result; + } + else +#endif + { + if((data->state.authwant == CURLAUTH_DIGEST) && + data->state.digest.nonce) { + result = Curl_output_digest(conn, + (unsigned char *)request, + (unsigned char *)ppath); + if(result) + return result; + } + else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ + conn->bits.user_passwd && + !checkheaders(data, "Authorization:")) { + result = Curl_output_basic(conn); + if(result) + return result; } } } + if((data->change.referer) && !checkheaders(data, "Referer:")) { if(conn->allocptr.ref) free(conn->allocptr.ref); -- cgit v1.2.1 From 45fc760985fa11ef98149418cbad02dadf748f31 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 4 Jul 2003 16:29:23 +0000 Subject: Peter Sylvester's patch was applied that introduces the following: CURLOPT_SSL_CTX_FUNCTION to set a callback that gets called with the OpenSSL's ssl_ctx pointer passed in and allow a callback to act on it. If anything but CURLE_OK is returned, that will also be returned by libcurl all the way back. If this function changes the CURLOPT_URL, libcurl will detect this and instead go use the new URL. CURLOPT_SSL_CTX_DATA is a pointer you set to get passed to the callback set with CURLOPT_SSL_CTX_FUNCTION. --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index aa5a64dc0..d710ff5f4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -617,6 +617,9 @@ CURLcode Curl_http_done(struct connectdata *conn) conn->fread = data->set.fread; /* restore */ conn->fread_in = data->set.in; /* restore */ + if (http == NULL) + return CURLE_OK; + if(http->send_buffer) { send_buffer *buff = http->send_buffer; -- cgit v1.2.1 From 52b631fadecb5ff5f038badfd79055e7d4272927 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Jul 2003 23:56:33 +0000 Subject: Access the user and passwd fields from the connectdata struct now instead of the sessionhandle struct, as that was not good. --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d710ff5f4..661ccd7d6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -650,8 +650,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn) char *authorization; struct SessionHandle *data=conn->data; - sprintf(data->state.buffer, "%s:%s", - data->state.user, data->state.passwd); + sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { if(conn->allocptr.userpwd) -- cgit v1.2.1 From 071c95128e2a43be1431c3c38202a1d54d97644a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 21 Jul 2003 13:16:30 +0000 Subject: moved the proxyuser and proxypasswd fields from the sessionhandle to the connectdata to work as expected --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 661ccd7d6..9a2f7fea9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -732,7 +732,7 @@ CURLcode Curl_http(struct connectdata *conn) #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn); + result = Curl_output_ntlm(conn, FALSE); if(result) return result; } -- cgit v1.2.1 From f0278ca114b266bfc1edd399e463e89f653e1ec8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 25 Jul 2003 08:30:58 +0000 Subject: Removed #include , as pointed out by Henry Bland we don't need it. --- lib/http.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9a2f7fea9..b361a204b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -54,7 +54,6 @@ #endif #endif -#include #ifdef HAVE_UNISTD_H #include #endif -- cgit v1.2.1 From 48a580e609c236be4d76be61f2e51821a964410f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 28 Jul 2003 10:21:57 +0000 Subject: clear http->send_buffer when we have freed the memory it pointed to --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b361a204b..7f6752ec5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -624,6 +624,7 @@ CURLcode Curl_http_done(struct connectdata *conn) free(buff->buffer); free(buff); + http->send_buffer = NULL; /* cleaer the pointer */ } if(HTTPREQ_POST_FORM == data->set.httpreq) { -- cgit v1.2.1 From db9f87f697c86cdeca4e6da9f8baabb8246b2d0e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 2 Aug 2003 23:36:35 +0000 Subject: When proxy authentication is used in a CONNECT request (as used for all SSL connects and otherwise enforced tunnel-thru-proxy requests), the same authentication header is also wrongly sent to the remote host. The name and password can then be captured by an evil host and possibly get used for malicious purposes. --- lib/http.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7f6752ec5..2418c1bd7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -91,6 +91,7 @@ #include "http_digest.h" #include "http_ntlm.h" #include "http_negotiate.h" +#include "url.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -552,6 +553,12 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, failf(data, "Received error code %d from proxy", httperror); return CURLE_RECV_ERROR; } + + /* If a proxy-authorization header was used for the proxy, then we should + make sure that it isn't accidentally used for the document request + after we've connected. So let's free and clear it here. */ + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = NULL; infof (data, "Proxy replied to CONNECT request\n"); return CURLE_OK; -- cgit v1.2.1 From 41ae97e710f728495a1d6adba6476c21b94c4881 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Aug 2003 15:02:42 +0000 Subject: Dirk Manske's patch that introduces cookie support to the share interface. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2418c1bd7..e0c5d73e7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -853,10 +853,12 @@ CURLcode Curl_http(struct connectdata *conn) } if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, conn->allocptr.cookiehost? conn->allocptr.cookiehost:host, ppath, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } if (conn->bits.httpproxy && -- cgit v1.2.1 From c704d1545c83950564476a0be66fe5b21326820c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 6 Aug 2003 15:26:24 +0000 Subject: include "share.h" for the cookie sharing --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e0c5d73e7..277e90266 100644 --- a/lib/http.c +++ b/lib/http.c @@ -92,6 +92,7 @@ #include "http_ntlm.h" #include "http_negotiate.h" #include "url.h" +#include "share.h" #define _MPRINTF_REPLACE /* use our functions only */ #include -- cgit v1.2.1 From 2dd1518d630e3fa0857d3086c75948bf26f6c833 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Aug 2003 09:55:48 +0000 Subject: support sending off cookies without contents --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 277e90266..a59ed8ac1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1030,7 +1030,7 @@ CURLcode Curl_http(struct connectdata *conn) struct Cookie *store=co; /* now loop through all cookies that matched */ while(co) { - if(co->value && strlen(co->value)) { + if(co->value) { if(0 == count) { add_bufferf(req_buffer, "Cookie: "); } -- cgit v1.2.1 From 7a19923afa17dbfa9b45d8620bac003398cf1ebd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Aug 2003 11:47:45 +0000 Subject: Serge Semashko added CURLOPT_PROXYAUTH support, and now NTLM for proxies work. --- lib/http.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 26 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a59ed8ac1..35f795725 100644 --- a/lib/http.c +++ b/lib/http.c @@ -93,6 +93,7 @@ #include "http_negotiate.h" #include "url.h" #include "share.h" +#include "http.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -102,6 +103,8 @@ #include "memdebug.h" #endif +static CURLcode Curl_output_basic_proxy(struct connectdata *conn); + /* fread() emulation to provide POST and/or request data */ static int readmoredata(char *buffer, size_t size, @@ -430,6 +433,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); + /* + * This code currently only supports Basic authentication for this CONNECT + * request to a proxy. + */ + if(conn->bits.proxy_user_passwd) + Curl_output_basic_proxy(conn); + /* OK, now send the connect request to the proxy */ result = Curl_sendf(tunnelsocket, conn, @@ -561,6 +571,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, Curl_safefree(conn->allocptr.proxyuserpwd); conn->allocptr.proxyuserpwd = NULL; + Curl_http_auth_stage(data, 401); /* move on to the host auth */ + infof (data, "Proxy replied to CONNECT request\n"); return CURLE_OK; } @@ -672,6 +684,37 @@ static CURLcode Curl_output_basic(struct connectdata *conn) return CURLE_OK; } +static CURLcode Curl_output_basic_proxy(struct connectdata *conn) +{ + char *authorization; + struct SessionHandle *data=conn->data; + + sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); + if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), + &authorization) >= 0) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = + aprintf("Proxy-authorization: Basic %s\015\012", authorization); + free(authorization); + } + else + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +void Curl_http_auth_stage(struct SessionHandle *data, + int stage) +{ + if(stage == 401) + data->state.authwant = data->set.httpauth; + else if(stage == 407) + data->state.authwant = data->set.proxyauth; + else + return; /* bad input stage */ + data->state.authstage = stage; + data->state.authavail = CURLAUTH_NONE; +} + CURLcode Curl_http(struct connectdata *conn) { struct SessionHandle *data=conn->data; @@ -685,6 +728,13 @@ CURLcode Curl_http(struct connectdata *conn) char *ptr; char *request; + if(!data->state.authstage) { + if(conn->bits.httpproxy) + Curl_http_auth_stage(data, 407); + else + Curl_http_auth_stage(data, 401); + } + if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -728,40 +778,63 @@ CURLcode Curl_http(struct connectdata *conn) curl_strequal(data->state.auth_host, conn->hostname) || data->set.http_disable_hostname_check_before_authentication) { -#ifdef GSSAPI - if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { - result = Curl_output_negotiate(conn); - if (result) - return result; - } - else -#endif + /* Send proxy authentication header if needed */ + if (data->state.authstage == 407) { #ifdef USE_SSLEAY - if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn, FALSE); - if(result) - return result; - } - else + if(data->state.authwant == CURLAUTH_NTLM) { + result = Curl_output_ntlm(conn, TRUE); + if(result) + return result; + } + else #endif - { - if((data->state.authwant == CURLAUTH_DIGEST) && - data->state.digest.nonce) { - result = Curl_output_digest(conn, - (unsigned char *)request, - (unsigned char *)ppath); + if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ + conn->bits.proxy_user_passwd && + !checkheaders(data, "Proxy-authorization:")) { + result = Curl_output_basic_proxy(conn); if(result) return result; + /* Switch to web authentication after proxy authentication is done */ + Curl_http_auth_stage(data, 401); } - else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ - conn->bits.user_passwd && - !checkheaders(data, "Authorization:")) { - result = Curl_output_basic(conn); + } + /* Send web authentication header if needed */ + if (data->state.authstage == 401) { +#ifdef GSSAPI + if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && + data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + result = Curl_output_negotiate(conn); + if (result) + return result; + } + else +#endif +#ifdef USE_SSLEAY + if(data->state.authwant == CURLAUTH_NTLM) { + result = Curl_output_ntlm(conn, FALSE); if(result) return result; } + else +#endif + { + if((data->state.authwant == CURLAUTH_DIGEST) && + data->state.digest.nonce) { + result = Curl_output_digest(conn, + (unsigned char *)request, + (unsigned char *)ppath); + if(result) + return result; + } + else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ + conn->bits.user_passwd && + !checkheaders(data, "Authorization:")) { + result = Curl_output_basic(conn); + if(result) + return result; + } + } } } -- cgit v1.2.1 From 27619fc450599bf6c0a152dd9206d8559603fc15 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Aug 2003 23:15:41 +0000 Subject: Added support for CURLINFO_HTTP_CONNECTCODE --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 35f795725..90dc5a63b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -556,6 +556,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(error) return CURLE_RECV_ERROR; + data->info.httpproxycode = httperror; + if(200 != httperror) { if(407 == httperror) /* Added Nov 6 1998 */ -- cgit v1.2.1 From a3c12482140ebb7bc9375afc60733219ad935f8d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 12 Aug 2003 08:20:16 +0000 Subject: Bugfix from Serge Semashko that fixes a bug introduced when we applied his NTLM patch. Test case 84 and 85 verify this. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 90dc5a63b..e95b40fd9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -731,7 +731,7 @@ CURLcode Curl_http(struct connectdata *conn) char *request; if(!data->state.authstage) { - if(conn->bits.httpproxy) + if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) Curl_http_auth_stage(data, 407); else Curl_http_auth_stage(data, 401); -- cgit v1.2.1 From 52ceab5e41a01b4d1227876d51a3680a3ce5a841 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Sep 2003 21:51:28 +0000 Subject: Re-arranged code to make the proxy-CONNECT loop able to do some of the authentication negotiations needed for NTLM, Digest etc. --- lib/http.c | 681 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 432 insertions(+), 249 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e95b40fd9..f4d200eeb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -105,6 +105,278 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn); +/* + * This function checks the linked list of custom HTTP headers for a particular + * header (prefix). + */ +static char *checkheaders(struct SessionHandle *data, const char *thisheader) +{ + struct curl_slist *head; + size_t thislen = strlen(thisheader); + + for(head = data->set.headers; head; head=head->next) { + if(strnequal(head->data, thisheader, thislen)) + return head->data; + } + return NULL; +} + +static CURLcode Curl_output_basic(struct connectdata *conn) +{ + char *authorization; + struct SessionHandle *data=conn->data; + + sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); + if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), + &authorization) >= 0) { + if(conn->allocptr.userpwd) + free(conn->allocptr.userpwd); + conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", + authorization); + free(authorization); + } + else + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +static CURLcode Curl_output_basic_proxy(struct connectdata *conn) +{ + char *authorization; + struct SessionHandle *data=conn->data; + + sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); + if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), + &authorization) >= 0) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = + aprintf("Proxy-authorization: Basic %s\015\012", authorization); + free(authorization); + } + else + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; +} + +void Curl_http_auth_act(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + + if(data->state.authavail) { + if(data->state.authavail & CURLAUTH_GSSNEGOTIATE) + data->state.authwant = CURLAUTH_GSSNEGOTIATE; + else if(data->state.authavail & CURLAUTH_DIGEST) + data->state.authwant = CURLAUTH_DIGEST; + else if(data->state.authavail & CURLAUTH_NTLM) + data->state.authwant = CURLAUTH_NTLM; + else if(data->state.authavail & CURLAUTH_BASIC) + data->state.authwant = CURLAUTH_BASIC; + else + data->state.authwant = CURLAUTH_NONE; /* none */ + + if(data->state.authwant) + conn->newurl = strdup(data->change.url); /* clone string */ + + data->state.authavail = CURLAUTH_NONE; /* clear it here */ + } +} + +/* + * Setup the authentication headers for the host/proxy and the correct + * authentication method. + */ + +CURLcode http_auth_headers(struct connectdata *conn, + char *request, + char *path) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + if(!data->state.authstage) { + if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) + Curl_http_auth_stage(data, 407); + else + Curl_http_auth_stage(data, 401); + } + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + !data->state.auth_host || + curl_strequal(data->state.auth_host, conn->hostname) || + data->set.http_disable_hostname_check_before_authentication) { + + /* Send proxy authentication header if needed */ + if (data->state.authstage == 407) { +#ifdef USE_SSLEAY + if(data->state.authwant == CURLAUTH_NTLM) { + result = Curl_output_ntlm(conn, TRUE); + if(result) + return result; + } + else +#endif + if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ + conn->bits.proxy_user_passwd && + !checkheaders(data, "Proxy-authorization:")) { + result = Curl_output_basic_proxy(conn); + if(result) + return result; + /* Switch to web authentication after proxy authentication is done */ + Curl_http_auth_stage(data, 401); + } + } + /* Send web authentication header if needed */ + if (data->state.authstage == 401) { +#ifdef GSSAPI + if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && + data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + result = Curl_output_negotiate(conn); + if (result) + return result; + } + else +#endif +#ifdef USE_SSLEAY + if(data->state.authwant == CURLAUTH_NTLM) { + result = Curl_output_ntlm(conn, FALSE); + if(result) + return result; + } + else +#endif + { + if((data->state.authwant == CURLAUTH_DIGEST) && + data->state.digest.nonce) { + result = Curl_output_digest(conn, + (unsigned char *)request, + (unsigned char *)path); + if(result) + return result; + } + else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ + conn->bits.user_passwd && + !checkheaders(data, "Authorization:")) { + result = Curl_output_basic(conn); + if(result) + return result; + } + } + } + } + + return result; +} + + +/* + * Curl_http_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * headers. They are dealt with both in the transfer.c main loop and in the + * proxy CONNECT loop. + */ + +CURLcode Curl_http_auth(struct connectdata *conn, + int httpcode, + char *header) /* pointing to the first non-space */ +{ + /* + * This resource requires authentication + */ + struct SessionHandle *data = conn->data; + + char *start = (httpcode == 407) ? + header+strlen("Proxy-authenticate:"): + header+strlen("WWW-Authenticate:"); + /* + * Switch from proxy to web authentication and back if needed + */ + if (httpcode == 407 && data->state.authstage != 407) + Curl_http_auth_stage(data, 407); + + else if (httpcode == 401 && data->state.authstage != 401) + Curl_http_auth_stage(data, 401); + + /* pass all white spaces */ + while(*start && isspace((int)*start)) + start++; + +#ifdef GSSAPI + if (checkprefix("GSS-Negotiate", start)) { + if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { + /* if exactly this is wanted, go */ + int neg = Curl_input_negotiate(conn, start); + if (neg == 0) + conn->newurl = strdup(data->change.url); + } + else + if(data->state.authwant & CURLAUTH_GSSNEGOTIATE) + data->state.authavail |= CURLAUTH_GSSNEGOTIATE; + } + else +#endif +#ifdef USE_SSLEAY + /* NTLM support requires the SSL crypto libs */ + if(checkprefix("NTLM", start)) { + if(data->state.authwant == CURLAUTH_NTLM) { + /* NTLM authentication is activated */ + CURLntlm ntlm = + Curl_input_ntlm(conn, (bool)(httpcode == 407), start); + + if(CURLNTLM_BAD != ntlm) + conn->newurl = strdup(data->change.url); /* clone string */ + else + infof(data, "Authentication problem. Ignoring this.\n"); + } + else + if(data->state.authwant & CURLAUTH_NTLM) + data->state.authavail |= CURLAUTH_NTLM; + } + else +#endif + if(checkprefix("Digest", start)) { + if(data->state.authwant == CURLAUTH_DIGEST) { + /* Digest authentication is activated */ + CURLdigest dig = CURLDIGEST_BAD; + + if(data->state.digest.nonce) + infof(data, "Authentication problem. Ignoring this.\n"); + else + dig = Curl_input_digest(conn, start); + + if(CURLDIGEST_FINE == dig) + /* We act on it. Store our new url, which happens to be + the same one we already use! */ + conn->newurl = strdup(data->change.url); /* clone string */ + } + else + if(data->state.authwant & CURLAUTH_DIGEST) { + /* We don't know if Digest is what we're gonna use, but we + call this function anyway to store the digest data that + is provided on this line, to skip the extra round-trip + we need to do otherwise. We must sure to free this + data! */ + Curl_input_digest(conn, start); + data->state.authavail |= CURLAUTH_DIGEST; + } + } + else if(checkprefix("Basic", start)) { + if((data->state.authwant == CURLAUTH_BASIC) && (httpcode == 401)) { + /* We asked for Basic authentication but got a 401 back + anyway, which basicly means our name+password isn't + valid. */ + data->state.authavail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + } + else if(data->state.authwant & CURLAUTH_BASIC) { + data->state.authavail |= CURLAUTH_BASIC; + } + } + return CURLE_OK; +} + + /* fread() emulation to provide POST and/or request data */ static int readmoredata(char *buffer, size_t size, @@ -383,22 +655,6 @@ Curl_compareheader(char *headerline, /* line to check */ return FALSE; /* no match */ } -/* - * This function checks the linked list of custom HTTP headers for a particular - * header (prefix). - */ -static char *checkheaders(struct SessionHandle *data, const char *thisheader) -{ - struct curl_slist *head; - size_t thislen = strlen(thisheader); - - for(head = data->set.headers; head; head=head->next) { - if(strnequal(head->data, thisheader, thislen)) - return head->data; - } - return NULL; -} - /* * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This * function will issue the necessary commands to get a seamless tunnel through @@ -407,9 +663,10 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int tunnelsocket, - char *hostname, int remote_port) + char *hostname, + int remote_port) { - int httperror=0; + int httpcode=0; int subversion=0; struct SessionHandle *data=conn->data; CURLcode result; @@ -425,6 +682,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, fd_set rkeepfd; fd_set readfd; char *line_start; + char *host_port; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -433,137 +691,168 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); - /* - * This code currently only supports Basic authentication for this CONNECT - * request to a proxy. - */ - if(conn->bits.proxy_user_passwd) - Curl_output_basic_proxy(conn); - - /* OK, now send the connect request to the proxy */ - result = - Curl_sendf(tunnelsocket, conn, - "CONNECT %s:%d HTTP/1.0\015\012" - "%s" - "%s" - "\r\n", - hostname, remote_port, - (conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"", - (data->set.useragent?conn->allocptr.uagent:"") - ); - if(result) { - failf(data, "Failed sending CONNECT to proxy"); - return result; - } - - /* Now, read the full reply we get from the proxy */ - - - if(data->set.timeout) { - /* if timeout is requested, find out how much remaining time we have */ - timeout = data->set.timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ - if(timeout <=0 ) { - failf(data, "Transfer aborted due to timeout"); - return -SELECT_TIMEOUT; /* already too little time */ + do { + if(conn->newurl) { + /* This only happens if we've looped here due to authentication reasons, + and we don't really use the newly cloned URL here then. Just free() + it. */ + free(conn->newurl); + conn->newurl = NULL; } - } - - FD_ZERO (&readfd); /* clear it */ - FD_SET (tunnelsocket, &readfd); /* read socket */ - - /* get this in a backup variable to be able to restore it on each lap in the - select() loop */ - rkeepfd = readfd; - - ptr=data->state.buffer; - line_start = ptr; - nread=0; - perline=0; - keepon=TRUE; + host_port = aprintf("%s:%d", hostname, remote_port); + if(!host_port) + return CURLE_OUT_OF_MEMORY; - while((nreadbits.proxy_user_passwd? + conn->allocptr.proxyuserpwd:"", + data->set.useragent?conn->allocptr.uagent:"" + ); + if(result) + failf(data, "Failed sending CONNECT to proxy"); + } + free(host_port); + if(result) + return result; - switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Transfer aborted due to select() error"); - break; - case 0: /* timeout */ - error = SELECT_TIMEOUT; - failf(data, "Transfer aborted due to timeout"); - break; - default: - /* - * This code previously didn't use the kerberos sec_read() code - * to read, but when we use Curl_read() it may do so. Do confirm - * that this is still ok and then remove this comment! - */ - res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, - &gotbytes); - if(res< 0) - /* EWOULDBLOCK */ - continue; /* go loop yourself */ - else if(res) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - error = SELECT_ERROR; - failf(data, "Connection aborted"); + FD_ZERO (&readfd); /* clear it */ + FD_SET (tunnelsocket, &readfd); /* read socket */ + + /* get this in a backup variable to be able to restore it on each lap in + the select() loop */ + rkeepfd = readfd; + + ptr=data->state.buffer; + line_start = ptr; + + nread=0; + perline=0; + keepon=TRUE; + + while((nreadset.timeout) { + /* if timeout is requested, find out how much remaining time we have */ + timeout = data->set.timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ + if(timeout <=0 ) { + failf(data, "Proxy connection aborted due to timeout"); + error = SELECT_TIMEOUT; /* already too little time */ + break; + } } - else { - /* we got a whole chunk of data, which can be anything from one - * byte to a set of lines and possibly just a piece of the last - * line */ - int i; - - nread += gotbytes; - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr=='\n') { - /* a newline is CRLF in ftp-talk, so the CR is ignored as - the line isn't really terminated until the LF comes */ - - if('\r' == line_start[0]) { - /* end of headers */ - keepon=FALSE; - break; /* breaks out of loop, not switch */ - } - - /* output debug output if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); - - if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &httperror)) { - ; + + switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) { + case -1: /* select() error, stop reading */ + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted due to select() error"); + break; + case 0: /* timeout */ + break; + default: + /* + * This code previously didn't use the kerberos sec_read() code + * to read, but when we use Curl_read() it may do so. Do confirm + * that this is still ok and then remove this comment! + */ + res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); + if(res< 0) + /* EWOULDBLOCK */ + continue; /* go loop yourself */ + else if(res) + keepon = FALSE; + else if(gotbytes <= 0) { + keepon = FALSE; + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + else { + /* + * We got a whole chunk of data, which can be anything from one byte + * to a set of lines and possibly just a piece of the last line. + * + * TODO: To make this code work less error-prone, we need to make + * sure that we read and create full lines before we compare them, + * as there is really nothing that stops the proxy from delivering + * the response lines in multiple parts, each part consisting of + * only a little piece of the line(s). */ + int i; + + nread += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; /* amount of bytes in this line so far */ + if(*ptr=='\n') { + char letter; + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes */ + + if('\r' == line_start[0]) { + /* end of response-headers from the proxy */ + keepon=FALSE; + break; /* breaks out of for-loop, not switch() */ + } + + /* output debug output if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); + + /* keep a backup of the position we are about to blank */ + letter = line_start[perline]; + line_start[perline]=0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", line_start) && + (401 == httpcode)) || + (checkprefix("Proxy-authenticate:", line_start) && + (407 == httpcode))) { + result = Curl_http_auth(conn, httpcode, line_start); + if(result) + return result; + } + else if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &httpcode)) { + ; + } + /* put back the letter we blanked out before */ + line_start[perline]= letter; + + perline=0; /* line starts over here */ + line_start = ptr+1; /* this skips the zero byte we wrote */ } - - perline=0; /* line starts over here */ - line_start = ptr+1; } } - } - break; - } /* switch */ - } /* while there's buffer left and loop is requested */ + break; + } /* switch */ + } /* while there's buffer left and loop is requested */ - if(error) - return CURLE_RECV_ERROR; + if(error) + return CURLE_RECV_ERROR; - data->info.httpproxycode = httperror; + /* Deal with the possibly already received authenticate headers. 'newurl' + is set to a new URL if we must loop. */ + Curl_http_auth_act(conn); + + } while(conn->newurl); + + /* store the HTTP code after the looping is done */ + data->info.httpproxycode = httpcode; - if(200 != httperror) { - if(407 == httperror) - /* Added Nov 6 1998 */ - failf(data, "Proxy requires authorization!"); - else - failf(data, "Received error code %d from proxy", httperror); + if(200 != httpcode) { + failf(data, "Received HTTP code %d from proxy after CONNECT", httpcode); return CURLE_RECV_ERROR; } @@ -575,7 +864,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, Curl_http_auth_stage(data, 401); /* move on to the host auth */ - infof (data, "Proxy replied to CONNECT request\n"); + infof (data, "Proxy replied OK to CONNECT request\n"); return CURLE_OK; } @@ -667,43 +956,6 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } -static CURLcode Curl_output_basic(struct connectdata *conn) -{ - char *authorization; - struct SessionHandle *data=conn->data; - - sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); - if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) >= 0) { - if(conn->allocptr.userpwd) - free(conn->allocptr.userpwd); - conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", - authorization); - free(authorization); - } - else - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; -} - -static CURLcode Curl_output_basic_proxy(struct connectdata *conn) -{ - char *authorization; - struct SessionHandle *data=conn->data; - - sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); - if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) >= 0) { - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = - aprintf("Proxy-authorization: Basic %s\015\012", authorization); - free(authorization); - } - else - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; -} - void Curl_http_auth_stage(struct SessionHandle *data, int stage) { @@ -730,13 +982,6 @@ CURLcode Curl_http(struct connectdata *conn) char *ptr; char *request; - if(!data->state.authstage) { - if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) - Curl_http_auth_stage(data, 407); - else - Curl_http_auth_stage(data, 401); - } - if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -773,72 +1018,10 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.uagent=NULL; } - /* To prevent the user+password to get sent to other than the original - host due to a location-follow, we do some weirdo checks here */ - if(!data->state.this_is_a_follow || - !data->state.auth_host || - curl_strequal(data->state.auth_host, conn->hostname) || - data->set.http_disable_hostname_check_before_authentication) { - - /* Send proxy authentication header if needed */ - if (data->state.authstage == 407) { -#ifdef USE_SSLEAY - if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn, TRUE); - if(result) - return result; - } - else -#endif - if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ - conn->bits.proxy_user_passwd && - !checkheaders(data, "Proxy-authorization:")) { - result = Curl_output_basic_proxy(conn); - if(result) - return result; - /* Switch to web authentication after proxy authentication is done */ - Curl_http_auth_stage(data, 401); - } - } - /* Send web authentication header if needed */ - if (data->state.authstage == 401) { -#ifdef GSSAPI - if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { - result = Curl_output_negotiate(conn); - if (result) - return result; - } - else -#endif -#ifdef USE_SSLEAY - if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn, FALSE); - if(result) - return result; - } - else -#endif - { - if((data->state.authwant == CURLAUTH_DIGEST) && - data->state.digest.nonce) { - result = Curl_output_digest(conn, - (unsigned char *)request, - (unsigned char *)ppath); - if(result) - return result; - } - else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ - conn->bits.user_passwd && - !checkheaders(data, "Authorization:")) { - result = Curl_output_basic(conn); - if(result) - return result; - } - } - } - } + /* setup the authentication headers */ + result = http_auth_headers(conn, request, ppath); + if(result) + return result; if((data->change.referer) && !checkheaders(data, "Referer:")) { if(conn->allocptr.ref) -- cgit v1.2.1 From 7410210f198c88ad9563f6ac5b50218063d91070 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Sep 2003 10:08:53 +0000 Subject: avoid proxy (and other) auth if no user+password is given --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f4d200eeb..3b447dddc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -196,8 +196,10 @@ CURLcode http_auth_headers(struct connectdata *conn, if(!data->state.authstage) { if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) Curl_http_auth_stage(data, 407); - else + else if(conn->bits.user_passwd) Curl_http_auth_stage(data, 401); + else + return CURLE_OK; /* no authentication with no user or password */ } /* To prevent the user+password to get sent to other than the original -- cgit v1.2.1 From 8fae12b2f1d110cf805df87c6a5448334f8d8355 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Sep 2003 10:18:12 +0000 Subject: 1. store the httpproxycode in the loop after it is parsed 2. made Curl_http_auth_act() reset 'authavail' unconditionally --- lib/http.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3b447dddc..e757a828d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -175,10 +175,9 @@ void Curl_http_auth_act(struct connectdata *conn) data->state.authwant = CURLAUTH_NONE; /* none */ if(data->state.authwant) - conn->newurl = strdup(data->change.url); /* clone string */ - - data->state.authavail = CURLAUTH_NONE; /* clear it here */ + conn->newurl = strdup(data->change.url); /* clone URL */ } + data->state.authavail = CURLAUTH_NONE; /* clear it here */ } /* @@ -827,7 +826,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &httpcode)) { - ; + /* store the HTTP code */ + data->info.httpproxycode = httpcode; } /* put back the letter we blanked out before */ line_start[perline]= letter; @@ -850,9 +850,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } while(conn->newurl); - /* store the HTTP code after the looping is done */ - data->info.httpproxycode = httpcode; - if(200 != httpcode) { failf(data, "Received HTTP code %d from proxy after CONNECT", httpcode); return CURLE_RECV_ERROR; -- cgit v1.2.1 From 1f9b0e70ab2131315744d0eedf9c5e29f34c8cb4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Sep 2003 10:55:20 +0000 Subject: Based on Joerg Mueller-Tolk's patch, this introduces support for CURLINFO_HTTPAUTH_AVAIL and CURLINFO_PROXYAUTH_AVAIL --- lib/http.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e757a828d..c1fc9552a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -287,9 +287,17 @@ CURLcode Curl_http_auth(struct connectdata *conn, */ struct SessionHandle *data = conn->data; - char *start = (httpcode == 407) ? - header+strlen("Proxy-authenticate:"): - header+strlen("WWW-Authenticate:"); + long *availp; + char *start; + + if (httpcode == 407) { + start = header+strlen("Proxy-authenticate:"); + availp = &data->info.proxyauthavail; + } + else { + start = header+strlen("WWW-Authenticate:"); + availp = &data->info.httpauthavail; + } /* * Switch from proxy to web authentication and back if needed */ @@ -305,6 +313,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, #ifdef GSSAPI if (checkprefix("GSS-Negotiate", start)) { + *availp |= CURLAUTH_GSSNEGOTIATE; if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, start); @@ -320,6 +329,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, #ifdef USE_SSLEAY /* NTLM support requires the SSL crypto libs */ if(checkprefix("NTLM", start)) { + *availp |= CURLAUTH_NTLM; if(data->state.authwant == CURLAUTH_NTLM) { /* NTLM authentication is activated */ CURLntlm ntlm = @@ -337,6 +347,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, else #endif if(checkprefix("Digest", start)) { + *availp |= CURLAUTH_DIGEST; if(data->state.authwant == CURLAUTH_DIGEST) { /* Digest authentication is activated */ CURLdigest dig = CURLDIGEST_BAD; @@ -363,6 +374,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, } } else if(checkprefix("Basic", start)) { + *availp |= CURLAUTH_BASIC; if((data->state.authwant == CURLAUTH_BASIC) && (httpcode == 401)) { /* We asked for Basic authentication but got a 401 back anyway, which basicly means our name+password isn't -- cgit v1.2.1 From 2956fe97a023f18a6ef9a1bc29f1b641891bcabb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Sep 2003 11:34:09 +0000 Subject: =?UTF-8?q?J=F6rg=20pointed=20out=20that=20I=20did=20this=20fix=20?= =?UTF-8?q?wrongly,=20now=20authwant=20is=20cleared=20properly=20if=20no?= =?UTF-8?q?=20auth=20is=20available?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c1fc9552a..694238397 100644 --- a/lib/http.c +++ b/lib/http.c @@ -162,6 +162,8 @@ void Curl_http_auth_act(struct connectdata *conn) { struct SessionHandle *data = conn->data; + data->state.authwant = CURLAUTH_NONE; /* clear it first */ + if(data->state.authavail) { if(data->state.authavail & CURLAUTH_GSSNEGOTIATE) data->state.authwant = CURLAUTH_GSSNEGOTIATE; @@ -171,13 +173,11 @@ void Curl_http_auth_act(struct connectdata *conn) data->state.authwant = CURLAUTH_NTLM; else if(data->state.authavail & CURLAUTH_BASIC) data->state.authwant = CURLAUTH_BASIC; - else - data->state.authwant = CURLAUTH_NONE; /* none */ if(data->state.authwant) conn->newurl = strdup(data->change.url); /* clone URL */ + data->state.authavail = CURLAUTH_NONE; /* clear it here */ } - data->state.authavail = CURLAUTH_NONE; /* clear it here */ } /* -- cgit v1.2.1 From f2057eb7441d2b07841fc23bf8682ad991268fcb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Sep 2003 13:07:09 +0000 Subject: ah, this change broke multiple test cases --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 694238397..aa037e99a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -162,8 +162,6 @@ void Curl_http_auth_act(struct connectdata *conn) { struct SessionHandle *data = conn->data; - data->state.authwant = CURLAUTH_NONE; /* clear it first */ - if(data->state.authavail) { if(data->state.authavail & CURLAUTH_GSSNEGOTIATE) data->state.authwant = CURLAUTH_GSSNEGOTIATE; @@ -173,6 +171,8 @@ void Curl_http_auth_act(struct connectdata *conn) data->state.authwant = CURLAUTH_NTLM; else if(data->state.authavail & CURLAUTH_BASIC) data->state.authwant = CURLAUTH_BASIC; + else + data->state.authwant = CURLAUTH_NONE; /* clear it */ if(data->state.authwant) conn->newurl = strdup(data->change.url); /* clone URL */ -- cgit v1.2.1 From fd42247cacff58fddba6a2629aa2978241f68402 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Sep 2003 22:21:11 +0000 Subject: Tim Bartley's patch that makes the GSSNEGOTIATE option work for Microsoft's "Negotiate" authentication as well. --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index aa037e99a..76198e0c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -312,7 +312,8 @@ CURLcode Curl_http_auth(struct connectdata *conn, start++; #ifdef GSSAPI - if (checkprefix("GSS-Negotiate", start)) { + if (checkprefix("GSS-Negotiate", start) || + checkprefix("Negotiate", start)) { *availp |= CURLAUTH_GSSNEGOTIATE; if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ -- cgit v1.2.1 From 58b1437cae71335fe78e850f0f2bacfcfb268333 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 15 Sep 2003 21:11:22 +0000 Subject: When we issue a HTTP request, first make sure if the authentication phase is over or not, as if it isn't we shall not begin any PUT or POST operation. This cures bug report #805853, and test case 88 verifies it! --- lib/http.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 76198e0c2..8cb97dd1d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -187,18 +187,25 @@ void Curl_http_auth_act(struct connectdata *conn) CURLcode http_auth_headers(struct connectdata *conn, char *request, - char *path) + char *path, + bool *ready) /* set TRUE when the auth phase is + done and ready to do the *actual* + request */ { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; + *ready = FALSE; /* default is no */ + if(!data->state.authstage) { if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) Curl_http_auth_stage(data, 407); else if(conn->bits.user_passwd) Curl_http_auth_stage(data, 401); - else + else { + *ready = TRUE; return CURLE_OK; /* no authentication with no user or password */ + } } /* To prevent the user+password to get sent to other than the original @@ -212,7 +219,7 @@ CURLcode http_auth_headers(struct connectdata *conn, if (data->state.authstage == 407) { #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn, TRUE); + result = Curl_output_ntlm(conn, TRUE, ready); if(result) return result; } @@ -224,6 +231,7 @@ CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_basic_proxy(conn); if(result) return result; + *ready = TRUE; /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); } @@ -237,12 +245,13 @@ CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_negotiate(conn); if (result) return result; + *ready = TRUE; } else #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { - result = Curl_output_ntlm(conn, FALSE); + result = Curl_output_ntlm(conn, FALSE, ready); if(result) return result; } @@ -256,6 +265,7 @@ CURLcode http_auth_headers(struct connectdata *conn, (unsigned char *)path); if(result) return result; + *ready = TRUE; } else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ conn->bits.user_passwd && @@ -263,10 +273,13 @@ CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_basic(conn); if(result) return result; + *ready = TRUE; } } } } + else + *ready = TRUE; return result; } @@ -706,6 +719,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); do { + bool auth; /* we don't really have to know when the auth phase is done, + but this variable will be set to true then */ + if(conn->newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() @@ -719,7 +735,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ - result = http_auth_headers(conn, (char *)"CONNECT", host_port); + result = http_auth_headers(conn, (char *)"CONNECT", host_port, &auth); if(CURLE_OK == result) { /* OK, now send the connect request to the proxy */ @@ -993,6 +1009,8 @@ CURLcode Curl_http(struct connectdata *conn) const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; + bool authdone=TRUE; /* if the authentication phase is done */ + Curl_HttpReq httpreq; /* type of HTTP request */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1031,7 +1049,7 @@ CURLcode Curl_http(struct connectdata *conn) } /* setup the authentication headers */ - result = http_auth_headers(conn, request, ppath); + result = http_auth_headers(conn, request, ppath, &authdone); if(result) return result; @@ -1384,7 +1402,13 @@ CURLcode Curl_http(struct connectdata *conn) http->postdata = NULL; /* nothing to post at this point */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - switch(data->set.httpreq) { + if(!authdone) + /* until the auth is done, pretend we only do GET */ + httpreq = HTTPREQ_GET; + else + httpreq = data->set.httpreq; + + switch(httpreq) { case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { -- cgit v1.2.1 From 09ccfcdcd422fc0b0421562bbdcf53f78a3f3e4b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Sep 2003 12:56:22 +0000 Subject: Markus Moeller's SPNEGO patch applied, with my edits, additions and minor cleanups. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8cb97dd1d..5195122a8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -238,7 +238,7 @@ CURLcode http_auth_headers(struct connectdata *conn, } /* Send web authentication header if needed */ if (data->state.authstage == 401) { -#ifdef GSSAPI +#ifdef HAVE_GSSAPI if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { @@ -324,7 +324,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, while(*start && isspace((int)*start)) start++; -#ifdef GSSAPI +#ifdef HAVE_GSSAPI if (checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { *availp |= CURLAUTH_GSSNEGOTIATE; -- cgit v1.2.1 From 780652e5b695ba2e85cfbefedf80ec1f5e951798 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 4 Oct 2003 15:48:15 +0000 Subject: Vincent Bronner pointed out that if you set CURLOPT_COOKIE to NULL, it still sends off the previously set cookie. This also concerns CURLOPT_REFERER. This fix should stop this. --- lib/http.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5195122a8..e0a280e28 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1053,16 +1053,17 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; - if((data->change.referer) && !checkheaders(data, "Referer:")) { - if(conn->allocptr.ref) - free(conn->allocptr.ref); + Curl_safefree(conn->allocptr.ref); + if(data->change.referer && !checkheaders(data, "Referer:")) conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer); - } - if(data->set.cookie && !checkheaders(data, "Cookie:")) { - if(conn->allocptr.cookie) - free(conn->allocptr.cookie); + else + conn->allocptr.ref = NULL; + + Curl_safefree(conn->allocptr.cookie); + if(data->set.cookie && !checkheaders(data, "Cookie:")) conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); - } + else + conn->allocptr.cookie = NULL; if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { /* not a chunky transfer but data is to be sent */ -- cgit v1.2.1 From b61c25af45ee21a04d2bbab73e21f48fb7345347 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 7 Oct 2003 14:39:32 +0000 Subject: make sure that a regular POST using the read callback works --- lib/http.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e0a280e28..ff6e432aa 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1568,11 +1568,15 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); } } - else + else { /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, data->set.infilesize); - /* issue the request, headers-only */ + /* set the pointer to mark that we will send the post body using + the read callback */ + http->postdata = (char *)&http->postdata; + } + /* issue the request */ result = add_buffer_send(req_buffer, conn->firstsocket, conn, &data->info.request_size); -- cgit v1.2.1 From 749f5387c19449209615b282ac738032f2a890e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Oct 2003 12:00:45 +0000 Subject: Gisle Vanem's IPv6-on-Windows patch applied! --- lib/http.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ff6e432aa..041d6f944 100644 --- a/lib/http.c +++ b/lib/http.c @@ -36,7 +36,6 @@ #include #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) -#include #include #include #else -- cgit v1.2.1 From 260c353577148c74b6b61c8222ab63c72a5ec820 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Oct 2003 07:05:26 +0000 Subject: show info text (verbose) about auth type and user name in use --- lib/http.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 041d6f944..217103c50 100644 --- a/lib/http.c +++ b/lib/http.c @@ -193,6 +193,7 @@ CURLcode http_auth_headers(struct connectdata *conn, { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; + char *auth=NULL; *ready = FALSE; /* default is no */ @@ -218,6 +219,7 @@ CURLcode http_auth_headers(struct connectdata *conn, if (data->state.authstage == 407) { #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { + auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE, ready); if(result) return result; @@ -227,6 +229,7 @@ CURLcode http_auth_headers(struct connectdata *conn, if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { + auth=(char *)"Basic"; result = Curl_output_basic_proxy(conn); if(result) return result; @@ -234,13 +237,17 @@ CURLcode http_auth_headers(struct connectdata *conn, /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); } + infof(data, "Proxy auth using %s with user '%s'\n", + auth, conn->proxyuser); } /* Send web authentication header if needed */ if (data->state.authstage == 401) { + auth = NULL; #ifdef HAVE_GSSAPI if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { + auth="GSS-Negotiate"; result = Curl_output_negotiate(conn); if (result) return result; @@ -250,6 +257,7 @@ CURLcode http_auth_headers(struct connectdata *conn, #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { + auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE, ready); if(result) return result; @@ -259,6 +267,7 @@ CURLcode http_auth_headers(struct connectdata *conn, { if((data->state.authwant == CURLAUTH_DIGEST) && data->state.digest.nonce) { + auth=(char *)"Digest"; result = Curl_output_digest(conn, (unsigned char *)request, (unsigned char *)path); @@ -269,12 +278,16 @@ CURLcode http_auth_headers(struct connectdata *conn, else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { + auth=(char *)"Basic"; result = Curl_output_basic(conn); if(result) return result; *ready = TRUE; } } + if(auth) + infof(data, "Server auth using %s with user '%s'\n", + auth, conn->user); } } else -- cgit v1.2.1 From 9935d33b8e63bc1772e1975ad66475375672b34b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Oct 2003 09:29:30 +0000 Subject: make empty names look fine in verbose output --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 217103c50..e277194fb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -238,7 +238,7 @@ CURLcode http_auth_headers(struct connectdata *conn, Curl_http_auth_stage(data, 401); } infof(data, "Proxy auth using %s with user '%s'\n", - auth, conn->proxyuser); + auth, conn->proxyuser?conn->proxyuser:""); } /* Send web authentication header if needed */ if (data->state.authstage == 401) { @@ -287,7 +287,7 @@ CURLcode http_auth_headers(struct connectdata *conn, } if(auth) infof(data, "Server auth using %s with user '%s'\n", - auth, conn->user); + auth, conn->user?conn->user:""); } } else -- cgit v1.2.1 From f0089b62919857bc7d3a5eda10fabdcfd8b20a27 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 18 Oct 2003 20:14:21 +0000 Subject: compiler warning fix --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e277194fb..61b9f4893 100644 --- a/lib/http.c +++ b/lib/http.c @@ -247,7 +247,7 @@ CURLcode http_auth_headers(struct connectdata *conn, if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { - auth="GSS-Negotiate"; + auth=(char *)"GSS-Negotiate"; result = Curl_output_negotiate(conn); if (result) return result; -- cgit v1.2.1 From 9df8f9a63dc08b12475f1c56f1beddf8ce8649f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 18 Oct 2003 20:35:03 +0000 Subject: builds warning-free with -Wshadow now --- lib/http.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 61b9f4893..9e2196ab2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1079,7 +1079,7 @@ CURLcode Curl_http(struct connectdata *conn) if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { /* not a chunky transfer but data is to be sent */ - char *ptr = checkheaders(data, "Transfer-Encoding:"); + ptr = checkheaders(data, "Transfer-Encoding:"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ if(Curl_compareheader(ptr, "Transfer-Encoding:", "chunked")) @@ -1108,7 +1108,6 @@ CURLcode Curl_http(struct connectdata *conn) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. */ char *start = ptr+strlen("Host:"); - char *ptr; while(*start && isspace((int)*start )) start++; ptr = start; /* start host-scanning here */ @@ -1395,7 +1394,7 @@ CURLcode Curl_http(struct connectdata *conn) } while(headers) { - char *ptr = strchr(headers->data, ':'); + ptr = strchr(headers->data, ':'); if(ptr) { /* we require a colon for this to be a true header */ -- cgit v1.2.1 From 7d6584e1407ad3c4a067515faf431c15e698103b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 20 Oct 2003 20:30:40 +0000 Subject: allow no user and no passwd when doing basic auth --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9e2196ab2..95e06ecf8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -125,7 +125,9 @@ static CURLcode Curl_output_basic(struct connectdata *conn) char *authorization; struct SessionHandle *data=conn->data; - sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); + sprintf(data->state.buffer, "%s:%s", + conn->user?conn->user:"", + conn->passwd?conn->passwd:""); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { if(conn->allocptr.userpwd) -- cgit v1.2.1 From b83c7ade10d9c1ded861f29953dc9ab384f45e89 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 20 Oct 2003 20:32:08 +0000 Subject: allow no user and password for proxy too, Basic --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 95e06ecf8..bb09be10d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -146,7 +146,9 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn) char *authorization; struct SessionHandle *data=conn->data; - sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); + sprintf(data->state.buffer, "%s:%s", + conn->proxyuser?conn->proxyuser:"", + conn->proxypasswd?conn->proxypasswd:""); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { Curl_safefree(conn->allocptr.proxyuserpwd); -- cgit v1.2.1 From d1c08e1d8526c200a300f3d20b49778aba3ff7dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 Oct 2003 06:34:15 +0000 Subject: conn->user and conn->passwd will now always be set to point to something. If not user or password is set, they will point to a "" string. --- lib/http.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bb09be10d..2f7db943b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -125,9 +125,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn) char *authorization; struct SessionHandle *data=conn->data; - sprintf(data->state.buffer, "%s:%s", - conn->user?conn->user:"", - conn->passwd?conn->passwd:""); + sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { if(conn->allocptr.userpwd) @@ -147,8 +145,7 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn) struct SessionHandle *data=conn->data; sprintf(data->state.buffer, "%s:%s", - conn->proxyuser?conn->proxyuser:"", - conn->proxypasswd?conn->proxypasswd:""); + conn->proxyuser, conn->proxypasswd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) >= 0) { Curl_safefree(conn->allocptr.proxyuserpwd); @@ -291,7 +288,7 @@ CURLcode http_auth_headers(struct connectdata *conn, } if(auth) infof(data, "Server auth using %s with user '%s'\n", - auth, conn->user?conn->user:""); + auth, conn->user); } } else -- cgit v1.2.1 From 7247041e219c0281b9ff0835eada711593b9d62f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 24 Oct 2003 12:58:29 +0000 Subject: Improved checks for bad memory situations and proper behaviour when we run out of memory. --- lib/http.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2f7db943b..4543faee8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -591,7 +591,6 @@ CURLcode add_buffer_send(send_buffer *in, static CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) { - CURLcode result = CURLE_OUT_OF_MEMORY; char *s; va_list ap; va_start(ap, fmt); @@ -599,10 +598,16 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) va_end(ap); if(s) { - result = add_buffer(in, s, strlen(s)); + CURLcode result = add_buffer(in, s, strlen(s)); free(s); + if(CURLE_OK == result) + return CURLE_OK; } - return result; + /* If we failed, we cleanup the whole buffer and return error */ + if(in->buffer) + free(in->buffer); + free(in); + return CURLE_OUT_OF_MEMORY; } /* @@ -1152,6 +1157,10 @@ CURLcode Curl_http(struct connectdata *conn) host, conn->bits.ipv6_ip?"]":"", conn->remote_port); + + if(!conn->allocptr.host) + /* without Host: we can't make a nice request */ + return CURLE_OUT_OF_MEMORY; } if(data->cookies) { @@ -1290,21 +1299,25 @@ CURLcode Curl_http(struct connectdata *conn) /* initialize a dynamic send-buffer */ req_buffer = add_buffer_init(); + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + /* add the main request stuff */ - add_bufferf(req_buffer, - "%s " /* GET/HEAD/POST/PUT */ - "%s HTTP/%s\r\n" /* path + HTTP version */ - "%s" /* proxyuserpwd */ - "%s" /* userpwd */ - "%s" /* range */ - "%s" /* user agent */ - "%s" /* cookie */ - "%s" /* host */ - "%s" /* pragma */ - "%s" /* accept */ - "%s" /* accept-encoding */ - "%s" /* referer */ - "%s",/* transfer-encoding */ + result = + add_bufferf(req_buffer, + "%s " /* GET/HEAD/POST/PUT */ + "%s HTTP/%s\r\n" /* path + HTTP version */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* cookie */ + "%s" /* host */ + "%s" /* pragma */ + "%s" /* accept */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s",/* transfer-encoding */ request, ppath, @@ -1326,6 +1339,9 @@ CURLcode Curl_http(struct connectdata *conn) te ); + if(result) + return result; + if(co) { int count=0; struct Cookie *store=co; -- cgit v1.2.1 From a717afc3a7e2649987cd276c500dae73990f6f91 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 31 Oct 2003 21:43:22 +0000 Subject: gmtime() really can't even return NULL, can it? --- lib/http.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4543faee8..9d01ef87a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1381,10 +1381,6 @@ CURLcode Curl_http(struct connectdata *conn) #else thistime = gmtime(&data->set.timevalue); #endif - if(NULL == thistime) { - failf(data, "localtime() failed!"); - return CURLE_OUT_OF_MEMORY; - } #ifdef HAVE_STRFTIME /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ -- cgit v1.2.1 From f481b3e1dc2428783cbafa3839e56d26444c24d4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 20 Nov 2003 09:53:42 +0000 Subject: bail out properly on a 407 when we can't authenticate basic, bug report #845247 --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9d01ef87a..d7496ecde 100644 --- a/lib/http.c +++ b/lib/http.c @@ -402,8 +402,9 @@ CURLcode Curl_http_auth(struct connectdata *conn, } else if(checkprefix("Basic", start)) { *availp |= CURLAUTH_BASIC; - if((data->state.authwant == CURLAUTH_BASIC) && (httpcode == 401)) { - /* We asked for Basic authentication but got a 401 back + if((data->state.authwant == CURLAUTH_BASIC) && + (httpcode == data->state.authstage)) { + /* We asked for Basic authentication but got a 40X back anyway, which basicly means our name+password isn't valid. */ data->state.authavail = CURLAUTH_NONE; -- cgit v1.2.1 From 1e98727c552ced5f8c7587f64ab69c6eaab743dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 Nov 2003 07:15:37 +0000 Subject: FTPS support added as RFC2228 and the murray-ftp-auth-ssl draft describe it --- lib/http.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d7496ecde..0b36f1eea 100644 --- a/lib/http.c +++ b/lib/http.c @@ -500,7 +500,6 @@ send_buffer *add_buffer_init(void) */ static CURLcode add_buffer_send(send_buffer *in, - int sockfd, struct connectdata *conn, long *bytes_written) /* add the number of sent bytes to this counter */ @@ -511,6 +510,7 @@ CURLcode add_buffer_send(send_buffer *in, int size; struct HTTP *http = conn->proto.http; int sendsize; + int sockfd = conn->sock[FIRSTSOCKET]; /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ @@ -708,7 +708,7 @@ Curl_compareheader(char *headerline, /* line to check */ */ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, - int tunnelsocket, + int sockindex, char *hostname, int remote_port) { @@ -729,6 +729,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, fd_set readfd; char *line_start; char *host_port; + int tunnelsocket = conn->sock[sockindex]; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -936,7 +937,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { /* either HTTPS over proxy, OR explicitly asked for a tunnel */ - result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, + result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, conn->hostname, conn->remote_port); if(CURLE_OK != result) return result; @@ -944,7 +945,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) if(conn->protocol & PROT_HTTPS) { /* now, perform the SSL initialization for this socket */ - result = Curl_SSLConnect(conn); + result = Curl_SSLConnect(conn, FIRSTSOCKET); if(result) return result; } @@ -1491,15 +1492,15 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - result = add_buffer_send(req_buffer, conn->firstsocket, conn, + result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - conn->firstsocket, + FIRSTSOCKET, &http->writebytecount); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ @@ -1521,15 +1522,15 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ - result = add_buffer_send(req_buffer, conn->firstsocket, conn, + result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) failf(data, "Failed sending POST request"); else /* prepare for transfer */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - conn->firstsocket, + FIRSTSOCKET, &http->writebytecount); if(result) return result; @@ -1602,16 +1603,16 @@ CURLcode Curl_http(struct connectdata *conn) http->postdata = (char *)&http->postdata; } /* issue the request */ - result = add_buffer_send(req_buffer, conn->firstsocket, conn, + result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) failf(data, "Failed sending HTTP POST request"); else result = - Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - http->postdata?conn->firstsocket:-1, + http->postdata?FIRSTSOCKET:-1, http->postdata?&http->writebytecount:NULL); break; @@ -1619,16 +1620,16 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* issue the request */ - result = add_buffer_send(req_buffer, conn->firstsocket, conn, + result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - http->postdata?conn->firstsocket:-1, + http->postdata?FIRSTSOCKET:-1, http->postdata?&http->writebytecount:NULL); } if(result) -- cgit v1.2.1 From 45614d54c6b49cfa3f6b1296e0f88e48e4d76e55 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 Nov 2003 16:17:55 +0000 Subject: allow the end-of-headers from a proxy response to CONNECT end with a CRCR as well as a CRLF --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0b36f1eea..d5c8cf604 100644 --- a/lib/http.c +++ b/lib/http.c @@ -849,9 +849,11 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(*ptr=='\n') { char letter; /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes */ + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ - if('\r' == line_start[0]) { + if(('\r' == line_start[0]) || + ('\n' == line_start[0])) { /* end of response-headers from the proxy */ keepon=FALSE; break; /* breaks out of for-loop, not switch() */ -- cgit v1.2.1 From 1d977b78481d1d430cb05c8297ee412e62f31c8e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 25 Nov 2003 09:05:15 +0000 Subject: When basic is the only auth wanted (which it is by default), the auth phase is always considered done immediately as Basic needs to extra passes. This fix corrects bug report #848371. --- lib/http.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d5c8cf604..9389f5bbd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -227,13 +227,15 @@ CURLcode http_auth_headers(struct connectdata *conn, } else #endif - if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ - conn->bits.proxy_user_passwd && - !checkheaders(data, "Proxy-authorization:")) { - auth=(char *)"Basic"; - result = Curl_output_basic_proxy(conn); - if(result) - return result; + if(data->state.authwant == CURLAUTH_BASIC) { + /* Basic */ + if(conn->bits.proxy_user_passwd && + !checkheaders(data, "Proxy-authorization:")) { + auth=(char *)"Basic"; + result = Curl_output_basic_proxy(conn); + if(result) + return result; + } *ready = TRUE; /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); @@ -276,13 +278,15 @@ CURLcode http_auth_headers(struct connectdata *conn, return result; *ready = TRUE; } - else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ - conn->bits.user_passwd && - !checkheaders(data, "Authorization:")) { - auth=(char *)"Basic"; - result = Curl_output_basic(conn); - if(result) - return result; + else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ + if(conn->bits.user_passwd && + !checkheaders(data, "Authorization:")) { + auth=(char *)"Basic"; + result = Curl_output_basic(conn); + if(result) + return result; + } + /* basic is always ready */ *ready = TRUE; } } -- cgit v1.2.1 From b60e0fa97ed7ddc66d0ad6d00dfd78319bb6ad36 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Jan 2004 22:29:29 +0000 Subject: David J Meyer's large file support. --- lib/http.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9389f5bbd..f441a1886 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1227,25 +1227,25 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->resume_from) { /* do we still game? */ - int passed=0; + off_t passed=0; /* Now, let's read off the proper amount of bytes from the input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - int readthisamountnow = (conn->resume_from - passed); - int actuallyread; + off_t readthisamountnow = (conn->resume_from - passed); + off_t actuallyread; if(readthisamountnow > BUFSIZE) readthisamountnow = BUFSIZE; actuallyread = - data->set.fread(data->state.buffer, 1, readthisamountnow, + data->set.fread(data->state.buffer, 1, (size_t)readthisamountnow, data->set.in); passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read %d bytes from the input", + failf(data, "Could only read %Od bytes from the input", passed); return CURLE_READ_ERROR; } @@ -1281,16 +1281,18 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->resume_from) { /* This is because "resume" was selected */ - long total_expected_size= conn->resume_from + data->set.infilesize; - conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", - conn->range, total_expected_size-1, - total_expected_size); + off_t total_expected_size= conn->resume_from + data->set.infilesize; + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s%Od/%Od\r\n", + conn->range, total_expected_size-1, + total_expected_size); } else { /* Range was selected and then we just pass the incoming range and append total size */ - conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", - conn->range, data->set.infilesize); + conn->allocptr.rangeline = + aprintf("Content-Range: bytes %s/%Od\r\n", + conn->range, data->set.infilesize); } } } @@ -1519,13 +1521,13 @@ CURLcode Curl_http(struct connectdata *conn) if((data->set.infilesize>0) && !conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: %d\r\n", /* file size */ + "Content-Length: %Od\r\n", /* file size */ data->set.infilesize ); add_bufferf(req_buffer, "\r\n"); /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ result = add_buffer_send(req_buffer, conn, @@ -1602,7 +1604,7 @@ CURLcode Curl_http(struct connectdata *conn) } else { /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); /* set the pointer to mark that we will send the post body using the read callback */ -- cgit v1.2.1 From 053f6c85efd0bf698f73343989474d672d0563a8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Jan 2004 09:19:33 +0000 Subject: updated year in the copyright string --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f441a1886..a992fd421 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 44031f32a149e9d4097b77c1e998db03887d209c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 9 Jan 2004 14:03:06 +0000 Subject: added one assert and a few comments describing how the auth stuff works --- lib/http.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a992fd421..6002ad977 100644 --- a/lib/http.c +++ b/lib/http.c @@ -158,11 +158,19 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn) return CURLE_OK; } +/* + * Curl_http_auth_act() checks what authentication methods that are available + * and decides which one (if any) to use. It will set 'newurl' if an auth + * metod was picked. + */ + void Curl_http_auth_act(struct connectdata *conn) { struct SessionHandle *data = conn->data; if(data->state.authavail) { + /* The order of these checks is highly relevant, as this will be the order + of preference in case of the existance of multiple accepted types. */ if(data->state.authavail & CURLAUTH_GSSNEGOTIATE) data->state.authwant = CURLAUTH_GSSNEGOTIATE; else if(data->state.authavail & CURLAUTH_DIGEST) @@ -341,6 +349,15 @@ CURLcode Curl_http_auth(struct connectdata *conn, while(*start && isspace((int)*start)) start++; + /* + * Here we check if we want the specific single authentiction (using ==) and + * if we do, we initiate usage of it. + * + * If the provided authentication is wanted as one out of several accepted + * types (using &), we OR this authenticaion type to the authavail + * variable. + */ + #ifdef HAVE_GSSAPI if (checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { @@ -1013,14 +1030,15 @@ CURLcode Curl_http_done(struct connectdata *conn) void Curl_http_auth_stage(struct SessionHandle *data, int stage) { - if(stage == 401) - data->state.authwant = data->set.httpauth; - else if(stage == 407) - data->state.authwant = data->set.proxyauth; - else - return; /* bad input stage */ + curlassert((stage == 401) || (stage == 407)); + + /* We set none, one or more bits for which authentication types we accept + for this stage. */ + data->state.authwant = (stage == 401)? + data->set.httpauth:data->set.proxyauth; + data->state.authstage = stage; - data->state.authavail = CURLAUTH_NONE; + data->state.authavail = CURLAUTH_NONE; /* no type available yet */ } CURLcode Curl_http(struct connectdata *conn) -- cgit v1.2.1 From b791e158f0e04a518dea19fdaf0bfbf71b343c64 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Jan 2004 12:45:50 +0000 Subject: use curl_off_t instead of off_t! --- lib/http.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6002ad977..2d8e87b65 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1245,14 +1245,14 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->resume_from) { /* do we still game? */ - off_t passed=0; + curl_off_t passed=0; /* Now, let's read off the proper amount of bytes from the input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - off_t readthisamountnow = (conn->resume_from - passed); - off_t actuallyread; + curl_off_t readthisamountnow = (conn->resume_from - passed); + curl_off_t actuallyread; if(readthisamountnow > BUFSIZE) readthisamountnow = BUFSIZE; @@ -1299,7 +1299,8 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->resume_from) { /* This is because "resume" was selected */ - off_t total_expected_size= conn->resume_from + data->set.infilesize; + curl_off_t total_expected_size= + conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%Od/%Od\r\n", conn->range, total_expected_size-1, -- cgit v1.2.1 From dc932f739a340cdbf38653182a31a3e96c0b3482 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 Jan 2004 12:54:22 +0000 Subject: CONNECT response headers are now passed back as "regular" headers --- lib/http.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2d8e87b65..0dcaf7866 100644 --- a/lib/http.c +++ b/lib/http.c @@ -869,6 +869,21 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, perline++; /* amount of bytes in this line so far */ if(*ptr=='\n') { char letter; + int writetype; + + /* output debug output if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); + + /* send the header to the callback */ + writetype = CLIENTWRITE_HEADER; + if(data->set.http_include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(data, writetype, line_start, perline); + if(result) + return result; + /* Newlines are CRLF, so the CR is ignored as the line isn't really terminated until the LF comes. Treat a following CR as end-of-headers as well.*/ @@ -880,10 +895,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, break; /* breaks out of for-loop, not switch() */ } - /* output debug output if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); - /* keep a backup of the position we are about to blank */ letter = line_start[perline]; line_start[perline]=0; /* zero terminate the buffer */ -- cgit v1.2.1 From 958987c214cacdfaad6fa960b39e0c917f43af2d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 28 Jan 2004 17:07:22 +0000 Subject: Chunked-transfers should have an additional CRLF after the final 0 CRLF sequence. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0dcaf7866..c3862cded 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1614,8 +1614,8 @@ CURLcode Curl_http(struct connectdata *conn) /* Append the POST data chunky-style */ add_bufferf(req_buffer, "%x\r\n", postsize); add_buffer(req_buffer, data->set.postfields, postsize); - add_buffer(req_buffer, "\r\n0\r\n", 5); /* end of a chunked - transfer stream */ + add_buffer(req_buffer, "\r\n0\r\n\r\n", 7); /* end of a chunked + transfer stream */ } } else { -- cgit v1.2.1 From 4d17d6876e4b2f08380812c4ec113073b0a14639 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 29 Jan 2004 13:56:45 +0000 Subject: Dan Fandrich's cleanup patch to make pedantic compiler options cause less warnings. Minor edits by me. --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c3862cded..fea11f59a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -193,11 +193,11 @@ void Curl_http_auth_act(struct connectdata *conn) * authentication method. */ -CURLcode http_auth_headers(struct connectdata *conn, - char *request, - char *path, - bool *ready) /* set TRUE when the auth phase is - done and ready to do the *actual* +static CURLcode http_auth_headers(struct connectdata *conn, + char *request, + char *path, + bool *ready) /* set TRUE when the auth phase + is done and ready to do the *actual* request */ { CURLcode result = CURLE_OK; -- cgit v1.2.1 From b84eaff1d57754e9d154fa7fc7bf941c9e430a31 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Feb 2004 14:49:54 +0000 Subject: set the 'retry' bit to TRUE when the connection is about to be retried, this allows the HTTP code to *not* return a failure just because no data has been received from the server --- lib/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fea11f59a..3bab60df3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1028,9 +1028,11 @@ CURLcode Curl_http_done(struct connectdata *conn) else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; - if(0 == (http->readbytecount + conn->headerbytecount)) { - /* nothing was read from the HTTP server, this can't be right - so we return an error here */ + if(!conn->bits.retry && + !(http->readbytecount + conn->headerbytecount)) { + /* If this connection isn't simply closed to be retried, AND nothing was + read from the HTTP server, this can't be right so we return an error + here */ failf(data, "Empty reply from server"); return CURLE_GOT_NOTHING; } -- cgit v1.2.1 From cc90a235f4792febd308640c6463c8bdc3aec863 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 Feb 2004 15:50:16 +0000 Subject: if an empty 'transfer-encoding:' header is provided, we switch off the chunky coding of uploads --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3bab60df3..665906196 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1123,17 +1123,16 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.cookie = NULL; if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { - /* not a chunky transfer but data is to be sent */ + /* not a chunky transfer yet, but data is to be sent */ ptr = checkheaders(data, "Transfer-Encoding:"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ - if(Curl_compareheader(ptr, "Transfer-Encoding:", "chunked")) - /* we have been told explicitly to upload chunky so deal with it! */ - conn->bits.upload_chunky = TRUE; + conn->bits.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); + te = ""; } } - - if(conn->bits.upload_chunky) { + else if(conn->bits.upload_chunky) { /* RFC2616 section 4.4: Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding. If the message does include a non- @@ -1143,8 +1142,9 @@ CURLcode Curl_http(struct connectdata *conn) te = "Transfer-Encoding: chunked\r\n"; } else { - /* The "Transfer-Encoding:" header was already added. */ te = ""; + conn->bits.upload_chunky = FALSE; /* transfer-encoding was disabled, + so don't chunkify this! */ } } -- cgit v1.2.1 From f56d753507849e11ea7ede0eb03d6b7bbb158d32 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Feb 2004 08:11:58 +0000 Subject: A custom Host: header is only considered if the request is not made by following a location. After discussions with Tim Baker. --- lib/http.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 665906196..7e9713d38 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1149,9 +1149,11 @@ CURLcode Curl_http(struct connectdata *conn) } ptr = checkheaders(data, "Host:"); - if(ptr) { - /* If we have a given custom Host: header, we extract the host name - in order to possibly use it for cookie reasons later on. */ + if(ptr && !data->state.this_is_a_follow) { + /* If we have a given custom Host: header, we extract the host name in + order to possibly use it for cookie reasons later on. We only allow the + custom Host: header if this is NOT a redirect, as setting Host: in the + redirected request is being out on thin ice. */ char *start = ptr+strlen("Host:"); while(*start && isspace((int)*start )) start++; @@ -1171,13 +1173,7 @@ CURLcode Curl_http(struct connectdata *conn) } } else { - /* if ptr_host is already set, it is almost OK since we only re-use - connections to the very same host and port, but when we use a HTTP - proxy we have a persistant connect and yet we must change the Host: - header! */ - - if(conn->allocptr.host) - free(conn->allocptr.host); + Curl_safefree(conn->allocptr.host); /* When building Host: headers, we must put the host name within [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ -- cgit v1.2.1 From 93e32e6f62c432612ad193bb192c9127f87dd707 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Feb 2004 12:46:41 +0000 Subject: Modified the default HTTP Accept: header to only be Accept: */* --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7e9713d38..09e1fc4c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1230,7 +1230,7 @@ CURLcode Curl_http(struct connectdata *conn) http->p_pragma = "Pragma: no-cache\r\n"; if(!checkheaders(data, "Accept:")) - http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; + http->p_accept = "Accept: */*\r\n"; if(( (HTTPREQ_POST == data->set.httpreq) || (HTTPREQ_POST_FORM == data->set.httpreq) || -- cgit v1.2.1 From e1b5e15431c95cc24665753ed31543c2ce6a55ab Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 23 Feb 2004 08:22:43 +0000 Subject: More size_t cleanups in the base64 functions. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 09e1fc4c2..dade9601f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -127,7 +127,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn) sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) >= 0) { + &authorization) > 0) { if(conn->allocptr.userpwd) free(conn->allocptr.userpwd); conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", @@ -147,7 +147,7 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn) sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) >= 0) { + &authorization) > 0) { Curl_safefree(conn->allocptr.proxyuserpwd); conn->allocptr.proxyuserpwd = aprintf("Proxy-authorization: Basic %s\015\012", authorization); -- cgit v1.2.1 From d571064b65195aa7c71200af549a95404a2f0ce1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 26 Feb 2004 13:40:43 +0000 Subject: Clear up int/long/size_t/ssize_t usage a bit --- lib/http.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dade9601f..348e0853e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -440,14 +440,14 @@ CURLcode Curl_http_auth(struct connectdata *conn, /* fread() emulation to provide POST and/or request data */ -static int readmoredata(char *buffer, - size_t size, - size_t nitems, - void *userp) +static size_t readmoredata(char *buffer, + size_t size, + size_t nitems, + void *userp) { struct connectdata *conn = (struct connectdata *)userp; struct HTTP *http = conn->proto.http; - int fullsize = size * nitems; + size_t fullsize = size * nitems; if(0 == http->postsize) /* nothing to return */ @@ -528,9 +528,9 @@ CURLcode add_buffer_send(send_buffer *in, ssize_t amount; CURLcode res; char *ptr; - int size; + size_t size; struct HTTP *http = conn->proto.http; - int sendsize; + size_t sendsize; int sockfd = conn->sock[FIRSTSOCKET]; /* The looping below is required since we use non-blocking sockets, but due @@ -570,7 +570,7 @@ CURLcode add_buffer_send(send_buffer *in, *bytes_written += amount; - if(amount != size) { + if((size_t)amount != size) { /* The whole request could not be sent in one system call. We must queue it up and send it later when we get the chance. We must not loop here and wait until it might work again. */ @@ -639,7 +639,7 @@ static CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) { char *new_rb; - int new_size; + size_t new_size; if(!in->buffer || ((in->size_used + size) > (in->size_max - 1))) { @@ -744,7 +744,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, bool keepon=TRUE; ssize_t gotbytes; char *ptr; - int timeout = 3600; /* default timeout in seconds */ + long timeout = 3600; /* default timeout in seconds */ struct timeval interval; fd_set rkeepfd; fd_set readfd; @@ -1164,7 +1164,7 @@ CURLcode Curl_http(struct connectdata *conn) ptr++; if(ptr != start) { - int len=ptr-start; + size_t len=ptr-start; conn->allocptr.cookiehost = malloc(len+1); if(!conn->allocptr.cookiehost) return CURLE_OUT_OF_MEMORY; @@ -1260,8 +1260,8 @@ CURLcode Curl_http(struct connectdata *conn) input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - curl_off_t readthisamountnow = (conn->resume_from - passed); - curl_off_t actuallyread; + size_t readthisamountnow = (conn->resume_from - passed); + size_t actuallyread; if(readthisamountnow > BUFSIZE) readthisamountnow = BUFSIZE; @@ -1509,12 +1509,12 @@ CURLcode Curl_http(struct connectdata *conn) work, but we support it anyway. */ char contentType[256]; - int linelength=0; - linelength = Curl_FormReadOneLine (contentType, - sizeof(contentType), - 1, - (FILE *)&http->form); - if(linelength == -1) { + size_t linelength=0; + linelength = Curl_FormReadOneLine(contentType, + sizeof(contentType), + 1, + (FILE *)&http->form); + if(!linelength) { failf(data, "Could not get Content-Type header line!"); return CURLE_HTTP_POST_ERROR; } -- cgit v1.2.1 From cb72a80fe06d96c46e69a869cceb16b491fcb23b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 1 Mar 2004 16:28:00 +0000 Subject: Use CURL_FORMAT_OFF_T for printf()inf curl_off_t variables. --- lib/http.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 348e0853e..26e2ec0ac 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1272,7 +1272,8 @@ CURLcode Curl_http(struct connectdata *conn) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read %Od bytes from the input", + failf(data, "Could only read " CURL_FORMAT_OFF_T + " bytes from the input", passed); return CURLE_READ_ERROR; } @@ -1311,7 +1312,8 @@ CURLcode Curl_http(struct connectdata *conn) curl_off_t total_expected_size= conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%Od/%Od\r\n", + aprintf("Content-Range: bytes %s" CURL_FORMAT_OFF_T "/" + CURL_FORMAT_OFF_T "\r\n", conn->range, total_expected_size-1, total_expected_size); } @@ -1319,7 +1321,7 @@ CURLcode Curl_http(struct connectdata *conn) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%Od\r\n", + aprintf("Content-Range: bytes %s/" CURL_FORMAT_OFF_T "\r\n", conn->range, data->set.infilesize); } } @@ -1549,7 +1551,7 @@ CURLcode Curl_http(struct connectdata *conn) if((data->set.infilesize>0) && !conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: %Od\r\n", /* file size */ + "Content-Length: " CURL_FORMAT_OFF_T "\r\n", /* size */ data->set.infilesize ); add_bufferf(req_buffer, "\r\n"); -- cgit v1.2.1 From 7ab3b5b3bb4c02dc00621efe13b8d3b29b819250 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Mar 2004 07:25:39 +0000 Subject: use FORMAT_OFF_T instead of CURL_FORMAT_OFF_T to reduce the complexity of having to redef that name --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 26e2ec0ac..c7e54ed89 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1272,7 +1272,7 @@ CURLcode Curl_http(struct connectdata *conn) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read " CURL_FORMAT_OFF_T + failf(data, "Could only read " FORMAT_OFF_T " bytes from the input", passed); return CURLE_READ_ERROR; @@ -1312,8 +1312,8 @@ CURLcode Curl_http(struct connectdata *conn) curl_off_t total_expected_size= conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s" CURL_FORMAT_OFF_T "/" - CURL_FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s" FORMAT_OFF_T "/" + FORMAT_OFF_T "\r\n", conn->range, total_expected_size-1, total_expected_size); } @@ -1321,7 +1321,7 @@ CURLcode Curl_http(struct connectdata *conn) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/" CURL_FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s/" FORMAT_OFF_T "\r\n", conn->range, data->set.infilesize); } } @@ -1551,7 +1551,7 @@ CURLcode Curl_http(struct connectdata *conn) if((data->set.infilesize>0) && !conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: " CURL_FORMAT_OFF_T "\r\n", /* size */ + "Content-Length: " FORMAT_OFF_T "\r\n", /* size */ data->set.infilesize ); add_bufferf(req_buffer, "\r\n"); -- cgit v1.2.1 From 353f7641193ddf3f6a42d49d53ea994e4ea4388b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Mar 2004 09:31:18 +0000 Subject: Yet another curl_off_t printf format attempt, we now exclude the %-letter from FORMAT_OFF_T to allow additional options to get specified, like with '"%5" FORMAT_OFF_T'. --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c7e54ed89..dcb5674bc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1272,7 +1272,7 @@ CURLcode Curl_http(struct connectdata *conn) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read " FORMAT_OFF_T + failf(data, "Could only read %" FORMAT_OFF_T " bytes from the input", passed); return CURLE_READ_ERROR; @@ -1312,8 +1312,8 @@ CURLcode Curl_http(struct connectdata *conn) curl_off_t total_expected_size= conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s" FORMAT_OFF_T "/" - FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s%" FORMAT_OFF_T + "/%" FORMAT_OFF_T "\r\n", conn->range, total_expected_size-1, total_expected_size); } @@ -1321,7 +1321,7 @@ CURLcode Curl_http(struct connectdata *conn) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/" FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", conn->range, data->set.infilesize); } } @@ -1551,7 +1551,7 @@ CURLcode Curl_http(struct connectdata *conn) if((data->set.infilesize>0) && !conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: " FORMAT_OFF_T "\r\n", /* size */ + "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ data->set.infilesize ); add_bufferf(req_buffer, "\r\n"); -- cgit v1.2.1 From 498666bdc3673e97a0a1bea97ecb358af05d1c2e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Mar 2004 12:54:18 +0000 Subject: issue 12 fix --- lib/http.c | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dcb5674bc..5be8a9e6f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1067,7 +1067,6 @@ CURLcode Curl_http(struct connectdata *conn) char *ptr; char *request; bool authdone=TRUE; /* if the authentication phase is done */ - Curl_HttpReq httpreq; /* type of HTTP request */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1467,13 +1466,11 @@ CURLcode Curl_http(struct connectdata *conn) http->postdata = NULL; /* nothing to post at this point */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - if(!authdone) - /* until the auth is done, pretend we only do GET */ - httpreq = HTTPREQ_GET; - else - httpreq = data->set.httpreq; + /* If 'authdone' is still FALSE, we must not set the write socket index to + the Curl_transfer() call below, as we're not ready to actually upload + any data yet. */ - switch(httpreq) { + switch(data->set.httpreq) { case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { @@ -1538,8 +1535,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + authdone?FIRSTSOCKET:-1, + authdone?&http->writebytecount:NULL); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -1554,7 +1551,16 @@ CURLcode Curl_http(struct connectdata *conn) "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ data->set.infilesize ); - add_bufferf(req_buffer, "\r\n"); + if(!checkheaders(data, "Expect:")) { + /* if not disabled explicitly we add a Expect: 100-continue + to the headers which actually speeds up post operations (as + there is one packet coming back from the web server) */ + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + data->set.expect100header = TRUE; + } + + add_buffer(req_buffer, "\r\n", 2); /* end of headers */ /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); @@ -1568,8 +1574,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + authdone?FIRSTSOCKET:-1, + authdone?&http->writebytecount:NULL); if(result) return result; break; @@ -1597,15 +1603,19 @@ CURLcode Curl_http(struct connectdata *conn) add_bufferf(req_buffer, "Content-Type: application/x-www-form-urlencoded\r\n"); - add_buffer(req_buffer, "\r\n", 2); - if(data->set.postfields) { - if(postsize < (100*1024)) { + if(authdone && (postsize < (100*1024))) { + /* If we're not done with the authentication phase, we don't expect + to actually send off any data yet. Hence, we delay the sending of + the body until we receive that friendly 100-continue response */ + /* The post data is less than 100K, then append it to the header. This limit is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(!conn->bits.upload_chunky) /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ @@ -1630,9 +1640,22 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); + + if(!authdone && !checkheaders(data, "Expect:")) { + /* if not disabled explicitly we add a Expect: 100-continue to the + headers which actually speeds up post operations (as there is + one packet coming back from the web server) */ + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + data->set.expect100header = TRUE; + } + + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ } } else { + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); -- cgit v1.2.1 From 7b2869338d344a89e69d6a41bae185cbf4804181 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Mar 2004 21:39:50 +0000 Subject: explicit typecast to visualize that we really want the result of the operation as a size_t --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5be8a9e6f..66e38bf94 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1259,7 +1259,7 @@ CURLcode Curl_http(struct connectdata *conn) input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - size_t readthisamountnow = (conn->resume_from - passed); + size_t readthisamountnow = (size_t)(conn->resume_from - passed); size_t actuallyread; if(readthisamountnow > BUFSIZE) -- cgit v1.2.1 From ce5805a955c5a79d85792caad47594987f0e0b26 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Mar 2004 22:52:50 +0000 Subject: Use curl_socket_t instead of int for holding sockets. The typedefs and defines are in setup.h. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 66e38bf94..0de90c7c5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -531,7 +531,7 @@ CURLcode add_buffer_send(send_buffer *in, size_t size; struct HTTP *http = conn->proto.http; size_t sendsize; - int sockfd = conn->sock[FIRSTSOCKET]; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ -- cgit v1.2.1 From cf004cbc7efd983111d976693fe1f18361cfa8e6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Mar 2004 09:44:42 +0000 Subject: keep the number of bytes read in a size_t variable --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0de90c7c5..a4fa44f95 100644 --- a/lib/http.c +++ b/lib/http.c @@ -739,7 +739,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, CURLcode result; int res; - int nread; /* total size read */ + size_t nread; /* total size read */ int perline; /* count bytes per line */ bool keepon=TRUE; ssize_t gotbytes; -- cgit v1.2.1 From 7225b1400236c786add1516e38676d65a7bbd327 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Mar 2004 16:01:47 +0000 Subject: curl_socket_t mistakes cleanup --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a4fa44f95..37976ac78 100644 --- a/lib/http.c +++ b/lib/http.c @@ -750,7 +750,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, fd_set readfd; char *line_start; char *host_port; - int tunnelsocket = conn->sock[sockindex]; + curl_socket_t tunnelsocket = conn->sock[sockindex]; #define SELECT_OK 0 #define SELECT_ERROR 1 -- cgit v1.2.1 From 0d1fc73f2119e1f75f58b32cdc9f9d45fa71ac9c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Mar 2004 16:20:33 +0000 Subject: Use more curl_off_t variables when doing the progress meter calculations and argument passing and try to convert to double only when providing data to the external world. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 37976ac78..9377d1ea1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1563,7 +1563,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* end of headers */ /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->set.infilesize); /* this sends the buffer and frees all the buffer resources */ result = add_buffer_send(req_buffer, conn, @@ -1657,7 +1657,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->set.infilesize); /* set the pointer to mark that we will send the post body using the read callback */ -- cgit v1.2.1 From ef776ab8937a1711e98fc3a56396fd8b75d9bb51 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Mar 2004 12:07:01 +0000 Subject: Made the 'postsize' variable an off_t type to be able to hold large file sizes if desired --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9377d1ea1..ca9978042 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1333,7 +1333,7 @@ CURLcode Curl_http(struct connectdata *conn) send_buffer *req_buffer; struct curl_slist *headers=data->set.headers; - size_t postsize; + curl_off_t postsize; /* off_t type to be able to hold a large file size */ /* initialize a dynamic send-buffer */ req_buffer = add_buffer_init(); @@ -1596,7 +1596,8 @@ CURLcode Curl_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 */ - add_bufferf(req_buffer, "Content-Length: %d\r\n", postsize); + add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T"\r\n", + postsize); } if(!checkheaders(data, "Content-Type:")) -- cgit v1.2.1 From 4ad68ec305fa3ecf1bffacc24b67b7d24d187f51 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Mar 2004 13:06:01 +0000 Subject: more variable type fixes for the large POST support --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ca9978042..a81a7bbf6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1620,11 +1620,11 @@ CURLcode Curl_http(struct connectdata *conn) if(!conn->bits.upload_chunky) /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ - add_buffer(req_buffer, data->set.postfields, postsize); + add_buffer(req_buffer, data->set.postfields, (size_t)postsize); else { /* Append the POST data chunky-style */ add_bufferf(req_buffer, "%x\r\n", postsize); - add_buffer(req_buffer, data->set.postfields, postsize); + add_buffer(req_buffer, data->set.postfields, (size_t)postsize); add_buffer(req_buffer, "\r\n0\r\n\r\n", 7); /* end of a chunked transfer stream */ } -- cgit v1.2.1 From 94a1d09ac7500afdd6f3cef3fbfefa16072f2704 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Mar 2004 14:22:16 +0000 Subject: more variable type fixing for the huge posts --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a81a7bbf6..19473d3f1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -457,8 +457,8 @@ static size_t readmoredata(char *buffer, conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; if(http->postsize <= fullsize) { - memcpy(buffer, http->postdata, http->postsize); - fullsize = http->postsize; + memcpy(buffer, http->postdata, (size_t)http->postsize); + fullsize = (size_t)http->postsize; if(http->backup.postsize) { /* move backup data into focus and continue on that */ -- cgit v1.2.1 From 24cfa7f1bb147f706680f7eddca9805a3b1de015 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 13 Mar 2004 17:03:17 +0000 Subject: the postsize is an off_t so use the proper printf format to output the content-length when doing multipart posts --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 19473d3f1..3aa5af34a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1487,7 +1487,7 @@ CURLcode Curl_http(struct connectdata *conn) if(!conn->bits.upload_chunky) /* only add Content-Length if not uploading chunked */ add_bufferf(req_buffer, - "Content-Length: %d\r\n", http->postsize); + "Content-Length: %" FORMAT_OFF_T "\r\n", http->postsize); if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue -- cgit v1.2.1 From d04ffd258b9f48b2d65bbe6ad3daa89cb0b0aca5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 13 Mar 2004 17:11:42 +0000 Subject: postsize is off_t now, so we typecase it to int before doing normal printf with it (knowing it won't be larger than what fits in an int) --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3aa5af34a..812bbc787 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1623,7 +1623,7 @@ CURLcode Curl_http(struct connectdata *conn) add_buffer(req_buffer, data->set.postfields, (size_t)postsize); else { /* Append the POST data chunky-style */ - add_bufferf(req_buffer, "%x\r\n", postsize); + add_bufferf(req_buffer, "%x\r\n", (int)postsize); add_buffer(req_buffer, data->set.postfields, (size_t)postsize); add_buffer(req_buffer, "\r\n0\r\n\r\n", 7); /* end of a chunked transfer stream */ -- cgit v1.2.1 From f788f988ea728f7a474a22f94d50ba2a891940cd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 14 Mar 2004 18:15:04 +0000 Subject: fix signed and unsigned warnings --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 812bbc787..ccbbf4962 100644 --- a/lib/http.c +++ b/lib/http.c @@ -456,7 +456,7 @@ static size_t readmoredata(char *buffer, /* make sure that a HTTP request is never sent away chunked! */ conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; - if(http->postsize <= fullsize) { + if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); fullsize = (size_t)http->postsize; @@ -1586,7 +1586,7 @@ CURLcode Curl_http(struct connectdata *conn) /* store the size of the postfields */ postsize = data->set.postfieldsize? data->set.postfieldsize: - (data->set.postfields?strlen(data->set.postfields):0); + (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if -- cgit v1.2.1 From 8e92600ddd6ed324fc1f8410e859cca3182018f7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 30 Mar 2004 06:40:01 +0000 Subject: David Byron made CURLOPT_FAILONERROR work with authentications such as NTLM or Digest. --- lib/http.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 101 insertions(+), 28 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ccbbf4962..7358f7aeb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -188,23 +188,23 @@ void Curl_http_auth_act(struct connectdata *conn) } } -/* +/** * Setup the authentication headers for the host/proxy and the correct - * authentication method. + * authentication method. @p conn->data->state.authdone set to TRUE + * when authentication is done. + * + * @param conn all information about the current connection */ - static CURLcode http_auth_headers(struct connectdata *conn, char *request, - char *path, - bool *ready) /* set TRUE when the auth phase - is done and ready to do the *actual* - request */ + char *path) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; char *auth=NULL; - *ready = FALSE; /* default is no */ + curlassert(data); + data->state.authdone = FALSE; /* default is no */ if(!data->state.authstage) { if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) @@ -212,7 +212,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, else if(conn->bits.user_passwd) Curl_http_auth_stage(data, 401); else { - *ready = TRUE; + data->state.authdone = TRUE; return CURLE_OK; /* no authentication with no user or password */ } } @@ -229,7 +229,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; - result = Curl_output_ntlm(conn, TRUE, ready); + result = Curl_output_ntlm(conn, TRUE); if(result) return result; } @@ -244,7 +244,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, if(result) return result; } - *ready = TRUE; + data->state.authdone = TRUE; /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); } @@ -262,14 +262,14 @@ static CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_negotiate(conn); if (result) return result; - *ready = TRUE; + data->state.authdone = TRUE; } else #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; - result = Curl_output_ntlm(conn, FALSE, ready); + result = Curl_output_ntlm(conn, FALSE); if(result) return result; } @@ -284,7 +284,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, (unsigned char *)path); if(result) return result; - *ready = TRUE; + data->state.authdone = TRUE; } else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ if(conn->bits.user_passwd && @@ -295,7 +295,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, return result; } /* basic is always ready */ - *ready = TRUE; + data->state.authdone = TRUE; } } if(auth) @@ -304,7 +304,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, } } else - *ready = TRUE; + data->state.authdone = TRUE; return result; } @@ -438,6 +438,83 @@ CURLcode Curl_http_auth(struct connectdata *conn, return CURLE_OK; } +/** + * determine whether an http response has gotten us into an + * error state or not. + * + * @param conn all information about the current connection + * + * @retval 0 communications should continue + * + * @retval 1 communications should not continue + */ +int Curl_http_should_fail(struct connectdata *conn) +{ + struct SessionHandle *data; + struct Curl_transfer_keeper *k; + + curlassert(conn); + data = conn->data; + curlassert(data); + + /* + ** For readability + */ + k = &conn->keep; + + /* + ** If we haven't been asked to fail on error, + ** don't fail. + */ + if (!data->set.http_fail_on_error) + return 0; + + /* + ** Any code < 400 is never terminal. + */ + if (k->httpcode < 400) + return 0; + + /* + ** Any code >= 400 that's not 401 or 407 is always + ** a terminal error + */ + if ((k->httpcode != 401) && + (k->httpcode != 407)) + return 1; + + /* + ** All we have left to deal with is 401 and 407 + */ + curlassert((k->httpcode == 401) || (k->httpcode == 407)); + + /* + ** Examine the current authentication state to see if this + ** is an error. The idea is for this function to get + ** called after processing all the headers in a response + ** message. So, if we've been to asked to authenticate a + ** particular stage, and we've done it, we're OK. But, if + ** we're already completely authenticated, it's not OK to + ** get another 401 or 407. + ** + ** It is possible for authentication to go stale such that + ** the client needs to reauthenticate. Once that info is + ** available, use it here. + */ + infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); + infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); + infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); + + if (data->state.authstage && + (data->state.authstage == k->httpcode)) + return data->state.authdone; + + /* + ** Either we're not authenticating, or we're supposed to + ** be authenticating something else. This is an error. + */ + return 1; +} /* fread() emulation to provide POST and/or request data */ static size_t readmoredata(char *buffer, @@ -760,9 +837,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); do { - bool auth; /* we don't really have to know when the auth phase is done, - but this variable will be set to true then */ - if(conn->newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() @@ -776,7 +850,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ - result = http_auth_headers(conn, (char *)"CONNECT", host_port, &auth); + result = http_auth_headers(conn, (char *)"CONNECT", host_port); if(CURLE_OK == result) { /* OK, now send the connect request to the proxy */ @@ -1066,7 +1140,6 @@ CURLcode Curl_http(struct connectdata *conn) const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; - bool authdone=TRUE; /* if the authentication phase is done */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1105,7 +1178,7 @@ CURLcode Curl_http(struct connectdata *conn) } /* setup the authentication headers */ - result = http_auth_headers(conn, request, ppath, &authdone); + result = http_auth_headers(conn, request, ppath); if(result) return result; @@ -1535,8 +1608,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - authdone?FIRSTSOCKET:-1, - authdone?&http->writebytecount:NULL); + data->state.authdone?FIRSTSOCKET:-1, + data->state.authdone?&http->writebytecount:NULL); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -1574,8 +1647,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - authdone?FIRSTSOCKET:-1, - authdone?&http->writebytecount:NULL); + data->state.authdone?FIRSTSOCKET:-1, + data->state.authdone?&http->writebytecount:NULL); if(result) return result; break; @@ -1606,7 +1679,7 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.postfields) { - if(authdone && (postsize < (100*1024))) { + if(data->state.authdone && (postsize < (100*1024))) { /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ @@ -1642,7 +1715,7 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - if(!authdone && !checkheaders(data, "Expect:")) { + if(!data->state.authdone && !checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ -- cgit v1.2.1 From 76f23acfa1cbe8e8133634710ec76efd8230cf62 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 30 Mar 2004 08:21:09 +0000 Subject: if 0'ed out a code section that uses __FUNCTION__ etc, used for debugging the new "fail with auth" code --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7358f7aeb..a7961cba5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -501,9 +501,11 @@ int Curl_http_should_fail(struct connectdata *conn) ** the client needs to reauthenticate. Once that info is ** available, use it here. */ +#if 0 /* set to 1 when debugging this functionality */ infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); +#endif if (data->state.authstage && (data->state.authstage == k->httpcode)) -- cgit v1.2.1 From 7ea837a18c7d22c790daf2733eaffcc5450b1bd9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 30 Mar 2004 13:02:31 +0000 Subject: adjusted to the new dns cache function to hide more hostip internals --- lib/http.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a7961cba5..41b1ef7c4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -398,17 +398,14 @@ CURLcode Curl_http_auth(struct connectdata *conn, *availp |= CURLAUTH_DIGEST; if(data->state.authwant == CURLAUTH_DIGEST) { /* Digest authentication is activated */ - CURLdigest dig = CURLDIGEST_BAD; - - if(data->state.digest.nonce) - infof(data, "Authentication problem. Ignoring this.\n"); - else - dig = Curl_input_digest(conn, start); + CURLdigest dig = Curl_input_digest(conn, start); if(CURLDIGEST_FINE == dig) /* We act on it. Store our new url, which happens to be the same one we already use! */ conn->newurl = strdup(data->change.url); /* clone string */ + else + infof(data, "Authentication problem. Ignoring this.\n"); } else if(data->state.authwant & CURLAUTH_DIGEST) { -- cgit v1.2.1 From 8ed44e8dfbe2182696becc3ca8a9950888251503 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 6 Apr 2004 15:14:10 +0000 Subject: New authentication code added, particularly noticable when doing POST or PUT with Digest or NTLM. libcurl will now use HEAD to negotiate the authentication and when done perform the requested POST. --- lib/http.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 24 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 41b1ef7c4..3c2eceff3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -186,6 +186,17 @@ void Curl_http_auth_act(struct connectdata *conn) conn->newurl = strdup(data->change.url); /* clone URL */ data->state.authavail = CURLAUTH_NONE; /* clear it here */ } + else if(!data->state.authdone && (data->info.httpcode < 400)) { + /* no (known) authentication available, + authentication is not "done" yet and + no authentication seems to be required and + we didn't try HEAD or GET */ + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + conn->newurl = strdup(data->change.url); /* clone URL */ + data->state.authdone = TRUE; + } + } } /** @@ -204,13 +215,16 @@ static CURLcode http_auth_headers(struct connectdata *conn, char *auth=NULL; curlassert(data); - data->state.authdone = FALSE; /* default is no */ if(!data->state.authstage) { - if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) + if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) { + data->state.authdone = FALSE; Curl_http_auth_stage(data, 407); - else if(conn->bits.user_passwd) + } + else if(conn->bits.user_passwd) { + data->state.authdone = FALSE; Curl_http_auth_stage(data, 401); + } else { data->state.authdone = TRUE; return CURLE_OK; /* no authentication with no user or password */ @@ -1139,6 +1153,7 @@ CURLcode Curl_http(struct connectdata *conn) const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; + Curl_HttpReq httpreq = data->set.httpreq; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1157,19 +1172,40 @@ CURLcode Curl_http(struct connectdata *conn) if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->set.upload) { - data->set.httpreq = HTTPREQ_PUT; + httpreq = HTTPREQ_PUT; } - request = data->set.customrequest? - data->set.customrequest: - (data->set.no_body?(char *)"HEAD": - ((HTTPREQ_POST == data->set.httpreq) || - (HTTPREQ_POST_FORM == data->set.httpreq))?(char *)"POST": - (HTTPREQ_PUT == data->set.httpreq)?(char *)"PUT":(char *)"GET"); + /* Now set the 'request' pointer to the proper request string */ + if(data->set.customrequest) + request = data->set.customrequest; + else { + if(conn->bits.no_body) + request = (char *)"HEAD"; + else { + curlassert((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + switch(httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + request = (char *)"POST"; + break; + case HTTPREQ_PUT: + request = (char *)"PUT"; + break; + case HTTPREQ_GET: + request = (char *)"GET"; + break; + case HTTPREQ_HEAD: + request = (char *)"HEAD"; + break; + default: /* this should never happen */ + break; + } + } + } - /* The User-Agent string has been built in url.c already, because it might - have been used in the proxy connect, but if we have got a header with - the user-agent string specified, we erase the previously made string + /* The User-Agent string might have been allocated in url.c already, because + it might have been used in the proxy connect, but if we have got a header + with the user-agent string specified, we erase the previously made string here. */ if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { free(conn->allocptr.uagent); @@ -1181,6 +1217,16 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; + if(!data->state.authdone && (httpreq != HTTPREQ_GET)) { + /* Until we are authenticated, we switch over to HEAD. Unless its a GET + we want to do. The explanation for this is rather long and boring, but + the point is that it can't be done otherwise without risking having to + send the POST or PUT data multiple times. */ + httpreq = HTTPREQ_HEAD; + request = (char *)"HEAD"; + conn->bits.no_body = TRUE; + } + Curl_safefree(conn->allocptr.ref); if(data->change.referer && !checkheaders(data, "Referer:")) conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer); @@ -1193,7 +1239,7 @@ CURLcode Curl_http(struct connectdata *conn) else conn->allocptr.cookie = NULL; - if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) { + if(!conn->bits.upload_chunky && (httpreq != HTTPREQ_GET)) { /* not a chunky transfer yet, but data is to be sent */ ptr = checkheaders(data, "Transfer-Encoding:"); if(ptr) { @@ -1284,7 +1330,7 @@ CURLcode Curl_http(struct connectdata *conn) /* The path sent to the proxy is in fact the entire URL */ ppath = data->change.url; } - if(HTTPREQ_POST_FORM == data->set.httpreq) { + if(HTTPREQ_POST_FORM == httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ result = Curl_getFormData(&http->sendit, data->set.httppost, @@ -1303,9 +1349,9 @@ CURLcode Curl_http(struct connectdata *conn) if(!checkheaders(data, "Accept:")) http->p_accept = "Accept: */*\r\n"; - if(( (HTTPREQ_POST == data->set.httpreq) || - (HTTPREQ_POST_FORM == data->set.httpreq) || - (HTTPREQ_PUT == data->set.httpreq) ) && + if(( (HTTPREQ_POST == httpreq) || + (HTTPREQ_POST_FORM == httpreq) || + (HTTPREQ_PUT == httpreq) ) && conn->resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have @@ -1368,14 +1414,14 @@ CURLcode Curl_http(struct connectdata *conn) * or uploading and we always let customized headers override our internal * ones if any such are specified. */ - if((data->set.httpreq == HTTPREQ_GET) && + if((httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); } - else if((data->set.httpreq != HTTPREQ_GET) && + else if((httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { if(conn->resume_from) { @@ -1538,11 +1584,11 @@ CURLcode Curl_http(struct connectdata *conn) http->postdata = NULL; /* nothing to post at this point */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - /* If 'authdone' is still FALSE, we must not set the write socket index to - the Curl_transfer() call below, as we're not ready to actually upload - any data yet. */ + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ - switch(data->set.httpreq) { + switch(httpreq) { case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { -- cgit v1.2.1 From 72b1144b8c1844ec81d5f5b73eb9b2a088377fec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Apr 2004 14:27:54 +0000 Subject: getting only a 100 Continue response and nothing else, when talking HTTP, is now treated as an error by libcurl --- lib/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3c2eceff3..32666d82b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1116,10 +1116,12 @@ CURLcode Curl_http_done(struct connectdata *conn) conn->bytecount = http->readbytecount + http->writebytecount; if(!conn->bits.retry && - !(http->readbytecount + conn->headerbytecount)) { + ((http->readbytecount + + conn->headerbytecount - + conn->deductheadercount)) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was - read from the HTTP server, this can't be right so we return an error - here */ + read from the HTTP server (that counts), this can't be right so we + return an error here */ failf(data, "Empty reply from server"); return CURLE_GOT_NOTHING; } -- cgit v1.2.1 From ee7d1d0701e8d7b87b5913c96f713b743196a2b0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 13 Apr 2004 07:37:28 +0000 Subject: remove an long time #defined struct member and use the actual "real" name instead to make it easier to find/read --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 32666d82b..3a1f89025 100644 --- a/lib/http.c +++ b/lib/http.c @@ -964,7 +964,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* send the header to the callback */ writetype = CLIENTWRITE_HEADER; - if(data->set.http_include_header) + if(data->set.include_header) writetype |= CLIENTWRITE_BODY; result = Curl_client_write(data, writetype, line_start, perline); -- cgit v1.2.1 From b7a760046545fa9afc3feca68d12dc087fbe625c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Apr 2004 07:53:24 +0000 Subject: Cleaned up hostname/name/gname and path/ppath confusion. Removed the fixed- length limit of the hostname part of the URL. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3a1f89025..66b5ce228 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1150,8 +1150,8 @@ CURLcode Curl_http(struct connectdata *conn) CURLcode result=CURLE_OK; struct HTTP *http; struct Cookie *co=NULL; /* no cookies from start */ - char *ppath = conn->ppath; /* three previous function arguments */ - char *host = conn->name; + char *ppath = conn->path; + char *host = conn->hostname; const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; -- cgit v1.2.1 From 33cb93ad0bf93879b5aaff76bef2c9a69b8ab985 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Apr 2004 12:35:45 +0000 Subject: Added comments --- lib/http.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 66b5ce228..b2f919f67 100644 --- a/lib/http.c +++ b/lib/http.c @@ -105,8 +105,10 @@ static CURLcode Curl_output_basic_proxy(struct connectdata *conn); /* - * This function checks the linked list of custom HTTP headers for a particular - * header (prefix). + * checkheaders() checks the linked list of custom HTTP headers for a + * particular header (prefix). + * + * Returns a pointer to the first matching header or NULL if none matched. */ static char *checkheaders(struct SessionHandle *data, const char *thisheader) { @@ -120,6 +122,12 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) return NULL; } +/* + * Curl_output_basic() sets up an Authorization: header for HTTP Basic + * authentication. It uses the conn->user, conn->passwd fields for it. + * + * Returns CURLcode. + */ static CURLcode Curl_output_basic(struct connectdata *conn) { char *authorization; @@ -139,6 +147,13 @@ static CURLcode Curl_output_basic(struct connectdata *conn) return CURLE_OK; } +/* + * Curl_output_basic_proxy() sets up a proxy-Authorization: header for HTTP + * Basic proxy authentication. It uses the conn->proxyuser and + * conn->proxypasswd fields for it. + * + * Returns CURLcode. + */ static CURLcode Curl_output_basic_proxy(struct connectdata *conn) { char *authorization; @@ -200,11 +215,13 @@ void Curl_http_auth_act(struct connectdata *conn) } /** - * Setup the authentication headers for the host/proxy and the correct - * authentication method. @p conn->data->state.authdone set to TRUE - * when authentication is done. + * http_auth_headers() setups the authentication headers for the host/proxy + * and the correct authentication method. conn->data->state.authdone is set to + * TRUE when authentication is done. * * @param conn all information about the current connection + * + * Returns CURLcode */ static CURLcode http_auth_headers(struct connectdata *conn, char *request, @@ -450,8 +467,8 @@ CURLcode Curl_http_auth(struct connectdata *conn, } /** - * determine whether an http response has gotten us into an - * error state or not. + * Curl_http_should_fail() determines whether an HTTP response has gotten us + * into an error state or not. * * @param conn all information about the current connection * @@ -529,7 +546,14 @@ int Curl_http_should_fail(struct connectdata *conn) return 1; } -/* fread() emulation to provide POST and/or request data */ +/* + * readmoredata() is a "fread() emulation" to provide POST and/or request + * data. It is used when a huge POST is to be made and the entire chunk wasn't + * sent in the first send(). This function will then be called from the + * transfer.c loop when more data is to be sent to the peer. + * + * Returns the amount of bytes it filled the buffer with. + */ static size_t readmoredata(char *buffer, size_t size, size_t nitems, @@ -592,7 +616,7 @@ static CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size); /* - * add_buffer_init() returns a fine buffer struct + * add_buffer_init() sets up and returns a fine buffer struct */ static send_buffer *add_buffer_init(void) @@ -608,6 +632,8 @@ send_buffer *add_buffer_init(void) /* * add_buffer_send() sends a buffer and frees all associated memory. + * + * Returns CURLcode */ static CURLcode add_buffer_send(send_buffer *in, @@ -698,7 +724,7 @@ CURLcode add_buffer_send(send_buffer *in, /* - * add_bufferf() builds a buffer from the formatted input + * add_bufferf() add the formatted input to the buffer. */ static CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) @@ -723,7 +749,7 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) } /* - * add_buffer() appends a memory chunk to the existing one + * add_buffer() appends a memory chunk to the existing buffer */ static CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) @@ -1038,7 +1064,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } /* - * HTTP stuff to do at connect-time. + * Curl_http_connect() performs HTTP stuff to do at connect-time, called from + * the generic Curl_connect(). */ CURLcode Curl_http_connect(struct connectdata *conn) { @@ -1084,6 +1111,11 @@ CURLcode Curl_http_connect(struct connectdata *conn) return CURLE_OK; } +/* + * Curl_http_done() gets called from Curl_done() after a single HTTP request + * has been performed. + */ + CURLcode Curl_http_done(struct connectdata *conn) { struct SessionHandle *data; @@ -1129,6 +1161,10 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } +/* + * Curl_http_auth_stage() sets the "authentication stage" - which is 407 for + * proxy authentication or 401 for host authentication. + */ void Curl_http_auth_stage(struct SessionHandle *data, int stage) { @@ -1143,6 +1179,11 @@ void Curl_http_auth_stage(struct SessionHandle *data, data->state.authavail = CURLAUTH_NONE; /* no type available yet */ } +/* + * Curl_http() gets called from the generic Curl_do() function when a HTTP + * request is to be performed. This creates and sends a propperly constructed + * HTTP request. + */ CURLcode Curl_http(struct connectdata *conn) { struct SessionHandle *data=conn->data; -- cgit v1.2.1 From 2ff30d067c19aea79cd82e0a45e313cf3bb07285 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Apr 2004 20:07:41 +0000 Subject: - David Byron found and fixed a small bug with the --fail and authentication stuff added a few weeks ago. Turns out that if you specify --proxy-ntlm and communicate with a proxy that requires basic authentication, the proxy properly returns a 407, but the failure detection code doesn't realize it should give up, so curl returns with exit code 0. Test case 162 verifies this. --- lib/http.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b2f919f67..0922b9eda 100644 --- a/lib/http.c +++ b/lib/http.c @@ -396,8 +396,13 @@ CURLcode Curl_http_auth(struct connectdata *conn, if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, start); - if (neg == 0) + if (neg == 0) { conn->newurl = strdup(data->change.url); + data->state.authproblem = (conn->newurl == NULL); + else { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } } else if(data->state.authwant & CURLAUTH_GSSNEGOTIATE) @@ -414,10 +419,14 @@ CURLcode Curl_http_auth(struct connectdata *conn, CURLntlm ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - if(CURLNTLM_BAD != ntlm) + if(CURLNTLM_BAD != ntlm) { conn->newurl = strdup(data->change.url); /* clone string */ - else + data->state.authproblem = (conn->newurl == NULL); + } + else { infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } } else if(data->state.authwant & CURLAUTH_NTLM) @@ -431,12 +440,16 @@ CURLcode Curl_http_auth(struct connectdata *conn, /* Digest authentication is activated */ CURLdigest dig = Curl_input_digest(conn, start); - if(CURLDIGEST_FINE == dig) + if(CURLDIGEST_FINE == dig) { /* We act on it. Store our new url, which happens to be the same one we already use! */ conn->newurl = strdup(data->change.url); /* clone string */ - else + data->state.authproblem = (conn->newurl == NULL); + } + else { infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } } else if(data->state.authwant & CURLAUTH_DIGEST) { @@ -458,9 +471,17 @@ CURLcode Curl_http_auth(struct connectdata *conn, valid. */ data->state.authavail = CURLAUTH_NONE; infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; } else if(data->state.authwant & CURLAUTH_BASIC) { data->state.authavail |= CURLAUTH_BASIC; + } else { + /* + ** We asked for something besides basic but got + ** Basic anyway. This is no good. + */ + infof(data, "Server expects Basic auth, but we're doing something else.\n"); + data->state.authproblem = TRUE; } } return CURLE_OK; @@ -531,13 +552,17 @@ int Curl_http_should_fail(struct connectdata *conn) */ #if 0 /* set to 1 when debugging this functionality */ infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); + infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant); + infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); + infof(data,"%s: newurl = %s\n",__FUNCTION__,conn->newurl ? conn->newurl : "(null)"); + infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); #endif if (data->state.authstage && (data->state.authstage == k->httpcode)) - return data->state.authdone; + return (data->state.authdone || data->state.authproblem); /* ** Either we're not authenticating, or we're supposed to -- cgit v1.2.1 From 550862f41abecc44714986f7bfec1267e42d6fcd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Apr 2004 21:27:32 +0000 Subject: missing brace --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0922b9eda..0c81752d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -399,6 +399,7 @@ CURLcode Curl_http_auth(struct connectdata *conn, if (neg == 0) { conn->newurl = strdup(data->change.url); data->state.authproblem = (conn->newurl == NULL); + } else { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; -- cgit v1.2.1 From 70e2aadc18fce9f6e3b9c06612c8314bf4f710b1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 23 Apr 2004 10:37:52 +0000 Subject: Replaced Curl_FormReadOneLine with Curl_formpostheader as that is the only use for it. It saves one extra copy of the header. I also added comments for several functions in formdata.c --- lib/http.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0c81752d3..1e95e1083 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1686,7 +1686,7 @@ CURLcode Curl_http(struct connectdata *conn) } if(!checkheaders(data, "Content-Type:")) { - /* Get Content-Type: line from Curl_FormReadOneLine, which happens + /* Get Content-Type: line from Curl_formpostheader, which happens to always be the first line. We can know this for sure since we always build the formpost linked list the same way! @@ -1694,13 +1694,11 @@ CURLcode Curl_http(struct connectdata *conn) string etc why disabling this header is likely to not make things work, but we support it anyway. */ - char contentType[256]; + char *contentType; size_t linelength=0; - linelength = Curl_FormReadOneLine(contentType, - sizeof(contentType), - 1, - (FILE *)&http->form); - if(!linelength) { + contentType = Curl_formpostheader((void *)&http->form, + &linelength); + if(!contentType) { failf(data, "Could not get Content-Type header line!"); return CURLE_HTTP_POST_ERROR; } -- cgit v1.2.1 From f5042cce34d0680ddfb8132d8d36521f10e5e3fe Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 26 Apr 2004 14:03:25 +0000 Subject: IDN adjustments and host cleanups by Gisle --- lib/http.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1e95e1083..4cc813e98 100644 --- a/lib/http.c +++ b/lib/http.c @@ -92,6 +92,7 @@ #include "http_negotiate.h" #include "url.h" #include "share.h" +#include "hostip.h" #include "http.h" #define _MPRINTF_REPLACE /* use our functions only */ @@ -252,7 +253,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || !data->state.auth_host || - curl_strequal(data->state.auth_host, conn->hostname) || + curl_strequal(data->state.auth_host, TRUE_HOSTNAME(conn)) || data->set.http_disable_hostname_check_before_authentication) { /* Send proxy authentication header if needed */ @@ -1112,7 +1113,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) /* either HTTPS over proxy, OR explicitly asked for a tunnel */ result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, - conn->hostname, conn->remote_port); + TRUE_HOSTNAME(conn), conn->remote_port); if(CURLE_OK != result) return result; } @@ -1131,7 +1132,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) /* Free to avoid leaking memory on multiple requests*/ free(data->state.auth_host); - data->state.auth_host = strdup(conn->hostname); + data->state.auth_host = strdup(TRUE_HOSTNAME(conn)); } return CURLE_OK; @@ -1218,7 +1219,7 @@ CURLcode Curl_http(struct connectdata *conn) struct HTTP *http; struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->path; - char *host = conn->hostname; + char *host = TRUE_HOSTNAME(conn); const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; -- cgit v1.2.1 From 4b9f8e766d0c4d989b0188a6dfd3c667e49a93a9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 Apr 2004 13:56:23 +0000 Subject: Made host name and proxy name get stored in a 'struct hostname' and set all things up to work with encoded host names internally, as well as keeping 'display names' to show in debug messages. IDN resolves work for me now using ipv6, ipv4 and ares resolving. Even cookies on IDN sites seem to do right. --- lib/http.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4cc813e98..4c517eb0e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -253,7 +253,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || !data->state.auth_host || - curl_strequal(data->state.auth_host, TRUE_HOSTNAME(conn)) || + curl_strequal(data->state.auth_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { /* Send proxy authentication header if needed */ @@ -1113,7 +1113,8 @@ CURLcode Curl_http_connect(struct connectdata *conn) /* either HTTPS over proxy, OR explicitly asked for a tunnel */ result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, - TRUE_HOSTNAME(conn), conn->remote_port); + conn->host.name, + conn->remote_port); if(CURLE_OK != result) return result; } @@ -1132,7 +1133,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) /* Free to avoid leaking memory on multiple requests*/ free(data->state.auth_host); - data->state.auth_host = strdup(TRUE_HOSTNAME(conn)); + data->state.auth_host = strdup(conn->host.name); } return CURLE_OK; @@ -1219,7 +1220,7 @@ CURLcode Curl_http(struct connectdata *conn) struct HTTP *http; struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->path; - char *host = TRUE_HOSTNAME(conn); + char *host = conn->host.name; const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; -- cgit v1.2.1 From 59907ebc0e4031e2447b57684d530da22a5d32c7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 29 Apr 2004 13:41:48 +0000 Subject: fixed the host/proxy name issue when re-using a connection and made IDN names work when using proxy by converting the IDN-name to the ACE-encoded version before the request-URL is passed to the proxy. --- lib/http.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4c517eb0e..fb538e516 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1398,7 +1398,40 @@ CURLcode Curl_http(struct connectdata *conn) if (conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy && !(conn->protocol&PROT_HTTPS)) { - /* The path sent to the proxy is in fact the entire URL */ + /* The path sent to the proxy is in fact the entire URL. But if the remote + host is a IDN-name, we must make sure that the request we produce only + uses the encoded host name! */ + if(conn->host.dispname != conn->host.name) { + char *url = data->change.url; + char *ptr = strstr(url, conn->host.dispname); + if(ptr) { + /* This is where the display name starts in the URL, now replace this + part with the encoded name. TODO: This method of replacing the host + name is rather crude as I believe there's a slight risk that the + user has entered a user name or password that contain the host name + string. */ + size_t currlen = strlen(conn->host.dispname); + size_t newlen = strlen(conn->host.name); + size_t urllen = strlen(url); + + char *newurl; + + newurl = malloc(urllen + newlen - currlen + 1); + + /* copy the part before the host name */ + memcpy(newurl, url, ptr - url); + /* append the new host name instead of the old */ + memcpy(newurl + (ptr - url), conn->host.name, newlen); + /* append the piece after the host name */ + memcpy(newurl + newlen + (ptr - url), + ptr + currlen, /* copy the trailing zero byte too */ + urllen - (ptr-url) - currlen + 1); + if(data->change.url_alloc) + free(data->change.url); + data->change.url = newurl; + data->change.url_alloc = TRUE; + } + } ppath = data->change.url; } if(HTTPREQ_POST_FORM == httpreq) { -- cgit v1.2.1 From fc6eff13b5414caf6edf22d73a3239e074a04216 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 May 2004 07:52:53 +0000 Subject: General HTTP authentication cleanup and fixes --- lib/http.c | 400 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 207 insertions(+), 193 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fb538e516..b8243b35a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -103,8 +103,6 @@ #include "memdebug.h" #endif -static CURLcode Curl_output_basic_proxy(struct connectdata *conn); - /* * checkheaders() checks the linked list of custom HTTP headers for a * particular header (prefix). @@ -124,23 +122,39 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) } /* - * Curl_output_basic() sets up an Authorization: header for HTTP Basic - * authentication. It uses the conn->user, conn->passwd fields for it. + * Curl_output_basic() sets up an Authorization: header (or the proxy version) + * for HTTP Basic authentication. * * Returns CURLcode. */ -static CURLcode Curl_output_basic(struct connectdata *conn) +static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) { char *authorization; struct SessionHandle *data=conn->data; - - sprintf(data->state.buffer, "%s:%s", conn->user, conn->passwd); - if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), + char **userp; + char *user; + char *pwd; + + if(proxy) { + userp = &conn->allocptr.proxyuserpwd; + user = conn->proxyuser; + pwd = conn->proxypasswd; + } + else { + userp = &conn->allocptr.userpwd; + user = conn->user; + pwd = conn->passwd; + } + + sprintf(data->state.buffer, "%s:%s", user, pwd); + if(Curl_base64_encode(data->state.buffer, + strlen(data->state.buffer), &authorization) > 0) { - if(conn->allocptr.userpwd) - free(conn->allocptr.userpwd); - conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012", - authorization); + if(*userp) + free(*userp); + *userp = aprintf( "%sAuthorization: Basic %s\015\012", + proxy?"Proxy-":"", + authorization); free(authorization); } else @@ -148,61 +162,74 @@ static CURLcode Curl_output_basic(struct connectdata *conn) return CURLE_OK; } -/* - * Curl_output_basic_proxy() sets up a proxy-Authorization: header for HTTP - * Basic proxy authentication. It uses the conn->proxyuser and - * conn->proxypasswd fields for it. +/* pickoneauth() selects the most favourable authentication method from the + * ones available and the ones we want. * - * Returns CURLcode. + * return TRUE if one was picked */ -static CURLcode Curl_output_basic_proxy(struct connectdata *conn) +static bool pickoneauth(struct auth *pick) { - char *authorization; - struct SessionHandle *data=conn->data; + bool picked; + if(pick->avail) { + /* only deal with authentication we want */ + long avail = pick->avail & pick->want; + picked = TRUE; - sprintf(data->state.buffer, "%s:%s", - conn->proxyuser, conn->proxypasswd); - if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), - &authorization) > 0) { - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = - aprintf("Proxy-authorization: Basic %s\015\012", authorization); - free(authorization); + /* The order of these checks is highly relevant, as this will be the order + of preference in case of the existance of multiple accepted types. */ + if(avail & CURLAUTH_GSSNEGOTIATE) + pick->picked = CURLAUTH_GSSNEGOTIATE; + else if(avail & CURLAUTH_DIGEST) + pick->picked = CURLAUTH_DIGEST; + else if(avail & CURLAUTH_NTLM) + pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_BASIC) + pick->picked = CURLAUTH_BASIC; + else { + pick->picked = CURLAUTH_NONE; /* none was picked clear it */ + picked = FALSE; + } + pick->avail = CURLAUTH_NONE; /* clear it here */ } else - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; + return FALSE; + + return picked; } /* - * Curl_http_auth_act() checks what authentication methods that are available - * and decides which one (if any) to use. It will set 'newurl' if an auth - * metod was picked. + * Curl_http_auth_act() gets called when a all HTTP headers have been received + * and it checks what authentication methods that are available and decides + * which one (if any) to use. It will set 'newurl' if an auth metod was + * picked. */ -void Curl_http_auth_act(struct connectdata *conn) +CURLcode Curl_http_auth_act(struct connectdata *conn) { struct SessionHandle *data = conn->data; + bool pickhost; + bool pickproxy; + CURLcode code = CURLE_OK; - if(data->state.authavail) { - /* The order of these checks is highly relevant, as this will be the order - of preference in case of the existance of multiple accepted types. */ - if(data->state.authavail & CURLAUTH_GSSNEGOTIATE) - data->state.authwant = CURLAUTH_GSSNEGOTIATE; - else if(data->state.authavail & CURLAUTH_DIGEST) - data->state.authwant = CURLAUTH_DIGEST; - else if(data->state.authavail & CURLAUTH_NTLM) - data->state.authwant = CURLAUTH_NTLM; - else if(data->state.authavail & CURLAUTH_BASIC) - data->state.authwant = CURLAUTH_BASIC; - else - data->state.authwant = CURLAUTH_NONE; /* clear it */ + if(data->state.authproblem) + return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; - if(data->state.authwant) - conn->newurl = strdup(data->change.url); /* clone URL */ - data->state.authavail = CURLAUTH_NONE; /* clear it here */ + if(conn->bits.user_passwd) { + pickhost = pickoneauth(&data->state.authhost); + if(!pickhost && (conn->keep.httpcode == 401)) + data->state.authproblem = TRUE; } - else if(!data->state.authdone && (data->info.httpcode < 400)) { + if(conn->bits.proxy_user_passwd) { + pickproxy = pickoneauth(&data->state.authproxy); + if(!pickproxy && (conn->keep.httpcode == 407)) + data->state.authproblem = TRUE; + } + + if(pickhost || pickproxy) + conn->newurl = strdup(data->change.url); /* clone URL */ + + else if((data->info.httpcode < 400) && + (!data->state.authhost.done)) { /* no (known) authentication available, authentication is not "done" yet and no authentication seems to be required and @@ -210,23 +237,34 @@ void Curl_http_auth_act(struct connectdata *conn) if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD)) { conn->newurl = strdup(data->change.url); /* clone URL */ - data->state.authdone = TRUE; + data->state.authhost.done = TRUE; } } + if (Curl_http_should_fail(conn)) { + failf (data, "The requested URL returned error: %d", + conn->keep.httpcode); + code = CURLE_HTTP_RETURNED_ERROR; + } + + return code; } /** - * http_auth_headers() setups the authentication headers for the host/proxy - * and the correct authentication method. conn->data->state.authdone is set to - * TRUE when authentication is done. + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. * * @param conn all information about the current connection * * Returns CURLcode */ -static CURLcode http_auth_headers(struct connectdata *conn, - char *request, - char *path) +static CURLcode +Curl_http_output_auth(struct connectdata *conn, + char *request, + char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; @@ -234,19 +272,29 @@ static CURLcode http_auth_headers(struct connectdata *conn, curlassert(data); - if(!data->state.authstage) { - if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) { - data->state.authdone = FALSE; - Curl_http_auth_stage(data, 407); - } - else if(conn->bits.user_passwd) { - data->state.authdone = FALSE; - Curl_http_auth_stage(data, 401); - } - else { - data->state.authdone = TRUE; - return CURLE_OK; /* no authentication with no user or password */ - } + if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || + conn->bits.user_passwd) + /* continue please */ ; + else { + data->state.authhost.done = TRUE; + data->state.authproxy.done = TRUE; + return CURLE_OK; /* no authentication with no user or password */ + } + + if(data->state.authhost.want && + !data->state.authhost.picked) { + /* The app has selected one or more methods, but none has been picked + so far by a server round-trip. Then we set the picked one to the + want one, and if this is one single bit it'll be used instantly. */ + data->state.authhost.picked = data->state.authhost.want; + } + + if(data->state.authproxy.want && + !data->state.authproxy.picked) { + /* The app has selected one or more methods, but none has been picked + so far by a server round-trip. Then we set the picked one to the + want one, and if this is one single bit it'll be used instantly. */ + data->state.authproxy.picked = data->state.authproxy.want; } /* To prevent the user+password to get sent to other than the original @@ -256,10 +304,11 @@ static CURLcode http_auth_headers(struct connectdata *conn, curl_strequal(data->state.auth_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { - /* Send proxy authentication header if needed */ - if (data->state.authstage == 407) { + /* Send proxy authentication header if needed */ + if (conn->bits.httpproxy && + (data->set.tunnel_thru_httpproxy == proxytunnel)) { #ifdef USE_SSLEAY - if(data->state.authwant == CURLAUTH_NTLM) { + if(data->state.authproxy.want == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE); if(result) @@ -267,39 +316,52 @@ static CURLcode http_auth_headers(struct connectdata *conn, } else #endif - if(data->state.authwant == CURLAUTH_BASIC) { + if(data->state.authproxy.want == CURLAUTH_BASIC) { /* Basic */ if(conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { auth=(char *)"Basic"; - result = Curl_output_basic_proxy(conn); + result = Curl_output_basic(conn, TRUE); if(result) return result; } - data->state.authdone = TRUE; - /* Switch to web authentication after proxy authentication is done */ - Curl_http_auth_stage(data, 401); + data->state.authproxy.done = TRUE; } + else if(data->state.authproxy.want == CURLAUTH_DIGEST) { + auth=(char *)"Digest"; + result = Curl_output_digest(conn, + TRUE, /* proxy */ + (unsigned char *)request, + (unsigned char *)path); + if(result) + return result; + } + infof(data, "Proxy auth using %s with user '%s'\n", auth, conn->proxyuser?conn->proxyuser:""); } + else + /* we have no proxy so let's pretend we're done authenticating + with it */ + data->state.authproxy.done = TRUE; + /* Send web authentication header if needed */ - if (data->state.authstage == 401) { + { auth = NULL; #ifdef HAVE_GSSAPI - if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && + if((data->state.authhost.want == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { auth=(char *)"GSS-Negotiate"; result = Curl_output_negotiate(conn); if (result) return result; - data->state.authdone = TRUE; + data->state.authhost.done = TRUE; } else #endif #ifdef USE_SSLEAY - if(data->state.authwant == CURLAUTH_NTLM) { + if(data->state.authhost.picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE); if(result) @@ -308,26 +370,25 @@ static CURLcode http_auth_headers(struct connectdata *conn, else #endif { - if((data->state.authwant == CURLAUTH_DIGEST) && - data->state.digest.nonce) { + if(data->state.authhost.picked == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, + FALSE, /* not a proxy */ (unsigned char *)request, (unsigned char *)path); if(result) return result; - data->state.authdone = TRUE; } - else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ + else if(data->state.authhost.picked == CURLAUTH_BASIC) { if(conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { auth=(char *)"Basic"; - result = Curl_output_basic(conn); + result = Curl_output_basic(conn, FALSE); if(result) return result; } /* basic is always ready */ - data->state.authdone = TRUE; + data->state.authhost.done = TRUE; } } if(auth) @@ -336,21 +397,21 @@ static CURLcode http_auth_headers(struct connectdata *conn, } } else - data->state.authdone = TRUE; + data->state.authhost.done = TRUE; return result; } /* - * Curl_http_auth() deals with Proxy-Authenticate: and WWW-Authenticate: + * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: * headers. They are dealt with both in the transfer.c main loop and in the * proxy CONNECT loop. */ -CURLcode Curl_http_auth(struct connectdata *conn, - int httpcode, - char *header) /* pointing to the first non-space */ +CURLcode Curl_http_input_auth(struct connectdata *conn, + int httpcode, + char *header) /* the first non-space */ { /* * This resource requires authentication @@ -359,23 +420,18 @@ CURLcode Curl_http_auth(struct connectdata *conn, long *availp; char *start; + struct auth *authp; if (httpcode == 407) { start = header+strlen("Proxy-authenticate:"); availp = &data->info.proxyauthavail; + authp = &data->state.authproxy; } else { start = header+strlen("WWW-Authenticate:"); availp = &data->info.httpauthavail; + authp = &data->state.authhost; } - /* - * Switch from proxy to web authentication and back if needed - */ - if (httpcode == 407 && data->state.authstage != 407) - Curl_http_auth_stage(data, 407); - - else if (httpcode == 401 && data->state.authstage != 401) - Curl_http_auth_stage(data, 401); /* pass all white spaces */ while(*start && isspace((int)*start)) @@ -394,7 +450,8 @@ CURLcode Curl_http_auth(struct connectdata *conn, if (checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { *availp |= CURLAUTH_GSSNEGOTIATE; - if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) { + authp->avail |= CURLAUTH_GSSNEGOTIATE; + if(authp->picked == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, start); if (neg == 0) { @@ -406,9 +463,6 @@ CURLcode Curl_http_auth(struct connectdata *conn, data->state.authproblem = TRUE; } } - else - if(data->state.authwant & CURLAUTH_GSSNEGOTIATE) - data->state.authavail |= CURLAUTH_GSSNEGOTIATE; } else #endif @@ -416,76 +470,50 @@ CURLcode Curl_http_auth(struct connectdata *conn, /* NTLM support requires the SSL crypto libs */ if(checkprefix("NTLM", start)) { *availp |= CURLAUTH_NTLM; - if(data->state.authwant == CURLAUTH_NTLM) { - /* NTLM authentication is activated */ + authp->avail |= CURLAUTH_NTLM; + if(authp->picked == CURLAUTH_NTLM) { + /* NTLM authentication is picked and activated */ CURLntlm ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - if(CURLNTLM_BAD != ntlm) { - conn->newurl = strdup(data->change.url); /* clone string */ - data->state.authproblem = (conn->newurl == NULL); - } + if(CURLNTLM_BAD != ntlm) + data->state.authproblem = FALSE; else { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; } } - else - if(data->state.authwant & CURLAUTH_NTLM) - data->state.authavail |= CURLAUTH_NTLM; } else #endif if(checkprefix("Digest", start)) { + CURLdigest dig; *availp |= CURLAUTH_DIGEST; - if(data->state.authwant == CURLAUTH_DIGEST) { - /* Digest authentication is activated */ - CURLdigest dig = Curl_input_digest(conn, start); + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are gonna use Digest. */ + dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); - if(CURLDIGEST_FINE == dig) { - /* We act on it. Store our new url, which happens to be - the same one we already use! */ - conn->newurl = strdup(data->change.url); /* clone string */ - data->state.authproblem = (conn->newurl == NULL); - } - else { - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } + if(CURLDIGEST_FINE != dig) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; } - else - if(data->state.authwant & CURLAUTH_DIGEST) { - /* We don't know if Digest is what we're gonna use, but we - call this function anyway to store the digest data that - is provided on this line, to skip the extra round-trip - we need to do otherwise. We must sure to free this - data! */ - Curl_input_digest(conn, start); - data->state.authavail |= CURLAUTH_DIGEST; - } } else if(checkprefix("Basic", start)) { *availp |= CURLAUTH_BASIC; - if((data->state.authwant == CURLAUTH_BASIC) && - (httpcode == data->state.authstage)) { + authp->avail |= CURLAUTH_BASIC; + if(authp->picked == CURLAUTH_BASIC) { /* We asked for Basic authentication but got a 40X back anyway, which basicly means our name+password isn't valid. */ - data->state.authavail = CURLAUTH_NONE; + authp->avail = CURLAUTH_NONE; infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; } - else if(data->state.authwant & CURLAUTH_BASIC) { - data->state.authavail |= CURLAUTH_BASIC; - } else { - /* - ** We asked for something besides basic but got - ** Basic anyway. This is no good. - */ - infof(data, "Server expects Basic auth, but we're doing something else.\n"); - data->state.authproblem = TRUE; - } } + return CURLE_OK; } @@ -562,15 +590,16 @@ int Curl_http_should_fail(struct connectdata *conn) infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); #endif - if (data->state.authstage && - (data->state.authstage == k->httpcode)) - return (data->state.authdone || data->state.authproblem); - /* ** Either we're not authenticating, or we're supposed to ** be authenticating something else. This is an error. */ - return 1; + if((k->httpcode == 401) && !conn->bits.user_passwd) + return TRUE; + if((k->httpcode == 407) && !conn->bits.proxy_user_passwd) + return TRUE; + + return data->state.authproblem; } /* @@ -876,9 +905,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, char *hostname, int remote_port) { - int httpcode=0; int subversion=0; struct SessionHandle *data=conn->data; + struct Curl_transfer_keeper *k = &conn->keep; CURLcode result; int res; @@ -916,7 +945,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ - result = http_auth_headers(conn, (char *)"CONNECT", host_port); + result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); if(CURLE_OK == result) { /* OK, now send the connect request to the proxy */ @@ -1039,18 +1068,18 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, letter = line_start[perline]; line_start[perline]=0; /* zero terminate the buffer */ if((checkprefix("WWW-Authenticate:", line_start) && - (401 == httpcode)) || + (401 == k->httpcode)) || (checkprefix("Proxy-authenticate:", line_start) && - (407 == httpcode))) { - result = Curl_http_auth(conn, httpcode, line_start); + (407 == k->httpcode))) { + result = Curl_http_input_auth(conn, k->httpcode, line_start); if(result) return result; } else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, - &httpcode)) { + &k->httpcode)) { /* store the HTTP code */ - data->info.httpproxycode = httpcode; + data->info.httpproxycode = k->httpcode; } /* put back the letter we blanked out before */ line_start[perline]= letter; @@ -1073,8 +1102,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } while(conn->newurl); - if(200 != httpcode) { - failf(data, "Received HTTP code %d from proxy after CONNECT", httpcode); + if(200 != k->httpcode) { + failf(data, "Received HTTP code %d from proxy after CONNECT", + k->httpcode); return CURLE_RECV_ERROR; } @@ -1084,7 +1114,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, Curl_safefree(conn->allocptr.proxyuserpwd); conn->allocptr.proxyuserpwd = NULL; - Curl_http_auth_stage(data, 401); /* move on to the host auth */ + data->state.authproxy.done = TRUE; infof (data, "Proxy replied OK to CONNECT request\n"); return CURLE_OK; @@ -1189,24 +1219,6 @@ CURLcode Curl_http_done(struct connectdata *conn) return CURLE_OK; } -/* - * Curl_http_auth_stage() sets the "authentication stage" - which is 407 for - * proxy authentication or 401 for host authentication. - */ -void Curl_http_auth_stage(struct SessionHandle *data, - int stage) -{ - curlassert((stage == 401) || (stage == 407)); - - /* We set none, one or more bits for which authentication types we accept - for this stage. */ - data->state.authwant = (stage == 401)? - data->set.httpauth:data->set.proxyauth; - - data->state.authstage = stage; - data->state.authavail = CURLAUTH_NONE; /* no type available yet */ -} - /* * Curl_http() gets called from the generic Curl_do() function when a HTTP * request is to be performed. This creates and sends a propperly constructed @@ -1284,11 +1296,12 @@ CURLcode Curl_http(struct connectdata *conn) } /* setup the authentication headers */ - result = http_auth_headers(conn, request, ppath); + result = Curl_http_output_auth(conn, request, ppath, FALSE); if(result) return result; - if(!data->state.authdone && (httpreq != HTTPREQ_GET)) { + if((!data->state.authhost.done || !data->state.authproxy.done ) && + (httpreq != HTTPREQ_GET)) { /* Until we are authenticated, we switch over to HEAD. Unless its a GET we want to do. The explanation for this is rather long and boring, but the point is that it can't be done otherwise without risking having to @@ -1583,7 +1596,7 @@ CURLcode Curl_http(struct connectdata *conn) request, ppath, httpstring, - (conn->bits.httpproxy && conn->allocptr.proxyuserpwd)? + conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", conn->allocptr.userpwd?conn->allocptr.userpwd:"", (conn->bits.use_range && conn->allocptr.rangeline)? @@ -1755,8 +1768,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - data->state.authdone?FIRSTSOCKET:-1, - data->state.authdone?&http->writebytecount:NULL); + FIRSTSOCKET, + &http->writebytecount); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -1794,8 +1807,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - data->state.authdone?FIRSTSOCKET:-1, - data->state.authdone?&http->writebytecount:NULL); + FIRSTSOCKET, + &http->writebytecount); if(result) return result; break; @@ -1826,7 +1839,8 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.postfields) { - if(data->state.authdone && (postsize < (100*1024))) { + if((data->state.authhost.done || data->state.authproxy.done ) + && (postsize < (100*1024))) { /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ @@ -1862,7 +1876,7 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - if(!data->state.authdone && !checkheaders(data, "Expect:")) { + if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ -- cgit v1.2.1 From 08d1da106ebe3817ce3aad083182fad4881a8d2a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 May 2004 13:39:24 +0000 Subject: check malloc() return code --- lib/http.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b8243b35a..cc0ef7f8c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1430,19 +1430,22 @@ CURLcode Curl_http(struct connectdata *conn) char *newurl; newurl = malloc(urllen + newlen - currlen + 1); - - /* copy the part before the host name */ - memcpy(newurl, url, ptr - url); - /* append the new host name instead of the old */ - memcpy(newurl + (ptr - url), conn->host.name, newlen); - /* append the piece after the host name */ - memcpy(newurl + newlen + (ptr - url), - ptr + currlen, /* copy the trailing zero byte too */ - urllen - (ptr-url) - currlen + 1); - if(data->change.url_alloc) - free(data->change.url); - data->change.url = newurl; - data->change.url_alloc = TRUE; + if(newurl) { + /* copy the part before the host name */ + memcpy(newurl, url, ptr - url); + /* append the new host name instead of the old */ + memcpy(newurl + (ptr - url), conn->host.name, newlen); + /* append the piece after the host name */ + memcpy(newurl + newlen + (ptr - url), + ptr + currlen, /* copy the trailing zero byte too */ + urllen - (ptr-url) - currlen + 1); + if(data->change.url_alloc) + free(data->change.url); + data->change.url = newurl; + data->change.url_alloc = TRUE; + } + else + return CURLE_OUT_OF_MEMORY; } } ppath = data->change.url; -- cgit v1.2.1 From 76ff92b8112c5efa50f38f1fda59bfa468948145 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 May 2004 14:27:07 +0000 Subject: bail out when an add_buffer() function returns failure --- lib/http.c | 98 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 32 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cc0ef7f8c..b86f031d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1626,16 +1626,22 @@ CURLcode Curl_http(struct connectdata *conn) while(co) { if(co->value) { if(0 == count) { - add_bufferf(req_buffer, "Cookie: "); + result = add_bufferf(req_buffer, "Cookie: "); + if(result) + return result; } - add_bufferf(req_buffer, - "%s%s=%s", count?"; ":"", co->name, co->value); + result = add_bufferf(req_buffer, + "%s%s=%s", count?"; ":"", co->name, co->value); + if(result) + return result; count++; } co = co->next; /* next cookie please */ } if(count) { - add_buffer(req_buffer, "\r\n", 2); + result = add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; } Curl_cookie_freelist(store); /* free the cookie list */ co=NULL; @@ -1669,18 +1675,20 @@ CURLcode Curl_http(struct connectdata *conn) switch(data->set.timecondition) { case CURL_TIMECOND_IFMODSINCE: default: - add_bufferf(req_buffer, - "If-Modified-Since: %s\r\n", buf); + result = add_bufferf(req_buffer, + "If-Modified-Since: %s\r\n", buf); break; case CURL_TIMECOND_IFUNMODSINCE: - add_bufferf(req_buffer, - "If-Unmodified-Since: %s\r\n", buf); + result = add_bufferf(req_buffer, + "If-Unmodified-Since: %s\r\n", buf); break; case CURL_TIMECOND_LASTMOD: - add_bufferf(req_buffer, - "Last-Modified: %s\r\n", buf); + result = add_bufferf(req_buffer, + "Last-Modified: %s\r\n", buf); break; } + if(result) + return result; } while(headers) { @@ -1695,7 +1703,9 @@ CURLcode Curl_http(struct connectdata *conn) if(*ptr) { /* only send this if the contents was non-blank */ - add_bufferf(req_buffer, "%s\r\n", headers->data); + result = add_bufferf(req_buffer, "%s\r\n", headers->data); + if(result) + return result; } } headers = headers->next; @@ -1722,17 +1732,23 @@ CURLcode Curl_http(struct connectdata *conn) http->sending = HTTPSEND_BODY; - if(!conn->bits.upload_chunky) + if(!conn->bits.upload_chunky) { /* only add Content-Length if not uploading chunked */ - add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", http->postsize); + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T "\r\n", + http->postsize); + if(result) + return result; + } if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ - add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); + result = add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + if(result) + return result; data->set.expect100header = TRUE; } @@ -1753,11 +1769,15 @@ CURLcode Curl_http(struct connectdata *conn) failf(data, "Could not get Content-Type header line!"); return CURLE_HTTP_POST_ERROR; } - add_buffer(req_buffer, contentType, linelength); + result = add_buffer(req_buffer, contentType, linelength); + if(result) + return result; } /* make the request end in a true CRLF */ - add_buffer(req_buffer, "\r\n", 2); + result = add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; /* set upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); @@ -1781,23 +1801,30 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - if((data->set.infilesize>0) && !conn->bits.upload_chunky) + if((data->set.infilesize>0) && !conn->bits.upload_chunky) { /* only add Content-Length if not uploading chunked */ - add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ - data->set.infilesize ); + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ + data->set.infilesize ); + if(result) + return result; + } if(!checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ - add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); + result = add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + if(result) + return result; data->set.expect100header = TRUE; } - add_buffer(req_buffer, "\r\n", 2); /* end of headers */ - + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ + if(result) + return result; + /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, data->set.infilesize); @@ -1829,16 +1856,23 @@ CURLcode Curl_http(struct connectdata *conn) we don't upload data chunked, as RFC2616 forbids us to set both kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - if(!checkheaders(data, "Content-Length:")) + if(!checkheaders(data, "Content-Length:")) { /* we allow replacing this header, although it isn't very wise to actually set your own */ - add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T"\r\n", - postsize); + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T"\r\n", + postsize); + if(result) + return result; + } } - if(!checkheaders(data, "Content-Type:")) - add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); + if(!checkheaders(data, "Content-Type:")) { + result = add_bufferf(req_buffer, + "Content-Type: application/x-www-form-urlencoded\r\n"); + if(result) + return result; + } if(data->set.postfields) { -- cgit v1.2.1 From afc1ed60f7aa36dce4335f7ca287677f0026c422 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 5 May 2004 13:00:03 +0000 Subject: initiate variables properly to default to no auth for server and proxy --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b86f031d3..5e663cb7d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -207,8 +207,8 @@ static bool pickoneauth(struct auth *pick) CURLcode Curl_http_auth_act(struct connectdata *conn) { struct SessionHandle *data = conn->data; - bool pickhost; - bool pickproxy; + bool pickhost = FALSE; + bool pickproxy = FALSE; CURLcode code = CURLE_OK; if(data->state.authproblem) -- cgit v1.2.1 From 71fdc063bd170d53f442e8b0e777756a38e2fa75 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 May 2004 10:49:35 +0000 Subject: better detection for when add_buffer() returns failure, and return when that happens --- lib/http.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5e663cb7d..34d79a7e2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1886,19 +1886,29 @@ CURLcode Curl_http(struct connectdata *conn) This limit is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ - add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result == add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; - if(!conn->bits.upload_chunky) + if(!conn->bits.upload_chunky) { /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ - add_buffer(req_buffer, data->set.postfields, (size_t)postsize); + result = add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + } else { /* Append the POST data chunky-style */ - add_bufferf(req_buffer, "%x\r\n", (int)postsize); - add_buffer(req_buffer, data->set.postfields, (size_t)postsize); - add_buffer(req_buffer, "\r\n0\r\n\r\n", 7); /* end of a chunked - transfer stream */ + result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, + "\r\n0\r\n\r\n", 7); /* end of a chunked + transfer stream */ } + if(result) + return result; } else { /* A huge POST coming up, do data separate from the request */ -- cgit v1.2.1 From 1f798affb91e09ddb6c36911d1d6c28386bfb69f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 May 2004 10:52:29 +0000 Subject: typo --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 34d79a7e2..3084d3211 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1886,7 +1886,7 @@ CURLcode Curl_http(struct connectdata *conn) This limit is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ - result == add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) return result; -- cgit v1.2.1 From 63f97b38eb3a86615e7cb92e70f91cf14d69945a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 May 2004 14:22:20 +0000 Subject: Moved the fetching of the list of matching cookies to make it easier to free that list in case something goes wrong in the function and we must bail out. Courtesy of the torture testing. --- lib/http.c | 69 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3084d3211..388f7debf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1230,7 +1230,6 @@ CURLcode Curl_http(struct connectdata *conn) char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; - struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->path; char *host = conn->host.name; const char *te = ""; /* tranfer-encoding */ @@ -1399,15 +1398,6 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; } - if(data->cookies) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, ppath, - (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } - if (conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy && !(conn->protocol&PROT_HTTPS)) { @@ -1611,40 +1601,51 @@ CURLcode Curl_http(struct connectdata *conn) http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? - conn->allocptr.accept_encoding:"", /* 08/28/02 jhrg */ - (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, te ); if(result) return result; - if(co) { - int count=0; - struct Cookie *store=co; - /* now loop through all cookies that matched */ - while(co) { - if(co->value) { - if(0 == count) { - result = add_bufferf(req_buffer, "Cookie: "); + if(data->cookies) { + struct Cookie *co; /* no cookies from start */ + + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, ppath, + (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + + if(co) { + int count=0; + struct Cookie *store=co; + /* now loop through all cookies that matched */ + while(co) { + if(co->value) { + if(0 == count) { + result = add_bufferf(req_buffer, "Cookie: "); + if(result) + break; + } + result = add_bufferf(req_buffer, + "%s%s=%s", count?"; ":"", + co->name, co->value); if(result) - return result; + break; + count++; } - result = add_bufferf(req_buffer, - "%s%s=%s", count?"; ":"", co->name, co->value); - if(result) - return result; - count++; + co = co->next; /* next cookie please */ } - co = co->next; /* next cookie please */ - } - if(count) { - result = add_buffer(req_buffer, "\r\n", 2); - if(result) - return result; + if(count && (CURLE_OK == result)) + result = add_buffer(req_buffer, "\r\n", 2); + + Curl_cookie_freelist(store); /* free the cookie list */ } - Curl_cookie_freelist(store); /* free the cookie list */ - co=NULL; + if(result) + return result; } if(data->set.timecondition) { -- cgit v1.2.1 From bbafb2eb27954c34967f91c705e74cc0c186970d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 May 2004 11:30:23 +0000 Subject: curl_global_init_mem() allows the memory functions to be replaced. memory.h is included everywhere for this. --- lib/http.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 388f7debf..48bffa904 100644 --- a/lib/http.c +++ b/lib/http.c @@ -74,7 +74,6 @@ #include #endif - #endif #include "urldata.h" @@ -94,14 +93,13 @@ #include "share.h" #include "hostip.h" #include "http.h" +#include "memory.h" #define _MPRINTF_REPLACE /* use our functions only */ #include /* The last #include file should be: */ -#ifdef CURLDEBUG #include "memdebug.h" -#endif /* * checkheaders() checks the linked list of custom HTTP headers for a -- cgit v1.2.1 From d60c22572b49cde9b839a59510580df079d2d5e2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 12 May 2004 12:06:39 +0000 Subject: Curl_done() and the protocol-specific conn->curl_done() functions now all take a CURLcode as a second argument, that is non-zero when Curl_done() is called after an error was returned from Curl_do() (or similar). --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 48bffa904..41b0398de 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1172,10 +1172,12 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has been performed. */ -CURLcode Curl_http_done(struct connectdata *conn) +CURLcode Curl_http_done(struct connectdata *conn, + CURLcode status) { struct SessionHandle *data; struct HTTP *http; + (void)status; /* no use for us */ data=conn->data; http=conn->proto.http; -- cgit v1.2.1 From 59f904d8de005755f87aa0a4312ab7570a62c6f7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 May 2004 07:13:48 +0000 Subject: Robert D. Young reported that CURLOPT_COOKIEFILE and CURLOPT_COOKIE could not be used both in one request. Fixed it and added test case 172 to verify. --- lib/http.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 41b0398de..64bbb1c3f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1236,6 +1236,7 @@ CURLcode Curl_http(struct connectdata *conn) char *ptr; char *request; Curl_HttpReq httpreq = data->set.httpreq; + char *addcookies = NULL; if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1316,11 +1317,8 @@ CURLcode Curl_http(struct connectdata *conn) else conn->allocptr.ref = NULL; - Curl_safefree(conn->allocptr.cookie); if(data->set.cookie && !checkheaders(data, "Cookie:")) - conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); - else - conn->allocptr.cookie = NULL; + addcookies = data->set.cookie; if(!conn->bits.upload_chunky && (httpreq != HTTPREQ_GET)) { /* not a chunky transfer yet, but data is to be sent */ @@ -1578,7 +1576,6 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* userpwd */ "%s" /* range */ "%s" /* user agent */ - "%s" /* cookie */ "%s" /* host */ "%s" /* pragma */ "%s" /* accept */ @@ -1596,7 +1593,6 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.rangeline:"", (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? conn->allocptr.uagent:"", - (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: */ (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", @@ -1609,18 +1605,19 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; - if(data->cookies) { - struct Cookie *co; /* no cookies from start */ - - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, ppath, - (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - + if(data->cookies || addcookies) { + struct Cookie *co=NULL; /* no cookies from start */ + int count=0; + + if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, ppath, + (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } if(co) { - int count=0; struct Cookie *store=co; /* now loop through all cookies that matched */ while(co) { @@ -1639,11 +1636,21 @@ CURLcode Curl_http(struct connectdata *conn) } co = co->next; /* next cookie please */ } - if(count && (CURLE_OK == result)) - result = add_buffer(req_buffer, "\r\n", 2); - Curl_cookie_freelist(store); /* free the cookie list */ } + if(addcookies && (CURLE_OK == result)) { + if(!count) + result = add_bufferf(req_buffer, "Cookie: "); + if(CURLE_OK == result) { + result = add_bufferf(req_buffer, "%s%s", + count?"; ":"", + addcookies); + count++; + } + } + if(count && (CURLE_OK == result)) + result = add_buffer(req_buffer, "\r\n", 2); + if(result) return result; } -- cgit v1.2.1 From 2c43d64302cc58532768e7e98fceb0e3032950cc Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 26 May 2004 08:54:36 +0000 Subject: Added a new 'bit' in the connect struct named 'tunnel_proxy' that is set if a connection is tunneled through a proxy. A tunnel is done with CONNECT, either when using HTTPS or FTPS, or if explicitly enabled by the app. --- lib/http.c | 109 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 56 insertions(+), 53 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 64bbb1c3f..6885e893d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -143,7 +143,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) user = conn->user; pwd = conn->passwd; } - + sprintf(data->state.buffer, "%s:%s", user, pwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), @@ -222,7 +222,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(!pickproxy && (conn->keep.httpcode == 407)) data->state.authproblem = TRUE; } - + if(pickhost || pickproxy) conn->newurl = strdup(data->change.url); /* clone URL */ @@ -254,8 +254,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) * done. * * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" * - * Returns CURLcode + * @returns CURLcode */ static CURLcode Curl_http_output_auth(struct connectdata *conn, @@ -304,7 +308,7 @@ Curl_http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if (conn->bits.httpproxy && - (data->set.tunnel_thru_httpproxy == proxytunnel)) { + (conn->bits.tunnel_proxy == proxytunnel)) { #ifdef USE_SSLEAY if(data->state.authproxy.want == CURLAUTH_NTLM) { auth=(char *)"NTLM"; @@ -334,21 +338,21 @@ Curl_http_output_auth(struct connectdata *conn, if(result) return result; } - + infof(data, "Proxy auth using %s with user '%s'\n", auth, conn->proxyuser?conn->proxyuser:""); } else /* we have no proxy so let's pretend we're done authenticating with it */ - data->state.authproxy.done = TRUE; + data->state.authproxy.done = TRUE; /* Send web authentication header if needed */ { auth = NULL; #ifdef HAVE_GSSAPI if((data->state.authhost.want == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && + data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { auth=(char *)"GSS-Negotiate"; result = Curl_output_negotiate(conn); @@ -443,7 +447,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, * types (using &), we OR this authenticaion type to the authavail * variable. */ - + #ifdef HAVE_GSSAPI if (checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { @@ -473,7 +477,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* NTLM authentication is picked and activated */ CURLntlm ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - + if(CURLNTLM_BAD != ntlm) data->state.authproblem = FALSE; else { @@ -488,12 +492,12 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, CURLdigest dig; *availp |= CURLAUTH_DIGEST; authp->avail |= CURLAUTH_DIGEST; - + /* We call this function on input Digest headers even if Digest * authentication isn't activated yet, as we need to store the * incoming data from this header in case we are gonna use Digest. */ dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); - + if(CURLDIGEST_FINE != dig) { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; @@ -596,7 +600,7 @@ int Curl_http_should_fail(struct connectdata *conn) return TRUE; if((k->httpcode == 407) && !conn->bits.proxy_user_passwd) return TRUE; - + return data->state.authproblem; } @@ -620,7 +624,7 @@ static size_t readmoredata(char *buffer, if(0 == http->postsize) /* nothing to return */ return 0; - + /* make sure that a HTTP request is never sent away chunked! */ conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; @@ -729,7 +733,7 @@ CURLcode add_buffer_send(send_buffer *in, } else sendsize = size; - + res = Curl_write(conn, sockfd, ptr, sendsize, &amount); if(CURLE_OK == res) { @@ -739,7 +743,7 @@ CURLcode add_buffer_send(send_buffer *in, Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); *bytes_written += amount; - + if((size_t)amount != size) { /* The whole request could not be sent in one system call. We must queue it up and send it later when we get the chance. We must not loop here @@ -748,7 +752,7 @@ CURLcode add_buffer_send(send_buffer *in, size -= amount; ptr = in->buffer + amount; - + /* backup the currently set pointers */ http->backup.fread = conn->fread; http->backup.fread_in = conn->fread_in; @@ -763,7 +767,7 @@ CURLcode add_buffer_send(send_buffer *in, http->send_buffer = in; http->sending = HTTPSEND_REQUEST; - + return CURLE_OK; } http->sending = HTTPSEND_BODY; @@ -777,7 +781,7 @@ CURLcode add_buffer_send(send_buffer *in, } -/* +/* * add_bufferf() add the formatted input to the buffer. */ static @@ -828,7 +832,7 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) in->size_max = new_size; } memcpy(&in->buffer[in->size_used], inptr, size); - + in->size_used += size; return CURLE_OK; @@ -934,7 +938,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() it. */ - free(conn->newurl); + free(conn->newurl); conn->newurl = NULL; } @@ -994,7 +998,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, break; } } - + switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; @@ -1037,7 +1041,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(*ptr=='\n') { char letter; int writetype; - + /* output debug output if that is requested */ if(data->set.verbose) Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); @@ -1077,7 +1081,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, &subversion, &k->httpcode)) { /* store the HTTP code */ - data->info.httpproxycode = k->httpcode; + data->info.httpproxycode = k->httpcode; } /* put back the letter we blanked out before */ line_start[perline]= letter; @@ -1097,7 +1101,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* Deal with the possibly already received authenticate headers. 'newurl' is set to a new URL if we must loop. */ Curl_http_auth_act(conn); - + } while(conn->newurl); if(200 != k->httpcode) { @@ -1105,7 +1109,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, k->httpcode); return CURLE_RECV_ERROR; } - + /* If a proxy-authorization header was used for the proxy, then we should make sure that it isn't accidentally used for the document request after we've connected. So let's free and clear it here. */ @@ -1136,16 +1140,15 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has occured, can we start talking SSL */ - if(conn->bits.httpproxy && - ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { + if(conn->bits.tunnel_proxy) { - /* either HTTPS over proxy, OR explicitly asked for a tunnel */ + /* either SSL over proxy, or explicitly asked for */ result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, conn->host.name, conn->remote_port); if(CURLE_OK != result) return result; - } + } if(conn->protocol & PROT_HTTPS) { /* now, perform the SSL initialization for this socket */ @@ -1186,12 +1189,12 @@ CURLcode Curl_http_done(struct connectdata *conn, conn->fread = data->set.fread; /* restore */ conn->fread_in = data->set.in; /* restore */ - if (http == NULL) + if (http == NULL) return CURLE_OK; if(http->send_buffer) { send_buffer *buff = http->send_buffer; - + free(buff->buffer); free(buff); http->send_buffer = NULL; /* cleaer the pointer */ @@ -1199,7 +1202,7 @@ CURLcode Curl_http_done(struct connectdata *conn, if(HTTPREQ_POST_FORM == data->set.httpreq) { conn->bytecount = http->readbytecount + http->writebytecount; - + Curl_formclean(http->sendit); /* Now free that whole lot */ } else if(HTTPREQ_PUT == data->set.httpreq) @@ -1285,7 +1288,7 @@ CURLcode Curl_http(struct connectdata *conn) } } } - + /* The User-Agent string might have been allocated in url.c already, because it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string @@ -1360,7 +1363,7 @@ CURLcode Curl_http(struct connectdata *conn) /* scan through the string to find the end (space or colon) */ while(*ptr && !isspace((int)*ptr) && !(':'==*ptr)) ptr++; - + if(ptr != start) { size_t len=ptr-start; conn->allocptr.cookiehost = malloc(len+1); @@ -1369,13 +1372,13 @@ CURLcode Curl_http(struct connectdata *conn) memcpy(conn->allocptr.cookiehost, start, len); conn->allocptr.cookiehost[len]=0; } - } + } else { Curl_safefree(conn->allocptr.host); /* When building Host: headers, we must put the host name within [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ - + if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include @@ -1396,9 +1399,9 @@ CURLcode Curl_http(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; } - if (conn->bits.httpproxy && - !data->set.tunnel_thru_httpproxy && - !(conn->protocol&PROT_HTTPS)) { + if (conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + /* Using a proxy but does not tunnel through it */ + /* The path sent to the proxy is in fact the entire URL. But if the remote host is a IDN-name, we must make sure that the request we produce only uses the encoded host name! */ @@ -1414,9 +1417,9 @@ CURLcode Curl_http(struct connectdata *conn) size_t currlen = strlen(conn->host.dispname); size_t newlen = strlen(conn->host.name); size_t urllen = strlen(url); - + char *newurl; - + newurl = malloc(urllen + newlen - currlen + 1); if(newurl) { /* copy the part before the host name */ @@ -1468,7 +1471,7 @@ CURLcode Curl_http(struct connectdata *conn) * the file the given number of bytes and decrease the assume upload * file size before we continue this venture in the dark lands of HTTP. *********************************************************************/ - + if(conn->resume_from < 0 ) { /* * This is meant to get the size of the present remote-file by itself. @@ -1543,7 +1546,7 @@ CURLcode Curl_http(struct connectdata *conn) total_expected_size); } else { - /* Range was selected and then we just pass the incoming range and + /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", @@ -1791,7 +1794,7 @@ CURLcode Curl_http(struct connectdata *conn) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - result = add_buffer_send(req_buffer, conn, + result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) failf(data, "Failed sending POST request"); @@ -1832,7 +1835,7 @@ CURLcode Curl_http(struct connectdata *conn) result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ if(result) return result; - + /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, data->set.infilesize); @@ -1858,7 +1861,7 @@ CURLcode Curl_http(struct connectdata *conn) postsize = data->set.postfieldsize? data->set.postfieldsize: (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); - + if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both @@ -1889,7 +1892,7 @@ CURLcode Curl_http(struct connectdata *conn) /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ - + /* The post data is less than 100K, then append it to the header. This limit is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ @@ -1969,7 +1972,7 @@ CURLcode Curl_http(struct connectdata *conn) default: add_buffer(req_buffer, "\r\n", 2); - + /* issue the request */ result = add_buffer_send(req_buffer, conn, &data->info.request_size); -- cgit v1.2.1 From ea81dd9e2e163f096df884b22e823f1a0e8569f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Jun 2004 11:41:05 +0000 Subject: Alexander Krasnostavsky's FTP third party transfer (proxy) support --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6885e893d..c664ac1d1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -740,7 +740,8 @@ CURLcode add_buffer_send(send_buffer *in, if(conn->data->set.verbose) /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount, + conn->host.dispname); *bytes_written += amount; @@ -1044,7 +1045,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* output debug output if that is requested */ if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); + Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, + conn->host.dispname); /* send the header to the callback */ writetype = CLIENTWRITE_HEADER; -- cgit v1.2.1 From fce9d5112286eb67b5f28ac0be49697ff7da89f9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Jun 2004 14:42:08 +0000 Subject: updated a comment --- lib/http.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c664ac1d1..f498be23b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1766,13 +1766,11 @@ CURLcode Curl_http(struct connectdata *conn) } if(!checkheaders(data, "Content-Type:")) { - /* Get Content-Type: line from Curl_formpostheader, which happens - to always be the first line. We can know this for sure since - we always build the formpost linked list the same way! + /* Get Content-Type: line from Curl_formpostheader. The Content-Type header line also contains the MIME boundary string etc why disabling this header is likely to not make things - work, but we support it anyway. + work, but we support disabling it anyway. */ char *contentType; size_t linelength=0; -- cgit v1.2.1 From 4cd96483f6cfe958286bddfb7ad0286a4d2a7e65 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 13 Jun 2004 09:08:38 +0000 Subject: moved default: in a switch case to prevent compiler warning that 'request' might be used uninitialized --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f498be23b..1e9693f8a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1279,14 +1279,13 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_PUT: request = (char *)"PUT"; break; + default: /* this should never happen */ case HTTPREQ_GET: request = (char *)"GET"; break; case HTTPREQ_HEAD: request = (char *)"HEAD"; break; - default: /* this should never happen */ - break; } } } -- cgit v1.2.1 From 80a1e972fcca1565f6f91f6c4baff52db3b45c79 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 15 Jun 2004 08:45:22 +0000 Subject: Fix the auth code to enable us to i.e set DIGEST and then find out that the server doesn't require any auth at all and then we just continue nicely. We now have an extra bit in the connection struct named 'authprobe' that is TRUE when doing pure "HTTP authentication probing". --- lib/http.c | 68 ++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1e9693f8a..9c9d6d533 100644 --- a/lib/http.c +++ b/lib/http.c @@ -168,29 +168,25 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) static bool pickoneauth(struct auth *pick) { bool picked; - if(pick->avail) { - /* only deal with authentication we want */ - long avail = pick->avail & pick->want; - picked = TRUE; - - /* The order of these checks is highly relevant, as this will be the order - of preference in case of the existance of multiple accepted types. */ - if(avail & CURLAUTH_GSSNEGOTIATE) - pick->picked = CURLAUTH_GSSNEGOTIATE; - else if(avail & CURLAUTH_DIGEST) - pick->picked = CURLAUTH_DIGEST; - else if(avail & CURLAUTH_NTLM) - pick->picked = CURLAUTH_NTLM; - else if(avail & CURLAUTH_BASIC) - pick->picked = CURLAUTH_BASIC; - else { - pick->picked = CURLAUTH_NONE; /* none was picked clear it */ - picked = FALSE; - } - pick->avail = CURLAUTH_NONE; /* clear it here */ + /* only deal with authentication we want */ + long avail = pick->avail & pick->want; + picked = TRUE; + + /* The order of these checks is highly relevant, as this will be the order + of preference in case of the existance of multiple accepted types. */ + if(avail & CURLAUTH_GSSNEGOTIATE) + pick->picked = CURLAUTH_GSSNEGOTIATE; + else if(avail & CURLAUTH_DIGEST) + pick->picked = CURLAUTH_DIGEST; + else if(avail & CURLAUTH_NTLM) + pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_BASIC) + pick->picked = CURLAUTH_BASIC; + else { + pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ + picked = FALSE; } - else - return FALSE; + pick->avail = CURLAUTH_NONE; /* clear it here */ return picked; } @@ -212,14 +208,16 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(data->state.authproblem) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; - if(conn->bits.user_passwd) { + if(conn->bits.user_passwd && + ((conn->keep.httpcode == 401) || conn->bits.authprobe)) { pickhost = pickoneauth(&data->state.authhost); - if(!pickhost && (conn->keep.httpcode == 401)) + if(!pickhost) data->state.authproblem = TRUE; } - if(conn->bits.proxy_user_passwd) { + if(conn->bits.proxy_user_passwd && + ((conn->keep.httpcode == 407) || conn->bits.authprobe) ) { pickproxy = pickoneauth(&data->state.authproxy); - if(!pickproxy && (conn->keep.httpcode == 407)) + if(!pickproxy) data->state.authproblem = TRUE; } @@ -283,21 +281,17 @@ Curl_http_output_auth(struct connectdata *conn, return CURLE_OK; /* no authentication with no user or password */ } - if(data->state.authhost.want && - !data->state.authhost.picked) { + if(data->state.authhost.want && !data->state.authhost.picked) /* The app has selected one or more methods, but none has been picked so far by a server round-trip. Then we set the picked one to the want one, and if this is one single bit it'll be used instantly. */ data->state.authhost.picked = data->state.authhost.want; - } - if(data->state.authproxy.want && - !data->state.authproxy.picked) { - /* The app has selected one or more methods, but none has been picked - so far by a server round-trip. Then we set the picked one to the - want one, and if this is one single bit it'll be used instantly. */ + if(data->state.authproxy.want && !data->state.authproxy.picked) + /* The app has selected one or more methods, but none has been picked so + far by a proxy round-trip. Then we set the picked one to the want one, + and if this is one single bit it'll be used instantly. */ data->state.authproxy.picked = data->state.authproxy.want; - } /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ @@ -1313,7 +1307,11 @@ CURLcode Curl_http(struct connectdata *conn) httpreq = HTTPREQ_HEAD; request = (char *)"HEAD"; conn->bits.no_body = TRUE; + conn->bits.authprobe = TRUE; /* this is a request done to probe for + authentication methods */ } + else + conn->bits.authprobe = FALSE; Curl_safefree(conn->allocptr.ref); if(data->change.referer && !checkheaders(data, "Referer:")) -- cgit v1.2.1 From d4b577114bcc1c0ddde3174a82177188d76c4b71 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 18 Jun 2004 06:15:26 +0000 Subject: With David Byron's test server I could repeat his problem and make sure that POSTing over HTTPS:// with NTLM works fine now. There was a general problem with multi-pass authentication with non-GET operations with CONNECT. --- lib/http.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9c9d6d533..14f45881d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1076,7 +1076,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &k->httpcode)) { - /* store the HTTP code */ + /* store the HTTP code from the proxy */ data->info.httpproxycode = k->httpcode; } /* put back the letter we blanked out before */ @@ -1094,9 +1094,10 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(error) return CURLE_RECV_ERROR; - /* Deal with the possibly already received authenticate headers. 'newurl' - is set to a new URL if we must loop. */ - Curl_http_auth_act(conn); + if(data->info.httpproxycode != 200) + /* Deal with the possibly already received authenticate + headers. 'newurl' is set to a new URL if we must loop. */ + Curl_http_auth_act(conn); } while(conn->newurl); -- cgit v1.2.1 From cd7a0f829fcd9ee5c58d7f20147b3d1ee77a431b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Jun 2004 10:10:24 +0000 Subject: When doing auth negotiations or authprobing, we only consider HTTP code <300 to be good. --- lib/http.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 14f45881d..74422c58e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -209,13 +209,15 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; if(conn->bits.user_passwd && - ((conn->keep.httpcode == 401) || conn->bits.authprobe)) { + ((conn->keep.httpcode == 401) || + (conn->bits.authprobe && conn->keep.httpcode < 300))) { pickhost = pickoneauth(&data->state.authhost); if(!pickhost) data->state.authproblem = TRUE; } if(conn->bits.proxy_user_passwd && - ((conn->keep.httpcode == 407) || conn->bits.authprobe) ) { + ((conn->keep.httpcode == 407) || + (conn->bits.authprobe && conn->keep.httpcode < 300))) { pickproxy = pickoneauth(&data->state.authproxy); if(!pickproxy) data->state.authproblem = TRUE; @@ -224,8 +226,9 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(pickhost || pickproxy) conn->newurl = strdup(data->change.url); /* clone URL */ - else if((data->info.httpcode < 400) && - (!data->state.authhost.done)) { + else if((conn->keep.httpcode < 300) && + (!data->state.authhost.done) && + conn->bits.authprobe) { /* no (known) authentication available, authentication is not "done" yet and no authentication seems to be required and -- cgit v1.2.1 From 0031d76f2a77e583528a817bcf7b605052b95893 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Jun 2004 10:43:22 +0000 Subject: use snprintf() to be on the safe side --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 74422c58e..bd6adf964 100644 --- a/lib/http.c +++ b/lib/http.c @@ -144,7 +144,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) pwd = conn->passwd; } - sprintf(data->state.buffer, "%s:%s", user, pwd); + snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), &authorization) > 0) { -- cgit v1.2.1 From e35187741be548ae869db90024b0486faa02dd7f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Jul 2004 06:08:06 +0000 Subject: spellfixed comments --- lib/http.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bd6adf964..ea7b49988 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1133,11 +1133,10 @@ CURLcode Curl_http_connect(struct connectdata *conn) data=conn->data; - /* If we are not using a proxy and we want a secure connection, - * perform SSL initialization & connection now. - * If using a proxy with https, then we must tell the proxy to CONNECT - * us to the host we want to talk to. Only after the connect - * has occured, can we start talking SSL + /* If we are not using a proxy and we want a secure connection, perform SSL + * initialization & connection now. If using a proxy with https, then we + * must tell the proxy to CONNECT to the host we want to talk to. Only + * after the connect has occured, can we start talking SSL */ if(conn->bits.tunnel_proxy) { @@ -1224,7 +1223,7 @@ CURLcode Curl_http_done(struct connectdata *conn, /* * Curl_http() gets called from the generic Curl_do() function when a HTTP - * request is to be performed. This creates and sends a propperly constructed + * request is to be performed. This creates and sends a properly constructed * HTTP request. */ CURLcode Curl_http(struct connectdata *conn) -- cgit v1.2.1 From fcfd4bef2dc9dc90e39ab5cb8f49686119917bb3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Jul 2004 07:30:19 +0000 Subject: typecast to prevent picky compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ea7b49988..d1128d499 100644 --- a/lib/http.c +++ b/lib/http.c @@ -761,7 +761,7 @@ CURLcode add_buffer_send(send_buffer *in, conn->fread = (curl_read_callback)readmoredata; conn->fread_in = (void *)conn; http->postdata = ptr; - http->postsize = size; + http->postsize = (curl_off_t)size; http->send_buffer = in; http->sending = HTTPSEND_REQUEST; -- cgit v1.2.1 From a7bed4fc7c8b734c66a731a49f92ee4c9b9ba707 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 28 Jul 2004 21:13:29 +0000 Subject: Fixes Brian Akins' reported problems with duplicate Host: headers on re-used connections. --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d1128d499..4b3e7dfb4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1351,6 +1351,8 @@ CURLcode Curl_http(struct connectdata *conn) } } + Curl_safefree(conn->allocptr.host); + ptr = checkheaders(data, "Host:"); if(ptr && !data->state.this_is_a_follow) { /* If we have a given custom Host: header, we extract the host name in @@ -1374,10 +1376,10 @@ CURLcode Curl_http(struct connectdata *conn) memcpy(conn->allocptr.cookiehost, start, len); conn->allocptr.cookiehost[len]=0; } + + conn->allocptr.host = NULL; } else { - Curl_safefree(conn->allocptr.host); - /* When building Host: headers, we must put the host name within [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ -- cgit v1.2.1 From 45197b188e64f135a8fc207b158e16b789b26f60 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 Aug 2004 07:24:25 +0000 Subject: Roland Krikava's cookies over proxy fix. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4b3e7dfb4..567d16dd2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1620,7 +1620,7 @@ CURLcode Curl_http(struct connectdata *conn) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, ppath, + conn->allocptr.cookiehost:host, conn->path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } -- cgit v1.2.1 From 2646af106b04480fa5b063625deb5feb25c8df65 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 Aug 2004 13:25:30 +0000 Subject: allow a custom "Accept-Encoding:" header override the internally set one that gets set with CURLOPT_ENCODING --- lib/http.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 567d16dd2..07354a1c4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1325,6 +1325,15 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.cookie && !checkheaders(data, "Cookie:")) addcookies = data->set.cookie; + if(!checkheaders(data, "Accept-Encoding:") && + data->set.encoding) { + Curl_safefree(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\015\012", data->set.encoding); + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + } + if(!conn->bits.upload_chunky && (httpreq != HTTPREQ_GET)) { /* not a chunky transfer yet, but data is to be sent */ ptr = checkheaders(data, "Transfer-Encoding:"); -- cgit v1.2.1 From 723bfe42e7d0de40fd80b25ec64a88122f2c69f1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 23 Aug 2004 12:34:55 +0000 Subject: Roman Koifman pointed out that libcurl send Expect: 100-continue on POSTs and PUTs even when told to use HTTP 1.0, which is not correct. --- lib/http.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 07354a1c4..29ce503f8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1765,10 +1765,12 @@ CURLcode Curl_http(struct connectdata *conn) return result; } - if(!checkheaders(data, "Expect:")) { - /* if not disabled explicitly we add a Expect: 100-continue - to the headers which actually speeds up post operations (as - there is one packet coming back from the web server) */ + if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + !checkheaders(data, "Expect:")) { + /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: + 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web + server) */ result = add_bufferf(req_buffer, "Expect: 100-continue\r\n"); if(result) @@ -1832,10 +1834,12 @@ CURLcode Curl_http(struct connectdata *conn) return result; } - if(!checkheaders(data, "Expect:")) { - /* if not disabled explicitly we add a Expect: 100-continue - to the headers which actually speeds up post operations (as - there is one packet coming back from the web server) */ + if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + !checkheaders(data, "Expect:")) { + /* if not HTTP 1.0 or disabled explicitly, we add a Expect: + 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web + server) */ result = add_bufferf(req_buffer, "Expect: 100-continue\r\n"); if(result) @@ -1945,10 +1949,12 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - if(!checkheaders(data, "Expect:")) { - /* if not disabled explicitly we add a Expect: 100-continue to the - headers which actually speeds up post operations (as there is - one packet coming back from the web server) */ + if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + !checkheaders(data, "Expect:")) { + /* if not HTTP 1.0 or disabled explicitly, we add a Expect: + 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web + server) */ add_bufferf(req_buffer, "Expect: 100-continue\r\n"); data->set.expect100header = TRUE; -- cgit v1.2.1 From b8b56248bddc646bf8d262dc9c5b45ce68a1ef08 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 10 Sep 2004 20:58:51 +0000 Subject: - Bug report #1025986. When following a Location: with a custom Host: header replacement, curl only replaced the Host: header on the initial request and didn't replace it on the following ones. This resulted in requests with two Host: headers. Now, curl checks if the location is on the same host as the initial request and then continues to replace the Host: header. And when it moves to another host, it doesn't replace the Host: header but it also doesn't make the second Host: header get used in the request. This change is verified by the two new test cases 184 and 185. --- lib/http.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 29ce503f8..52dc8486b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -299,8 +299,8 @@ Curl_http_output_auth(struct connectdata *conn, /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || - !data->state.auth_host || - curl_strequal(data->state.auth_host, conn->host.name) || + !data->state.first_host || + curl_strequal(data->state.first_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { /* Send proxy authentication header if needed */ @@ -1156,14 +1156,13 @@ CURLcode Curl_http_connect(struct connectdata *conn) return result; } - if(conn->bits.user_passwd && !data->state.this_is_a_follow) { - /* Authorization: is requested, this is not a followed location, get the - original host name */ - if (data->state.auth_host) + if(!data->state.this_is_a_follow) { + /* this is not a followed location, get the original host name */ + if (data->state.first_host) /* Free to avoid leaking memory on multiple requests*/ - free(data->state.auth_host); + free(data->state.first_host); - data->state.auth_host = strdup(conn->host.name); + data->state.first_host = strdup(conn->host.name); } return CURLE_OK; @@ -1363,11 +1362,13 @@ CURLcode Curl_http(struct connectdata *conn) Curl_safefree(conn->allocptr.host); ptr = checkheaders(data, "Host:"); - if(ptr && !data->state.this_is_a_follow) { + if(ptr && (!data->state.this_is_a_follow || + curl_strequal(data->state.first_host, conn->host.name))) { /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the custom Host: header if this is NOT a redirect, as setting Host: in the - redirected request is being out on thin ice. */ + redirected request is being out on thin ice. Except if the host name + is the same as the first one! */ char *start = ptr+strlen("Host:"); while(*start && isspace((int)*start )) start++; @@ -1379,6 +1380,7 @@ CURLcode Curl_http(struct connectdata *conn) if(ptr != start) { size_t len=ptr-start; + Curl_safefree(conn->allocptr.cookiehost); conn->allocptr.cookiehost = malloc(len+1); if(!conn->allocptr.cookiehost) return CURLE_OUT_OF_MEMORY; @@ -1727,9 +1729,17 @@ CURLcode Curl_http(struct connectdata *conn) if(*ptr) { /* only send this if the contents was non-blank */ - result = add_bufferf(req_buffer, "%s\r\n", headers->data); - if(result) - return result; + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + curl_strnequal("Host:", headers->data, 5)) + ; + else { + + result = add_bufferf(req_buffer, "%s\r\n", headers->data); + if(result) + return result; + } } } headers = headers->next; -- cgit v1.2.1 From 39af394a1c3ae1d8ac71ad263a7c524988702c2e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 6 Oct 2004 07:50:18 +0000 Subject: removed tabs and trailing whitespace from source --- lib/http.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 52dc8486b..80484975f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -967,7 +967,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(result) return result; - FD_ZERO (&readfd); /* clear it */ + FD_ZERO (&readfd); /* clear it */ FD_SET (tunnelsocket, &readfd); /* read socket */ /* get this in a backup variable to be able to restore it on each lap in @@ -1555,17 +1555,17 @@ CURLcode Curl_http(struct connectdata *conn) curl_off_t total_expected_size= conn->resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%" FORMAT_OFF_T + aprintf("Content-Range: bytes %s%" FORMAT_OFF_T "/%" FORMAT_OFF_T "\r\n", - conn->range, total_expected_size-1, - total_expected_size); + conn->range, total_expected_size-1, + total_expected_size); } else { /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", - conn->range, data->set.infilesize); + aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", + conn->range, data->set.infilesize); } } } -- cgit v1.2.1 From a00e7f0f5ecd8fd93951a85ef86eb8b3c58f092e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Oct 2004 11:28:40 +0000 Subject: Tomas Pospisek filed bug report #1053287 that proved -C - and --fail on a file that was already completely downloaded caused an error, while it doesn't if you don't use --fail! I added test case 194 to verify the fix. Grrr. CURLOPT_FAILONERROR is now added to the list stuff to remove in libcurl v8 due to all the kludges needed to support it. --- lib/http.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 80484975f..ee5b81ff6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -553,6 +553,14 @@ int Curl_http_should_fail(struct connectdata *conn) if (k->httpcode < 400) return 0; + if (conn->resume_from && + (data->set.httpreq==HTTPREQ_GET) && + (k->httpcode == 416)) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + return 0; + } + /* ** Any code >= 400 that's not 401 or 407 is always ** a terminal error -- cgit v1.2.1 From 24d47a6e07304cf0921f2d30734b3c64360773c3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Nov 2004 10:12:22 +0000 Subject: Paul Nolan fix to make libcurl build nicely on Windows CE --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ee5b81ff6..1de316b2f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -30,8 +30,12 @@ #include #include #include +#ifdef HAVE_SYS_TYPES_H #include +#endif +#ifdef HAVE_SYS_STAT_H #include +#endif #include -- cgit v1.2.1 From 6b49fd74838d674011e18fcddcf497ba073052a2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Nov 2004 14:43:35 +0000 Subject: Tim Sneddon's VMS fix for huge HTTP POSTs --- lib/http.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1de316b2f..9b51cc7d6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1925,14 +1925,15 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.postfields) { if((data->state.authhost.done || data->state.authproxy.done ) - && (postsize < (100*1024))) { + && (postsize < MAX_INITIAL_POST_SIZE)) { /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ - /* The post data is less than 100K, then append it to the header. - This limit is no magic limit but only set to prevent really huge - POSTs to get the data duplicated with malloc() and family. */ + /* The post data is less than MAX_INITIAL_PORT_SIZE, then append it + to the header. This limit is no magic limit but only set to + prevent really huge POSTs to get the data duplicated with + malloc() and family. */ result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) -- cgit v1.2.1 From 59c063dfd38972e06a7f3a0b8f94860a67acdc96 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Nov 2004 23:11:04 +0000 Subject: Fix behaviour when passing NULL to CURLOPT_POSTFIELDS and CURLOPT_HTTPPOST. --- lib/http.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9b51cc7d6..cdc3e1d8c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1767,6 +1767,24 @@ CURLcode Curl_http(struct connectdata *conn) switch(httpreq) { case HTTPREQ_POST_FORM: + if(!http->sendit) { + /* nothing to post! */ + result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); + if(result) + return result; + + result = add_buffer_send(req_buffer, conn, + &data->info.request_size); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + -1, NULL); + break; + } + if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!"); return CURLE_HTTP_POST_ERROR; @@ -1895,7 +1913,7 @@ CURLcode Curl_http(struct connectdata *conn) /* this is the simple POST, using x-www-form-urlencoded style */ /* store the size of the postfields */ - postsize = data->set.postfieldsize? + postsize = (data->set.postfieldsize != -1)? data->set.postfieldsize: (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); @@ -1989,12 +2007,14 @@ CURLcode Curl_http(struct connectdata *conn) else { add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + if(data->set.postfieldsize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); - /* set the pointer to mark that we will send the post body using - the read callback */ - http->postdata = (char *)&http->postdata; + /* set the pointer to mark that we will send the post body using + the read callback */ + http->postdata = (char *)&http->postdata; + } } /* issue the request */ result = add_buffer_send(req_buffer, conn, -- cgit v1.2.1 From 94043b11508b9a4bf1fbee9ea17ef658c6413d9d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 12 Nov 2004 09:18:14 +0000 Subject: Dan Fandrich added the --disable-crypto-auth option to configure to allow libcurl to build without Digest support. (I figure it should also explicitly disable Negotiate and NTLM.) --- lib/http.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cdc3e1d8c..20cd1c15f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -330,6 +330,7 @@ Curl_http_output_auth(struct connectdata *conn, } data->state.authproxy.done = TRUE; } +#ifndef CURL_DISABLE_CRYPTO_AUTH else if(data->state.authproxy.want == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, @@ -339,7 +340,7 @@ Curl_http_output_auth(struct connectdata *conn, if(result) return result; } - +#endif infof(data, "Proxy auth using %s with user '%s'\n", auth, conn->proxyuser?conn->proxyuser:""); } @@ -373,6 +374,7 @@ Curl_http_output_auth(struct connectdata *conn, else #endif { +#ifndef CURL_DISABLE_CRYPTO_AUTH if(data->state.authhost.picked == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, @@ -381,8 +383,9 @@ Curl_http_output_auth(struct connectdata *conn, (unsigned char *)path); if(result) return result; - } - else if(data->state.authhost.picked == CURLAUTH_BASIC) { + } else +#endif + if(data->state.authhost.picked == CURLAUTH_BASIC) { if(conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { auth=(char *)"Basic"; @@ -489,6 +492,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } else #endif +#ifndef CURL_DISABLE_CRYPTO_AUTH if(checkprefix("Digest", start)) { CURLdigest dig; *availp |= CURLAUTH_DIGEST; @@ -504,7 +508,9 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, data->state.authproblem = TRUE; } } - else if(checkprefix("Basic", start)) { + else +#endif + if(checkprefix("Basic", start)) { *availp |= CURLAUTH_BASIC; authp->avail |= CURLAUTH_BASIC; if(authp->picked == CURLAUTH_BASIC) { -- cgit v1.2.1 From 1a05a90f1ce86394d7966aaaa9539adaa228c6bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Nov 2004 08:52:33 +0000 Subject: David Phillips' FD_SETSIZE fix --- lib/http.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 20cd1c15f..50638f5bf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -74,10 +74,6 @@ #include #endif -#ifdef HAVE_SYS_SELECT_H -#include -#endif - #endif #include "urldata.h" @@ -98,6 +94,7 @@ #include "hostip.h" #include "http.h" #include "memory.h" +#include "select.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -935,9 +932,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, ssize_t gotbytes; char *ptr; long timeout = 3600; /* default timeout in seconds */ - struct timeval interval; - fd_set rkeepfd; - fd_set readfd; + int interval_ms; char *line_start; char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; @@ -985,13 +980,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(result) return result; - FD_ZERO (&readfd); /* clear it */ - FD_SET (tunnelsocket, &readfd); /* read socket */ - - /* get this in a backup variable to be able to restore it on each lap in - the select() loop */ - rkeepfd = readfd; - ptr=data->state.buffer; line_start = ptr; @@ -1000,9 +988,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, keepon=TRUE; while((nreadset.timeout) { /* if timeout is requested, find out how much remaining time we have */ @@ -1015,7 +1001,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } } - switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) { + switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, interval_ms)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; failf(data, "Proxy CONNECT aborted due to select() error"); -- cgit v1.2.1 From 3e1caa61859a6057a65eb7c1585d47e05026c4f2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Nov 2004 16:11:35 +0000 Subject: HTTP "auth done right". See lib/README.httpauth --- lib/http.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 151 insertions(+), 49 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 50638f5bf..1277fa21d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -192,6 +192,80 @@ static bool pickoneauth(struct auth *pick) return picked; } +/* + * perhapsrewind() + * + * If we are doing POST or PUT { + * If we have more data to send { + * If we are doing NTLM { + * Keep sending since we must not disconnect + * } + * else { + * If there is more than just a little data left to send, close + * the current connection by force. + * } + * } + * If we have sent any data { + * If we don't have track of all the data { + * call app to tell it to rewind + * } + * else { + * rewind internally so that the operation can restart fine + * } + * } + * } + */ +static CURLcode perhapsrewind(struct connectdata *conn) +{ + struct HTTP *http = conn->proto.http; + struct SessionHandle *data = conn->data; + curl_off_t bytessent = http->writebytecount; + curl_off_t expectsend = -1; /* default is unknown */ + + /* figure out how much data we are expected to send */ + switch(data->set.httpreq) { + case HTTPREQ_POST: + if(data->set.postfieldsize != -1) + expectsend = data->set.postfieldsize; + break; + case HTTPREQ_PUT: + if(data->set.infilesize != -1) + expectsend = data->set.infilesize; + break; + case HTTPREQ_POST_FORM: + expectsend = http->postsize; + break; + default: + break; + } + + conn->bits.rewindaftersend = FALSE; /* default */ + + if((expectsend == -1) || (expectsend > bytessent)) { + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) ||/* using NTLM */ + (data->state.authhost.picked == CURLAUTH_NTLM) ) { + conn->bits.close = FALSE; /* don't close, keep on sending */ + + /* rewind data when completely done sending! */ + conn->bits.rewindaftersend = TRUE; + return CURLE_OK; + } + else { + /* If there is more than just a little data left to send, close the + * current connection by force. + */ + conn->bits.close = TRUE; + conn->size = 0; /* don't download any more than 0 bytes */ + } + } + + if(bytessent) + return Curl_readrewind(conn); + + return CURLE_OK; +} + /* * Curl_http_auth_act() gets called when a all HTTP headers have been received * and it checks what authentication methods that are available and decides @@ -211,25 +285,33 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(conn->bits.user_passwd && ((conn->keep.httpcode == 401) || - (conn->bits.authprobe && conn->keep.httpcode < 300))) { + (conn->bits.authneg && conn->keep.httpcode < 300))) { pickhost = pickoneauth(&data->state.authhost); if(!pickhost) data->state.authproblem = TRUE; } if(conn->bits.proxy_user_passwd && ((conn->keep.httpcode == 407) || - (conn->bits.authprobe && conn->keep.httpcode < 300))) { + (conn->bits.authneg && conn->keep.httpcode < 300))) { pickproxy = pickoneauth(&data->state.authproxy); if(!pickproxy) data->state.authproblem = TRUE; } - if(pickhost || pickproxy) + if(pickhost || pickproxy) { conn->newurl = strdup(data->change.url); /* clone URL */ + if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { + code = perhapsrewind(conn); + if(code) + return code; + } + } + else if((conn->keep.httpcode < 300) && (!data->state.authhost.done) && - conn->bits.authprobe) { + conn->bits.authneg) { /* no (known) authentication available, authentication is not "done" yet and no authentication seems to be required and @@ -273,29 +355,34 @@ Curl_http_output_auth(struct connectdata *conn, CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; char *auth=NULL; + struct auth *authhost; + struct auth *authproxy; curlassert(data); + authhost = &data->state.authhost; + authproxy = &data->state.authproxy; + if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || conn->bits.user_passwd) /* continue please */ ; else { - data->state.authhost.done = TRUE; - data->state.authproxy.done = TRUE; + authhost->done = TRUE; + authproxy->done = TRUE; return CURLE_OK; /* no authentication with no user or password */ } - if(data->state.authhost.want && !data->state.authhost.picked) + if(authhost->want && !authhost->picked) /* The app has selected one or more methods, but none has been picked so far by a server round-trip. Then we set the picked one to the want one, and if this is one single bit it'll be used instantly. */ - data->state.authhost.picked = data->state.authhost.want; + authhost->picked = authhost->want; - if(data->state.authproxy.want && !data->state.authproxy.picked) + if(authproxy->want && !authproxy->picked) /* The app has selected one or more methods, but none has been picked so far by a proxy round-trip. Then we set the picked one to the want one, and if this is one single bit it'll be used instantly. */ - data->state.authproxy.picked = data->state.authproxy.want; + authproxy->picked = authproxy->want; /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ @@ -308,7 +395,7 @@ Curl_http_output_auth(struct connectdata *conn, if (conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { #ifdef USE_SSLEAY - if(data->state.authproxy.want == CURLAUTH_NTLM) { + if(authproxy->want == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE); if(result) @@ -316,7 +403,7 @@ Curl_http_output_auth(struct connectdata *conn, } else #endif - if(data->state.authproxy.want == CURLAUTH_BASIC) { + if(authproxy->want == CURLAUTH_BASIC) { /* Basic */ if(conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { @@ -325,10 +412,12 @@ Curl_http_output_auth(struct connectdata *conn, if(result) return result; } - data->state.authproxy.done = TRUE; + /* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth + functions work that way */ + authproxy->done = TRUE; } #ifndef CURL_DISABLE_CRYPTO_AUTH - else if(data->state.authproxy.want == CURLAUTH_DIGEST) { + else if(authproxy->want == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, TRUE, /* proxy */ @@ -338,31 +427,36 @@ Curl_http_output_auth(struct connectdata *conn, return result; } #endif - infof(data, "Proxy auth using %s with user '%s'\n", - auth, conn->proxyuser?conn->proxyuser:""); + if(auth) { + infof(data, "Proxy auth using %s with user '%s'\n", + auth, conn->proxyuser?conn->proxyuser:""); + authproxy->multi = !authproxy->done; + } + else + authproxy->multi = FALSE; } else /* we have no proxy so let's pretend we're done authenticating with it */ - data->state.authproxy.done = TRUE; + authproxy->done = TRUE; /* Send web authentication header if needed */ { auth = NULL; #ifdef HAVE_GSSAPI - if((data->state.authhost.want == CURLAUTH_GSSNEGOTIATE) && + if((authhost->want == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { auth=(char *)"GSS-Negotiate"; result = Curl_output_negotiate(conn); if (result) return result; - data->state.authhost.done = TRUE; + authhost->done = TRUE; } else #endif #ifdef USE_SSLEAY - if(data->state.authhost.picked == CURLAUTH_NTLM) { + if(authhost->picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE); if(result) @@ -372,7 +466,7 @@ Curl_http_output_auth(struct connectdata *conn, #endif { #ifndef CURL_DISABLE_CRYPTO_AUTH - if(data->state.authhost.picked == CURLAUTH_DIGEST) { + if(authhost->picked == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, FALSE, /* not a proxy */ @@ -382,7 +476,7 @@ Curl_http_output_auth(struct connectdata *conn, return result; } else #endif - if(data->state.authhost.picked == CURLAUTH_BASIC) { + if(authhost->picked == CURLAUTH_BASIC) { if(conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { auth=(char *)"Basic"; @@ -391,16 +485,21 @@ Curl_http_output_auth(struct connectdata *conn, return result; } /* basic is always ready */ - data->state.authhost.done = TRUE; + authhost->done = TRUE; } } - if(auth) + if(auth) { infof(data, "Server auth using %s with user '%s'\n", auth, conn->user); + + authhost->multi = !authhost->done; + } + else + authhost->multi = FALSE; } } else - data->state.authhost.done = TRUE; + authhost->done = TRUE; return result; } @@ -1304,20 +1403,15 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; - if((!data->state.authhost.done || !data->state.authproxy.done ) && - (httpreq != HTTPREQ_GET)) { - /* Until we are authenticated, we switch over to HEAD. Unless its a GET - we want to do. The explanation for this is rather long and boring, but - the point is that it can't be done otherwise without risking having to - send the POST or PUT data multiple times. */ - httpreq = HTTPREQ_HEAD; - request = (char *)"HEAD"; - conn->bits.no_body = TRUE; - conn->bits.authprobe = TRUE; /* this is a request done to probe for - authentication methods */ + if((data->state.authhost.multi || data->state.authproxy.multi) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST + with content-length zero as a "probe". */ + conn->bits.authneg = TRUE; } else - conn->bits.authprobe = FALSE; + conn->bits.authneg = FALSE; Curl_safefree(conn->allocptr.ref); if(data->change.referer && !checkheaders(data, "Referer:")) @@ -1759,7 +1853,7 @@ CURLcode Curl_http(struct connectdata *conn) switch(httpreq) { case HTTPREQ_POST_FORM: - if(!http->sendit) { + if(!http->sendit || conn->bits.authneg) { /* nothing to post! */ result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); if(result) @@ -1857,11 +1951,16 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - if((data->set.infilesize>0) && !conn->bits.upload_chunky) { + if(conn->bits.authneg) + postsize = 0; + else + postsize = data->set.infilesize; + + if((postsize != -1) && !conn->bits.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ - data->set.infilesize ); + "Content-Length: %" FORMAT_OFF_T "\r\n", + postsize ); if(result) return result; } @@ -1884,19 +1983,19 @@ CURLcode Curl_http(struct connectdata *conn) return result; /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, postsize); /* this sends the buffer and frees all the buffer resources */ result = add_buffer_send(req_buffer, conn, &data->info.request_size); if(result) - failf(data, "Failed sending POST request"); + failf(data, "Failed sending PUT request"); else /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + postsize?FIRSTSOCKET:-1, + postsize?&http->writebytecount:NULL); if(result) return result; break; @@ -1904,10 +2003,13 @@ CURLcode Curl_http(struct connectdata *conn) case HTTPREQ_POST: /* this is the simple POST, using x-www-form-urlencoded style */ - /* store the size of the postfields */ - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: - (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); + if(conn->bits.authneg) + postsize = 0; + else + /* figure out the size of the postfields */ + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: + (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if -- cgit v1.2.1 From 15360e5e51aabb142cb71b130ae6a24ff2ba86dd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Dec 2004 17:08:37 +0000 Subject: prevent an initial "(nil)" to get sent in the initial request when doing CONNECT to a proxy with digest --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1277fa21d..c397438c4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1068,7 +1068,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, "%s" "\r\n", hostname, remote_port, - conn->bits.proxy_user_passwd? + conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", data->set.useragent?conn->allocptr.uagent:"" ); -- cgit v1.2.1 From 8726a6b6ed8c063e51cd605347b9dc4baff886b7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Dec 2004 22:52:14 +0000 Subject: comment cleanup --- lib/http.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c397438c4..0a20c833c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1031,7 +1031,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, ssize_t gotbytes; char *ptr; long timeout = 3600; /* default timeout in seconds */ - int interval_ms; + char *line_start; char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; @@ -1087,7 +1087,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, keepon=TRUE; while((nreadset.timeout) { /* if timeout is requested, find out how much remaining time we have */ @@ -1100,7 +1099,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } } - switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, interval_ms)) { + /* timeout each second and check the timeout */ + switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, 1000)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; failf(data, "Proxy CONNECT aborted due to select() error"); @@ -1108,12 +1108,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, case 0: /* timeout */ break; default: - /* - * This code previously didn't use the kerberos sec_read() code - * to read, but when we use Curl_read() it may do so. Do confirm - * that this is still ok and then remove this comment! - */ - res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); + res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); if(res< 0) /* EWOULDBLOCK */ continue; /* go loop yourself */ @@ -1128,12 +1123,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* * We got a whole chunk of data, which can be anything from one byte * to a set of lines and possibly just a piece of the last line. - * - * TODO: To make this code work less error-prone, we need to make - * sure that we read and create full lines before we compare them, - * as there is really nothing that stops the proxy from delivering - * the response lines in multiple parts, each part consisting of - * only a little piece of the line(s). */ + */ int i; nread += gotbytes; @@ -1143,7 +1133,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, char letter; int writetype; - /* output debug output if that is requested */ + /* output debug if that is requested */ if(data->set.verbose) Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, conn->host.dispname); -- cgit v1.2.1 From 6ac9e67bd758e99a5ec385dba4492de3c35cd25f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Dec 2004 23:30:13 +0000 Subject: made the intended one hour default timeout in the CONNECT loop actually work --- lib/http.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0a20c833c..d7a43ab30 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1024,14 +1024,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, struct Curl_transfer_keeper *k = &conn->keep; CURLcode result; int res; - size_t nread; /* total size read */ int perline; /* count bytes per line */ bool keepon=TRUE; ssize_t gotbytes; char *ptr; - long timeout = 3600; /* default timeout in seconds */ - + long timeout = + data->set.timeout?data->set.timeout:3600; /* in seconds */ char *line_start; char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; @@ -1088,15 +1087,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, while((nreadset.timeout) { - /* if timeout is requested, find out how much remaining time we have */ - timeout = data->set.timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ - if(timeout <=0 ) { - failf(data, "Proxy connection aborted due to timeout"); - error = SELECT_TIMEOUT; /* already too little time */ - break; - } + /* if timeout is requested, find out how much remaining time we have */ + long check = timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ + if(check <=0 ) { + failf(data, "Proxy CONNECT aborted due to timeout"); + error = SELECT_TIMEOUT; /* already too little time */ + break; } /* timeout each second and check the timeout */ -- cgit v1.2.1 From ac269a8f68323db6b579f11f864035bc2691081d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 5 Dec 2004 23:59:32 +0000 Subject: Dan Fandrich added the --disable-cookies option to configure to build libcurl without cookie support. This is mainly useful if you want to build a minimalistic libcurl with no cookies support at all. Like for embedded systems or similar. --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d7a43ab30..8303c5301 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1449,6 +1449,7 @@ CURLcode Curl_http(struct connectdata *conn) ptr = checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || curl_strequal(data->state.first_host, conn->host.name))) { +#if !defined(CURL_DISABLE_COOKIES) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the custom Host: header if this is NOT a redirect, as setting Host: in the @@ -1472,6 +1473,7 @@ CURLcode Curl_http(struct connectdata *conn) memcpy(conn->allocptr.cookiehost, start, len); conn->allocptr.cookiehost[len]=0; } +#endif conn->allocptr.host = NULL; } @@ -1708,6 +1710,7 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; +#if !defined(CURL_DISABLE_COOKIES) if(data->cookies || addcookies) { struct Cookie *co=NULL; /* no cookies from start */ int count=0; @@ -1757,6 +1760,7 @@ CURLcode Curl_http(struct connectdata *conn) if(result) return result; } +#endif if(data->set.timecondition) { struct tm *thistime; -- cgit v1.2.1 From c0c885a1f37c5cbced25cb9616c4f868151fd740 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 10 Dec 2004 14:45:35 +0000 Subject: don't try the rewind if no http struct is allocated yet --- lib/http.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8303c5301..d984eddc1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -219,9 +219,16 @@ static CURLcode perhapsrewind(struct connectdata *conn) { struct HTTP *http = conn->proto.http; struct SessionHandle *data = conn->data; - curl_off_t bytessent = http->writebytecount; + curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ + if(!http) + /* If this is still NULL, we have not reach very far and we can + safely skip this rewinding stuff */ + return CURLE_OK; + + bytessent = http->writebytecount; + /* figure out how much data we are expected to send */ switch(data->set.httpreq) { case HTTPREQ_POST: -- cgit v1.2.1 From d3b414724b18e84ed32c044527aac9a85e434690 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Dec 2004 09:52:36 +0000 Subject: Dinar in bug report #1086121, found a file handle leak when a multipart formpost (including a file upload part) was aborted before the whole file was sent. --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d984eddc1..79e51b752 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1299,6 +1299,9 @@ CURLcode Curl_http_done(struct connectdata *conn, conn->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ + if(http->form.fp) + /* a file being uploaded was left opened, close it! */ + fclose(http->form.fp); } else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; -- cgit v1.2.1 From 494c40fd983ef591dd37c2901d8a24554ace7a95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Dec 2004 13:55:19 +0000 Subject: NULL the fp pointer after it has been fclosed() --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 79e51b752..8e4ee7d82 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1299,9 +1299,11 @@ CURLcode Curl_http_done(struct connectdata *conn, conn->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ - if(http->form.fp) + if(http->form.fp) { /* a file being uploaded was left opened, close it! */ fclose(http->form.fp); + http->form.fp = NULL; + } } else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; -- cgit v1.2.1 From 7e42cb61f75890832792c082510ec610f4c32cbe Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 21 Jan 2005 09:32:32 +0000 Subject: FTP third transfer support overhaul. See CHANGES for details. --- lib/http.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8e4ee7d82..2618c325f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -858,8 +858,7 @@ CURLcode add_buffer_send(send_buffer *in, if(conn->data->set.verbose) /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount, - conn->host.dispname); + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount, conn); *bytes_written += amount; @@ -1140,7 +1139,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* output debug if that is requested */ if(data->set.verbose) Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, - conn->host.dispname); + conn); /* send the header to the callback */ writetype = CLIENTWRITE_HEADER; -- cgit v1.2.1 From 7b23eff9cf32d498b8b04b5a983f1b26e2eb5795 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 6 Feb 2005 12:43:40 +0000 Subject: Preserve previous status in Curl_http_done(). --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2618c325f..3a7af8f6e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1274,7 +1274,6 @@ CURLcode Curl_http_done(struct connectdata *conn, { struct SessionHandle *data; struct HTTP *http; - (void)status; /* no use for us */ data=conn->data; http=conn->proto.http; @@ -1291,7 +1290,7 @@ CURLcode Curl_http_done(struct connectdata *conn, free(buff->buffer); free(buff); - http->send_buffer = NULL; /* cleaer the pointer */ + http->send_buffer = NULL; /* clear the pointer */ } if(HTTPREQ_POST_FORM == data->set.httpreq) { @@ -1307,6 +1306,9 @@ CURLcode Curl_http_done(struct connectdata *conn, else if(HTTPREQ_PUT == data->set.httpreq) conn->bytecount = http->readbytecount + http->writebytecount; + if (status != CURLE_OK) + return (status); + if(!conn->bits.retry && ((http->readbytecount + conn->headerbytecount - -- cgit v1.2.1 From 6a2e21ec8cbaf7c719902e06953d9dbec629ad4f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 9 Feb 2005 13:06:40 +0000 Subject: FTP code turned into state machine. Not completely yet, but a good start. The tag 'before_ftp_statemachine' was set just before this commit in case of future need. --- lib/http.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3a7af8f6e..051643126 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1222,7 +1222,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, * Curl_http_connect() performs HTTP stuff to do at connect-time, called from * the generic Curl_connect(). */ -CURLcode Curl_http_connect(struct connectdata *conn) +CURLcode Curl_http_connect(struct connectdata *conn, bool *done) { struct SessionHandle *data; CURLcode result; @@ -1261,6 +1261,8 @@ CURLcode Curl_http_connect(struct connectdata *conn) data->state.first_host = strdup(conn->host.name); } + *done = TRUE; + return CURLE_OK; } @@ -1328,7 +1330,7 @@ CURLcode Curl_http_done(struct connectdata *conn, * request is to be performed. This creates and sends a properly constructed * HTTP request. */ -CURLcode Curl_http(struct connectdata *conn) +CURLcode Curl_http(struct connectdata *conn, bool *done) { struct SessionHandle *data=conn->data; char *buf = data->state.buffer; /* this is a short cut to the buffer */ @@ -1342,6 +1344,11 @@ CURLcode Curl_http(struct connectdata *conn) Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; + /* Always consider the DO phase done after this function call, even if there + may be parts of the request that is not yet sent, since we can deal with + the rest of the request in the PERFORM phase. */ + *done = TRUE; + if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ -- cgit v1.2.1 From e7cefd684b2d5e1f3710eb24babc0b9974095c97 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 11 Feb 2005 00:03:49 +0000 Subject: Removed all uses of strftime() since it uses the localised version of the week day names and month names and servers don't like that. --- lib/http.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 051643126..706cf7e30 100644 --- a/lib/http.c +++ b/lib/http.c @@ -95,6 +95,7 @@ #include "http.h" #include "memory.h" #include "select.h" +#include "parsedate.h" /* for the week day and month names */ #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1783,7 +1784,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #endif if(data->set.timecondition) { - struct tm *thistime; + struct tm *tm; /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since * header family should have their times set in GMT as RFC2616 defines: @@ -1795,18 +1796,22 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #ifdef HAVE_GMTIME_R /* thread-safe version */ struct tm keeptime; - thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); + tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); #else - thistime = gmtime(&data->set.timevalue); + tm = gmtime(&data->set.timevalue); #endif -#ifdef HAVE_STRFTIME /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S GMT", thistime); -#else - /* TODO: Right, we *could* write a replacement here */ - strcpy(buf, "no strftime() support"); -#endif + snprintf(buf, BUFSIZE-1, + "%s, %02d %s %4d %02d:%02d:%02d GMT", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + switch(data->set.timecondition) { case CURL_TIMECOND_IFMODSINCE: default: -- cgit v1.2.1 From ac022b2e30f42f860f365348ee569f87d0fbe1cf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 16 Feb 2005 14:31:23 +0000 Subject: Christopher R. Palmer reported a problem with HTTP-POSTing using "anyauth" that picks NTLM. Thanks to David Byron letting me test NTLM against his servers, I could quickly repeat and fix the problem. It turned out to be: When libcurl POSTs without knowing/using an authentication and it gets back a list of types from which it picks NTLM, it needs to either continue sending its data if it keeps the connection alive, or not send the data but close the connection. Then do the first step in the NTLM auth. libcurl didn't send the data nor close the connection but simply read the response-body and then sent the first negotiation step. Which then failed miserably of course. The fixed version forces a connection if there is more than 2000 bytes left to send. --- lib/http.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 706cf7e30..a5f29da3b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -251,21 +251,31 @@ static CURLcode perhapsrewind(struct connectdata *conn) if((expectsend == -1) || (expectsend > bytessent)) { /* There is still data left to send */ - if((data->state.authproxy.picked == CURLAUTH_NTLM) ||/* using NTLM */ - (data->state.authhost.picked == CURLAUTH_NTLM) ) { - conn->bits.close = FALSE; /* don't close, keep on sending */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM)) { + if(((expectsend - bytessent) < 2000) || + (conn->ntlm.state != NTLMSTATE_NONE)) { + /* The NTLM-negotiation has started *OR* there is just a little (<2K) + data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg) + conn->bits.rewindaftersend = TRUE; + + return CURLE_OK; + } + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; - /* rewind data when completely done sending! */ - conn->bits.rewindaftersend = TRUE; - return CURLE_OK; - } - else { - /* If there is more than just a little data left to send, close the - * current connection by force. - */ - conn->bits.close = TRUE; - conn->size = 0; /* don't download any more than 0 bytes */ + infof(data, "NTLM send, close instead of sending %ld bytes\n", + expectsend - bytessent); } + + /* This is not NTLM or NTLM with many bytes left to send: close + */ + conn->bits.close = TRUE; + conn->size = 0; /* don't download any more than 0 bytes */ } if(bytessent) @@ -310,7 +320,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) conn->newurl = strdup(data->change.url); /* clone URL */ if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD)) { + (data->set.httpreq != HTTPREQ_HEAD) && + !conn->bits.rewindaftersend) { code = perhapsrewind(conn); if(code) return code; -- cgit v1.2.1 From 5ba188ab2dda19d63a908fd245d9727f2d5df4ea Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 18 Feb 2005 23:53:07 +0000 Subject: Ralph Mitchell reported a flaw when you used a proxy with auth, and you requested data from a host and then followed a redirect to another host. libcurl then didn't use the proxy-auth properly in the second request, due to the host-only check for original host name wrongly being extended to the proxy auth as well. Added test case 233 to verify the flaw and that the fix removed the problem. --- lib/http.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a5f29da3b..ae2594737 100644 --- a/lib/http.c +++ b/lib/http.c @@ -403,24 +403,17 @@ Curl_http_output_auth(struct connectdata *conn, and if this is one single bit it'll be used instantly. */ authproxy->picked = authproxy->want; - /* To prevent the user+password to get sent to other than the original - host due to a location-follow, we do some weirdo checks here */ - if(!data->state.this_is_a_follow || - !data->state.first_host || - curl_strequal(data->state.first_host, conn->host.name) || - data->set.http_disable_hostname_check_before_authentication) { - - /* Send proxy authentication header if needed */ - if (conn->bits.httpproxy && - (conn->bits.tunnel_proxy == proxytunnel)) { + /* Send proxy authentication header if needed */ + if (conn->bits.httpproxy && + (conn->bits.tunnel_proxy == proxytunnel)) { #ifdef USE_SSLEAY - if(authproxy->want == CURLAUTH_NTLM) { - auth=(char *)"NTLM"; - result = Curl_output_ntlm(conn, TRUE); - if(result) - return result; - } - else + if(authproxy->want == CURLAUTH_NTLM) { + auth=(char *)"NTLM"; + result = Curl_output_ntlm(conn, TRUE); + if(result) + return result; + } + else #endif if(authproxy->want == CURLAUTH_BASIC) { /* Basic */ @@ -454,10 +447,17 @@ Curl_http_output_auth(struct connectdata *conn, else authproxy->multi = FALSE; } - else - /* we have no proxy so let's pretend we're done authenticating - with it */ - authproxy->done = TRUE; + else + /* we have no proxy so let's pretend we're done authenticating + with it */ + authproxy->done = TRUE; + + /* To prevent the user+password to get sent to other than the original + host due to a location-follow, we do some weirdo checks here */ + if(!data->state.this_is_a_follow || + !data->state.first_host || + curl_strequal(data->state.first_host, conn->host.name) || + data->set.http_disable_hostname_check_before_authentication) { /* Send web authentication header if needed */ { -- cgit v1.2.1 From d1d35ba85fe6f8a9e6a86d2a6c60109cf90edd6c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Mar 2005 23:15:29 +0000 Subject: Christopher R. Palmer made it possible to build libcurl with the USE_WINDOWS_SSPI on Windows, and then libcurl will be built to use the native way to do NTLM. SSPI also allows libcurl to pass on the current user and its password in the request. --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ae2594737..28799a6a4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -406,7 +406,7 @@ Curl_http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if (conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { -#ifdef USE_SSLEAY +#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) if(authproxy->want == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE); @@ -474,7 +474,7 @@ Curl_http_output_auth(struct connectdata *conn, } else #endif -#ifdef USE_SSLEAY +#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) if(authhost->picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE); @@ -587,7 +587,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } else #endif -#ifdef USE_SSLEAY +#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) /* NTLM support requires the SSL crypto libs */ if(checkprefix("NTLM", start)) { *availp |= CURLAUTH_NTLM; -- cgit v1.2.1 From 8a076d1dba48493eb009982ef68406dc5fc90ce9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 28 Mar 2005 22:19:31 +0000 Subject: Based on Augustus Saunders' comments and findings, the HTTP output auth function was fixed to use the proper proxy authentication when multiple ones were added as accepted. test 239 and test 243 were added to repeat the problems and verify the fixes. --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 28799a6a4..d86b34fa3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -407,7 +407,7 @@ Curl_http_output_auth(struct connectdata *conn, if (conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { #if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) - if(authproxy->want == CURLAUTH_NTLM) { + if(authproxy->picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE); if(result) @@ -415,7 +415,7 @@ Curl_http_output_auth(struct connectdata *conn, } else #endif - if(authproxy->want == CURLAUTH_BASIC) { + if(authproxy->picked == CURLAUTH_BASIC) { /* Basic */ if(conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { @@ -429,7 +429,7 @@ Curl_http_output_auth(struct connectdata *conn, authproxy->done = TRUE; } #ifndef CURL_DISABLE_CRYPTO_AUTH - else if(authproxy->want == CURLAUTH_DIGEST) { + else if(authproxy->picked == CURLAUTH_DIGEST) { auth=(char *)"Digest"; result = Curl_output_digest(conn, TRUE, /* proxy */ @@ -463,7 +463,7 @@ Curl_http_output_auth(struct connectdata *conn, { auth = NULL; #ifdef HAVE_GSSAPI - if((authhost->want == CURLAUTH_GSSNEGOTIATE) && + if((authhost->picked == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { auth=(char *)"GSS-Negotiate"; -- cgit v1.2.1 From 158588640a6d79bb20b1b1ed6497b7802969868e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Mar 2005 12:28:25 +0000 Subject: Don't close the connection if we're in a known negotiation mode and we won't send any data anyway. Probably the bug Tom Moers noticed. --- lib/http.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d86b34fa3..308f9efc3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -230,21 +230,27 @@ static CURLcode perhapsrewind(struct connectdata *conn) bytessent = http->writebytecount; - /* figure out how much data we are expected to send */ - switch(data->set.httpreq) { - case HTTPREQ_POST: - if(data->set.postfieldsize != -1) - expectsend = data->set.postfieldsize; - break; - case HTTPREQ_PUT: - if(data->set.infilesize != -1) - expectsend = data->set.infilesize; - break; - case HTTPREQ_POST_FORM: - expectsend = http->postsize; - break; - default: - break; + if(conn->bits.authneg) + /* This is a state where we are known to be negotiating and we don't send + any data then. */ + expectsend = 0; + else { + /* figure out how much data we are expected to send */ + switch(data->set.httpreq) { + case HTTPREQ_POST: + if(data->set.postfieldsize != -1) + expectsend = data->set.postfieldsize; + break; + case HTTPREQ_PUT: + if(data->set.infilesize != -1) + expectsend = data->set.infilesize; + break; + case HTTPREQ_POST_FORM: + expectsend = http->postsize; + break; + default: + break; + } } conn->bits.rewindaftersend = FALSE; /* default */ -- cgit v1.2.1 From 74816fed6c82132b0ef32bd8775b0ef659a5b4c3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Apr 2005 22:46:25 +0000 Subject: Hardeep Singh reported a problem doing HTTP POST with Digest. (It was actually also affecting NTLM and Negotiate.) It turned out that if the server responded with 100 Continue before the initial 401 response, libcurl didn't take care of the response properly. Test case 245 and 246 added to verify this. --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 308f9efc3..c689b6596 100644 --- a/lib/http.c +++ b/lib/http.c @@ -304,6 +304,10 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) bool pickproxy = FALSE; CURLcode code = CURLE_OK; + if(100 == conn->keep.httpcode) + /* this is a transient response code, ignore */ + return CURLE_OK; + if(data->state.authproblem) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; -- cgit v1.2.1 From 6e619393824922118317689ef59a73c556b7ef98 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Apr 2005 15:27:13 +0000 Subject: GnuTLS support added. There's now a "generic" SSL layer that we use all over internally, with code provided by sslgen.c. All SSL-layer-specific code is then written in ssluse.c (for OpenSSL) and gtls.c (for GnuTLS). As far as possible, internals should not need to know what SSL layer that is in use. Building with GnuTLS currently makes two test cases fail. TODO.gnutls contains a few known outstanding issues for the GnuTLS support. GnuTLS support is enabled with configure --with-gnutls --- lib/http.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c689b6596..392e70657 100644 --- a/lib/http.c +++ b/lib/http.c @@ -85,7 +85,7 @@ #include "base64.h" #include "cookie.h" #include "strequal.h" -#include "ssluse.h" +#include "sslgen.h" #include "http_digest.h" #include "http_ntlm.h" #include "http_negotiate.h" @@ -416,7 +416,7 @@ Curl_http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if (conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { -#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) +#ifdef USE_NTLM if(authproxy->picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE); @@ -484,7 +484,7 @@ Curl_http_output_auth(struct connectdata *conn, } else #endif -#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) +#ifdef USE_NTLM if(authhost->picked == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE); @@ -597,7 +597,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } else #endif -#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) +#ifdef USE_NTLM /* NTLM support requires the SSL crypto libs */ if(checkprefix("NTLM", start)) { *availp |= CURLAUTH_NTLM; @@ -1268,8 +1268,8 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } if(conn->protocol & PROT_HTTPS) { - /* now, perform the SSL initialization for this socket */ - result = Curl_SSLConnect(conn, FIRSTSOCKET); + /* perform SSL initialization for this socket */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } -- cgit v1.2.1 From c904b6b5bf6c6e980480e63cd066dc2ae2aace23 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 18 Apr 2005 17:14:58 +0000 Subject: Toshiyuki Maezawa reported that when doing a POST with a read callback, libcurl didn't properly send an Expect: 100-continue header. It does now. --- lib/http.c | 68 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 392e70657..c3c805956 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1347,6 +1347,27 @@ CURLcode Curl_http_done(struct connectdata *conn, return CURLE_OK; } +/* check and possibly add an Expect: header */ +static CURLcode expect100(struct SessionHandle *data, + send_buffer *req_buffer) +{ + CURLcode result = CURLE_OK; + if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + !checkheaders(data, "Expect:")) { + /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: + 100-continue to the headers which actually speeds up post + operations (as there is one packet coming back from the web + server) */ + result = add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + if(result == CURLE_OK) + data->set.expect100header = TRUE; + } + return result; +} + + + /* * Curl_http() gets called from the generic Curl_do() function when a HTTP * request is to be performed. This creates and sends a properly constructed @@ -1928,18 +1949,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - !checkheaders(data, "Expect:")) { - /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: - 100-continue to the headers which actually speeds up post - operations (as there is one packet coming back from the web - server) */ - result = add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); - if(result) - return result; - data->set.expect100header = TRUE; - } + result = expect100(data, req_buffer); + if(result) + return result; if(!checkheaders(data, "Content-Type:")) { /* Get Content-Type: line from Curl_formpostheader. @@ -2002,18 +2014,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - !checkheaders(data, "Expect:")) { - /* if not HTTP 1.0 or disabled explicitly, we add a Expect: - 100-continue to the headers which actually speeds up post - operations (as there is one packet coming back from the web - server) */ - result = add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); - if(result) - return result; - data->set.expect100header = TRUE; - } + result = expect100(data, req_buffer); + if(result) + return result; result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ if(result) @@ -2121,21 +2124,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - !checkheaders(data, "Expect:")) { - /* if not HTTP 1.0 or disabled explicitly, we add a Expect: - 100-continue to the headers which actually speeds up post - operations (as there is one packet coming back from the web - server) */ - add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); - data->set.expect100header = TRUE; - } + result = expect100(data, req_buffer); + if(result) + return result; add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ } } else { + result = expect100(data, req_buffer); + if(result) + return result; + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(data->set.postfieldsize) { -- cgit v1.2.1 From 01165e08e0d131b399fba2190f17af67e66f0888 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Apr 2005 21:39:48 +0000 Subject: Fred New reported a bug where we used Basic auth and user name and password in .netrc, and when following a Location: the subsequent requests didn't properly use the auth as found in the netrc file. Added test case 257 to verify my fix. --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c3c805956..f61ce42c4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -465,6 +465,7 @@ Curl_http_output_auth(struct connectdata *conn, /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || + conn->bits.netrc || !data->state.first_host || curl_strequal(data->state.first_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { -- cgit v1.2.1 From 5d9fc28fa760e1b0b7f68fce7ae845f4e659e0fd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 May 2005 09:52:59 +0000 Subject: Modified the default HTTP headers used by libcurl: A) Normal non-proxy HTTP: - no more "Pragma: no-cache" (this only makes sense to proxies) B) Non-CONNECT HTTP request over proxy: - "Pragma: no-cache" is used (like before) - "Proxy-Connection: Keep-alive" (for older style 1.0-proxies) C) CONNECT HTTP request over proxy: - "Host: [name]:[port]" - "Proxy-Connection: Keep-alive" --- lib/http.c | 209 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 143 insertions(+), 66 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f61ce42c4..84f357a9c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -811,6 +811,8 @@ struct send_buffer { }; typedef struct send_buffer send_buffer; +static CURLcode add_custom_headers(struct connectdata *conn, + send_buffer *req_buffer); static CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size); @@ -885,34 +887,47 @@ CURLcode add_buffer_send(send_buffer *in, *bytes_written += amount; - if((size_t)amount != size) { - /* The whole request could not be sent in one system call. We must queue - it up and send it later when we get the chance. We must not loop here - and wait until it might work again. */ + if(http) { + if((size_t)amount != size) { + /* The whole request could not be sent in one system call. We must + queue it up and send it later when we get the chance. We must not + loop here and wait until it might work again. */ - size -= amount; + size -= amount; - ptr = in->buffer + amount; + ptr = in->buffer + amount; - /* backup the currently set pointers */ - http->backup.fread = conn->fread; - http->backup.fread_in = conn->fread_in; - http->backup.postdata = http->postdata; - http->backup.postsize = http->postsize; + /* backup the currently set pointers */ + http->backup.fread = conn->fread; + http->backup.fread_in = conn->fread_in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; - /* set the new pointers for the request-sending */ - conn->fread = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; - http->postdata = ptr; - http->postsize = (curl_off_t)size; + /* set the new pointers for the request-sending */ + conn->fread = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; + http->postdata = ptr; + http->postsize = (curl_off_t)size; - http->send_buffer = in; - http->sending = HTTPSEND_REQUEST; + http->send_buffer = in; + http->sending = HTTPSEND_REQUEST; - return CURLE_OK; + return CURLE_OK; + } + http->sending = HTTPSEND_BODY; + /* the full buffer was sent, clean up and return */ + } + else { + if((size_t)amount != size) + /* We have no continue-send mechanism now, fail. This can only happen + when this function is used from the CONNECT sending function. We + currently (stupidly) assume that the whole request is always sent + away in the first single chunk. + + This needs FIXing. + */ + return CURLE_SEND_ERROR; } - http->sending = HTTPSEND_BODY; - /* the full buffer was sent, clean up and return */ } if(in->buffer) free(in->buffer); @@ -1038,9 +1053,15 @@ Curl_compareheader(char *headerline, /* line to check */ } /* - * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This - * function will issue the necessary commands to get a seamless tunnel through - * this proxy. After that, the socket can be used just as a normal socket. + * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP + * proxy. This function will issue the necessary commands to get a seamless + * tunnel through this proxy. After that, the socket can be used just as a + * normal socket. + * + * This badly needs to be rewritten. CONNECT should be sent and dealt with + * like any ordinary HTTP request, and not specially crafted like this. This + * function only remains here like this for now since the rewrite is a bit too + * much work to do at the moment. */ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, @@ -1063,6 +1084,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, char *line_start; char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; + send_buffer *req_buffer; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -1080,26 +1102,66 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, conn->newurl = NULL; } + /* initialize a dynamic send-buffer */ + req_buffer = add_buffer_init(); + + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; + host_port = aprintf("%s:%d", hostname, remote_port); if(!host_port) return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); + if(CURLE_OK == result) { + char *host=(char *)""; + const char *proxyconn=""; + char *ptr; + + ptr = checkheaders(data, "Host:"); + if(!ptr) { + host = aprintf("Host: %s\r\n", host_port); + if(!host) + result = CURLE_OUT_OF_MEMORY; + } + ptr = checkheaders(data, "Proxy-Connection:"); + if(!ptr) + proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - /* OK, now send the connect request to the proxy */ - result = - Curl_sendf(tunnelsocket, conn, - "CONNECT %s:%d HTTP/1.0\015\012" - "%s" - "%s" - "\r\n", - hostname, remote_port, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - data->set.useragent?conn->allocptr.uagent:"" - ); + if(CURLE_OK == result) { + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + add_bufferf(req_buffer, + "CONNECT %s:%d HTTP/1.0\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostname, remote_port, + host, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + data->set.useragent?conn->allocptr.uagent:"", + proxyconn); + + if(CURLE_OK == result) + result = add_custom_headers(conn, req_buffer); + + if(host && *host) + free(host); + + if(CURLE_OK == result) + /* CRLF terminate the request */ + result = add_bufferf(req_buffer, "\r\n"); + + if(CURLE_OK == result) + /* Now send off the request */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size); + } if(result) failf(data, "Failed sending CONNECT to proxy"); } @@ -1367,7 +1429,42 @@ static CURLcode expect100(struct SessionHandle *data, return result; } +static CURLcode add_custom_headers(struct connectdata *conn, + send_buffer *req_buffer) +{ + CURLcode result = CURLE_OK; + char *ptr; + struct curl_slist *headers=conn->data->set.headers; + + while(headers) { + ptr = strchr(headers->data, ':'); + if(ptr) { + /* we require a colon for this to be a true header */ + + ptr++; /* pass the colon */ + while(*ptr && isspace((int)*ptr)) + ptr++; + if(*ptr) { + /* only send this if the contents was non-blank */ + + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + curl_strnequal("Host:", headers->data, 5)) + ; + else { + + result = add_bufferf(req_buffer, "%s\r\n", headers->data); + if(result) + return result; + } + } + } + headers = headers->next; + } + return result; +} /* * Curl_http() gets called from the generic Curl_do() function when a HTTP @@ -1620,8 +1717,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } - if(!checkheaders(data, "Pragma:")) - http->p_pragma = "Pragma: no-cache\r\n"; + http->p_pragma = + (!checkheaders(data, "Pragma:") && + (conn->bits.httpproxy && !conn->bits.tunnel_proxy) )? + "Pragma: no-cache\r\n":NULL; if(!checkheaders(data, "Accept:")) http->p_accept = "Accept: */*\r\n"; @@ -1727,7 +1826,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; send_buffer *req_buffer; - struct curl_slist *headers=data->set.headers; curl_off_t postsize; /* off_t type to be able to hold a large file size */ /* initialize a dynamic send-buffer */ @@ -1750,6 +1848,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) "%s" /* accept */ "%s" /* accept-encoding */ "%s" /* referer */ + "%s" /* Proxy-Connection */ "%s",/* transfer-encoding */ request, @@ -1768,6 +1867,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? conn->allocptr.accept_encoding:"", (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && !conn->bits.tunnel_proxy)? + "Proxy-Connection: Keep-Alive\r\n":"", te ); @@ -1874,33 +1975,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - while(headers) { - ptr = strchr(headers->data, ':'); - if(ptr) { - /* we require a colon for this to be a true header */ - - ptr++; /* pass the colon */ - while(*ptr && isspace((int)*ptr)) - ptr++; - - if(*ptr) { - /* only send this if the contents was non-blank */ - - if(conn->allocptr.host && - /* a Host: header was sent already, don't pass on any custom Host: - header as that will produce *two* in the same request! */ - curl_strnequal("Host:", headers->data, 5)) - ; - else { - - result = add_bufferf(req_buffer, "%s\r\n", headers->data); - if(result) - return result; - } - } - } - headers = headers->next; - } + result = add_custom_headers(conn, req_buffer); + if(result) + return result; http->postdata = NULL; /* nothing to post at this point */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ -- cgit v1.2.1 From 20005a83d2ce3db5a7e6ea95ffdd8a047fd5e427 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Jul 2005 22:25:15 +0000 Subject: Andrew Bushnell provided enough info for me to tell that we badly needed to fix the CONNECT authentication code with multi-pass auth methods (such as NTLM) as it didn't previously properly ignore response-bodies - in fact it stopped reading after all response headers had been received. This could lead to libcurl sending the next request and reading the body from the first request as response to the second request. (I also renamed the function, which wasn't strictly necessary but...) The best fix would to once and for all make the CONNECT code use the ordinary request sending/receiving code, treating it as any ordinary request instead of the special-purpose function we have now. It should make it better for multi-interface too. And possibly lead to less code... Added test case 265 for this. It doesn't work as a _really_ good test case since the test proxy is too stupid, but the test case helps when running the debugger to verify. --- lib/http.c | 52 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 84f357a9c..9d9bb3e42 100644 --- a/lib/http.c +++ b/lib/http.c @@ -96,6 +96,7 @@ #include "memory.h" #include "select.h" #include "parsedate.h" /* for the week day and month names */ +#include "strtoofft.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1053,10 +1054,9 @@ Curl_compareheader(char *headerline, /* line to check */ } /* - * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP - * proxy. This function will issue the necessary commands to get a seamless - * tunnel through this proxy. After that, the socket can be used just as a - * normal socket. + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. * * This badly needs to be rewritten. CONNECT should be sent and dealt with * like any ordinary HTTP request, and not specially crafted like this. This @@ -1064,10 +1064,10 @@ Curl_compareheader(char *headerline, /* line to check */ * much work to do at the moment. */ -CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, - int sockindex, - char *hostname, - int remote_port) +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + char *hostname, + int remote_port) { int subversion=0; struct SessionHandle *data=conn->data; @@ -1076,7 +1076,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int res; size_t nread; /* total size read */ int perline; /* count bytes per line */ - bool keepon=TRUE; + int keepon=TRUE; ssize_t gotbytes; char *ptr; long timeout = @@ -1085,6 +1085,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; send_buffer *req_buffer; + curl_off_t cl=0; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -1215,6 +1216,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int i; nread += gotbytes; + + if(keepon > TRUE) { + cl -= gotbytes; + if(!cl) + break; + } + else for(i = 0; i < gotbytes; ptr++, i++) { perline++; /* amount of bytes in this line so far */ if(*ptr=='\n') { @@ -1242,7 +1250,21 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(('\r' == line_start[0]) || ('\n' == line_start[0])) { /* end of response-headers from the proxy */ - keepon=FALSE; + if(cl && (407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length when we + * have no auth problem, we must ignore the whole + * response-body */ + keepon = 2; + infof(data, "Ignore %" FORMAT_OFF_T + " bytes of response-body\n", cl); + cl -= (gotbytes - i);/* remove the remaining chunk of what + we already read */ + if(cl<=0) + /* if the whole thing was already read, we are done! */ + keepon=FALSE; + } + else + keepon = FALSE; break; /* breaks out of for-loop, not switch() */ } @@ -1257,6 +1279,10 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(result) return result; } + else if(checkprefix("Content-Length:", line_start)) { + cl = curlx_strtoofft(line_start + strlen("Content-Length:"), + NULL, 10); + } else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &k->httpcode)) { @@ -1323,9 +1349,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) if(conn->bits.tunnel_proxy) { /* either SSL over proxy, or explicitly asked for */ - result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, - conn->host.name, - conn->remote_port); + result = Curl_proxyCONNECT(conn, FIRSTSOCKET, + conn->host.name, + conn->remote_port); if(CURLE_OK != result) return result; } -- cgit v1.2.1 From c3a826fdcef1e64d9fe66877eb36c1649c4b886b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Jul 2005 22:07:34 +0000 Subject: correction for the 407 with response-body case --- lib/http.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9d9bb3e42..f46c1585a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1218,9 +1218,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, nread += gotbytes; if(keepon > TRUE) { + /* This means we are currently ignoring a response-body, so we + simply count down our counter and make sure to break out of the + loop when we're done! */ cl -= gotbytes; - if(!cl) + if(cl<=0) { + keepon = FALSE; break; + } } else for(i = 0; i < gotbytes; ptr++, i++) { -- cgit v1.2.1 From be9c873a6e97423bc0b2a2dd45835c35c7d81231 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 20 Oct 2005 20:07:32 +0000 Subject: Dave Dribin made libcurl understand and handle cases when the server (wrongly) sends *two* WWW-Authenticate headers for Digest. While this should never happen in a sane world, libcurl previously got into an infinite loop when this occurred. Dave added test 273 to verify this. --- lib/http.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f46c1585a..fe06c7dc7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -621,18 +621,23 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, #endif #ifndef CURL_DISABLE_CRYPTO_AUTH if(checkprefix("Digest", start)) { - CURLdigest dig; - *availp |= CURLAUTH_DIGEST; - authp->avail |= CURLAUTH_DIGEST; - - /* We call this function on input Digest headers even if Digest - * authentication isn't activated yet, as we need to store the - * incoming data from this header in case we are gonna use Digest. */ - dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); - - if(CURLDIGEST_FINE != dig) { - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; + if((authp->avail & CURLAUTH_DIGEST) != 0) { + infof(data, "Ignoring duplicate digest auth header.\n"); + } + else { + CURLdigest dig; + *availp |= CURLAUTH_DIGEST; + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are gonna use Digest. */ + dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); + + if(CURLDIGEST_FINE != dig) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } } } else -- cgit v1.2.1 From f4cc8153aeb5209ddb9698b2b0780ab2bfdb3d44 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 7 Jan 2006 22:24:16 +0000 Subject: Mike Jean fixed so that the second CONNECT when doing FTP over a HTTP proxy actually used a new connection and not sent the second request on the first socket! --- lib/http.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fe06c7dc7..e1ab7f9b4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -845,8 +845,9 @@ send_buffer *add_buffer_init(void) static CURLcode add_buffer_send(send_buffer *in, struct connectdata *conn, - long *bytes_written) /* add the number of sent + long *bytes_written, /* add the number of sent bytes to this counter */ + int socketindex) { ssize_t amount; CURLcode res; @@ -854,7 +855,11 @@ CURLcode add_buffer_send(send_buffer *in, size_t size; struct HTTP *http = conn->proto.http; size_t sendsize; - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + curl_socket_t sockfd; + + curlassert(socketindex <= SECONDARYSOCKET); + + sockfd = conn->sock[socketindex]; /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ @@ -1166,7 +1171,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(CURLE_OK == result) /* Now send off the request */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, sockindex); } if(result) failf(data, "Failed sending CONNECT to proxy"); @@ -2032,7 +2037,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else @@ -2097,7 +2102,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* fire away the whole request to the server */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else @@ -2141,7 +2146,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* this sends the buffer and frees all the buffer resources */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, FIRSTSOCKET); if(result) failf(data, "Failed sending PUT request"); else @@ -2263,7 +2268,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* issue the request */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP POST request"); @@ -2280,7 +2285,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* issue the request */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size); + &data->info.request_size, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP request"); -- cgit v1.2.1 From bda1e9aeab019d003036a3ec24193605bc191b3a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Jan 2006 13:17:14 +0000 Subject: Made the copyright year match the latest modification's year. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e1ab7f9b4..39e2940ff 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 87bcb6f3775a437579c7526d0972c714c2e5d31d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Feb 2006 22:35:16 +0000 Subject: Karl M added the CURLOPT_CONNECT_ONLY and CURLINFO_LASTSOCKET options that an app can use to let libcurl only connect to a remote host and then extract the socket from libcurl. libcurl will then not attempt to do any transfer at all after the connect is done. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 39e2940ff..e15054f57 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1361,7 +1361,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) * after the connect has occured, can we start talking SSL */ - if(conn->bits.tunnel_proxy) { + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* either SSL over proxy, or explicitly asked for */ result = Curl_proxyCONNECT(conn, FIRSTSOCKET, -- cgit v1.2.1 From 83367f67de9584b91570bcb53a153b8aa496d455 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 Mar 2006 21:54:44 +0000 Subject: Xavier Bouchoux made the SSL connection non-blocking for the multi interface (when using OpenSSL). --- lib/http.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e15054f57..a7db903fd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1371,13 +1371,6 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return result; } - if(conn->protocol & PROT_HTTPS) { - /* perform SSL initialization for this socket */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(result) - return result; - } - if(!data->state.this_is_a_follow) { /* this is not a followed location, get the original host name */ if (data->state.first_host) @@ -1387,11 +1380,68 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) data->state.first_host = strdup(conn->host.name); } - *done = TRUE; + if(conn->protocol & PROT_HTTPS) { + /* perform SSL initialization */ + if(data->state.used_interface == Curl_if_multi) { + result = Curl_https_connecting(conn, done); + if(result) + return result; + } + else { + /* BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(result) + return result; + *done = TRUE; + } + } + else { + *done = TRUE; + } return CURLE_OK; } +CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) +{ + CURLcode result; + curlassert(conn->protocol & PROT_HTTPS); + + /* perform SSL initialization for this socket */ + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); + if(result) + return result; + + return CURLE_OK; +} + +#ifdef USE_SSLEAY +CURLcode Curl_https_proto_fdset(struct connectdata *conn, + fd_set *read_fd_set, + fd_set *write_fd_set, + int *max_fdp) +{ + if (conn->protocol & PROT_HTTPS) { + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + if (connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + FD_SET(sockfd, write_fd_set); + if((int)sockfd > *max_fdp) + *max_fdp = (int)sockfd; + } + else if (connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + FD_SET(sockfd, read_fd_set); + if((int)sockfd > *max_fdp) + *max_fdp = (int)sockfd; + } + } + return CURLE_OK; +} +#endif + /* * Curl_http_done() gets called from Curl_done() after a single HTTP request * has been performed. -- cgit v1.2.1 From 686d90745be4417127050ad4b36d0a5403def200 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 Apr 2006 15:00:53 +0000 Subject: First curl_multi_socket() commit. Should primarily be considered as an internal code rearrange to fit the future better. --- lib/http.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a7db903fd..5a43f2478 100644 --- a/lib/http.c +++ b/lib/http.c @@ -97,6 +97,7 @@ #include "select.h" #include "parsedate.h" /* for the week day and month names */ #include "strtoofft.h" +#include "multiif.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1416,26 +1417,25 @@ CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) } #ifdef USE_SSLEAY -CURLcode Curl_https_proto_fdset(struct connectdata *conn, - fd_set *read_fd_set, - fd_set *write_fd_set, - int *max_fdp) +int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) { if (conn->protocol & PROT_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; if (connssl->connecting_state == ssl_connect_2_writing) { /* write mode */ - FD_SET(sockfd, write_fd_set); - if((int)sockfd > *max_fdp) - *max_fdp = (int)sockfd; + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); } else if (connssl->connecting_state == ssl_connect_2_reading) { /* read mode */ - FD_SET(sockfd, read_fd_set); - if((int)sockfd > *max_fdp) - *max_fdp = (int)sockfd; + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); } } return CURLE_OK; -- cgit v1.2.1 From e85e30546c89e17b6fb0cf383de25b7ed7f3bf3d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 May 2006 22:39:47 +0000 Subject: Roland Blom filed bug report #1481217 (http://curl.haxx.se/bug/view.cgi?id=1481217), with follow-ups by Michele Bini and David Byron. libcurl previously wrongly used GetLastError() on windows to get error details after socket-related function calls, when it really should use WSAGetLastError() instead. When changing to this, the former function Curl_ourerrno() is now instead called Curl_sockerrno() as it is necessary to only use it to get errno from socket-related functions as otherwise it won't work as intended on Windows. --- lib/http.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5a43f2478..3b6d57977 100644 --- a/lib/http.c +++ b/lib/http.c @@ -37,8 +37,6 @@ #include #endif -#include - #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #include #include -- cgit v1.2.1 From b62c230ca26b8080b3b5be8f42b48a6fa733d716 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 May 2006 22:14:40 +0000 Subject: Curl_https_getsock() was OpenSSL-specific and really should not be present like this in this source file. The quickfix for now is to provide a simple version for GnuTLS builds. The GnuTLS version of libcurl doesn't yet allow fully non-blocking connects anyway so this function doesn't get used. --- lib/http.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3b6d57977..b1995e61e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1415,6 +1415,8 @@ CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) } #ifdef USE_SSLEAY +/* This function is OpenSSL-specific. It should be made to query the generic + SSL layer instead. */ int Curl_https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -1438,6 +1440,18 @@ int Curl_https_getsock(struct connectdata *conn, } return CURLE_OK; } +#else +#ifdef USE_GNUTLS +int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif #endif /* -- cgit v1.2.1 From 8bed45340a48585bbd91e508f1ac44f5ed5bf178 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Jul 2006 12:01:59 +0000 Subject: Toshiyuki Maezawa fixed a problem where you couldn't override the Proxy-Connection: header when using a proxy and not doing CONNECT. --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b1995e61e..ac2a9cf3d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1970,7 +1970,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? conn->allocptr.accept_encoding:"", (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, - (conn->bits.httpproxy && !conn->bits.tunnel_proxy)? + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !checkheaders(data, "Proxy-Connection:"))? "Proxy-Connection: Keep-Alive\r\n":"", te ); -- cgit v1.2.1 From 840aacf7dd633a4d03db797f89b567548722544d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 19 Jul 2006 18:19:30 +0000 Subject: Remove variable declaration shadowing previously declared one --- lib/http.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ac2a9cf3d..3c0f1fb6d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1128,17 +1128,15 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(CURLE_OK == result) { char *host=(char *)""; const char *proxyconn=""; - char *ptr; - ptr = checkheaders(data, "Host:"); - if(!ptr) { + if(!checkheaders(data, "Host:")) { host = aprintf("Host: %s\r\n", host_port); if(!host) result = CURLE_OUT_OF_MEMORY; } - ptr = checkheaders(data, "Proxy-Connection:"); - if(!ptr) + if(!checkheaders(data, "Proxy-Connection:")) { proxyconn = "Proxy-Connection: Keep-Alive\r\n"; + } if(CURLE_OK == result) { /* Send the connect request to the proxy */ -- cgit v1.2.1 From 4ac54f8c2cee47cc2e2398c10b908e70c146ac90 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 19 Jul 2006 18:32:38 +0000 Subject: remove variable declaration shadowing previously declared one --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3c0f1fb6d..58564be37 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1771,7 +1771,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) uses the encoded host name! */ if(conn->host.dispname != conn->host.name) { char *url = data->change.url; - char *ptr = strstr(url, conn->host.dispname); + ptr = strstr(url, conn->host.dispname); if(ptr) { /* This is where the display name starts in the URL, now replace this part with the encoded name. TODO: This method of replacing the host -- cgit v1.2.1 From a88deadd6f85a6ac3b7f9d574bbb7eaab3115700 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 27 Jul 2006 22:35:09 +0000 Subject: Yves Lejeune fixed so that replacing Content-Type: when doing multipart formposts work exactly the way you want it (and the way you'd assume it works) --- lib/http.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 58564be37..f4898fcd5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1554,8 +1554,12 @@ static CURLcode add_custom_headers(struct connectdata *conn, header as that will produce *two* in the same request! */ curl_strnequal("Host:", headers->data, 5)) ; + else if(conn->data->set.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + curl_strnequal("Content-Type:", headers->data, + strlen("Content-Type:"))) + ; else { - result = add_bufferf(req_buffer, "%s\r\n", headers->data); if(result) return result; @@ -1809,6 +1813,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ result = Curl_getFormData(&http->sendit, data->set.httppost, + checkheaders(data, "Content-Type:"), &http->postsize); if(CURLE_OK != result) { /* Curl_getFormData() doesn't use failf() */ @@ -2134,12 +2139,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - if(!checkheaders(data, "Content-Type:")) { - /* Get Content-Type: line from Curl_formpostheader. + { - The Content-Type header line also contains the MIME boundary - string etc why disabling this header is likely to not make things - work, but we support disabling it anyway. + /* Get Content-Type: line from Curl_formpostheader. */ char *contentType; size_t linelength=0; @@ -2149,6 +2151,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Could not get Content-Type header line!"); return CURLE_HTTP_POST_ERROR; } + result = add_buffer(req_buffer, contentType, linelength); if(result) return result; -- cgit v1.2.1 From 8a38c72c48cdc75e21aa1d13235215783115007f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 2 Aug 2006 18:18:47 +0000 Subject: Mark Lentczner fixed how libcurl was not properly doing chunked encoding if the header "Transfer-Encoding: chunked" was set by the application. http://curl.haxx.se/bug/view.cgi?id=1531838 --- lib/http.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f4898fcd5..512b17312 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1684,30 +1684,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if(!conn->bits.upload_chunky && (httpreq != HTTPREQ_GET)) { - /* not a chunky transfer yet, but data is to be sent */ - ptr = checkheaders(data, "Transfer-Encoding:"); - if(ptr) { - /* Some kind of TE is requested, check if 'chunked' is chosen */ - conn->bits.upload_chunky = - Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); - te = ""; - } + ptr = checkheaders(data, "Transfer-Encoding:"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + conn->bits.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } - else if(conn->bits.upload_chunky) { - /* RFC2616 section 4.4: - Messages MUST NOT include both a Content-Length header field and a - non-identity transfer-coding. If the message does include a non- - identity transfer-coding, the Content-Length MUST be ignored. */ - - if(!checkheaders(data, "Transfer-Encoding:")) { + else { + if (httpreq == HTTPREQ_GET) + conn->bits.upload_chunky = FALSE; + if(conn->bits.upload_chunky) te = "Transfer-Encoding: chunked\r\n"; - } - else { - te = ""; - conn->bits.upload_chunky = FALSE; /* transfer-encoding was disabled, - so don't chunkify this! */ - } } Curl_safefree(conn->allocptr.host); -- cgit v1.2.1 From a4ebf5b507490ceac7d741c4462ad162629a4bae Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 8 Aug 2006 21:12:49 +0000 Subject: Fixed a flaw in the "Expect: 100-continue" treatment. If you did two POSTs on a persistent connection and allowed the first to use that header, you could not disable it for the second request. --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 512b17312..310c0a617 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1516,6 +1516,8 @@ static CURLcode expect100(struct SessionHandle *data, send_buffer *req_buffer) { CURLcode result = CURLE_OK; + data->state.expect100header = FALSE; /* default to false unless it is set + to TRUE below */ if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && !checkheaders(data, "Expect:")) { /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: @@ -1525,7 +1527,7 @@ static CURLcode expect100(struct SessionHandle *data, result = add_bufferf(req_buffer, "Expect: 100-continue\r\n"); if(result == CURLE_OK) - data->set.expect100header = TRUE; + data->state.expect100header = TRUE; } return result; } -- cgit v1.2.1 From 490cccba3cfd5ba54ecb64a10fb63c2f0e94a67d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 18 Aug 2006 22:54:57 +0000 Subject: Andrew Biggs pointed out a "Expect: 100-continue" flaw where libcurl didn't send the whole request at once, even though the Expect: header was disabled by the application. An effect of this change is also that small (< 1024 bytes) POSTs are now always sent without Expect: header since we deem it more costly to bother about that than the risk that we send the data in vain. --- lib/http.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 310c0a617..4df91be0a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2249,16 +2249,24 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->set.postfields) { - if((data->state.authhost.done || data->state.authproxy.done ) - && (postsize < MAX_INITIAL_POST_SIZE)) { - /* If we're not done with the authentication phase, we don't expect - to actually send off any data yet. Hence, we delay the sending of - the body until we receive that friendly 100-continue response */ + /* for really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it */ + if(postsize > TINY_INITIAL_POST_SIZE) { + result = expect100(data, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; + + if(!data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect:-100 AND + postsize is less than MAX_INITIAL_POST_SIZE - /* The post data is less than MAX_INITIAL_PORT_SIZE, then append it - to the header. This limit is no magic limit but only set to - prevent really huge POSTs to get the data duplicated with - malloc() and family. */ + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) @@ -2297,18 +2305,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - result = expect100(data, req_buffer); - if(result) - return result; - add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ } } else { - result = expect100(data, req_buffer); - if(result) - return result; - add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(data->set.postfieldsize) { -- cgit v1.2.1 From cfdcae4bc75fba04b9864cae18e0bbe66b8655b9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Aug 2006 21:18:36 +0000 Subject: Based on a patch by Armel Asselin, the FTP code no longer re-issues the TYPE command on subsequent requests on a re-used connection unless it has to. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4df91be0a..aab0b85a2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1251,7 +1251,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(data->set.include_header) writetype |= CLIENTWRITE_BODY; - result = Curl_client_write(data, writetype, line_start, perline); + result = Curl_client_write(conn, writetype, line_start, perline); if(result) return result; -- cgit v1.2.1 From 59cf6fd4f058917839a407f5a206f5f1c1a004a6 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Tue, 29 Aug 2006 18:45:55 +0000 Subject: Watcom lacks . --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index aab0b85a2..c148b4c79 100644 --- a/lib/http.c +++ b/lib/http.c @@ -47,7 +47,9 @@ #ifdef HAVE_NETINET_IN_H #include #endif +#ifndef __WATCOMC__ #include +#endif #ifdef HAVE_TIME_H #ifdef TIME_WITH_SYS_TIME -- cgit v1.2.1 From c7aae1030004da71c7c046fd6af259f91bbfa991 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Wed, 30 Aug 2006 16:17:06 +0000 Subject: Removed "#ifndef__WATCOMC__". Use "#ifdef HAVE_SYS_TIME_H" instead. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c148b4c79..1b638829b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -47,7 +47,7 @@ #ifdef HAVE_NETINET_IN_H #include #endif -#ifndef __WATCOMC__ +#ifdef HAVE_SYS_TIME_H #include #endif -- cgit v1.2.1 From 4f4277d9c73b876d0054474d1f696a555c5c9966 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 3 Sep 2006 13:52:07 +0000 Subject: Simplified #ifdef on WIN32; the statement " !defined(__GNUC__) || defined(__MINGW32__)" implies CygWin. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1b638829b..f7d495529 100644 --- a/lib/http.c +++ b/lib/http.c @@ -37,7 +37,7 @@ #include #endif -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#if defined(WIN32) && !defined(__CYGWIN__) #include #include #else -- cgit v1.2.1 From b7eeb6e67fca686f840eacd6b8394edb58b07482 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Sep 2006 21:49:20 +0000 Subject: Major overhaul introducing http pipelining support and shared connection cache within the multi handle. --- lib/http.c | 129 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 65 insertions(+), 64 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f7d495529..f4b642bd1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -220,8 +220,9 @@ static bool pickoneauth(struct auth *pick) */ static CURLcode perhapsrewind(struct connectdata *conn) { - struct HTTP *http = conn->proto.http; struct SessionHandle *data = conn->data; + struct HTTP *http = data->reqdata.proto.http; + struct Curl_transfer_keeper *k = &data->reqdata.keep; curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ @@ -283,7 +284,7 @@ static CURLcode perhapsrewind(struct connectdata *conn) /* This is not NTLM or NTLM with many bytes left to send: close */ conn->bits.close = TRUE; - conn->size = 0; /* don't download any more than 0 bytes */ + k->size = 0; /* don't download any more than 0 bytes */ } if(bytessent) @@ -306,7 +307,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) bool pickproxy = FALSE; CURLcode code = CURLE_OK; - if(100 == conn->keep.httpcode) + if(100 == data->reqdata.keep.httpcode) /* this is a transient response code, ignore */ return CURLE_OK; @@ -314,22 +315,22 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; if(conn->bits.user_passwd && - ((conn->keep.httpcode == 401) || - (conn->bits.authneg && conn->keep.httpcode < 300))) { + ((data->reqdata.keep.httpcode == 401) || + (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { pickhost = pickoneauth(&data->state.authhost); if(!pickhost) data->state.authproblem = TRUE; } if(conn->bits.proxy_user_passwd && - ((conn->keep.httpcode == 407) || - (conn->bits.authneg && conn->keep.httpcode < 300))) { + ((data->reqdata.keep.httpcode == 407) || + (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { pickproxy = pickoneauth(&data->state.authproxy); if(!pickproxy) data->state.authproblem = TRUE; } if(pickhost || pickproxy) { - conn->newurl = strdup(data->change.url); /* clone URL */ + data->reqdata.newurl = strdup(data->change.url); /* clone URL */ if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD) && @@ -340,7 +341,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } } - else if((conn->keep.httpcode < 300) && + else if((data->reqdata.keep.httpcode < 300) && (!data->state.authhost.done) && conn->bits.authneg) { /* no (known) authentication available, @@ -349,13 +350,13 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) we didn't try HEAD or GET */ if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD)) { - conn->newurl = strdup(data->change.url); /* clone URL */ + data->reqdata.newurl = strdup(data->change.url); /* clone URL */ data->state.authhost.done = TRUE; } } if (Curl_http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", - conn->keep.httpcode); + data->reqdata.keep.httpcode); code = CURLE_HTTP_RETURNED_ERROR; } @@ -589,8 +590,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, start); if (neg == 0) { - conn->newurl = strdup(data->change.url); - data->state.authproblem = (conn->newurl == NULL); + data->reqdata.newurl = strdup(data->change.url); + data->state.authproblem = (data->reqdata.newurl == NULL); } else { infof(data, "Authentication problem. Ignoring this.\n"); @@ -681,7 +682,7 @@ int Curl_http_should_fail(struct connectdata *conn) /* ** For readability */ - k = &conn->keep; + k = &data->reqdata.keep; /* ** If we haven't been asked to fail on error, @@ -696,7 +697,7 @@ int Curl_http_should_fail(struct connectdata *conn) if (k->httpcode < 400) return 0; - if (conn->resume_from && + if (data->reqdata.resume_from && (data->set.httpreq==HTTPREQ_GET) && (k->httpcode == 416)) { /* "Requested Range Not Satisfiable", just proceed and @@ -736,7 +737,7 @@ int Curl_http_should_fail(struct connectdata *conn) infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); - infof(data,"%s: newurl = %s\n",__FUNCTION__,conn->newurl ? conn->newurl : "(null)"); + infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)"); infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); #endif @@ -766,7 +767,7 @@ static size_t readmoredata(char *buffer, void *userp) { struct connectdata *conn = (struct connectdata *)userp; - struct HTTP *http = conn->proto.http; + struct HTTP *http = conn->data->reqdata.proto.http; size_t fullsize = size * nitems; if(0 == http->postsize) @@ -854,7 +855,7 @@ CURLcode add_buffer_send(send_buffer *in, CURLcode res; char *ptr; size_t size; - struct HTTP *http = conn->proto.http; + struct HTTP *http = conn->data->reqdata.proto.http; size_t sendsize; curl_socket_t sockfd; @@ -939,6 +940,8 @@ CURLcode add_buffer_send(send_buffer *in, This needs FIXing. */ return CURLE_SEND_ERROR; + else + conn->writechannel_inuse = FALSE; } } if(in->buffer) @@ -1082,7 +1085,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, { int subversion=0; struct SessionHandle *data=conn->data; - struct Curl_transfer_keeper *k = &conn->keep; + struct Curl_transfer_keeper *k = &data->reqdata.keep; CURLcode result; int res; size_t nread; /* total size read */ @@ -1106,12 +1109,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); do { - if(conn->newurl) { + if(data->reqdata.newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() it. */ - free(conn->newurl); - conn->newurl = NULL; + free(data->reqdata.newurl); + data->reqdata.newurl = NULL; } /* initialize a dynamic send-buffer */ @@ -1323,7 +1326,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, headers. 'newurl' is set to a new URL if we must loop. */ Curl_http_auth_act(conn); - } while(conn->newurl); + } while(data->reqdata.newurl); if(200 != k->httpcode) { failf(data, "Received HTTP code %d from proxy after CONNECT", @@ -1462,11 +1465,9 @@ int Curl_https_getsock(struct connectdata *conn, CURLcode Curl_http_done(struct connectdata *conn, CURLcode status) { - struct SessionHandle *data; - struct HTTP *http; - - data=conn->data; - http=conn->proto.http; + struct SessionHandle *data = conn->data; + struct HTTP *http =data->reqdata.proto.http; + struct Curl_transfer_keeper *k = &data->reqdata.keep; /* set the proper values (possibly modified on POST) */ conn->fread = data->set.fread; /* restore */ @@ -1484,7 +1485,7 @@ CURLcode Curl_http_done(struct connectdata *conn, } if(HTTPREQ_POST_FORM == data->set.httpreq) { - conn->bytecount = http->readbytecount + http->writebytecount; + k->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ if(http->form.fp) { @@ -1494,15 +1495,15 @@ CURLcode Curl_http_done(struct connectdata *conn, } } else if(HTTPREQ_PUT == data->set.httpreq) - conn->bytecount = http->readbytecount + http->writebytecount; + k->bytecount = http->readbytecount + http->writebytecount; if (status != CURLE_OK) return (status); if(!conn->bits.retry && ((http->readbytecount + - conn->headerbytecount - - conn->deductheadercount)) <= 0) { + k->headerbytecount - + k->deductheadercount)) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was read from the HTTP server (that counts), this can't be right so we return an error here */ @@ -1586,7 +1587,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; - char *ppath = conn->path; + char *ppath = data->reqdata.path; char *host = conn->host.name; const char *te = ""; /* tranfer-encoding */ char *ptr; @@ -1599,17 +1600,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) the rest of the request in the PERFORM phase. */ *done = TRUE; - if(!conn->proto.http) { + if(!data->reqdata.proto.http) { /* Only allocate this struct if we don't already have it! */ http = (struct HTTP *)malloc(sizeof(struct HTTP)); if(!http) return CURLE_OUT_OF_MEMORY; memset(http, 0, sizeof(struct HTTP)); - conn->proto.http = http; + data->reqdata.proto.http = http; } else - http = conn->proto.http; + http = data->reqdata.proto.http; /* We default to persistant connections */ conn->bits.close = FALSE; @@ -1825,7 +1826,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(( (HTTPREQ_POST == httpreq) || (HTTPREQ_POST_FORM == httpreq) || (HTTPREQ_PUT == httpreq) ) && - conn->resume_from) { + data->reqdata.resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have * got a resume_from value set. The resume value has already created @@ -1834,15 +1835,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * file size before we continue this venture in the dark lands of HTTP. *********************************************************************/ - if(conn->resume_from < 0 ) { + if(data->reqdata.resume_from < 0 ) { /* * This is meant to get the size of the present remote-file by itself. * We don't support this now. Bail out! */ - conn->resume_from = 0; + data->reqdata.resume_from = 0; } - if(conn->resume_from) { + if(data->reqdata.resume_from) { /* do we still game? */ curl_off_t passed=0; @@ -1850,7 +1851,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - size_t readthisamountnow = (size_t)(conn->resume_from - passed); + size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed); size_t actuallyread; if(readthisamountnow > BUFSIZE) @@ -1867,11 +1868,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) passed); return CURLE_READ_ERROR; } - } while(passed != conn->resume_from); /* loop until done */ + } while(passed != data->reqdata.resume_from); /* loop until done */ /* now, decrease the size of the read */ if(data->set.infilesize>0) { - data->set.infilesize -= conn->resume_from; + data->set.infilesize -= data->reqdata.resume_from; if(data->set.infilesize <= 0) { failf(data, "File already completely uploaded"); @@ -1881,7 +1882,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we've passed, proceed as normal */ } } - if(conn->bits.use_range) { + if(data->reqdata.use_range) { /* * A range is selected. We use different headers whether we're downloading * or uploading and we always let customized headers override our internal @@ -1892,19 +1893,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); - conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->reqdata.range); } else if((httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { - if(conn->resume_from) { + if(data->reqdata.resume_from) { /* This is because "resume" was selected */ curl_off_t total_expected_size= - conn->resume_from + data->set.infilesize; + data->reqdata.resume_from + data->set.infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%" FORMAT_OFF_T "/%" FORMAT_OFF_T "\r\n", - conn->range, total_expected_size-1, + data->reqdata.range, total_expected_size-1, total_expected_size); } else { @@ -1912,7 +1913,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", - conn->range, data->set.infilesize); + data->reqdata.range, data->set.infilesize); } } } @@ -1954,7 +1955,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", conn->allocptr.userpwd?conn->allocptr.userpwd:"", - (conn->bits.use_range && conn->allocptr.rangeline)? + (data->reqdata.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? conn->allocptr.uagent:"", @@ -1983,7 +1984,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, conn->path, + conn->allocptr.cookiehost:host, data->reqdata.path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } @@ -2100,9 +2101,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - -1, NULL); + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + -1, NULL); break; } @@ -2163,10 +2164,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + FIRSTSOCKET, + &http->writebytecount); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -2207,10 +2208,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending PUT request"); else /* prepare for transfer */ - result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + postsize?FIRSTSOCKET:-1, + postsize?&http->writebytecount:NULL); if(result) return result; break; @@ -2330,7 +2331,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending HTTP POST request"); else result = - Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, http->postdata?FIRSTSOCKET:-1, http->postdata?&http->writebytecount:NULL); @@ -2347,7 +2348,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, http->postdata?FIRSTSOCKET:-1, http->postdata?&http->writebytecount:NULL); -- cgit v1.2.1 From c30e908034dec008990d58759dd28d3cdbef536b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 10 Sep 2006 23:37:42 +0000 Subject: Compiler warning fix --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f4b642bd1..e69eb74b3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -775,7 +775,7 @@ static size_t readmoredata(char *buffer, return 0; /* make sure that a HTTP request is never sent away chunked! */ - conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; + conn->bits.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST); if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); -- cgit v1.2.1 From 733a184ce0747c65fbc634e066cfac0ffae43d80 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 12 Sep 2006 23:51:01 +0000 Subject: Compiler warning fix --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e69eb74b3..809f20ca9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -455,7 +455,7 @@ Curl_http_output_auth(struct connectdata *conn, if(auth) { infof(data, "Proxy auth using %s with user '%s'\n", auth, conn->proxyuser?conn->proxyuser:""); - authproxy->multi = !authproxy->done; + authproxy->multi = (bool)(!authproxy->done); } else authproxy->multi = FALSE; @@ -525,7 +525,7 @@ Curl_http_output_auth(struct connectdata *conn, infof(data, "Server auth using %s with user '%s'\n", auth, conn->user); - authhost->multi = !authhost->done; + authhost->multi = (bool)(!authhost->done); } else authhost->multi = FALSE; -- cgit v1.2.1 From e150150d9f1e0578c85af05de15ab6336066cec1 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 11 Oct 2006 16:01:16 +0000 Subject: Remove redundant __CYGWIN__ symbol check --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 809f20ca9..596a380d7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -37,7 +37,7 @@ #include #endif -#if defined(WIN32) && !defined(__CYGWIN__) +#ifdef WIN32 #include #include #else -- cgit v1.2.1 From 5ccbbe40c2257a24b758008b83de8c5ac018ed28 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 13 Oct 2006 21:02:27 +0000 Subject: The tagging of application/x-www-form-urlencoded POST body data sent to the CURLOPT_DEBUGFUNCTION callback has been fixed (it was erroneously included as part of the header). A message was also added to the command line tool to show when data is being sent, enabled when --verbose is used. --- lib/http.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 596a380d7..12c774164 100644 --- a/lib/http.c +++ b/lib/http.c @@ -573,11 +573,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, start++; /* - * Here we check if we want the specific single authentiction (using ==) and + * Here we check if we want the specific single authentication (using ==) and * if we do, we initiate usage of it. * * If the provided authentication is wanted as one out of several accepted - * types (using &), we OR this authenticaion type to the authavail + * types (using &), we OR this authentication type to the authavail * variable. */ @@ -840,7 +840,8 @@ send_buffer *add_buffer_init(void) } /* - * add_buffer_send() sends a buffer and frees all associated memory. + * add_buffer_send() sends a header buffer and frees all associated memory. + * Body data may be appended to the header data if desired. * * Returns CURLcode */ @@ -849,7 +850,10 @@ CURLcode add_buffer_send(send_buffer *in, struct connectdata *conn, long *bytes_written, /* add the number of sent bytes to this counter */ + int included_body_bytes, /* how much of the buffer + contains body data (for log tracing) */ int socketindex) + { ssize_t amount; CURLcode res; @@ -894,9 +898,14 @@ CURLcode add_buffer_send(send_buffer *in, if(CURLE_OK == res) { - if(conn->data->set.verbose) + if(conn->data->set.verbose) { /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount, conn); + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, + amount-included_body_bytes, conn); + if (included_body_bytes) + Curl_debug(conn->data, CURLINFO_DATA_OUT, + ptr+amount-included_body_bytes, included_body_bytes, conn); + } *bytes_written += amount; @@ -1173,7 +1182,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(CURLE_OK == result) /* Now send off the request */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size, sockindex); + &data->info.request_size, 0, sockindex); } if(result) failf(data, "Failed sending CONNECT to proxy"); @@ -1360,7 +1369,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) /* If we are not using a proxy and we want a secure connection, perform SSL * initialization & connection now. If using a proxy with https, then we * must tell the proxy to CONNECT to the host we want to talk to. Only - * after the connect has occured, can we start talking SSL + * after the connect has occurred, can we start talking SSL */ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { @@ -1594,6 +1603,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *request; Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; + int included_body = 0; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with @@ -1612,7 +1622,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else http = data->reqdata.proto.http; - /* We default to persistant connections */ + /* We default to persistent connections */ conn->bits.close = FALSE; if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && @@ -2096,7 +2106,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; result = add_buffer_send(req_buffer, conn, - &data->info.request_size, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else @@ -2159,7 +2169,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* fire away the whole request to the server */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else @@ -2203,7 +2213,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* this sends the buffer and frees all the buffer resources */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending PUT request"); else @@ -2280,6 +2290,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) already now to reduce the number if send() calls */ result = add_buffer(req_buffer, data->set.postfields, (size_t)postsize); + included_body = postsize; } else { /* Append the POST data chunky-style */ @@ -2291,6 +2302,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) result = add_buffer(req_buffer, "\r\n0\r\n\r\n", 7); /* end of a chunked transfer stream */ + included_body = postsize + 7; } if(result) return result; @@ -2324,8 +2336,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } /* issue the request */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, FIRSTSOCKET); + result = add_buffer_send(req_buffer, conn, &data->info.request_size, + included_body, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP POST request"); @@ -2342,7 +2354,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* issue the request */ result = add_buffer_send(req_buffer, conn, - &data->info.request_size, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP request"); -- cgit v1.2.1 From 10d1fc0e73cf23a06433ad6a933c3dcfef034a6c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 15 Oct 2006 23:13:12 +0000 Subject: Compiler warning fix --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 12c774164..3ca6cc543 100644 --- a/lib/http.c +++ b/lib/http.c @@ -850,7 +850,7 @@ CURLcode add_buffer_send(send_buffer *in, struct connectdata *conn, long *bytes_written, /* add the number of sent bytes to this counter */ - int included_body_bytes, /* how much of the buffer + long included_body_bytes, /* how much of the buffer contains body data (for log tracing) */ int socketindex) @@ -1603,7 +1603,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *request; Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; - int included_body = 0; + long included_body = 0; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with -- cgit v1.2.1 From 433c0c895e497efcf080d0a9d9fbb6a9f84d4460 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 17 Oct 2006 02:31:06 +0000 Subject: Compiler warning fix --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3ca6cc543..04ec4db99 100644 --- a/lib/http.c +++ b/lib/http.c @@ -277,8 +277,8 @@ static CURLcode perhapsrewind(struct connectdata *conn) /* this is already marked to get closed */ return CURLE_OK; - infof(data, "NTLM send, close instead of sending %ld bytes\n", - expectsend - bytessent); + infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T + " bytes\n", (curl_off_t)(expectsend - bytessent)); } /* This is not NTLM or NTLM with many bytes left to send: close @@ -850,7 +850,7 @@ CURLcode add_buffer_send(send_buffer *in, struct connectdata *conn, long *bytes_written, /* add the number of sent bytes to this counter */ - long included_body_bytes, /* how much of the buffer + size_t included_body_bytes, /* how much of the buffer contains body data (for log tracing) */ int socketindex) @@ -1603,7 +1603,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *request; Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; - long included_body = 0; + curl_off_t included_body = 0; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with @@ -2337,7 +2337,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* issue the request */ result = add_buffer_send(req_buffer, conn, &data->info.request_size, - included_body, FIRSTSOCKET); + (size_t)included_body, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP POST request"); -- cgit v1.2.1 From ec956b03345cd8d90330db406190b45d45817568 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 17 Oct 2006 10:04:13 +0000 Subject: Explicit typecast for Curl_debug() size argument --- lib/http.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 04ec4db99..0b3111f47 100644 --- a/lib/http.c +++ b/lib/http.c @@ -901,10 +901,11 @@ CURLcode add_buffer_send(send_buffer *in, if(conn->data->set.verbose) { /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, - amount-included_body_bytes, conn); + (size_t)(amount-included_body_bytes), conn); if (included_body_bytes) - Curl_debug(conn->data, CURLINFO_DATA_OUT, - ptr+amount-included_body_bytes, included_body_bytes, conn); + Curl_debug(conn->data, CURLINFO_DATA_OUT, + ptr+amount-included_body_bytes, + (size_t)included_body_bytes, conn); } *bytes_written += amount; @@ -1257,8 +1258,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* output debug if that is requested */ if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, - conn); + Curl_debug(data, CURLINFO_HEADER_IN, + line_start, (size_t)perline, conn); /* send the header to the callback */ writetype = CLIENTWRITE_HEADER; -- cgit v1.2.1 From 44d84ac1646cf04ccc2c1a736f3c9d1644ccacec Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 Oct 2006 21:32:56 +0000 Subject: Avoid typecasting a signed char to an int when using is*() functions, as that could very well cause a negate number get passed in and thus cause reading outside of the array usually used for this purpose. We avoid this by using the uppercase macro versions introduced just now that does some extra crazy typecasts to avoid byte codes > 127 to cause negative int values. --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0b3111f47..e31730e7d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -569,7 +569,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } /* pass all white spaces */ - while(*start && isspace((int)*start)) + while(*start && ISSPACE(*start)) start++; /* @@ -1051,7 +1051,7 @@ Curl_compareheader(char *headerline, /* line to check */ start = &headerline[hlen]; /* pass all white spaces */ - while(*start && isspace((int)*start)) + while(*start && ISSPACE(*start)) start++; /* find the end of the header line */ @@ -1558,7 +1558,7 @@ static CURLcode add_custom_headers(struct connectdata *conn, /* we require a colon for this to be a true header */ ptr++; /* pass the colon */ - while(*ptr && isspace((int)*ptr)) + while(*ptr && ISSPACE(*ptr)) ptr++; if(*ptr) { @@ -1725,12 +1725,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) redirected request is being out on thin ice. Except if the host name is the same as the first one! */ char *start = ptr+strlen("Host:"); - while(*start && isspace((int)*start )) + while(*start && ISSPACE(*start )) start++; ptr = start; /* start host-scanning here */ /* scan through the string to find the end (space or colon) */ - while(*ptr && !isspace((int)*ptr) && !(':'==*ptr)) + while(*ptr && !ISSPACE(*ptr) && !(':'==*ptr)) ptr++; if(ptr != start) { -- cgit v1.2.1 From a777eb3d816dbd437d9b8a9e3b7b52be91d68e3b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 3 Nov 2006 12:43:55 +0000 Subject: Olaf Stueben provided a patch that I edited slightly. It fixes the notorious KNOWN_BUGS #25, which happens when a proxy closes the connection when libcurl has sent CONNECT, as part of an authentication negotiation. Starting now, libcurl will re-connect accordingly and continue the authentication as it should. --- lib/http.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e31730e7d..0670f1e78 100644 --- a/lib/http.c +++ b/lib/http.c @@ -903,8 +903,8 @@ CURLcode add_buffer_send(send_buffer *in, Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, (size_t)(amount-included_body_bytes), conn); if (included_body_bytes) - Curl_debug(conn->data, CURLINFO_DATA_OUT, - ptr+amount-included_body_bytes, + Curl_debug(conn->data, CURLINFO_DATA_OUT, + ptr+amount-included_body_bytes, (size_t)included_body_bytes, conn); } @@ -1110,6 +1110,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, curl_socket_t tunnelsocket = conn->sock[sockindex]; send_buffer *req_buffer; curl_off_t cl=0; + bool closeConnection = FALSE; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -1117,6 +1118,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int error = SELECT_OK; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); + conn->bits.proxy_connect_closed = FALSE; do { if(data->reqdata.newurl) { @@ -1258,7 +1260,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* output debug if that is requested */ if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, + Curl_debug(data, CURLINFO_HEADER_IN, line_start, (size_t)perline, conn); /* send the header to the callback */ @@ -1310,6 +1312,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, cl = curlx_strtoofft(line_start + strlen("Content-Length:"), NULL, 10); } + else if(Curl_compareheader(line_start, + "Connection:", "close")) + closeConnection = TRUE; else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &k->httpcode)) { @@ -1336,11 +1341,21 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, headers. 'newurl' is set to a new URL if we must loop. */ Curl_http_auth_act(conn); + if (closeConnection && data->reqdata.newurl) { + /* Connection closed by server. Don't use it anymore */ + sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + break; + } } while(data->reqdata.newurl); if(200 != k->httpcode) { failf(data, "Received HTTP code %d from proxy after CONNECT", k->httpcode); + + if (closeConnection && data->reqdata.newurl) + conn->bits.proxy_connect_closed = TRUE; + return CURLE_RECV_ERROR; } -- cgit v1.2.1 From 33831759b5241ae11832c1da204c8cf76503867e Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Fri, 15 Dec 2006 16:49:40 +0000 Subject: Fix typo. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0670f1e78..0b537e45e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1614,7 +1614,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) struct HTTP *http; char *ppath = data->reqdata.path; char *host = conn->host.name; - const char *te = ""; /* tranfer-encoding */ + const char *te = ""; /* transfer-encoding */ char *ptr; char *request; Curl_HttpReq httpreq = data->set.httpreq; -- cgit v1.2.1 From 89ab5f4380b9fd6507e0bc365310d88c82dd3de1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 21 Dec 2006 10:15:38 +0000 Subject: Robson Braga Araujo reported bug #1618359 (http://curl.haxx.se/bug/view.cgi?id=1618359) and subsequently provided a patch for it: when downloading 2 zero byte files in a row, curl 7.16.0 enters an infinite loop, while curl 7.16.1-20061218 does one additional unnecessary request. Fix: During the "Major overhaul introducing http pipelining support and shared connection cache within the multi handle." change, headerbytecount was moved to live in the Curl_transfer_keeper structure. But that structure is reset in the Transfer method, losing the information that we had about the header size. This patch moves it back to the connectdata struct. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0b537e45e..2f8b98e2e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1527,8 +1527,8 @@ CURLcode Curl_http_done(struct connectdata *conn, if(!conn->bits.retry && ((http->readbytecount + - k->headerbytecount - - k->deductheadercount)) <= 0) { + conn->headerbytecount - + conn->deductheadercount)) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was read from the HTTP server (that counts), this can't be right so we return an error here */ -- cgit v1.2.1 From 359d5009089b8b9450ab54825c08448f9e51ed64 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Jan 2007 23:04:38 +0000 Subject: - David McCreedy made changes to allow base64 encoding/decoding to work on non-ASCII platforms. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2f8b98e2e..ae7c3cfbc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -149,7 +149,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) } snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); - if(Curl_base64_encode(data->state.buffer, + if(Curl_base64_encode(data, data->state.buffer, strlen(data->state.buffer), &authorization) > 0) { if(*userp) -- cgit v1.2.1 From 0fb5a65a58130da7882f0a8d396e24b95c25064f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 14 Jan 2007 14:57:51 +0000 Subject: - David McCreedy provided libcurl changes for doing HTTP communication on non-ASCII platforms. It does add some complexity, most notably with more #ifdefs, but I want to see this supported added and I can't see how we can add it without the extra stuff added. --- lib/http.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ae7c3cfbc..0387298c1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -80,6 +80,7 @@ #include #include "transfer.h" #include "sendf.h" +#include "easyif.h" /* for Curl_convert_... prototypes */ #include "formdata.h" #include "progress.h" #include "base64.h" @@ -154,7 +155,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) &authorization) > 0) { if(*userp) free(*userp); - *userp = aprintf( "%sAuthorization: Basic %s\015\012", + *userp = aprintf( "%sAuthorization: Basic %s\r\n", proxy?"Proxy-":"", authorization); free(authorization); @@ -873,6 +874,20 @@ CURLcode add_buffer_send(send_buffer *in, ptr = in->buffer; size = in->size_used; +#ifdef CURL_DOES_CONVERSIONS + if(size - included_body_bytes > 0) { + res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(res != CURLE_OK) { + /* conversion failed, free memory and return to the caller */ + if(in->buffer) + free(in->buffer); + free(in); + return res; + } + } +#endif /* CURL_DOES_CONVERSIONS */ + if(conn->protocol & PROT_HTTPS) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data @@ -1512,7 +1527,7 @@ CURLcode Curl_http_done(struct connectdata *conn, if(HTTPREQ_POST_FORM == data->set.httpreq) { k->bytecount = http->readbytecount + http->writebytecount; - Curl_formclean(http->sendit); /* Now free that whole lot */ + Curl_formclean(&http->sendit); /* Now free that whole lot */ if(http->form.fp) { /* a file being uploaded was left opened, close it! */ fclose(http->form.fp); @@ -1699,7 +1714,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_safefree(conn->allocptr.ref); if(data->change.referer && !checkheaders(data, "Referer:")) - conn->allocptr.ref = aprintf("Referer: %s\015\012", data->change.referer); + conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); else conn->allocptr.ref = NULL; @@ -1710,7 +1725,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->set.encoding) { Curl_safefree(conn->allocptr.accept_encoding); conn->allocptr.accept_encoding = - aprintf("Accept-Encoding: %s\015\012", data->set.encoding); + aprintf("Accept-Encoding: %s\r\n", data->set.encoding); if(!conn->allocptr.accept_encoding) return CURLE_OUT_OF_MEMORY; } @@ -2194,10 +2209,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) &http->readbytecount, FIRSTSOCKET, &http->writebytecount); + + if(result) { + Curl_formclean(&http->sendit); /* free that whole lot */ + return result; + } +#ifdef CURL_DOES_CONVERSIONS +/* time to convert the form data... */ + result = Curl_formconvert(data, http->sendit); if(result) { - Curl_formclean(http->sendit); /* free that whole lot */ + Curl_formclean(&http->sendit); /* free that whole lot */ return result; } +#endif /* CURL_DOES_CONVERSIONS */ break; case HTTPREQ_PUT: /* Let's PUT the data to the server! */ @@ -2316,8 +2340,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) (size_t)postsize); if(CURLE_OK == result) result = add_buffer(req_buffer, - "\r\n0\r\n\r\n", 7); /* end of a chunked - transfer stream */ + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + /* CR LF 0 CR LF CR LF */ included_body = postsize + 7; } if(result) -- cgit v1.2.1 From 385e612fa5b7663fc2bc815677b8c27bec2f0fe4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 16 Jan 2007 22:22:10 +0000 Subject: - Armel Asselin improved libcurl to behave a lot better when an easy handle doing an FTP transfer is removed from a multi handle before completion. The fix also fixed the "alive counter" to be correct on "premature removal" for all protocols. --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0387298c1..babe3f111 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1503,11 +1503,12 @@ int Curl_https_getsock(struct connectdata *conn, */ CURLcode Curl_http_done(struct connectdata *conn, - CURLcode status) + CURLcode status, bool premature) { struct SessionHandle *data = conn->data; struct HTTP *http =data->reqdata.proto.http; struct Curl_transfer_keeper *k = &data->reqdata.keep; + (void)premature; /* not used */ /* set the proper values (possibly modified on POST) */ conn->fread = data->set.fread; /* restore */ -- cgit v1.2.1 From 45bac25d90e89110f211dc41461bcdce81e74427 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Jan 2007 12:34:23 +0000 Subject: bail out on strdup() errors --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index babe3f111..89509491f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1420,6 +1420,8 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) free(data->state.first_host); data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) + return CURLE_OUT_OF_MEMORY; } if(conn->protocol & PROT_HTTPS) { -- cgit v1.2.1 From abdbd3100f3d42d35730419e1aea02db40f5c214 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Jan 2007 09:26:36 +0000 Subject: - Michael Wallner reported that when doing a CONNECT with a custom User-Agent header, you got _two_ User-Agent headers in the CONNECT request...! Added test case 287 to verify the fix. --- lib/http.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 89509491f..c07053bdd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1101,6 +1101,8 @@ Curl_compareheader(char *headerline, /* line to check */ * like any ordinary HTTP request, and not specially crafted like this. This * function only remains here like this for now since the rewrite is a bit too * much work to do at the moment. + * + * This function is BLOCKING which is nasty for all multi interface using apps. */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, @@ -1160,15 +1162,18 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(CURLE_OK == result) { char *host=(char *)""; const char *proxyconn=""; + const char *useragent=""; if(!checkheaders(data, "Host:")) { host = aprintf("Host: %s\r\n", host_port); if(!host) result = CURLE_OUT_OF_MEMORY; } - if(!checkheaders(data, "Proxy-Connection:")) { + if(!checkheaders(data, "Proxy-Connection:")) proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - } + + if(!checkheaders(data, "User-Agent:") && data->set.useragent) + useragent = conn->allocptr.uagent; if(CURLE_OK == result) { /* Send the connect request to the proxy */ @@ -1184,7 +1189,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, host, conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", - data->set.useragent?conn->allocptr.uagent:"", + useragent, proxyconn); if(CURLE_OK == result) -- cgit v1.2.1 From 91386937ff120d11f7bf24dc487f00751362a61c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Feb 2007 22:51:32 +0000 Subject: - Michael Wallner provided a patch that adds support for CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS that, as their names should hint, do the timeouts with millisecond resolution instead. The only restriction to that is the alarm() (sometimes) used to abort name resolves as that uses full seconds. I fixed the FTP response timeout part of the patch. Internally we now count and keep the timeouts in milliseconds but it also means we multiply set timeouts with 1000. The effect of this is that no timeout can be set to more than 2^31 milliseconds (on 32 bit systems), which equals 24.86 days. We probably couldn't before either since the code did *1000 on the timeout values on several places already. --- lib/http.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c07053bdd..ad42273cd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1121,7 +1121,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, ssize_t gotbytes; char *ptr; long timeout = - data->set.timeout?data->set.timeout:3600; /* in seconds */ + data->set.timeout?data->set.timeout:3600000; /* in milliseconds */ char *line_start; char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; @@ -1225,15 +1225,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* if timeout is requested, find out how much remaining time we have */ long check = timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ - if(check <=0 ) { + Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ + if(check <= 0) { failf(data, "Proxy CONNECT aborted due to timeout"); error = SELECT_TIMEOUT; /* already too little time */ break; } - /* timeout each second and check the timeout */ - switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, 1000)) { + /* loop every second at least, less if the timeout is near */ + switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, + check<1000?check:1000)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; failf(data, "Proxy CONNECT aborted due to select() error"); -- cgit v1.2.1 From e213555c98856d82ff0bed679712f4c00baf128e Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 6 Feb 2007 18:06:37 +0000 Subject: compiler warning fix --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ad42273cd..bca1197d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1234,7 +1234,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* loop every second at least, less if the timeout is near */ switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, - check<1000?check:1000)) { + check<1000L?(int)check:1000)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; failf(data, "Proxy CONNECT aborted due to select() error"); -- cgit v1.2.1 From 7f70dbcad58eb7183d129860192d6968dd7063a1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 Feb 2007 22:32:37 +0000 Subject: Rob Crittenden added support for NSS (Network Security Service) for the SSL/TLS layer. http://www.mozilla.org/projects/security/pki/nss/ --- lib/http.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bca1197d8..8b9e5665c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1502,6 +1502,18 @@ int Curl_https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } +#else +#ifdef USE_NSS +int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif #endif #endif -- cgit v1.2.1 From cbf58d88d0a84042d9dd8a7a6b1644f15242cf02 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 18 Feb 2007 23:02:42 +0000 Subject: - Jeff Pohlmeyer identified two problems: first a rather obscure problem with the multi interface and connection re-use that could make a curl_multi_remove_handle() ruin a pointer in another handle. The second problem was less of an actual problem but more of minor quirk: the re-using of connections wasn't properly checking if the connection was marked for closure. --- lib/http.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8b9e5665c..638c5fad2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1403,6 +1403,10 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) data=conn->data; + /* We default to persistent connections. We set this already in this connect + function to make the re-use checks properly be able to check this bit. */ + conn->bits.close = FALSE; + /* If we are not using a proxy and we want a secure connection, perform SSL * initialization & connection now. If using a proxy with https, then we * must tell the proxy to CONNECT to the host we want to talk to. Only @@ -1674,9 +1678,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else http = data->reqdata.proto.http; - /* We default to persistent connections */ - conn->bits.close = FALSE; - if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->set.upload) { httpreq = HTTPREQ_PUT; -- cgit v1.2.1 From 3a634a273a7bff3d219883f572db786e2c1004b1 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 21 Feb 2007 19:03:20 +0000 Subject: curlassert macro replaced with DEBUGASSERT macro defined in setup_once.h --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 638c5fad2..522bc00f4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -391,7 +391,7 @@ Curl_http_output_auth(struct connectdata *conn, struct auth *authhost; struct auth *authproxy; - curlassert(data); + DEBUGASSERT(data); authhost = &data->state.authhost; authproxy = &data->state.authproxy; @@ -676,9 +676,9 @@ int Curl_http_should_fail(struct connectdata *conn) struct SessionHandle *data; struct Curl_transfer_keeper *k; - curlassert(conn); + DEBUGASSERT(conn); data = conn->data; - curlassert(data); + DEBUGASSERT(data); /* ** For readability @@ -717,7 +717,7 @@ int Curl_http_should_fail(struct connectdata *conn) /* ** All we have left to deal with is 401 and 407 */ - curlassert((k->httpcode == 401) || (k->httpcode == 407)); + DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407)); /* ** Examine the current authentication state to see if this @@ -864,7 +864,7 @@ CURLcode add_buffer_send(send_buffer *in, size_t sendsize; curl_socket_t sockfd; - curlassert(socketindex <= SECONDARYSOCKET); + DEBUGASSERT(socketindex <= SECONDARYSOCKET); sockfd = conn->sock[socketindex]; @@ -1459,7 +1459,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) { CURLcode result; - curlassert(conn->protocol & PROT_HTTPS); + DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); @@ -1690,7 +1690,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->bits.no_body) request = (char *)"HEAD"; else { - curlassert((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); + DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); switch(httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: -- cgit v1.2.1 From b819c72700d5f01cab5848f1cd3c880205d01c81 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 25 Feb 2007 11:38:13 +0000 Subject: - Adam D. Moss made the HTTP CONNECT procedure less blocking when used from the multi interface. Note that it still does a part of the connection in a blocking manner. --- lib/http.c | 491 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 273 insertions(+), 218 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 522bc00f4..16c59fb87 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1115,259 +1115,309 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, struct Curl_transfer_keeper *k = &data->reqdata.keep; CURLcode result; int res; - size_t nread; /* total size read */ - int perline; /* count bytes per line */ - int keepon=TRUE; - ssize_t gotbytes; - char *ptr; long timeout = data->set.timeout?data->set.timeout:3600000; /* in milliseconds */ - char *line_start; - char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; - send_buffer *req_buffer; curl_off_t cl=0; bool closeConnection = FALSE; + long check; #define SELECT_OK 0 #define SELECT_ERROR 1 #define SELECT_TIMEOUT 2 int error = SELECT_OK; - infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); conn->bits.proxy_connect_closed = FALSE; do { - if(data->reqdata.newurl) { - /* This only happens if we've looped here due to authentication reasons, - and we don't really use the newly cloned URL here then. Just free() - it. */ - free(data->reqdata.newurl); - data->reqdata.newurl = NULL; - } - - /* initialize a dynamic send-buffer */ - req_buffer = add_buffer_init(); + if (!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ + char *host_port; + send_buffer *req_buffer; + + infof(data, "Establish HTTP proxy tunnel to %s:%d\n", + hostname, remote_port); + + if(data->reqdata.newurl) { + /* This only happens if we've looped here due to authentication + reasons, and we don't really use the newly cloned URL here + then. Just free() it. */ + free(data->reqdata.newurl); + data->reqdata.newurl = NULL; + } - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; + /* initialize a dynamic send-buffer */ + req_buffer = add_buffer_init(); - host_port = aprintf("%s:%d", hostname, remote_port); - if(!host_port) - return CURLE_OUT_OF_MEMORY; + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; - /* Setup the proxy-authorization header, if any */ - result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); + host_port = aprintf("%s:%d", hostname, remote_port); + if(!host_port) + return CURLE_OUT_OF_MEMORY; - if(CURLE_OK == result) { - char *host=(char *)""; - const char *proxyconn=""; - const char *useragent=""; + /* Setup the proxy-authorization header, if any */ + result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); - if(!checkheaders(data, "Host:")) { - host = aprintf("Host: %s\r\n", host_port); - if(!host) - result = CURLE_OUT_OF_MEMORY; - } - if(!checkheaders(data, "Proxy-Connection:")) - proxyconn = "Proxy-Connection: Keep-Alive\r\n"; + if(CURLE_OK == result) { + char *host=(char *)""; + const char *proxyconn=""; + const char *useragent=""; + + if(!checkheaders(data, "Host:")) { + host = aprintf("Host: %s\r\n", host_port); + if(!host) + result = CURLE_OUT_OF_MEMORY; + } + if(!checkheaders(data, "Proxy-Connection:")) + proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - if(!checkheaders(data, "User-Agent:") && data->set.useragent) - useragent = conn->allocptr.uagent; + if(!checkheaders(data, "User-Agent:") && data->set.useragent) + useragent = conn->allocptr.uagent; - if(CURLE_OK == result) { - /* Send the connect request to the proxy */ - /* BLOCKING */ - result = - add_bufferf(req_buffer, - "CONNECT %s:%d HTTP/1.0\r\n" - "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ - hostname, remote_port, - host, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - useragent, - proxyconn); - - if(CURLE_OK == result) - result = add_custom_headers(conn, req_buffer); - - if(host && *host) - free(host); - - if(CURLE_OK == result) - /* CRLF terminate the request */ - result = add_bufferf(req_buffer, "\r\n"); - - if(CURLE_OK == result) - /* Now send off the request */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); + if(CURLE_OK == result) { + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + add_bufferf(req_buffer, + "CONNECT %s:%d HTTP/1.0\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostname, remote_port, + host, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(CURLE_OK == result) + result = add_custom_headers(conn, req_buffer); + + if(host && *host) + free(host); + + if(CURLE_OK == result) + /* CRLF terminate the request */ + result = add_bufferf(req_buffer, "\r\n"); + + if(CURLE_OK == result) + /* Now send off the request */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, sockindex); + } + if(result) + failf(data, "Failed sending CONNECT to proxy"); } + free(host_port); if(result) - failf(data, "Failed sending CONNECT to proxy"); - } - free(host_port); - if(result) - return result; + return result; - ptr=data->state.buffer; - line_start = ptr; + conn->bits.tunnel_connecting = TRUE; + } /* END CONNECT PHASE */ - nread=0; - perline=0; - keepon=TRUE; + /* now we've issued the CONNECT and we're waiting to hear back - + we try not to block here in multi-mode because that might be a LONG + wait if the proxy cannot connect-through to the remote host. */ - while((nreadnow); /* spent time */ + if(check <=0 ) { + failf(data, "Proxy CONNECT aborted due to timeout"); + error = SELECT_TIMEOUT; /* already too little time */ + break; + } - /* if timeout is requested, find out how much remaining time we have */ - long check = timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - if(check <= 0) { - failf(data, "Proxy CONNECT aborted due to timeout"); - error = SELECT_TIMEOUT; /* already too little time */ - break; + /* if we're in multi-mode and we would block, return instead for a retry */ + if (Curl_if_multi == data->state.used_interface) { + if (0 == Curl_select(tunnelsocket, CURL_SOCKET_BAD, 0)) + /* return so we'll be called again polling-style */ + return CURLE_OK; + else { + DEBUGF(infof(data, + "Multi mode finished polling for response from " + "proxy CONNECT.")); } + } + else { + DEBUGF(infof(data, "Easy mode waiting for response from proxy CONNECT.")); + } - /* loop every second at least, less if the timeout is near */ - switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, - check<1000L?(int)check:1000)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select() error"); - break; - case 0: /* timeout */ - break; - default: - res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); - if(res< 0) - /* EWOULDBLOCK */ - continue; /* go loop yourself */ - else if(res) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); + /* at this point, either: + 1) we're in easy-mode and so it's okay to block waiting for a CONNECT + response + 2) we're in multi-mode and we didn't block - it's either an error or we + now have some data waiting. + In any case, the tunnel_connecting phase is over. */ + conn->bits.tunnel_connecting = FALSE; + + { /* BEGIN NEGOTIATION PHASE */ + size_t nread; /* total size read */ + int perline; /* count bytes per line */ + int keepon=TRUE; + ssize_t gotbytes; + char *ptr; + char *line_start; + + ptr=data->state.buffer; + line_start = ptr; + + nread=0; + perline=0; + keepon=TRUE; + + while((nreadnow); /* spent time */ + if(check <= 0) { + failf(data, "Proxy CONNECT aborted due to timeout"); + error = SELECT_TIMEOUT; /* already too little time */ + break; } - else { - /* - * We got a whole chunk of data, which can be anything from one byte - * to a set of lines and possibly just a piece of the last line. - */ - int i; - - nread += gotbytes; - - if(keepon > TRUE) { - /* This means we are currently ignoring a response-body, so we - simply count down our counter and make sure to break out of the - loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; - } - } - else - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr=='\n') { - char letter; - int writetype; - - /* output debug if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - line_start, (size_t)perline, conn); - - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - result = Curl_client_write(conn, writetype, line_start, perline); - if(result) - return result; - - /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes. Treat a following CR - as end-of-headers as well.*/ - - if(('\r' == line_start[0]) || - ('\n' == line_start[0])) { - /* end of response-headers from the proxy */ - if(cl && (407 == k->httpcode) && !data->state.authproblem) { - /* If we get a 407 response code with content length when we - * have no auth problem, we must ignore the whole - * response-body */ - keepon = 2; - infof(data, "Ignore %" FORMAT_OFF_T - " bytes of response-body\n", cl); - cl -= (gotbytes - i);/* remove the remaining chunk of what - we already read */ - if(cl<=0) - /* if the whole thing was already read, we are done! */ - keepon=FALSE; - } - else - keepon = FALSE; - break; /* breaks out of for-loop, not switch() */ - } - /* keep a backup of the position we are about to blank */ - letter = line_start[perline]; - line_start[perline]=0; /* zero terminate the buffer */ - if((checkprefix("WWW-Authenticate:", line_start) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", line_start) && - (407 == k->httpcode))) { - result = Curl_http_input_auth(conn, k->httpcode, line_start); - if(result) - return result; - } - else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + strlen("Content-Length:"), - NULL, 10); - } - else if(Curl_compareheader(line_start, - "Connection:", "close")) - closeConnection = TRUE; - else if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &k->httpcode)) { - /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode; + /* loop every second at least, less if the timeout is near */ + switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, + check<1000L?(int)check:1000)) { + case -1: /* select() error, stop reading */ + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted due to select() error"); + break; + case 0: /* timeout */ + break; + default: + res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); + if(res< 0) + /* EWOULDBLOCK */ + continue; /* go loop yourself */ + else if(res) + keepon = FALSE; + else if(gotbytes <= 0) { + keepon = FALSE; + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + else { + /* + * We got a whole chunk of data, which can be anything from one + * byte to a set of lines and possibly just a piece of the last + * line. + */ + int i; + + nread += gotbytes; + + if(keepon > TRUE) { + /* This means we are currently ignoring a response-body, so we + simply count down our counter and make sure to break out of + the loop when we're done! */ + cl -= gotbytes; + if(cl<=0) { + keepon = FALSE; + break; } - /* put back the letter we blanked out before */ - line_start[perline]= letter; - - perline=0; /* line starts over here */ - line_start = ptr+1; /* this skips the zero byte we wrote */ } + else + for(i = 0; i < gotbytes; ptr++, i++) { + perline++; /* amount of bytes in this line so far */ + if(*ptr=='\n') { + char letter; + int writetype; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + line_start, (size_t)perline, conn); + + /* send the header to the callback */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, line_start, perline); + if(result) + return result; + + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ + + if(('\r' == line_start[0]) || + ('\n' == line_start[0])) { + /* end of response-headers from the proxy */ + if(cl && (407 == k->httpcode) && + !data->state.authproblem) { + /* If we get a 407 response code with content length + * when we have no auth problem, we must ignore the + * whole response-body */ + keepon = 2; + infof(data, "Ignore %" FORMAT_OFF_T + " bytes of response-body\n", cl); + cl -= (gotbytes - i);/* remove the remaining chunk of + what we already read */ + if(cl<=0) + /* if the whole thing was already read, we are done! */ + keepon=FALSE; + } + else + keepon = FALSE; + break; /* breaks out of for-loop, not switch() */ + } + + /* keep a backup of the position we are about to blank */ + letter = line_start[perline]; + line_start[perline]=0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", line_start) && + (407 == k->httpcode))) { + result = Curl_http_input_auth(conn, k->httpcode, + line_start); + if(result) + return result; + } + else if(checkprefix("Content-Length:", line_start)) { + cl = curlx_strtoofft(line_start + strlen("Content-Length:"), + NULL, 10); + } + else if(Curl_compareheader(line_start, + "Connection:", "close")) + closeConnection = TRUE; + else if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + /* put back the letter we blanked out before */ + line_start[perline]= letter; + + perline=0; /* line starts over here */ + line_start = ptr+1; /* this skips the zero byte we wrote */ + } + } } - } + break; + } /* switch */ + } /* while there's buffer left and loop is requested */ + + if(error) + return CURLE_RECV_ERROR; + + if(data->info.httpproxycode != 200) + /* Deal with the possibly already received authenticate + headers. 'newurl' is set to a new URL if we must loop. */ + Curl_http_auth_act(conn); + + if (closeConnection && data->reqdata.newurl) { + /* Connection closed by server. Don't use it anymore */ + sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; break; - } /* switch */ - } /* while there's buffer left and loop is requested */ - - if(error) - return CURLE_RECV_ERROR; - - if(data->info.httpproxycode != 200) - /* Deal with the possibly already received authenticate - headers. 'newurl' is set to a new URL if we must loop. */ - Curl_http_auth_act(conn); - - if (closeConnection && data->reqdata.newurl) { - /* Connection closed by server. Don't use it anymore */ - sclose(conn->sock[sockindex]); - conn->sock[sockindex] = CURL_SOCKET_BAD; - break; - } + } + } /* END NEGOTIATION PHASE */ } while(data->reqdata.newurl); if(200 != k->httpcode) { @@ -1423,6 +1473,11 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return result; } + if (conn->bits.tunnel_connecting) { + /* nothing else to do except wait right now - we're not done here. */ + return CURLE_OK; + } + if(!data->state.this_is_a_follow) { /* this is not a followed location, get the original host name */ if (data->state.first_host) -- cgit v1.2.1 From c514a2a89aa1c1e06b70405eedb4e1f70b27fd10 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Mon, 26 Feb 2007 04:24:26 +0000 Subject: Removed inclusion of and in .c-files since they're already included through "setup.h". --- lib/http.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 16c59fb87..b4a62f496 100644 --- a/lib/http.c +++ b/lib/http.c @@ -30,12 +30,6 @@ #include #include #include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif #ifdef WIN32 #include -- cgit v1.2.1 From fba4cd0e625cdba3561b3530317ba87ae348aeaf Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 26 Mar 2007 23:23:46 +0000 Subject: Internal function Curl_select() renamed to Curl_socket_ready() --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b4a62f496..94d2cc00c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1225,7 +1225,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* if we're in multi-mode and we would block, return instead for a retry */ if (Curl_if_multi == data->state.used_interface) { - if (0 == Curl_select(tunnelsocket, CURL_SOCKET_BAD, 0)) + if (0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) /* return so we'll be called again polling-style */ return CURLE_OK; else { @@ -1273,7 +1273,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } /* loop every second at least, less if the timeout is near */ - switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, + switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, check<1000L?(int)check:1000)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; -- cgit v1.2.1 From d58c7a8bdd6b54df30c7814c52847d32e2059172 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 27 Mar 2007 18:16:35 +0000 Subject: Update message --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 94d2cc00c..187c0a43d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1277,7 +1277,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, check<1000L?(int)check:1000)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select() error"); + failf(data, "Proxy CONNECT aborted due to select/poll error"); break; case 0: /* timeout */ break; -- cgit v1.2.1 From 990b15e40288ad89c423d331b9563d8259284d9c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Apr 2007 20:54:37 +0000 Subject: Rob Jones fixed better #ifdef'ing for a bunch of #include lines. --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 187c0a43d..884d7e3d2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -54,14 +54,18 @@ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_NETDB_H #include +#endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_NET_IF_H #include #endif +#ifdef HAVE_SYS_IOCTL_H #include +#endif #include #ifdef HAVE_SYS_PARAM_H -- cgit v1.2.1 From c895dc8a19eacd53cbca7d443f2673cacf119919 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 5 Apr 2007 11:09:46 +0000 Subject: runtests -t discovered this out of memory handling issues --- lib/http.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 884d7e3d2..b59779b1b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -157,6 +157,8 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) proxy?"Proxy-":"", authorization); free(authorization); + if(!*userp) + return CURLE_OUT_OF_MEMORY; } else return CURLE_OUT_OF_MEMORY; @@ -1150,8 +1152,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; host_port = aprintf("%s:%d", hostname, remote_port); - if(!host_port) + if(!host_port) { + free(req_buffer); return CURLE_OUT_OF_MEMORY; + } /* Setup the proxy-authorization header, if any */ result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); @@ -1163,8 +1167,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(!checkheaders(data, "Host:")) { host = aprintf("Host: %s\r\n", host_port); - if(!host) + if(!host) { + free(req_buffer); + free(host_port); result = CURLE_OUT_OF_MEMORY; + } } if(!checkheaders(data, "Proxy-Connection:")) proxyconn = "Proxy-Connection: Keep-Alive\r\n"; -- cgit v1.2.1 From 0d635a11199c3eae6f2ad8cb02e588fe189cd3c7 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 6 Apr 2007 20:53:15 +0000 Subject: fix out of memory handling issue --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b59779b1b..011f1141e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1170,7 +1170,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(!host) { free(req_buffer); free(host_port); - result = CURLE_OUT_OF_MEMORY; + return CURLE_OUT_OF_MEMORY; } } if(!checkheaders(data, "Proxy-Connection:")) -- cgit v1.2.1 From 910ee13b20b622b9aa0c53025d86b19e9dcdf586 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 10 Apr 2007 00:38:41 +0000 Subject: Fixed an out of memory handling issue. --- lib/http.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 011f1141e..8e4d322af 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1206,15 +1206,18 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* CRLF terminate the request */ result = add_bufferf(req_buffer, "\r\n"); - if(CURLE_OK == result) + if(CURLE_OK == result) { /* Now send off the request */ result = add_buffer_send(req_buffer, conn, &data->info.request_size, 0, sockindex); + req_buffer = NULL; + } } if(result) failf(data, "Failed sending CONNECT to proxy"); } free(host_port); + Curl_safefree(req_buffer); if(result) return result; -- cgit v1.2.1 From 5daa6b93679b1e9a630975fef66191ae3bc71ab1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Apr 2007 20:46:40 +0000 Subject: Ravi Pratap provided fixes for HTTP pipelining --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8e4d322af..c412df5bb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1630,8 +1630,8 @@ CURLcode Curl_http_done(struct connectdata *conn, if(!conn->bits.retry && ((http->readbytecount + - conn->headerbytecount - - conn->deductheadercount)) <= 0) { + data->reqdata.keep.headerbytecount - + data->reqdata.keep.deductheadercount)) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was read from the HTTP server (that counts), this can't be right so we return an error here */ -- cgit v1.2.1 From d46d995766a849dbbcfa2f362ccdbca24401a006 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 10 Apr 2007 22:52:50 +0000 Subject: Fixed some out of memory handling issues. --- lib/http.c | 96 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 43 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c412df5bb..9c7a2bd11 100644 --- a/lib/http.c +++ b/lib/http.c @@ -332,6 +332,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(pickhost || pickproxy) { data->reqdata.newurl = strdup(data->change.url); /* clone URL */ + if (!data->reqdata.newurl) + return CURLE_OUT_OF_MEMORY; if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD) && @@ -352,6 +354,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD)) { data->reqdata.newurl = strdup(data->change.url); /* clone URL */ + if (!data->reqdata.newurl) + return CURLE_OUT_OF_MEMORY; data->state.authhost.done = TRUE; } } @@ -992,8 +996,7 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) if(s) { CURLcode result = add_buffer(in, s, strlen(s)); free(s); - if(CURLE_OK == result) - return CURLE_OK; + return result; } /* If we failed, we cleanup the whole buffer and return error */ if(in->buffer) @@ -1021,8 +1024,12 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) /* create a new buffer */ new_rb = (char *)malloc(new_size); - if(!new_rb) + if(!new_rb) { + /* If we failed, we cleanup the whole buffer and return error */ + Curl_safefree(in->buffer); + free(in); return CURLE_OUT_OF_MEMORY; + } in->buffer = new_rb; in->size_max = new_size; @@ -1179,40 +1186,38 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(!checkheaders(data, "User-Agent:") && data->set.useragent) useragent = conn->allocptr.uagent; - if(CURLE_OK == result) { - /* Send the connect request to the proxy */ - /* BLOCKING */ - result = - add_bufferf(req_buffer, - "CONNECT %s:%d HTTP/1.0\r\n" - "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ - hostname, remote_port, - host, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - useragent, - proxyconn); - - if(CURLE_OK == result) - result = add_custom_headers(conn, req_buffer); - - if(host && *host) - free(host); - - if(CURLE_OK == result) - /* CRLF terminate the request */ - result = add_bufferf(req_buffer, "\r\n"); - - if(CURLE_OK == result) { - /* Now send off the request */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); - req_buffer = NULL; - } - } + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + add_bufferf(req_buffer, + "CONNECT %s:%d HTTP/1.0\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostname, remote_port, + host, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(host && *host) + free(host); + + if(CURLE_OK == result) + result = add_custom_headers(conn, req_buffer); + + if(CURLE_OK == result) + /* CRLF terminate the request */ + result = add_bufferf(req_buffer, "\r\n"); + + if(CURLE_OK == result) { + /* Now send off the request */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, sockindex); + } + req_buffer = NULL; if(result) failf(data, "Failed sending CONNECT to proxy"); } @@ -1666,7 +1671,6 @@ static CURLcode expect100(struct SessionHandle *data, static CURLcode add_custom_headers(struct connectdata *conn, send_buffer *req_buffer) { - CURLcode result = CURLE_OK; char *ptr; struct curl_slist *headers=conn->data->set.headers; @@ -1693,7 +1697,7 @@ static CURLcode add_custom_headers(struct connectdata *conn, strlen("Content-Type:"))) ; else { - result = add_bufferf(req_buffer, "%s\r\n", headers->data); + CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data); if(result) return result; } @@ -1701,7 +1705,7 @@ static CURLcode add_custom_headers(struct connectdata *conn, } headers = headers->next; } - return result; + return CURLE_OK; } /* @@ -2445,11 +2449,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; } } else { - add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; if(data->set.postfieldsize) { /* set the upload size to the progress meter */ @@ -2475,7 +2483,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) break; default: - add_buffer(req_buffer, "\r\n", 2); + result = add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; /* issue the request */ result = add_buffer_send(req_buffer, conn, -- cgit v1.2.1 From dc2c70be070f0da6e61777d7a8cb2e47576b461c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Jul 2007 22:31:13 +0000 Subject: Giancarlo Formicuccia reported and fixed a problem with a closed connection to a proxy during CONNECT auth negotiation. --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9c7a2bd11..a9b483dbd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1398,6 +1398,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, else if(Curl_compareheader(line_start, "Connection:", "close")) closeConnection = TRUE; + else if(Curl_compareheader(line_start, + "Proxy-Connection:", "close")) + closeConnection = TRUE; else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &k->httpcode)) { -- cgit v1.2.1 From 5ecd56d9646c2adcc70c0369fb6196f62ecc62f4 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 23 Jul 2007 18:51:22 +0000 Subject: Implemented only the parts of Patrick Monnerat's OS/400 patch that renamed some few internal identifiers to avoid conflicts, which could be useful on other platforms. --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a9b483dbd..217ccf234 100644 --- a/lib/http.c +++ b/lib/http.c @@ -790,7 +790,7 @@ static size_t readmoredata(char *buffer, /* move backup data into focus and continue on that */ http->postdata = http->backup.postdata; http->postsize = http->backup.postsize; - conn->fread = http->backup.fread; + conn->fread_func = http->backup.fread_func; conn->fread_in = http->backup.fread_in; http->sending++; /* move one step up */ @@ -940,13 +940,13 @@ CURLcode add_buffer_send(send_buffer *in, ptr = in->buffer + amount; /* backup the currently set pointers */ - http->backup.fread = conn->fread; + http->backup.fread_func = conn->fread_func; http->backup.fread_in = conn->fread_in; http->backup.postdata = http->postdata; http->backup.postsize = http->postsize; /* set the new pointers for the request-sending */ - conn->fread = (curl_read_callback)readmoredata; + conn->fread_func = (curl_read_callback)readmoredata; conn->fread_in = (void *)conn; http->postdata = ptr; http->postsize = (curl_off_t)size; @@ -1606,7 +1606,7 @@ CURLcode Curl_http_done(struct connectdata *conn, (void)premature; /* not used */ /* set the proper values (possibly modified on POST) */ - conn->fread = data->set.fread; /* restore */ + conn->fread_func = data->set.fread_func; /* restore */ conn->fread_in = data->set.in; /* restore */ if (http == NULL) @@ -1991,7 +1991,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) readthisamountnow = BUFSIZE; actuallyread = - data->set.fread(data->state.buffer, 1, (size_t)readthisamountnow, + data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow, data->set.in); passed += actuallyread; @@ -2246,7 +2246,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* set the read function to read from the generated form data */ - conn->fread = (curl_read_callback)Curl_FormReader; + conn->fread_func = (curl_read_callback)Curl_FormReader; conn->fread_in = &http->form; http->sending = HTTPSEND_BODY; @@ -2446,7 +2446,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) http->sending = HTTPSEND_BODY; - conn->fread = (curl_read_callback)readmoredata; + conn->fread_func = (curl_read_callback)readmoredata; conn->fread_in = (void *)conn; /* set the upload size to the progress meter */ -- cgit v1.2.1 From f01c6e51f463a14eee8fdb43835cb7d2a144a214 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 30 Jul 2007 21:41:12 +0000 Subject: Patrick Monnerat restored qssl successful compilation and loading --- lib/http.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 217ccf234..529889c86 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1588,6 +1588,18 @@ int Curl_https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } +#else +#ifdef USE_QSOSSL +int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif #endif #endif #endif -- cgit v1.2.1 From 006878686cfd3faa9eca92fc8fe60cb8f8073a59 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 1 Aug 2007 12:58:04 +0000 Subject: Greg Morse reported a problem with POSTing using ANYAUTH to a server requiring NTLM, and he provided test code and a test server and we worked out a bug fix. We failed to count sent body data at times, which then caused internal confusions when libcurl tried to send the rest of the data in order to maintain the same connection alive. (and then I did some minor reformatting of code in lib/http.c) --- lib/http.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 529889c86..19e7483df 100644 --- a/lib/http.c +++ b/lib/http.c @@ -853,10 +853,10 @@ send_buffer *add_buffer_init(void) static CURLcode add_buffer_send(send_buffer *in, struct connectdata *conn, - long *bytes_written, /* add the number of sent - bytes to this counter */ + long *bytes_written, /* add the number of sent bytes + to this counter */ size_t included_body_bytes, /* how much of the buffer - contains body data (for log tracing) */ + contains body data */ int socketindex) { @@ -921,10 +921,14 @@ CURLcode add_buffer_send(send_buffer *in, /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, (size_t)(amount-included_body_bytes), conn); - if (included_body_bytes) + if (included_body_bytes) { Curl_debug(conn->data, CURLINFO_DATA_OUT, ptr+amount-included_body_bytes, (size_t)included_body_bytes, conn); + /* since we sent a piece of the body here, up the byte counter for it + accordingly */ + http->writebytecount = included_body_bytes; + } } *bytes_written += amount; @@ -2038,7 +2042,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); - conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->reqdata.range); + conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", + data->reqdata.range); } else if((httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { @@ -2418,7 +2423,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->state.expect100header && (postsize < MAX_INITIAL_POST_SIZE)) { - /* if we don't use expect:-100 AND + /* if we don't use expect: 100 AND postsize is less than MAX_INITIAL_POST_SIZE then append the post data to the HTTP request header. This limit @@ -2492,9 +2497,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); break; default: -- cgit v1.2.1 From 50c10aa5bf545eedfdbe561116656b6ec12654cd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 1 Aug 2007 21:20:01 +0000 Subject: Patrick Monnerat and I modified libcurl so that now it *copies* all strings passed to it with curl_easy_setopt()! Previously it has always just refered to the data, forcing the user to keep the data around until libcurl is done with it. That is now history and libcurl will instead clone the given strings and keep private copies. --- lib/http.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 19e7483df..61511b57a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1187,7 +1187,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(!checkheaders(data, "Proxy-Connection:")) proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - if(!checkheaders(data, "User-Agent:") && data->set.useragent) + if(!checkheaders(data, "User-Agent:") && + data->set.str[STRING_USERAGENT]) useragent = conn->allocptr.uagent; /* Send the connect request to the proxy */ @@ -1770,8 +1771,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* Now set the 'request' pointer to the proper request string */ - if(data->set.customrequest) - request = data->set.customrequest; + if(data->set.str[STRING_CUSTOMREQUEST]) + request = data->set.str[STRING_CUSTOMREQUEST]; else { if(conn->bits.no_body) request = (char *)"HEAD"; @@ -1826,14 +1827,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else conn->allocptr.ref = NULL; - if(data->set.cookie && !checkheaders(data, "Cookie:")) - addcookies = data->set.cookie; + if(data->set.str[STRING_COOKIE] && !checkheaders(data, "Cookie:")) + addcookies = data->set.str[STRING_COOKIE]; if(!checkheaders(data, "Accept-Encoding:") && - data->set.encoding) { + data->set.str[STRING_ENCODING]) { Curl_safefree(conn->allocptr.accept_encoding); conn->allocptr.accept_encoding = - aprintf("Accept-Encoding: %s\r\n", data->set.encoding); + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); if(!conn->allocptr.accept_encoding) return CURLE_OUT_OF_MEMORY; } @@ -2107,19 +2108,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.userpwd?conn->allocptr.userpwd:"", (data->reqdata.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", - (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)? + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? conn->allocptr.uagent:"", (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", - (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? - conn->allocptr.accept_encoding:"", - (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: */, - (conn->bits.httpproxy && - !conn->bits.tunnel_proxy && - !checkheaders(data, "Proxy-Connection:"))? + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !checkheaders(data, "Proxy-Connection:"))? "Proxy-Connection: Keep-Alive\r\n":"", - te + te ); if(result) @@ -2384,7 +2389,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* figure out the size of the postfields */ postsize = (data->set.postfieldsize != -1)? data->set.postfieldsize: - (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0); + (data->set.str[STRING_POSTFIELDS]? + (curl_off_t)strlen(data->set.str[STRING_POSTFIELDS]):0); if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if @@ -2409,7 +2415,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if(data->set.postfields) { + if(data->set.str[STRING_POSTFIELDS]) { /* for really small posts we don't use Expect: headers at all, and for the somewhat bigger ones we allow the app to disable it */ @@ -2437,7 +2443,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!conn->bits.upload_chunky) { /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ - result = add_buffer(req_buffer, data->set.postfields, + result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS], (size_t)postsize); included_body = postsize; } @@ -2445,7 +2451,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Append the POST data chunky-style */ result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); if(CURLE_OK == result) - result = add_buffer(req_buffer, data->set.postfields, + result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS], (size_t)postsize); if(CURLE_OK == result) result = add_buffer(req_buffer, @@ -2459,7 +2465,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else { /* A huge POST coming up, do data separate from the request */ http->postsize = postsize; - http->postdata = data->set.postfields; + http->postdata = data->set.str[STRING_POSTFIELDS]; http->sending = HTTPSEND_BODY; -- cgit v1.2.1 From 59c16a570fffdb9442e1ff0ceb4dca93950cd57c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Aug 2007 11:34:50 +0000 Subject: argh, Greg Morse pointed out that the NTLM POST fix only worked if VERBOSE was set, this should make it work for all cases! --- lib/http.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 61511b57a..d22c591f9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -921,15 +921,15 @@ CURLcode add_buffer_send(send_buffer *in, /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, (size_t)(amount-included_body_bytes), conn); - if (included_body_bytes) { + if (included_body_bytes) Curl_debug(conn->data, CURLINFO_DATA_OUT, ptr+amount-included_body_bytes, (size_t)included_body_bytes, conn); - /* since we sent a piece of the body here, up the byte counter for it - accordingly */ - http->writebytecount = included_body_bytes; - } } + if (included_body_bytes) + /* since we sent a piece of the body here, up the byte counter for it + accordingly */ + http->writebytecount = included_body_bytes; *bytes_written += amount; -- cgit v1.2.1 From 5a79532aee07ddd423b7038be53a6353468134af Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 Aug 2007 20:21:32 +0000 Subject: Song Ma provided a patch that cures a problem libcurl has when doing resume HTTP PUT using Digest authentication. Test case 5320 and 5322 were also added to verify the functionality. --- lib/http.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d22c591f9..e72ed43e1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1993,7 +1993,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->reqdata.resume_from = 0; } - if(data->reqdata.resume_from) { + if(data->reqdata.resume_from && !data->state.this_is_a_follow) { /* do we still game? */ curl_off_t passed=0; @@ -2049,6 +2049,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else if((httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { + /* if a line like this was already allocated, free the previous one */ + if(conn->allocptr.rangeline) + free(conn->allocptr.rangeline); + if(data->reqdata.resume_from) { /* This is because "resume" was selected */ curl_off_t total_expected_size= @@ -2066,6 +2070,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", data->reqdata.range, data->set.infilesize); } + if(!conn->allocptr.rangeline) + return CURLE_OUT_OF_MEMORY; } } @@ -2185,11 +2191,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->set.timecondition) { struct tm *tm; - /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since - * header family should have their times set in GMT as RFC2616 defines: - * "All HTTP date/time stamps MUST be represented in Greenwich Mean Time - * (GMT), without exception. For the purposes of HTTP, GMT is exactly - * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). */ #ifdef HAVE_GMTIME_R -- cgit v1.2.1 From 523767660c05cf359091694fcaccb763ebb7b2d7 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sun, 26 Aug 2007 05:53:26 +0000 Subject: Fixed some minor mismatched types found by splint. --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e72ed43e1..715031658 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1055,7 +1055,7 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) * Pass headers WITH the colon. */ bool -Curl_compareheader(char *headerline, /* line to check */ +Curl_compareheader(const char *headerline, /* line to check */ const char *header, /* header keyword _with_ colon */ const char *content) /* content string to find */ { @@ -1067,8 +1067,8 @@ Curl_compareheader(char *headerline, /* line to check */ size_t hlen = strlen(header); size_t clen; size_t len; - char *start; - char *end; + const char *start; + const char *end; if(!strnequal(headerline, header, hlen)) return FALSE; /* doesn't start with header */ @@ -1119,7 +1119,7 @@ Curl_compareheader(char *headerline, /* line to check */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int sockindex, char *hostname, - int remote_port) + unsigned short remote_port) { int subversion=0; struct SessionHandle *data=conn->data; -- cgit v1.2.1 From 8cf0814a143d99de813fbd1653b785252b4c58a6 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 27 Aug 2007 06:31:28 +0000 Subject: Fixed some minor type mismatches and missing consts mainly found by splint. --- lib/http.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 715031658..2938c37ca 100644 --- a/lib/http.c +++ b/lib/http.c @@ -384,14 +384,14 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) */ static CURLcode Curl_http_output_auth(struct connectdata *conn, - char *request, - char *path, + const char *request, + const char *path, bool proxytunnel) /* TRUE if this is the request setting up the proxy tunnel */ { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; - char *auth=NULL; + const char *auth=NULL; struct auth *authhost; struct auth *authproxy; @@ -426,7 +426,7 @@ Curl_http_output_auth(struct connectdata *conn, (conn->bits.tunnel_proxy == proxytunnel)) { #ifdef USE_NTLM if(authproxy->picked == CURLAUTH_NTLM) { - auth=(char *)"NTLM"; + auth="NTLM"; result = Curl_output_ntlm(conn, TRUE); if(result) return result; @@ -437,7 +437,7 @@ Curl_http_output_auth(struct connectdata *conn, /* Basic */ if(conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { - auth=(char *)"Basic"; + auth="Basic"; result = Curl_output_basic(conn, TRUE); if(result) return result; @@ -448,11 +448,11 @@ Curl_http_output_auth(struct connectdata *conn, } #ifndef CURL_DISABLE_CRYPTO_AUTH else if(authproxy->picked == CURLAUTH_DIGEST) { - auth=(char *)"Digest"; + auth="Digest"; result = Curl_output_digest(conn, TRUE, /* proxy */ - (unsigned char *)request, - (unsigned char *)path); + (const unsigned char *)request, + (const unsigned char *)path); if(result) return result; } @@ -485,7 +485,7 @@ Curl_http_output_auth(struct connectdata *conn, if((authhost->picked == CURLAUTH_GSSNEGOTIATE) && data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { - auth=(char *)"GSS-Negotiate"; + auth="GSS-Negotiate"; result = Curl_output_negotiate(conn); if (result) return result; @@ -495,7 +495,7 @@ Curl_http_output_auth(struct connectdata *conn, #endif #ifdef USE_NTLM if(authhost->picked == CURLAUTH_NTLM) { - auth=(char *)"NTLM"; + auth="NTLM"; result = Curl_output_ntlm(conn, FALSE); if(result) return result; @@ -505,11 +505,11 @@ Curl_http_output_auth(struct connectdata *conn, { #ifndef CURL_DISABLE_CRYPTO_AUTH if(authhost->picked == CURLAUTH_DIGEST) { - auth=(char *)"Digest"; + auth="Digest"; result = Curl_output_digest(conn, FALSE, /* not a proxy */ - (unsigned char *)request, - (unsigned char *)path); + (const unsigned char *)request, + (const unsigned char *)path); if(result) return result; } else @@ -517,7 +517,7 @@ Curl_http_output_auth(struct connectdata *conn, if(authhost->picked == CURLAUTH_BASIC) { if(conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { - auth=(char *)"Basic"; + auth="Basic"; result = Curl_output_basic(conn, FALSE); if(result) return result; @@ -551,7 +551,7 @@ Curl_http_output_auth(struct connectdata *conn, CURLcode Curl_http_input_auth(struct connectdata *conn, int httpcode, - char *header) /* the first non-space */ + const char *header) /* the first non-space */ { /* * This resource requires authentication @@ -559,7 +559,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, struct SessionHandle *data = conn->data; long *availp; - char *start; + const char *start; struct auth *authp; if (httpcode == 407) { @@ -1118,7 +1118,7 @@ Curl_compareheader(const char *headerline, /* line to check */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int sockindex, - char *hostname, + const char *hostname, unsigned short remote_port) { int subversion=0; -- cgit v1.2.1 From e04151ed76a04613221d8a6ef6079645ee230844 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 15 Sep 2007 21:14:12 +0000 Subject: Michal Marek made libcurl automatically append ";type=" when using HTTP proxies for FTP urls. --- lib/http.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2938c37ca..090aad3d2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1740,6 +1740,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) CURLcode result=CURLE_OK; struct HTTP *http; char *ppath = data->reqdata.path; + char ftp_typecode[sizeof(";type=?")] = ""; char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ char *ptr; @@ -1950,6 +1951,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } ppath = data->change.url; + /* when doing ftp, append ;type= if not present */ + if (checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { + char *p = strstr(ppath, ";type="); + if (p && p[6] && p[7] == 0) { + switch (toupper(p[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + p = NULL; + } + } + if (!p) + snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); + } } if(HTTPREQ_POST_FORM == httpreq) { /* we must build the whole darned post sequence first, so that we have @@ -2093,7 +2111,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) result = add_bufferf(req_buffer, "%s " /* GET/HEAD/POST/PUT */ - "%s HTTP/%s\r\n" /* path + HTTP version */ + "%s%s HTTP/%s\r\n" /* path + HTTP version */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ @@ -2108,6 +2126,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) request, ppath, + ftp_typecode, httpstring, conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", -- cgit v1.2.1 From 015d5869d7e3daf81548e4d5d55209adfd4285bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 21 Sep 2007 11:05:31 +0000 Subject: Mark Davies fixed Negotiate authentication over proxy, and also introduced the --proxy-negotiate command line option to allow a user to explicitly select it. --- lib/http.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 090aad3d2..67b2d3f55 100644 --- a/lib/http.c +++ b/lib/http.c @@ -424,6 +424,18 @@ Curl_http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if (conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { +#ifdef HAVE_GSSAPI + if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) && + data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + auth="GSS-Negotiate"; + result = Curl_output_negotiate(conn, TRUE); + if (result) + return result; + authproxy->done = TRUE; + } + else +#endif #ifdef USE_NTLM if(authproxy->picked == CURLAUTH_NTLM) { auth="NTLM"; @@ -486,7 +498,7 @@ Curl_http_output_auth(struct connectdata *conn, data->state.negotiate.context && !GSS_ERROR(data->state.negotiate.status)) { auth="GSS-Negotiate"; - result = Curl_output_negotiate(conn); + result = Curl_output_negotiate(conn, FALSE); if (result) return result; authhost->done = TRUE; @@ -593,7 +605,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, authp->avail |= CURLAUTH_GSSNEGOTIATE; if(authp->picked == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ - int neg = Curl_input_negotiate(conn, start); + int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); if (neg == 0) { data->reqdata.newurl = strdup(data->change.url); data->state.authproblem = (data->reqdata.newurl == NULL); -- cgit v1.2.1 From 119364741ef2ca0931c0ceaa6f92cb476457863c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Oct 2007 10:21:36 +0000 Subject: known bug #46: chunked-encoded CONNECT responses from a http proxy now works. Added test case 1008 to verify. Note that #47 is still there. --- lib/http.c | 169 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 120 insertions(+), 49 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 67b2d3f55..90f56f1ba 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1143,6 +1143,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, curl_socket_t tunnelsocket = conn->sock[sockindex]; curl_off_t cl=0; bool closeConnection = FALSE; + bool chunked_encoding = FALSE; long check; #define SELECT_OK 0 @@ -1203,37 +1204,37 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->set.str[STRING_USERAGENT]) useragent = conn->allocptr.uagent; - /* Send the connect request to the proxy */ - /* BLOCKING */ - result = - add_bufferf(req_buffer, - "CONNECT %s:%d HTTP/1.0\r\n" - "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ - hostname, remote_port, - host, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - useragent, - proxyconn); - - if(host && *host) - free(host); - - if(CURLE_OK == result) - result = add_custom_headers(conn, req_buffer); - - if(CURLE_OK == result) - /* CRLF terminate the request */ - result = add_bufferf(req_buffer, "\r\n"); - - if(CURLE_OK == result) { - /* Now send off the request */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); - } + /* Send the connect request to the proxy */ + /* BLOCKING */ + result = + add_bufferf(req_buffer, + "CONNECT %s:%d HTTP/1.0\r\n" + "%s" /* Host: */ + "%s" /* Proxy-Authorization */ + "%s" /* User-Agent */ + "%s", /* Proxy-Connection */ + hostname, remote_port, + host, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + useragent, + proxyconn); + + if(host && *host) + free(host); + + if(CURLE_OK == result) + result = add_custom_headers(conn, req_buffer); + + if(CURLE_OK == result) + /* CRLF terminate the request */ + result = add_bufferf(req_buffer, "\r\n"); + + if(CURLE_OK == result) { + /* Now send off the request */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, sockindex); + } req_buffer = NULL; if(result) failf(data, "Failed sending CONNECT to proxy"); @@ -1340,13 +1341,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, nread += gotbytes; if(keepon > TRUE) { - /* This means we are currently ignoring a response-body, so we - simply count down our counter and make sure to break out of - the loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; + /* This means we are currently ignoring a response-body */ + if(cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + cl -= gotbytes; + if(cl<=0) { + keepon = FALSE; + break; + } + } + else { + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof=0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + } + else + infof(data, "Read %d bytes of chunk, continue\n", + tookcareof); } } else @@ -1366,7 +1387,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(data->set.include_header) writetype |= CLIENTWRITE_BODY; - result = Curl_client_write(conn, writetype, line_start, perline); + result = Curl_client_write(conn, writetype, line_start, + perline); if(result) return result; @@ -1377,19 +1399,60 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(('\r' == line_start[0]) || ('\n' == line_start[0])) { /* end of response-headers from the proxy */ - if(cl && (407 == k->httpcode) && - !data->state.authproblem) { + if((407 == k->httpcode) && !data->state.authproblem) { /* If we get a 407 response code with content length - * when we have no auth problem, we must ignore the - * whole response-body */ + when we have no auth problem, we must ignore the + whole response-body */ keepon = 2; - infof(data, "Ignore %" FORMAT_OFF_T - " bytes of response-body\n", cl); - cl -= (gotbytes - i);/* remove the remaining chunk of - what we already read */ - if(cl<=0) - /* if the whole thing was already read, we are done! */ + + if(cl) { + + infof(data, "Ignore %" FORMAT_OFF_T + " bytes of response-body\n", cl); + /* remove the remaining chunk of what we already + read */ + cl -= (gotbytes - i); + + if(cl<=0) + /* if the whole thing was already read, we are done! + */ + keepon=FALSE; + } + else if(chunked_encoding) { + CHUNKcode r; + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + infof(data, "%d bytes of chunk left\n", gotbytes-i); + + if(line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + line_start++; + i++; + } + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, line_start+1, + gotbytes -i, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + } + else + infof(data, "Read %d bytes of chunk, continue\n", + gotbytes); + } + else { + /* without content-length or chunked encoding, we + can't keep the connection alive since the close is + the end signal so we bail out at once instead */ keepon=FALSE; + } } else keepon = FALSE; @@ -1415,6 +1478,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, else if(Curl_compareheader(line_start, "Connection:", "close")) closeConnection = TRUE; + else if(Curl_compareheader(line_start, + "Transfer-Encoding:", "chunked")) { + infof(data, "CONNECT responded chunked\n"); + chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } else if(Curl_compareheader(line_start, "Proxy-Connection:", "close")) closeConnection = TRUE; @@ -1472,6 +1542,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->state.authproxy.done = TRUE; infof (data, "Proxy replied OK to CONNECT request\n"); + k->ignorebody = FALSE; /* put it (back) to non-ignore state */ return CURLE_OK; } -- cgit v1.2.1 From 08fd1829e0e01cd9cee3a7da60d315f11aa591c8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 7 Oct 2007 08:28:03 +0000 Subject: Known bug #47, which confused libcurl if doing NTLM auth over a proxy with a response that was larger than 16KB is now improved slightly so that now the restriction at 16KB is for the headers only and it should be a rare situation where the response-headers exceed 16KB. Thus, I consider #47 fixed and the header limitation is now known as known bug #48. --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 90f56f1ba..babd406d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1342,6 +1342,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(keepon > TRUE) { /* This means we are currently ignoring a response-body */ + + nread = 0; /* make next read start over in the read buffer */ if(cl) { /* A Content-Length based body: simply count down the counter and make sure to break out of the loop when we're done! */ @@ -1399,6 +1401,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(('\r' == line_start[0]) || ('\n' == line_start[0])) { /* end of response-headers from the proxy */ + nread = 0; /* make next read start over in the read + buffer */ if((407 == k->httpcode) && !data->state.authproblem) { /* If we get a 407 response code with content length when we have no auth problem, we must ignore the -- cgit v1.2.1 From 07b6e7363d910ad4828376d568a2f19fd8d64661 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Fri, 12 Oct 2007 13:36:37 +0000 Subject: Added per-protocol callback static tables, replacing callback ptr storage in the connectdata structure by a single handler table ptr. --- lib/http.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index babd406d8..173106c6e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -104,6 +104,57 @@ /* The last #include file should be: */ #include "memdebug.h" + +/* + * Forward declarations. + */ + +static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done); +static int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +/* + * HTTP handler interface. + */ +const struct Curl_handler Curl_handler_http = { + "HTTP", /* scheme */ + NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + NULL, /* connecting */ + NULL, /* doing */ + NULL, /* proto_getsock */ + NULL, /* doing_getsock */ + NULL, /* disconnect */ + PORT_HTTP, /* defport */ + PROT_HTTP, /* protocol */ +}; + +#ifdef USE_SSL +/* + * HTTPS handler interface. + */ +const struct Curl_handler Curl_handler_https = { + "HTTPS", /* scheme */ + NULL, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + NULL, /* do_more */ + Curl_http_connect, /* connect_it */ + Curl_https_connecting, /* connecting */ + NULL, /* doing */ + Curl_https_getsock, /* proto_getsock */ + NULL, /* doing_getsock */ + NULL, /* disconnect */ + PORT_HTTPS, /* defport */ + PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */ +}; +#endif + + /* * checkheaders() checks the linked list of custom HTTP headers for a * particular header (prefix). @@ -1619,7 +1670,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) +static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) { CURLcode result; DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); @@ -1635,9 +1686,9 @@ CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) #ifdef USE_SSLEAY /* This function is OpenSSL-specific. It should be made to query the generic SSL layer instead. */ -int Curl_https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) +static int Curl_https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) { if (conn->protocol & PROT_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; -- cgit v1.2.1 From 7831c1ae445b9920440dd40e52e6ead31dfbe962 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 12 Oct 2007 18:49:14 +0000 Subject: Fixed a few compile errors and warnings. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 173106c6e..9839912d7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -110,9 +110,11 @@ */ static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done); +#ifdef USE_SSL static int Curl_https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks); +#endif /* * HTTP handler interface. -- cgit v1.2.1 From a005243908803662d4a05427bc1061db42f4d057 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Mon, 15 Oct 2007 18:32:01 +0000 Subject: Fix dynamic CURLOPT_POSTFIELDS bug: back to static. CURLOPT_COPYPOSTFIELDS option added for dynamic. Fix some OS400 features. --- lib/http.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9839912d7..d3954338f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2554,8 +2554,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* figure out the size of the postfields */ postsize = (data->set.postfieldsize != -1)? data->set.postfieldsize: - (data->set.str[STRING_POSTFIELDS]? - (curl_off_t)strlen(data->set.str[STRING_POSTFIELDS]):0); + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); if(!conn->bits.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if @@ -2580,7 +2579,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if(data->set.str[STRING_POSTFIELDS]) { + if(data->set.postfields) { /* for really small posts we don't use Expect: headers at all, and for the somewhat bigger ones we allow the app to disable it */ @@ -2608,7 +2607,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!conn->bits.upload_chunky) { /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ - result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS], + result = add_buffer(req_buffer, data->set.postfields, (size_t)postsize); included_body = postsize; } @@ -2616,7 +2615,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Append the POST data chunky-style */ result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); if(CURLE_OK == result) - result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS], + result = add_buffer(req_buffer, data->set.postfields, (size_t)postsize); if(CURLE_OK == result) result = add_buffer(req_buffer, @@ -2630,7 +2629,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else { /* A huge POST coming up, do data separate from the request */ http->postsize = postsize; - http->postdata = data->set.str[STRING_POSTFIELDS]; + http->postdata = data->set.postfields; http->sending = HTTPSEND_BODY; -- cgit v1.2.1 From 92433e596b7fbfa5c75926705dcfef0080ebf012 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 17 Oct 2007 16:58:32 +0000 Subject: We use this ZERO_NULL to avoid picky compiler warnings, when assigning a NULL pointer to a function pointer var. --- lib/http.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d3954338f..b32ca1d5b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -121,16 +121,16 @@ static int Curl_https_getsock(struct connectdata *conn, */ const struct Curl_handler Curl_handler_http = { "HTTP", /* scheme */ - NULL, /* setup_connection */ + ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ - NULL, /* do_more */ + ZERO_NULL, /* do_more */ Curl_http_connect, /* connect_it */ - NULL, /* connecting */ - NULL, /* doing */ - NULL, /* proto_getsock */ - NULL, /* doing_getsock */ - NULL, /* disconnect */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* disconnect */ PORT_HTTP, /* defport */ PROT_HTTP, /* protocol */ }; @@ -141,16 +141,16 @@ const struct Curl_handler Curl_handler_http = { */ const struct Curl_handler Curl_handler_https = { "HTTPS", /* scheme */ - NULL, /* setup_connection */ + ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ - NULL, /* do_more */ + ZERO_NULL, /* do_more */ Curl_http_connect, /* connect_it */ Curl_https_connecting, /* connecting */ - NULL, /* doing */ + ZERO_NULL, /* doing */ Curl_https_getsock, /* proto_getsock */ - NULL, /* doing_getsock */ - NULL, /* disconnect */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */ }; -- cgit v1.2.1 From 5b358603bd8897dcd38795c1ae971a8f917e97df Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Oct 2007 15:05:35 +0000 Subject: Michal Marek forwarded the bug report https://bugzilla.novell.com/show_bug.cgi?id=332917 about a HTTP redirect to FTP that caused memory havoc. His work together with my efforts created two fixes: #1 - FTP::file was moved to struct ftp_conn, because is has to be dealt with at connection cleanup, at which time the struct HandleData could be used by another connection. Also, the unused char *urlpath member is removed from struct FTP. #2 - provide a Curl_reset_reqproto() function that frees data->reqdata.proto.* on connection setup if needed (that is if the SessionHandle was used by a different connection). --- lib/http.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b32ca1d5b..7c63097c9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1894,13 +1894,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) the rest of the request in the PERFORM phase. */ *done = TRUE; + /* If there already is a protocol-specific struct allocated for this + sessionhandle, deal with it */ + Curl_reset_reqproto(conn); + if(!data->reqdata.proto.http) { /* Only allocate this struct if we don't already have it! */ - http = (struct HTTP *)malloc(sizeof(struct HTTP)); + http = (struct HTTP *)calloc(sizeof(struct HTTP), 1); if(!http) return CURLE_OUT_OF_MEMORY; - memset(http, 0, sizeof(struct HTTP)); data->reqdata.proto.http = http; } else -- cgit v1.2.1 From e550df675a6e6d3b1f55a779df92c9b7b9747842 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 23 Oct 2007 10:14:24 +0000 Subject: Fix compiler warning: subscript has type `char' --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7c63097c9..1e36a2d0e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2098,7 +2098,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if (checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { char *p = strstr(ppath, ";type="); if (p && p[6] && p[7] == 0) { - switch (toupper(p[6])) { + switch (toupper((int)((unsigned char)p[6]))) { case 'A': case 'D': case 'I': -- cgit v1.2.1 From ad6e28073c985a42e8b15d2234baa7ef67ffcb35 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 5 Nov 2007 09:45:09 +0000 Subject: removed space after if and while before the parenthesis for better source code consistency --- lib/http.c | 68 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1e36a2d0e..7d9c80b00 100644 --- a/lib/http.c +++ b/lib/http.c @@ -385,7 +385,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if(pickhost || pickproxy) { data->reqdata.newurl = strdup(data->change.url); /* clone URL */ - if (!data->reqdata.newurl) + if(!data->reqdata.newurl) return CURLE_OUT_OF_MEMORY; if((data->set.httpreq != HTTPREQ_GET) && @@ -407,12 +407,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD)) { data->reqdata.newurl = strdup(data->change.url); /* clone URL */ - if (!data->reqdata.newurl) + if(!data->reqdata.newurl) return CURLE_OUT_OF_MEMORY; data->state.authhost.done = TRUE; } } - if (Curl_http_should_fail(conn)) { + if(Curl_http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", data->reqdata.keep.httpcode); code = CURLE_HTTP_RETURNED_ERROR; @@ -475,7 +475,7 @@ Curl_http_output_auth(struct connectdata *conn, authproxy->picked = authproxy->want; /* Send proxy authentication header if needed */ - if (conn->bits.httpproxy && + if(conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { #ifdef HAVE_GSSAPI if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) && @@ -483,7 +483,7 @@ Curl_http_output_auth(struct connectdata *conn, !GSS_ERROR(data->state.negotiate.status)) { auth="GSS-Negotiate"; result = Curl_output_negotiate(conn, TRUE); - if (result) + if(result) return result; authproxy->done = TRUE; } @@ -552,7 +552,7 @@ Curl_http_output_auth(struct connectdata *conn, !GSS_ERROR(data->state.negotiate.status)) { auth="GSS-Negotiate"; result = Curl_output_negotiate(conn, FALSE); - if (result) + if(result) return result; authhost->done = TRUE; } @@ -627,7 +627,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, const char *start; struct auth *authp; - if (httpcode == 407) { + if(httpcode == 407) { start = header+strlen("Proxy-authenticate:"); availp = &data->info.proxyauthavail; authp = &data->state.authproxy; @@ -652,14 +652,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, */ #ifdef HAVE_GSSAPI - if (checkprefix("GSS-Negotiate", start) || + if(checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { *availp |= CURLAUTH_GSSNEGOTIATE; authp->avail |= CURLAUTH_GSSNEGOTIATE; if(authp->picked == CURLAUTH_GSSNEGOTIATE) { /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); - if (neg == 0) { + if(neg == 0) { data->reqdata.newurl = strdup(data->change.url); data->state.authproblem = (data->reqdata.newurl == NULL); } @@ -758,16 +758,16 @@ int Curl_http_should_fail(struct connectdata *conn) ** If we haven't been asked to fail on error, ** don't fail. */ - if (!data->set.http_fail_on_error) + if(!data->set.http_fail_on_error) return 0; /* ** Any code < 400 is never terminal. */ - if (k->httpcode < 400) + if(k->httpcode < 400) return 0; - if (data->reqdata.resume_from && + if(data->reqdata.resume_from && (data->set.httpreq==HTTPREQ_GET) && (k->httpcode == 416)) { /* "Requested Range Not Satisfiable", just proceed and @@ -779,7 +779,7 @@ int Curl_http_should_fail(struct connectdata *conn) ** Any code >= 400 that's not 401 or 407 is always ** a terminal error */ - if ((k->httpcode != 401) && + if((k->httpcode != 401) && (k->httpcode != 407)) return 1; @@ -986,12 +986,12 @@ CURLcode add_buffer_send(send_buffer *in, /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, (size_t)(amount-included_body_bytes), conn); - if (included_body_bytes) + if(included_body_bytes) Curl_debug(conn->data, CURLINFO_DATA_OUT, ptr+amount-included_body_bytes, (size_t)included_body_bytes, conn); } - if (included_body_bytes) + if(included_body_bytes) /* since we sent a piece of the body here, up the byte counter for it accordingly */ http->writebytecount = included_body_bytes; @@ -1207,7 +1207,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, conn->bits.proxy_connect_closed = FALSE; do { - if (!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ + if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ char *host_port; send_buffer *req_buffer; @@ -1314,8 +1314,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } /* if we're in multi-mode and we would block, return instead for a retry */ - if (Curl_if_multi == data->state.used_interface) { - if (0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) + if(Curl_if_multi == data->state.used_interface) { + if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) /* return so we'll be called again polling-style */ return CURLE_OK; else { @@ -1571,7 +1571,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, headers. 'newurl' is set to a new URL if we must loop. */ Curl_http_auth_act(conn); - if (closeConnection && data->reqdata.newurl) { + if(closeConnection && data->reqdata.newurl) { /* Connection closed by server. Don't use it anymore */ sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; @@ -1584,7 +1584,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, failf(data, "Received HTTP code %d from proxy after CONNECT", k->httpcode); - if (closeConnection && data->reqdata.newurl) + if(closeConnection && data->reqdata.newurl) conn->bits.proxy_connect_closed = TRUE; return CURLE_RECV_ERROR; @@ -1634,14 +1634,14 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return result; } - if (conn->bits.tunnel_connecting) { + if(conn->bits.tunnel_connecting) { /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; } if(!data->state.this_is_a_follow) { /* this is not a followed location, get the original host name */ - if (data->state.first_host) + if(data->state.first_host) /* Free to avoid leaking memory on multiple requests*/ free(data->state.first_host); @@ -1692,18 +1692,18 @@ static int Curl_https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if (conn->protocol & PROT_HTTPS) { + if(conn->protocol & PROT_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; if(!numsocks) return GETSOCK_BLANK; - if (connssl->connecting_state == ssl_connect_2_writing) { + if(connssl->connecting_state == ssl_connect_2_writing) { /* write mode */ socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_WRITESOCK(0); } - else if (connssl->connecting_state == ssl_connect_2_reading) { + else if(connssl->connecting_state == ssl_connect_2_reading) { /* read mode */ socks[0] = conn->sock[FIRSTSOCKET]; return GETSOCK_READSOCK(0); @@ -1766,7 +1766,7 @@ CURLcode Curl_http_done(struct connectdata *conn, conn->fread_func = data->set.fread_func; /* restore */ conn->fread_in = data->set.in; /* restore */ - if (http == NULL) + if(http == NULL) return CURLE_OK; if(http->send_buffer) { @@ -1790,7 +1790,7 @@ CURLcode Curl_http_done(struct connectdata *conn, else if(HTTPREQ_PUT == data->set.httpreq) k->bytecount = http->readbytecount + http->writebytecount; - if (status != CURLE_OK) + if(status != CURLE_OK) return (status); if(!conn->bits.retry && @@ -1909,7 +1909,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else http = data->reqdata.proto.http; - if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && + if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->set.upload) { httpreq = HTTPREQ_PUT; } @@ -1990,7 +1990,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } else { - if (httpreq == HTTPREQ_GET) + if(httpreq == HTTPREQ_GET) conn->bits.upload_chunky = FALSE; if(conn->bits.upload_chunky) te = "Transfer-Encoding: chunked\r\n"; @@ -2035,7 +2035,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) - /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include + /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ conn->allocptr.host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip?"[":"", @@ -2053,7 +2053,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if (conn->bits.httpproxy && !conn->bits.tunnel_proxy) { + if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { /* Using a proxy but does not tunnel through it */ /* The path sent to the proxy is in fact the entire URL. But if the remote @@ -2095,9 +2095,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } ppath = data->change.url; /* when doing ftp, append ;type= if not present */ - if (checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { + if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { char *p = strstr(ppath, ";type="); - if (p && p[6] && p[7] == 0) { + if(p && p[6] && p[7] == 0) { switch (toupper((int)((unsigned char)p[6]))) { case 'A': case 'D': @@ -2107,7 +2107,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) p = NULL; } } - if (!p) + if(!p) snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", data->set.prefer_ascii ? 'a' : 'i'); } -- cgit v1.2.1 From a2926ebe7ca9e619f9d85d9b1d12d90f1fc714f4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 14 Nov 2007 00:48:11 +0000 Subject: Fix a variable potential wrapping in add_buffer() when using absolutely huge send buffer sizes --- lib/http.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7d9c80b00..e7b39ad4b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1083,9 +1083,28 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) char *new_rb; size_t new_size; + if(~size < in->size_used) { + /* If resulting used size of send buffer would wrap size_t, cleanup + the whole buffer and return error. Otherwise the required buffer + size will fit into a single allocatable memory chunk */ + Curl_safefree(in->buffer); + free(in); + return CURLE_OUT_OF_MEMORY; + } + if(!in->buffer || ((in->size_used + size) > (in->size_max - 1))) { - new_size = (in->size_used+size)*2; + + /* If current buffer size isn't enough to hold the result, use a + buffer size that doubles the required size. If this new size + would wrap size_t, then just use the largest possible one */ + + if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) || + (~(size*2) < (in->size_used*2))) + new_size = (size_t)-1; + else + 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); -- cgit v1.2.1 From 1125d45397972276ffbc27d9180e0faba10f139c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Nov 2007 23:30:59 +0000 Subject: removed unnecessary check from add_buffer_send() that only was made within #ifdef CURL_DOES_CONVERSIONS anyway! I turned it into a DEBUGASSERT() instead. --- lib/http.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e7b39ad4b..eba69bdac 100644 --- a/lib/http.c +++ b/lib/http.c @@ -943,17 +943,17 @@ CURLcode add_buffer_send(send_buffer *in, ptr = in->buffer; size = in->size_used; + DEBUGASSERT(size - included_body_bytes > 0); + #ifdef CURL_DOES_CONVERSIONS - if(size - included_body_bytes > 0) { - res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res != CURLE_OK) { - /* conversion failed, free memory and return to the caller */ - if(in->buffer) - free(in->buffer); - free(in); - return res; - } + res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(res != CURLE_OK) { + /* conversion failed, free memory and return to the caller */ + if(in->buffer) + free(in->buffer); + free(in); + return res; } #endif /* CURL_DOES_CONVERSIONS */ -- cgit v1.2.1 From 22e52ddd6e4aafdde50d54d1456c0c2c891f12c1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Nov 2007 23:42:21 +0000 Subject: Ates Goral identified a problem in http.c:add_buffer_send() when a debug callback was used, as it could wrongly pass on a bad size for the outgoing HTTP header. The bad size would be a very large value as it was a wrapped size_t content. This happened when the whole HTTP request failed to get sent in one single send. http://curl.haxx.se/mail/lib-2007-11/0165.html --- lib/http.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index eba69bdac..d0d3bc1ea 100644 --- a/lib/http.c +++ b/lib/http.c @@ -932,6 +932,7 @@ CURLcode add_buffer_send(send_buffer *in, struct HTTP *http = conn->data->reqdata.proto.http; size_t sendsize; curl_socket_t sockfd; + size_t headersize; DEBUGASSERT(socketindex <= SECONDARYSOCKET); @@ -943,10 +944,13 @@ CURLcode add_buffer_send(send_buffer *in, ptr = in->buffer; size = in->size_used; - DEBUGASSERT(size - included_body_bytes > 0); + headersize = size - included_body_bytes; /* the initial part that isn't body + is header */ + + DEBUGASSERT(headersize > 0); #ifdef CURL_DOES_CONVERSIONS - res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes); + res = Curl_convert_to_network(conn->data, ptr, headersize); /* Curl_convert_to_network calls failf if unsuccessful */ if(res != CURLE_OK) { /* conversion failed, free memory and return to the caller */ @@ -981,20 +985,29 @@ CURLcode add_buffer_send(send_buffer *in, res = Curl_write(conn, sockfd, ptr, sendsize, &amount); if(CURLE_OK == res) { + /* + * Note that we may not send the entire chunk at once, and we have a set + * number of data bytes at the end of the big buffer (out of which we may + * only send away a part). + */ + /* how much of the header that was sent */ + size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount; + size_t bodylen = amount - headlen; if(conn->data->set.verbose) { /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, - (size_t)(amount-included_body_bytes), conn); - if(included_body_bytes) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); + if((size_t)amount > headlen) { + /* there was body data sent beyond the initial header part, pass that + on to the debug callback too */ Curl_debug(conn->data, CURLINFO_DATA_OUT, - ptr+amount-included_body_bytes, - (size_t)included_body_bytes, conn); + ptr+headlen, bodylen, conn); + } } - if(included_body_bytes) + if(bodylen) /* since we sent a piece of the body here, up the byte counter for it accordingly */ - http->writebytecount = included_body_bytes; + http->writebytecount += bodylen; *bytes_written += amount; -- cgit v1.2.1 From 4f05613fbbc6d90cfa20b0ee5e19e457b826c5c5 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 16 Nov 2007 01:19:46 +0000 Subject: Fix unsigned integral math check in add_buffer_send() --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d0d3bc1ea..00b91a5d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -947,7 +947,7 @@ CURLcode add_buffer_send(send_buffer *in, headersize = size - included_body_bytes; /* the initial part that isn't body is header */ - DEBUGASSERT(headersize > 0); + DEBUGASSERT(size > included_body_bytes); #ifdef CURL_DOES_CONVERSIONS res = Curl_convert_to_network(conn->data, ptr, headersize); -- cgit v1.2.1 From 86956c226130e4c9a088021047f79ef2c833697e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 20 Nov 2007 23:02:58 +0000 Subject: white space changes only to clean up indent and source width --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 00b91a5d3..5fceb8f82 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2339,7 +2339,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, data->reqdata.path, + conn->allocptr.cookiehost:host, + data->reqdata.path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } -- cgit v1.2.1 From 13648f8ccda6f99674ac407640474634e856804c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 24 Nov 2007 23:16:55 +0000 Subject: struct HandleData is now called struct SingleRequest, and is only for data that is inited at the start of the DO action. I removed the Curl_transfer_keeper struct completely, and I had to move out a few struct members (that had to be set before DO or used after DONE) to the UrlState struct. The SingleRequest struct is accessed with SessionHandle->req. One of the biggest reasons for doing this was the bunch of duplicate struct members in HandleData and Curl_transfer_keeper since it was really messy to keep track of two variables with the same name and basically the same purpose! --- lib/http.c | 132 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 64 insertions(+), 68 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5fceb8f82..635506e08 100644 --- a/lib/http.c +++ b/lib/http.c @@ -275,8 +275,7 @@ static bool pickoneauth(struct auth *pick) static CURLcode perhapsrewind(struct connectdata *conn) { struct SessionHandle *data = conn->data; - struct HTTP *http = data->reqdata.proto.http; - struct Curl_transfer_keeper *k = &data->reqdata.keep; + struct HTTP *http = data->state.proto.http; curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ @@ -338,7 +337,7 @@ static CURLcode perhapsrewind(struct connectdata *conn) /* This is not NTLM or NTLM with many bytes left to send: close */ conn->bits.close = TRUE; - k->size = 0; /* don't download any more than 0 bytes */ + data->req.size = 0; /* don't download any more than 0 bytes */ } if(bytessent) @@ -361,7 +360,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) bool pickproxy = FALSE; CURLcode code = CURLE_OK; - if(100 == data->reqdata.keep.httpcode) + if(100 == data->req.httpcode) /* this is a transient response code, ignore */ return CURLE_OK; @@ -369,23 +368,23 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; if(conn->bits.user_passwd && - ((data->reqdata.keep.httpcode == 401) || - (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { + ((data->req.httpcode == 401) || + (conn->bits.authneg && data->req.httpcode < 300))) { pickhost = pickoneauth(&data->state.authhost); if(!pickhost) data->state.authproblem = TRUE; } if(conn->bits.proxy_user_passwd && - ((data->reqdata.keep.httpcode == 407) || - (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { + ((data->req.httpcode == 407) || + (conn->bits.authneg && data->req.httpcode < 300))) { pickproxy = pickoneauth(&data->state.authproxy); if(!pickproxy) data->state.authproblem = TRUE; } if(pickhost || pickproxy) { - data->reqdata.newurl = strdup(data->change.url); /* clone URL */ - if(!data->reqdata.newurl) + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; if((data->set.httpreq != HTTPREQ_GET) && @@ -397,7 +396,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } } - else if((data->reqdata.keep.httpcode < 300) && + else if((data->req.httpcode < 300) && (!data->state.authhost.done) && conn->bits.authneg) { /* no (known) authentication available, @@ -406,15 +405,15 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) we didn't try HEAD or GET */ if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD)) { - data->reqdata.newurl = strdup(data->change.url); /* clone URL */ - if(!data->reqdata.newurl) + data->req.newurl = strdup(data->change.url); /* clone URL */ + if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; data->state.authhost.done = TRUE; } } if(Curl_http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", - data->reqdata.keep.httpcode); + data->req.httpcode); code = CURLE_HTTP_RETURNED_ERROR; } @@ -660,8 +659,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); if(neg == 0) { - data->reqdata.newurl = strdup(data->change.url); - data->state.authproblem = (data->reqdata.newurl == NULL); + data->req.newurl = strdup(data->change.url); + data->state.authproblem = (data->req.newurl == NULL); } else { infof(data, "Authentication problem. Ignoring this.\n"); @@ -743,16 +742,13 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, int Curl_http_should_fail(struct connectdata *conn) { struct SessionHandle *data; - struct Curl_transfer_keeper *k; + int httpcode; DEBUGASSERT(conn); data = conn->data; DEBUGASSERT(data); - /* - ** For readability - */ - k = &data->reqdata.keep; + httpcode = data->req.httpcode; /* ** If we haven't been asked to fail on error, @@ -764,12 +760,12 @@ int Curl_http_should_fail(struct connectdata *conn) /* ** Any code < 400 is never terminal. */ - if(k->httpcode < 400) + if(httpcode < 400) return 0; - if(data->reqdata.resume_from && - (data->set.httpreq==HTTPREQ_GET) && - (k->httpcode == 416)) { + if(data->state.resume_from && + (data->set.httpreq==HTTPREQ_GET) && + (httpcode == 416)) { /* "Requested Range Not Satisfiable", just proceed and pretend this is no error */ return 0; @@ -779,14 +775,14 @@ int Curl_http_should_fail(struct connectdata *conn) ** Any code >= 400 that's not 401 or 407 is always ** a terminal error */ - if((k->httpcode != 401) && - (k->httpcode != 407)) + if((httpcode != 401) && + (httpcode != 407)) return 1; /* ** All we have left to deal with is 401 and 407 */ - DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407)); + DEBUGASSERT((httpcode == 401) || (httpcode == 407)); /* ** Examine the current authentication state to see if this @@ -807,7 +803,8 @@ int Curl_http_should_fail(struct connectdata *conn) infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); - infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)"); + infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ? + data->req.newurl : "(null)"); infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); #endif @@ -815,9 +812,9 @@ int Curl_http_should_fail(struct connectdata *conn) ** Either we're not authenticating, or we're supposed to ** be authenticating something else. This is an error. */ - if((k->httpcode == 401) && !conn->bits.user_passwd) + if((httpcode == 401) && !conn->bits.user_passwd) return TRUE; - if((k->httpcode == 407) && !conn->bits.proxy_user_passwd) + if((httpcode == 407) && !conn->bits.proxy_user_passwd) return TRUE; return data->state.authproblem; @@ -837,7 +834,7 @@ static size_t readmoredata(char *buffer, void *userp) { struct connectdata *conn = (struct connectdata *)userp; - struct HTTP *http = conn->data->reqdata.proto.http; + struct HTTP *http = conn->data->state.proto.http; size_t fullsize = size * nitems; if(0 == http->postsize) @@ -929,7 +926,7 @@ CURLcode add_buffer_send(send_buffer *in, CURLcode res; char *ptr; size_t size; - struct HTTP *http = conn->data->reqdata.proto.http; + struct HTTP *http = conn->data->state.proto.http; size_t sendsize; curl_socket_t sockfd; size_t headersize; @@ -1220,7 +1217,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, { int subversion=0; struct SessionHandle *data=conn->data; - struct Curl_transfer_keeper *k = &data->reqdata.keep; + struct SingleRequest *k = &data->req; CURLcode result; int res; long timeout = @@ -1246,12 +1243,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); - if(data->reqdata.newurl) { + if(data->req.newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() it. */ - free(data->reqdata.newurl); - data->reqdata.newurl = NULL; + free(data->req.newurl); + data->req.newurl = NULL; } /* initialize a dynamic send-buffer */ @@ -1603,20 +1600,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, headers. 'newurl' is set to a new URL if we must loop. */ Curl_http_auth_act(conn); - if(closeConnection && data->reqdata.newurl) { + if(closeConnection && data->req.newurl) { /* Connection closed by server. Don't use it anymore */ sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; break; } } /* END NEGOTIATION PHASE */ - } while(data->reqdata.newurl); + } while(data->req.newurl); - if(200 != k->httpcode) { + if(200 != data->req.httpcode) { failf(data, "Received HTTP code %d from proxy after CONNECT", - k->httpcode); + data->req.httpcode); - if(closeConnection && data->reqdata.newurl) + if(closeConnection && data->req.newurl) conn->bits.proxy_connect_closed = TRUE; return CURLE_RECV_ERROR; @@ -1631,7 +1628,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->state.authproxy.done = TRUE; infof (data, "Proxy replied OK to CONNECT request\n"); - k->ignorebody = FALSE; /* put it (back) to non-ignore state */ + data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ return CURLE_OK; } @@ -1790,8 +1787,7 @@ CURLcode Curl_http_done(struct connectdata *conn, CURLcode status, bool premature) { struct SessionHandle *data = conn->data; - struct HTTP *http =data->reqdata.proto.http; - struct Curl_transfer_keeper *k = &data->reqdata.keep; + struct HTTP *http =data->state.proto.http; (void)premature; /* not used */ /* set the proper values (possibly modified on POST) */ @@ -1810,7 +1806,7 @@ CURLcode Curl_http_done(struct connectdata *conn, } if(HTTPREQ_POST_FORM == data->set.httpreq) { - k->bytecount = http->readbytecount + http->writebytecount; + data->req.bytecount = http->readbytecount + http->writebytecount; Curl_formclean(&http->sendit); /* Now free that whole lot */ if(http->form.fp) { @@ -1820,15 +1816,15 @@ CURLcode Curl_http_done(struct connectdata *conn, } } else if(HTTPREQ_PUT == data->set.httpreq) - k->bytecount = http->readbytecount + http->writebytecount; + data->req.bytecount = http->readbytecount + http->writebytecount; if(status != CURLE_OK) return (status); if(!conn->bits.retry && ((http->readbytecount + - data->reqdata.keep.headerbytecount - - data->reqdata.keep.deductheadercount)) <= 0) { + data->req.headerbytecount - + data->req.deductheadercount)) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was read from the HTTP server (that counts), this can't be right so we return an error here */ @@ -1911,7 +1907,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; - char *ppath = data->reqdata.path; + char *ppath = data->state.path; char ftp_typecode[sizeof(";type=?")] = ""; char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ @@ -1930,16 +1926,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) sessionhandle, deal with it */ Curl_reset_reqproto(conn); - if(!data->reqdata.proto.http) { + if(!data->state.proto.http) { /* Only allocate this struct if we don't already have it! */ http = (struct HTTP *)calloc(sizeof(struct HTTP), 1); if(!http) return CURLE_OUT_OF_MEMORY; - data->reqdata.proto.http = http; + data->state.proto.http = http; } else - http = data->reqdata.proto.http; + http = data->state.proto.http; if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->set.upload) { @@ -2169,7 +2165,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(( (HTTPREQ_POST == httpreq) || (HTTPREQ_POST_FORM == httpreq) || (HTTPREQ_PUT == httpreq) ) && - data->reqdata.resume_from) { + data->state.resume_from) { /********************************************************************** * Resuming upload in HTTP means that we PUT or POST and that we have * got a resume_from value set. The resume value has already created @@ -2178,15 +2174,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * file size before we continue this venture in the dark lands of HTTP. *********************************************************************/ - if(data->reqdata.resume_from < 0 ) { + if(data->state.resume_from < 0 ) { /* * This is meant to get the size of the present remote-file by itself. * We don't support this now. Bail out! */ - data->reqdata.resume_from = 0; + data->state.resume_from = 0; } - if(data->reqdata.resume_from && !data->state.this_is_a_follow) { + if(data->state.resume_from && !data->state.this_is_a_follow) { /* do we still game? */ curl_off_t passed=0; @@ -2194,7 +2190,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) input. If we knew it was a proper file we could've just fseek()ed but we only have a stream here */ do { - size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed); + size_t readthisamountnow = (size_t)(data->state.resume_from - passed); size_t actuallyread; if(readthisamountnow > BUFSIZE) @@ -2211,11 +2207,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) passed); return CURLE_READ_ERROR; } - } while(passed != data->reqdata.resume_from); /* loop until done */ + } while(passed != data->state.resume_from); /* loop until done */ /* now, decrease the size of the read */ if(data->set.infilesize>0) { - data->set.infilesize -= data->reqdata.resume_from; + data->set.infilesize -= data->state.resume_from; if(data->set.infilesize <= 0) { failf(data, "File already completely uploaded"); @@ -2225,7 +2221,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we've passed, proceed as normal */ } } - if(data->reqdata.use_range) { + if(data->state.use_range) { /* * A range is selected. We use different headers whether we're downloading * or uploading and we always let customized headers override our internal @@ -2237,7 +2233,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", - data->reqdata.range); + data->state.range); } else if((httpreq != HTTPREQ_GET) && !checkheaders(data, "Content-Range:")) { @@ -2246,14 +2242,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); - if(data->reqdata.resume_from) { + if(data->state.resume_from) { /* This is because "resume" was selected */ curl_off_t total_expected_size= - data->reqdata.resume_from + data->set.infilesize; + data->state.resume_from + data->set.infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%" FORMAT_OFF_T "/%" FORMAT_OFF_T "\r\n", - data->reqdata.range, total_expected_size-1, + data->state.range, total_expected_size-1, total_expected_size); } else { @@ -2261,7 +2257,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", - data->reqdata.range, data->set.infilesize); + data->state.range, data->set.infilesize); } if(!conn->allocptr.rangeline) return CURLE_OUT_OF_MEMORY; @@ -2306,7 +2302,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", conn->allocptr.userpwd?conn->allocptr.userpwd:"", - (data->reqdata.use_range && conn->allocptr.rangeline)? + (data->state.use_range && conn->allocptr.rangeline)? conn->allocptr.rangeline:"", (data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? @@ -2340,7 +2336,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) co = Curl_cookie_getlist(data->cookies, conn->allocptr.cookiehost? conn->allocptr.cookiehost:host, - data->reqdata.path, + data->state.path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } -- cgit v1.2.1 From 1c93e75375882ed309c7d93a1ce59d27a53f23d3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 2 Dec 2007 23:38:23 +0000 Subject: Michal Marek introduced CURLOPT_PROXY_TRANSFER_MODE which is used to control the appending of the "type=" thing on FTP URLs when they are passed to a HTTP proxy. Some proxies just don't like that appending (which is done unconditionally in 7.17.1), and some proxies treat binary/ascii transfers better with the appending done! --- lib/http.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 635506e08..7cfb23f3c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2122,22 +2122,24 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } ppath = data->change.url; - /* when doing ftp, append ;type= if not present */ - if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { - char *p = strstr(ppath, ";type="); - if(p && p[6] && p[7] == 0) { - switch (toupper((int)((unsigned char)p[6]))) { - case 'A': - case 'D': - case 'I': - break; - default: - p = NULL; + if (data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { + char *p = strstr(ppath, ";type="); + if(p && p[6] && p[7] == 0) { + switch (toupper((int)((unsigned char)p[6]))) { + case 'A': + case 'D': + case 'I': + break; + default: + p = NULL; + } } + if(!p) + snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); } - if(!p) - snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); } } if(HTTPREQ_POST_FORM == httpreq) { -- cgit v1.2.1 From 7d3ea12b625fd07d9d41a68e7cc2cd5322247584 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 5 Dec 2007 21:20:14 +0000 Subject: Spacen Jasset reported a problem with doing POST (with data read with a callback) over a proxy when NTLM is used as auth with the proxy. The bug also concerned Digest and was limited to using callback only. Spacen worked with us to provide a useful patch. I added the test case 547 and 548 to verify two variations of POST over proxy with NTLM. --- lib/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7cfb23f3c..70418af96 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2687,9 +2687,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, postsize?postsize:-1); - /* set the pointer to mark that we will send the post body using - the read callback */ - http->postdata = (char *)&http->postdata; + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) + http->postdata = (char *)&http->postdata; } } /* issue the request */ -- cgit v1.2.1 From 662bee71930fc30ef3fe43077bf696def44c5c7b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 8 Dec 2007 22:50:55 +0000 Subject: All static functions that were previously name Curl_* something no longer use that prefix as we use that prefix only for library-wide internal global symbols. --- lib/http.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 70418af96..7f3ff35a3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -109,9 +109,9 @@ * Forward declarations. */ -static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done); +static CURLcode https_connecting(struct connectdata *conn, bool *done); #ifdef USE_SSL -static int Curl_https_getsock(struct connectdata *conn, +static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks); #endif @@ -146,9 +146,9 @@ const struct Curl_handler Curl_handler_https = { Curl_http_done, /* done */ ZERO_NULL, /* do_more */ Curl_http_connect, /* connect_it */ - Curl_https_connecting, /* connecting */ + https_connecting, /* connecting */ ZERO_NULL, /* doing */ - Curl_https_getsock, /* proto_getsock */ + https_getsock, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ @@ -176,12 +176,12 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) } /* - * Curl_output_basic() sets up an Authorization: header (or the proxy version) + * http_output_basic() sets up an Authorization: header (or the proxy version) * for HTTP Basic authentication. * * Returns CURLcode. */ -static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) +static CURLcode http_output_basic(struct connectdata *conn, bool proxy) { char *authorization; struct SessionHandle *data=conn->data; @@ -435,11 +435,11 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) * @returns CURLcode */ static CURLcode -Curl_http_output_auth(struct connectdata *conn, - const char *request, - const char *path, - bool proxytunnel) /* TRUE if this is the request setting - up the proxy tunnel */ +http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; @@ -502,11 +502,11 @@ Curl_http_output_auth(struct connectdata *conn, if(conn->bits.proxy_user_passwd && !checkheaders(data, "Proxy-authorization:")) { auth="Basic"; - result = Curl_output_basic(conn, TRUE); + result = http_output_basic(conn, TRUE); if(result) return result; } - /* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth + /* NOTE: http_output_basic() should set 'done' TRUE, as the other auth functions work that way */ authproxy->done = TRUE; } @@ -582,7 +582,7 @@ Curl_http_output_auth(struct connectdata *conn, if(conn->bits.user_passwd && !checkheaders(data, "Authorization:")) { auth="Basic"; - result = Curl_output_basic(conn, FALSE); + result = http_output_basic(conn, FALSE); if(result) return result; } @@ -1264,7 +1264,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } /* Setup the proxy-authorization header, if any */ - result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); + result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); if(CURLE_OK == result) { char *host=(char *)""; @@ -1682,7 +1682,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) if(conn->protocol & PROT_HTTPS) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { - result = Curl_https_connecting(conn, done); + result = https_connecting(conn, done); if(result) return result; } @@ -1701,7 +1701,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return CURLE_OK; } -static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) +static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); @@ -1717,7 +1717,7 @@ static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) #ifdef USE_SSLEAY /* This function is OpenSSL-specific. It should be made to query the generic SSL layer instead. */ -static int Curl_https_getsock(struct connectdata *conn, +static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { @@ -1742,7 +1742,7 @@ static int Curl_https_getsock(struct connectdata *conn, } #else #ifdef USE_GNUTLS -int Curl_https_getsock(struct connectdata *conn, +int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { @@ -1753,7 +1753,7 @@ int Curl_https_getsock(struct connectdata *conn, } #else #ifdef USE_NSS -int Curl_https_getsock(struct connectdata *conn, +int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { @@ -1764,7 +1764,7 @@ int Curl_https_getsock(struct connectdata *conn, } #else #ifdef USE_QSOSSL -int Curl_https_getsock(struct connectdata *conn, +int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { @@ -1979,7 +1979,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* setup the authentication headers */ - result = Curl_http_output_auth(conn, request, ppath, FALSE); + result = http_output_auth(conn, request, ppath, FALSE); if(result) return result; -- cgit v1.2.1 From 7b1a22147e97e06316ca8707d6177fa9187d7550 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 13 Dec 2007 10:00:06 +0000 Subject: David Wright filed bug report #1849764 (http://curl.haxx.se/bug/view.cgi?id=1849764) with an included fix. He identified a problem for re-used connections that previously had sent Expect: 100-continue and in some situations the subsequent POST (that didn't use Expect:) still had the internal flag set for its use. David's fix (that makes the setting of the flag in every single request unconditionally) is fine and is now used! --- lib/http.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7f3ff35a3..e41a8f750 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2613,17 +2613,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if(data->set.postfields) { + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + if(postsize > TINY_INITIAL_POST_SIZE) { + result = expect100(data, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; - /* for really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it */ - if(postsize > TINY_INITIAL_POST_SIZE) { - result = expect100(data, req_buffer); - if(result) - return result; - } - else - data->state.expect100header = FALSE; + if(data->set.postfields) { if(!data->state.expect100header && (postsize < MAX_INITIAL_POST_SIZE)) { -- cgit v1.2.1 From 18faa509403c39b4914114cfe2966241b62b2959 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 10 Jan 2008 10:30:19 +0000 Subject: Georg Lippitsch brought CURLOPT_SEEKFUNCTION and CURLOPT_SEEKDATA to allow libcurl to seek in a given input stream. This is particularly important when doing upload resumes when there's already a huge part of the file present remotely. Before, and still if this callback isn't used, libcurl will read and through away the entire file up to the point to where the resuming begins (which of course can be a slow opereration depending on file size, I/O bandwidth and more). This new function will also be preferred to get used instead of the CURLOPT_IOCTLFUNCTION for seeking back in a stream when doing multi-stage HTTP auth with POST/PUT. --- lib/http.c | 55 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e41a8f750..fd58c06cc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1793,6 +1793,8 @@ CURLcode Curl_http_done(struct connectdata *conn, /* set the proper values (possibly modified on POST) */ conn->fread_func = data->set.fread_func; /* restore */ conn->fread_in = data->set.in; /* restore */ + conn->seek_func = data->set.seek_func; /* restore */ + conn->seek_client = data->set.seek_client; /* restore */ if(http == NULL) return CURLE_OK; @@ -2186,30 +2188,41 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->state.resume_from && !data->state.this_is_a_follow) { /* do we still game? */ - curl_off_t passed=0; /* Now, let's read off the proper amount of bytes from the - input. If we knew it was a proper file we could've just - fseek()ed but we only have a stream here */ - do { - size_t readthisamountnow = (size_t)(data->state.resume_from - passed); - size_t actuallyread; - - if(readthisamountnow > BUFSIZE) - readthisamountnow = BUFSIZE; - - actuallyread = - data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow, - data->set.in); - - passed += actuallyread; - if(actuallyread != readthisamountnow) { - failf(data, "Could only read %" FORMAT_OFF_T - " bytes from the input", - passed); + input. */ + if(conn->seek_func) { + curl_off_t readthisamountnow = data->state.resume_from; + + if(conn->seek_func(conn->seek_client, + readthisamountnow, SEEK_SET) != 0) { + failf(data, "Could not seek stream"); return CURLE_READ_ERROR; } - } while(passed != data->state.resume_from); /* loop until done */ + } + else { + curl_off_t passed=0; + + do { + size_t readthisamountnow = (size_t)(data->state.resume_from - passed); + size_t actuallyread; + + if(readthisamountnow > BUFSIZE) + readthisamountnow = BUFSIZE; + + actuallyread = data->set.fread_func(data->state.buffer, 1, + (size_t)readthisamountnow, + data->set.in); + + passed += actuallyread; + if(actuallyread != readthisamountnow) { + failf(data, "Could only read %" FORMAT_OFF_T + " bytes from the input", + passed); + return CURLE_READ_ERROR; + } + } while(passed != data->state.resume_from); /* loop until done */ + } /* now, decrease the size of the read */ if(data->set.infilesize>0) { -- cgit v1.2.1 From 53108806af58264196b188f2f9ac8d128b8dc239 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Jan 2008 22:02:14 +0000 Subject: Joe Malicki filed bug report #1871269 (http://curl.haxx.se/bug/view.cgi?id=1871269) and we could fix his hang- problem that occurred when doing a large HTTP POST request with the response-body read from a callback. --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fd58c06cc..1dcdc0f91 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2705,8 +2705,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the pointer to mark that we will send the post body using the read callback, but only if we're not in authenticate negotiation */ - if(!conn->bits.authneg) + if(!conn->bits.authneg) { http->postdata = (char *)&http->postdata; + http->postsize = postsize; + } } } /* issue the request */ -- cgit v1.2.1 From c914e6ea5dad4dc6281b189a9b1f20bc77c223c8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 23 Jan 2008 22:22:12 +0000 Subject: "Igor" pointed out that CURLOPT_COOKIELIST set to "ALL" leaked memory, and so did "SESS". Fixed now. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1dcdc0f91..89f5c7615 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2374,7 +2374,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } co = co->next; /* next cookie please */ } - Curl_cookie_freelist(store); /* free the cookie list */ + Curl_cookie_freelist(store, FALSE); /* free the cookie list */ } if(addcookies && (CURLE_OK == result)) { if(!count) -- cgit v1.2.1 From c6df78886654c2b5672612f114fadb9402b7027f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 25 Jan 2008 23:33:45 +0000 Subject: - Kevin Reed filed bug report #1879375 (http://curl.haxx.se/bug/view.cgi?id=1879375) which describes how libcurl got lost in this scenario: proxy tunnel (or HTTPS over proxy), ask to do any proxy authentication and the proxy replies with an auth (like NTLM) and then closes the connection after that initial informational response. libcurl would not properly re-initialize the connection to the proxy and continue the auth negotiation like supposed. It does now however, as it will now detect if one or more authentication methods were available and asked for, and will thus retry the connection and continue from there. - I made the progress callback get called properly during proxy CONNECT. --- lib/http.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 89f5c7615..d537407d2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1409,8 +1409,15 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, keepon = FALSE; else if(gotbytes <= 0) { keepon = FALSE; - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } } else { /* @@ -1590,6 +1597,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } break; } /* switch */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; } /* while there's buffer left and loop is requested */ if(error) -- cgit v1.2.1 From b620e62f0f4e90f4d1338117c67580a6f5f37377 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 31 Jan 2008 12:04:33 +0000 Subject: - Dmitry Kurochkin moved several struct fields from the connectdata struct to the SingleRequest one to make pipelining better. It is a bit tricky to keep them in the right place, to keep things related to the actual request or to the actual connection in the right place. --- lib/http.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d537407d2..4d42635e2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -842,7 +842,7 @@ static size_t readmoredata(char *buffer, return 0; /* make sure that a HTTP request is never sent away chunked! */ - conn->bits.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST); + conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST); if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); @@ -1957,7 +1957,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->set.str[STRING_CUSTOMREQUEST]) request = data->set.str[STRING_CUSTOMREQUEST]; else { - if(conn->bits.no_body) + if(data->set.opt_no_body) request = (char *)"HEAD"; else { DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); @@ -2025,13 +2025,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ptr = checkheaders(data, "Transfer-Encoding:"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ - conn->bits.upload_chunky = + data->req.upload_chunky = Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } else { - if(httpreq == HTTPREQ_GET) - conn->bits.upload_chunky = FALSE; - if(conn->bits.upload_chunky) + if((conn->protocol&PROT_HTTP) && + data->set.upload && + (data->set.infilesize == -1) && + (data->set.httpversion != CURL_HTTP_VERSION_1_0)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } + else { + /* else, no chunky upload */ + data->req.upload_chunky = FALSE; + } + + if(data->req.upload_chunky) te = "Transfer-Encoding: chunked\r\n"; } @@ -2494,7 +2504,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) http->sending = HTTPSEND_BODY; - if(!conn->bits.upload_chunky) { + if(!data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T "\r\n", @@ -2566,7 +2576,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else postsize = data->set.infilesize; - if((postsize != -1) && !conn->bits.upload_chunky) { + if((postsize != -1) && !data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T "\r\n", @@ -2612,7 +2622,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->set.postfieldsize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); - if(!conn->bits.upload_chunky) { + if(!data->req.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both kinds of headers (Transfer-Encoding: chunked and Content-Length) */ @@ -2662,7 +2672,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - if(!conn->bits.upload_chunky) { + if(!data->req.upload_chunky) { /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ result = add_buffer(req_buffer, data->set.postfields, -- cgit v1.2.1 From d25aab2704f1dcc92ae913e4ad38dd1da2b205a2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 15 Feb 2008 08:56:06 +0000 Subject: - Pooyan McSporran found and fixed a flaw where you first would do a normal http request and then you'd reuse the handle and replace the Accept: header, as then libcurl would send two Accept: headers! --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4d42635e2..08c2ea88f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2182,8 +2182,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) (conn->bits.httpproxy && !conn->bits.tunnel_proxy) )? "Pragma: no-cache\r\n":NULL; - if(!checkheaders(data, "Accept:")) - http->p_accept = "Accept: */*\r\n"; + http->p_accept = checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; if(( (HTTPREQ_POST == httpreq) || (HTTPREQ_POST_FORM == httpreq) || -- cgit v1.2.1 From 4180ca7638889eebad02d0201062b5f8fc8e3350 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 17 Feb 2008 13:40:35 +0000 Subject: don't do the GOT_NOTHING error check if the DONE function was called with premature set TRUE, which means it was done before the request comleted. It could then very well not have received any data. --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 08c2ea88f..bf71f89c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1832,7 +1832,9 @@ CURLcode Curl_http_done(struct connectdata *conn, if(status != CURLE_OK) return (status); - if(!conn->bits.retry && + if(!premature && /* this check is pointless is the DONE is done before the + entire operation is complete */ + !conn->bits.retry && ((http->readbytecount + data->req.headerbytecount - data->req.deductheadercount)) <= 0) { -- cgit v1.2.1 From ba3e7a8656d90152eafacc82486c9e8cd6671fc1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 17 Feb 2008 13:49:01 +0000 Subject: rephrased comment --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bf71f89c2..cffcac002 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1832,7 +1832,7 @@ CURLcode Curl_http_done(struct connectdata *conn, if(status != CURLE_OK) return (status); - if(!premature && /* this check is pointless is the DONE is done before the + if(!premature && /* this check is pointless when DONE is called before the entire operation is complete */ !conn->bits.retry && ((http->readbytecount + -- cgit v1.2.1 From 0d722204c315513cc3ebadfe6c62cd6869cde8a7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 18 Feb 2008 19:53:31 +0000 Subject: https_getsock() should be static all over (and did some fixed indenting) --- lib/http.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cffcac002..45cabd4b6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -112,8 +112,8 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done); #ifdef USE_SSL static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); + curl_socket_t *socks, + int numsocks); #endif /* @@ -146,9 +146,9 @@ const struct Curl_handler Curl_handler_https = { Curl_http_done, /* done */ ZERO_NULL, /* do_more */ Curl_http_connect, /* connect_it */ - https_connecting, /* connecting */ + https_connecting, /* connecting */ ZERO_NULL, /* doing */ - https_getsock, /* proto_getsock */ + https_getsock, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ @@ -1727,8 +1727,8 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) /* This function is OpenSSL-specific. It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) + curl_socket_t *socks, + int numsocks) { if(conn->protocol & PROT_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; @@ -1751,9 +1751,9 @@ static int https_getsock(struct connectdata *conn, } #else #ifdef USE_GNUTLS -int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) { (void)conn; (void)socks; @@ -1762,9 +1762,9 @@ int https_getsock(struct connectdata *conn, } #else #ifdef USE_NSS -int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) { (void)conn; (void)socks; @@ -1773,9 +1773,9 @@ int https_getsock(struct connectdata *conn, } #else #ifdef USE_QSOSSL -int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) { (void)conn; (void)socks; @@ -2759,9 +2759,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else /* HTTP GET/HEAD download: */ result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); } if(result) return result; -- cgit v1.2.1 From 590f0358d86c402f94b329f2ce0d612cbb749c95 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 1 Mar 2008 22:32:03 +0000 Subject: - Anatoli Tubman found and fixed a crash with Negotiate authentication used on a re-used connection where both requests used Negotiate. --- lib/http.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 45cabd4b6..59a275d0d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2358,6 +2358,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) te ); + /* + * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM + * with basic and digest, it will be freed anyway by the next request + */ + + Curl_safefree (conn->allocptr.userpwd); + conn->allocptr.userpwd = NULL; + if(result) return result; -- cgit v1.2.1 From b425e851fb946b814bccde07ae18225106e9da4d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 27 Mar 2008 13:07:12 +0000 Subject: - As found out and reported by Dan Petitt, libcurl didn't show progress/call the progress callback for the first (potentially huge) piece of body data sent together with the POST request headers in the initial send(). --- lib/http.c | 746 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 376 insertions(+), 370 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 59a275d0d..a76c16053 100644 --- a/lib/http.c +++ b/lib/http.c @@ -485,7 +485,7 @@ http_output_auth(struct connectdata *conn, if(result) return result; authproxy->done = TRUE; - } + } else #endif #ifdef USE_NTLM @@ -1929,6 +1929,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; curl_off_t included_body = 0; + const char *httpstring; + send_buffer *req_buffer; + curl_off_t postsize; /* off_t type to be able to hold a large file size */ + /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with @@ -2215,16 +2219,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t readthisamountnow = data->state.resume_from; if(conn->seek_func(conn->seek_client, - readthisamountnow, SEEK_SET) != 0) { + readthisamountnow, SEEK_SET) != 0) { failf(data, "Could not seek stream"); return CURLE_READ_ERROR; } } else { - curl_off_t passed=0; + curl_off_t passed=0; do { - size_t readthisamountnow = (size_t)(data->state.resume_from - passed); + size_t readthisamountnow = (size_t)(data->state.resume_from - passed); size_t actuallyread; if(readthisamountnow > BUFSIZE) @@ -2299,36 +2303,31 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - { - /* Use 1.1 unless the use specificly asked for 1.0 */ - const char *httpstring= - data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; + /* Use 1.1 unless the use specificly asked for 1.0 */ + httpstring= data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; - send_buffer *req_buffer; - curl_off_t postsize; /* off_t type to be able to hold a large file size */ + /* initialize a dynamic send-buffer */ + req_buffer = add_buffer_init(); - /* initialize a dynamic send-buffer */ - req_buffer = add_buffer_init(); - - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; + if(!req_buffer) + return CURLE_OUT_OF_MEMORY; - /* add the main request stuff */ - result = - add_bufferf(req_buffer, - "%s " /* GET/HEAD/POST/PUT */ - "%s%s HTTP/%s\r\n" /* path + HTTP version */ - "%s" /* proxyuserpwd */ - "%s" /* userpwd */ - "%s" /* range */ - "%s" /* user agent */ - "%s" /* host */ - "%s" /* pragma */ - "%s" /* accept */ - "%s" /* accept-encoding */ - "%s" /* referer */ - "%s" /* Proxy-Connection */ - "%s",/* transfer-encoding */ + /* add the main request stuff */ + result = + add_bufferf(req_buffer, + "%s " /* GET/HEAD/POST/PUT */ + "%s%s HTTP/%s\r\n" /* path + HTTP version */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* host */ + "%s" /* pragma */ + "%s" /* accept */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s",/* transfer-encoding */ request, ppath, @@ -2348,433 +2347,440 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) (data->set.str[STRING_ENCODING] && *data->set.str[STRING_ENCODING] && conn->allocptr.accept_encoding)? - conn->allocptr.accept_encoding:"", - (data->change.referer && conn->allocptr.ref)? - conn->allocptr.ref:"" /* Referer: */, - (conn->bits.httpproxy && - !conn->bits.tunnel_proxy && - !checkheaders(data, "Proxy-Connection:"))? - "Proxy-Connection: Keep-Alive\r\n":"", - te - ); + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !checkheaders(data, "Proxy-Connection:"))? + "Proxy-Connection: Keep-Alive\r\n":"", + te + ); - /* - * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM - * with basic and digest, it will be freed anyway by the next request - */ + /* + * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM + * with basic and digest, it will be freed anyway by the next request + */ - Curl_safefree (conn->allocptr.userpwd); - conn->allocptr.userpwd = NULL; + Curl_safefree (conn->allocptr.userpwd); + conn->allocptr.userpwd = NULL; - if(result) - return result; + if(result) + return result; #if !defined(CURL_DISABLE_COOKIES) - if(data->cookies || addcookies) { - struct Cookie *co=NULL; /* no cookies from start */ - int count=0; - - if(data->cookies) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, - data->state.path, - (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } - if(co) { - struct Cookie *store=co; - /* now loop through all cookies that matched */ - while(co) { - if(co->value) { - if(0 == count) { - result = add_bufferf(req_buffer, "Cookie: "); - if(result) - break; - } - result = add_bufferf(req_buffer, - "%s%s=%s", count?"; ":"", - co->name, co->value); + if(data->cookies || addcookies) { + struct Cookie *co=NULL; /* no cookies from start */ + int count=0; + + if(data->cookies) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + co = Curl_cookie_getlist(data->cookies, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, + data->state.path, + (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + if(co) { + struct Cookie *store=co; + /* now loop through all cookies that matched */ + while(co) { + if(co->value) { + if(0 == count) { + result = add_bufferf(req_buffer, "Cookie: "); if(result) break; - count++; } - co = co->next; /* next cookie please */ - } - Curl_cookie_freelist(store, FALSE); /* free the cookie list */ - } - if(addcookies && (CURLE_OK == result)) { - if(!count) - result = add_bufferf(req_buffer, "Cookie: "); - if(CURLE_OK == result) { - result = add_bufferf(req_buffer, "%s%s", - count?"; ":"", - addcookies); + result = add_bufferf(req_buffer, + "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) + break; count++; } + co = co->next; /* next cookie please */ } - if(count && (CURLE_OK == result)) - result = add_buffer(req_buffer, "\r\n", 2); - - if(result) - return result; + Curl_cookie_freelist(store, FALSE); /* free the cookie list */ } + if(addcookies && (CURLE_OK == result)) { + if(!count) + result = add_bufferf(req_buffer, "Cookie: "); + if(CURLE_OK == result) { + result = add_bufferf(req_buffer, "%s%s", + count?"; ":"", + addcookies); + count++; + } + } + if(count && (CURLE_OK == result)) + result = add_buffer(req_buffer, "\r\n", 2); + + if(result) + return result; + } #endif - if(data->set.timecondition) { - struct tm *tm; + if(data->set.timecondition) { + struct tm *tm; - /* The If-Modified-Since header family should have their times set in - * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be - * represented in Greenwich Mean Time (GMT), without exception. For the - * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal - * Time)." (see page 20 of RFC2616). - */ + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). + */ #ifdef HAVE_GMTIME_R - /* thread-safe version */ - struct tm keeptime; - tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); + /* thread-safe version */ + struct tm keeptime; + tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); #else - tm = gmtime(&data->set.timevalue); + tm = gmtime(&data->set.timevalue); #endif - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - - switch(data->set.timecondition) { - case CURL_TIMECOND_IFMODSINCE: - default: - result = add_bufferf(req_buffer, - "If-Modified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_IFUNMODSINCE: - result = add_bufferf(req_buffer, - "If-Unmodified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_LASTMOD: - result = add_bufferf(req_buffer, - "Last-Modified: %s\r\n", buf); - break; - } - if(result) - return result; + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + snprintf(buf, BUFSIZE-1, + "%s, %02d %s %4d %02d:%02d:%02d GMT", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + result = add_bufferf(req_buffer, + "If-Modified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_IFUNMODSINCE: + result = add_bufferf(req_buffer, + "If-Unmodified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_LASTMOD: + result = add_bufferf(req_buffer, + "Last-Modified: %s\r\n", buf); + break; } - - result = add_custom_headers(conn, req_buffer); if(result) return result; + } - http->postdata = NULL; /* nothing to post at this point */ - Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ + result = add_custom_headers(conn, req_buffer); + if(result) + return result; - /* If 'authdone' is FALSE, we must not set the write socket index to the - Curl_transfer() call below, as we're not ready to actually upload any - data yet. */ + http->postdata = NULL; /* nothing to post at this point */ + Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - switch(httpreq) { + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ - case HTTPREQ_POST_FORM: - if(!http->sendit || conn->bits.authneg) { - /* nothing to post! */ - result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); - if(result) - return result; + switch(httpreq) { - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* setup variables for the upcoming transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - -1, NULL); - break; - } + case HTTPREQ_POST_FORM: + if(!http->sendit || conn->bits.authneg) { + /* nothing to post! */ + result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); + if(result) + return result; - if(Curl_FormInit(&http->form, http->sendit)) { - failf(data, "Internal HTTP POST error!"); - return CURLE_HTTP_POST_ERROR; - } + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + -1, NULL); + break; + } - /* set the read function to read from the generated form data */ - conn->fread_func = (curl_read_callback)Curl_FormReader; - conn->fread_in = &http->form; + if(Curl_FormInit(&http->form, http->sendit)) { + failf(data, "Internal HTTP POST error!"); + return CURLE_HTTP_POST_ERROR; + } - http->sending = HTTPSEND_BODY; + /* set the read function to read from the generated form data */ + conn->fread_func = (curl_read_callback)Curl_FormReader; + conn->fread_in = &http->form; - if(!data->req.upload_chunky) { - /* only add Content-Length if not uploading chunked */ - result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - http->postsize); - if(result) - return result; - } + http->sending = HTTPSEND_BODY; - result = expect100(data, req_buffer); + if(!data->req.upload_chunky) { + /* only add Content-Length if not uploading chunked */ + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T "\r\n", + http->postsize); if(result) return result; + } - { + result = expect100(data, req_buffer); + if(result) + return result; - /* Get Content-Type: line from Curl_formpostheader. - */ - char *contentType; - size_t linelength=0; - contentType = Curl_formpostheader((void *)&http->form, - &linelength); - if(!contentType) { - failf(data, "Could not get Content-Type header line!"); - return CURLE_HTTP_POST_ERROR; - } + { - result = add_buffer(req_buffer, contentType, linelength); - if(result) - return result; + /* Get Content-Type: line from Curl_formpostheader. + */ + char *contentType; + size_t linelength=0; + contentType = Curl_formpostheader((void *)&http->form, + &linelength); + if(!contentType) { + failf(data, "Could not get Content-Type header line!"); + return CURLE_HTTP_POST_ERROR; } - /* make the request end in a true CRLF */ - result = add_buffer(req_buffer, "\r\n", 2); + result = add_buffer(req_buffer, contentType, linelength); if(result) return result; + } - /* set upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); + /* make the request end in a true CRLF */ + result = add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; - /* fire away the whole request to the server */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* setup variables for the upcoming transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + /* set upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); - if(result) { - Curl_formclean(&http->sendit); /* free that whole lot */ - return result; - } + /* fire away the whole request to the server */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); + else + /* setup variables for the upcoming transfer */ + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + FIRSTSOCKET, + &http->writebytecount); + + if(result) { + Curl_formclean(&http->sendit); /* free that whole lot */ + return result; + } #ifdef CURL_DOES_CONVERSIONS /* time to convert the form data... */ - result = Curl_formconvert(data, http->sendit); - if(result) { - Curl_formclean(&http->sendit); /* free that whole lot */ - return result; - } + result = Curl_formconvert(data, http->sendit); + if(result) { + Curl_formclean(&http->sendit); /* free that whole lot */ + return result; + } #endif /* CURL_DOES_CONVERSIONS */ - break; - - case HTTPREQ_PUT: /* Let's PUT the data to the server! */ + break; - if(conn->bits.authneg) - postsize = 0; - else - postsize = data->set.infilesize; + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - if((postsize != -1) && !data->req.upload_chunky) { - /* only add Content-Length if not uploading chunked */ - result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - postsize ); - if(result) - return result; - } + if(conn->bits.authneg) + postsize = 0; + else + postsize = data->set.infilesize; - result = expect100(data, req_buffer); + if((postsize != -1) && !data->req.upload_chunky) { + /* only add Content-Length if not uploading chunked */ + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T "\r\n", + postsize ); if(result) return result; + } - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ - if(result) - return result; + result = expect100(data, req_buffer); + if(result) + return result; - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize); + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ + if(result) + return result; - /* this sends the buffer and frees all the buffer resources */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending PUT request"); - else - /* prepare for transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); - if(result) - return result; - break; + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize); - case HTTPREQ_POST: - /* this is the simple POST, using x-www-form-urlencoded style */ + /* this sends the buffer and frees all the buffer resources */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); + else + /* prepare for transfer */ + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + postsize?FIRSTSOCKET:-1, + postsize?&http->writebytecount:NULL); + if(result) + return result; + break; - if(conn->bits.authneg) - postsize = 0; - else - /* figure out the size of the postfields */ - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: - (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); - - if(!data->req.upload_chunky) { - /* We only set Content-Length and allow a custom Content-Length if - we don't upload data chunked, as RFC2616 forbids us to set both - kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - - if(!checkheaders(data, "Content-Length:")) { - /* we allow replacing this header, although it isn't very wise to - actually set your own */ + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ + + if(conn->bits.authneg) + postsize = 0; + else + /* figure out the size of the postfields */ + postsize = (data->set.postfieldsize != -1)? + data->set.postfieldsize: + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + + if(!data->req.upload_chunky) { + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + + if(!checkheaders(data, "Content-Length:")) { + /* we allow replacing this header, although it isn't very wise to + actually set your own */ + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T"\r\n", + postsize); + if(result) + return result; + } + } + + if(!checkheaders(data, "Content-Type:")) { result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", - postsize); + "Content-Type: application/x-www-form-urlencoded\r\n"); if(result) return result; } - } - - if(!checkheaders(data, "Content-Type:")) { - result = add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); - if(result) - return result; - } - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - if(postsize > TINY_INITIAL_POST_SIZE) { - result = expect100(data, req_buffer); - if(result) - return result; - } - else - data->state.expect100header = FALSE; + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + if(postsize > TINY_INITIAL_POST_SIZE) { + result = expect100(data, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; - if(data->set.postfields) { + if(data->set.postfields) { - if(!data->state.expect100header && - (postsize < MAX_INITIAL_POST_SIZE)) { - /* if we don't use expect: 100 AND - postsize is less than MAX_INITIAL_POST_SIZE + if(!data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE - then append the post data to the HTTP request header. This limit - is no magic limit but only set to prevent really huge POSTs to - get the data duplicated with malloc() and family. */ + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; - if(!data->req.upload_chunky) { - /* We're not sending it 'chunked', append it to the request - already now to reduce the number if send() calls */ - result = add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - included_body = postsize; - } - else { - /* Append the POST data chunky-style */ - result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); - if(CURLE_OK == result) + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ result = add_buffer(req_buffer, data->set.postfields, (size_t)postsize); - if(CURLE_OK == result) - result = add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ - included_body = postsize + 7; + included_body = postsize; + } + else { + /* Append the POST data chunky-style */ + result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + /* CR LF 0 CR LF CR LF */ + included_body = postsize + 7; + } + if(result) + return result; } - if(result) - return result; - } - else { - /* A huge POST coming up, do data separate from the request */ - http->postsize = postsize; - http->postdata = data->set.postfields; + else { + /* A huge POST coming up, do data separate from the request */ + http->postsize = postsize; + http->postdata = data->set.postfields; - http->sending = HTTPSEND_BODY; + http->sending = HTTPSEND_BODY; - conn->fread_func = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + } + } + else { result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) return result; - } - } - else { - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; - if(data->set.postfieldsize) { - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + if(data->set.postfieldsize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); - /* set the pointer to mark that we will send the post body using the - read callback, but only if we're not in authenticate - negotiation */ - if(!conn->bits.authneg) { - http->postdata = (char *)&http->postdata; - http->postsize = postsize; + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) { + http->postdata = (char *)&http->postdata; + http->postsize = postsize; + } } } - } - /* issue the request */ - result = add_buffer_send(req_buffer, conn, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); + /* issue the request */ + result = add_buffer_send(req_buffer, conn, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); - if(result) - failf(data, "Failed sending HTTP POST request"); - else - result = - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); - break; + if(result) + failf(data, "Failed sending HTTP POST request"); + else + result = + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); + break; - default: - result = add_buffer(req_buffer, "\r\n", 2); - if(result) - return result; + default: + result = add_buffer(req_buffer, "\r\n", 2); + if(result) + return result; - /* issue the request */ - result = add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); + /* issue the request */ + result = add_buffer_send(req_buffer, conn, + &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending HTTP request"); - else - /* HTTP GET/HEAD download: */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); - } if(result) - return result; + failf(data, "Failed sending HTTP request"); + else + /* HTTP GET/HEAD download: */ + result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); } + if(result) + return result; - return CURLE_OK; + if(http->writebytecount) { + /* if a request-body has been sent off, we make sure this progress is noted + properly */ + Curl_pgrsSetUploadCounter(data, http->writebytecount); + if(Curl_pgrsUpdate(conn)) + result = CURLE_ABORTED_BY_CALLBACK; + } + + return result; } #endif -- cgit v1.2.1 From a2314225e02ea2f3bd49dc8557f2452846e49b19 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Mar 2008 10:02:23 +0000 Subject: - Added CURLFORM_STREAM as a supported option to curl_formadd() to allow an application to provide data for a multipart with the read callback. Note that the size needs to be provided with CURLFORM_CONTENTSLENGTH when the stream option is used. This feature is verified by the new test case 554. This feature was sponsored by Xponaut. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a76c16053..356741fe8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2507,6 +2507,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* set the read function to read from the generated form data */ + http->form.fread_func = conn->fread_func; /* get the previously set callback + function pointer */ conn->fread_func = (curl_read_callback)Curl_FormReader; conn->fread_in = &http->form; -- cgit v1.2.1 From f1c69192da0a7326329629550795101e40092438 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 31 Mar 2008 10:16:34 +0000 Subject: expanded a comment around some of the new formpost callback usage --- lib/http.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 356741fe8..cb330c6cf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2506,9 +2506,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_HTTP_POST_ERROR; } - /* set the read function to read from the generated form data */ - http->form.fread_func = conn->fread_func; /* get the previously set callback - function pointer */ + /* Get the currently set callback function pointer and store that in the + form struct since we might want the actual user-provided callback later + on. The conn->fread_func pointer itself will be changed for the + multipart case to the function that returns a multipart formatted + stream. */ + http->form.fread_func = conn->fread_func; + + /* Set the read function to read from the generated form data */ conn->fread_func = (curl_read_callback)Curl_FormReader; conn->fread_in = &http->form; -- cgit v1.2.1 From 09777a4fc2ed0f2b09447eb89fb8cd4b99278944 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 17 Apr 2008 00:45:33 +0000 Subject: Some trivial changes --- lib/http.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cb330c6cf..f8ef9a4ea 100644 --- a/lib/http.c +++ b/lib/http.c @@ -104,6 +104,8 @@ /* The last #include file should be: */ #include "memdebug.h" +/* Default proxy timeout in milliseconds */ +#define PROXY_TIMEOUT (3600*1000) /* * Forward declarations. @@ -1221,7 +1223,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, CURLcode result; int res; long timeout = - data->set.timeout?data->set.timeout:3600000; /* in milliseconds */ + data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ curl_socket_t tunnelsocket = conn->sock[sockindex]; curl_off_t cl=0; bool closeConnection = FALSE; -- cgit v1.2.1 From 21a0f09081e4f64f27de576621ce921505eb43b4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 3 May 2008 21:44:50 +0000 Subject: Added comments, check Curl_http_auth_act()'s return code and added a check that closes the connection somewhat faster when perhapsrewind() has marked the connection for closure. --- lib/http.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f8ef9a4ea..266c1cacb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -340,9 +340,13 @@ static CURLcode perhapsrewind(struct connectdata *conn) */ conn->bits.close = TRUE; data->req.size = 0; /* don't download any more than 0 bytes */ + + /* There still is data left to send, but this connection is marked for + closure so we can safely do the rewind right now */ } if(bytessent) + /* we rewind now at once since if we already sent something */ return Curl_readrewind(conn); return CURLE_OK; @@ -1606,10 +1610,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(error) return CURLE_RECV_ERROR; - if(data->info.httpproxycode != 200) + if(data->info.httpproxycode != 200) { /* Deal with the possibly already received authenticate headers. 'newurl' is set to a new URL if we must loop. */ - Curl_http_auth_act(conn); + result = Curl_http_auth_act(conn); + if(result) + return result; + + if(conn->bits.close) + /* the connection has been marked for closure, most likely in the + Curl_http_auth_act() function and thus we can kill it at once + below + */ + closeConnection = TRUE; + } if(closeConnection && data->req.newurl) { /* Connection closed by server. Don't use it anymore */ -- cgit v1.2.1 From 3cb0dd6685235fca006f9bb4923740dcb9c52f3f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 19 May 2008 20:57:28 +0000 Subject: when the multi handle was in DO and DOING states, the HTTP and HTTPS protocol handler functions didn't return that the socket should be waited for writing, but instead it was treated as if no socket was needing monitoring so REMOVE was called prematurely --- lib/http.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 266c1cacb..acb0f94d7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -111,6 +111,9 @@ * Forward declarations. */ +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); static CURLcode https_connecting(struct connectdata *conn, bool *done); #ifdef USE_SSL static int https_getsock(struct connectdata *conn, @@ -131,7 +134,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ + http_getsock_do, /* doing_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTP, /* defport */ PROT_HTTP, /* protocol */ @@ -151,7 +154,7 @@ const struct Curl_handler Curl_handler_https = { https_connecting, /* connecting */ ZERO_NULL, /* doing */ https_getsock, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ + http_getsock_do, /* doing_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */ @@ -1726,6 +1729,19 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) return CURLE_OK; } +/* this returns the socket to wait for in the DO and DOING state for the multi + interface and then we're always _sending_ a request and thus we wait for + the single socket to become writable only */ +static int http_getsock_do(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + /* write mode */ + (void)numsocks; /* unused, we trust it to be at least 1 */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); +} + static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; -- cgit v1.2.1 From d92945bb8af8fd7ee2e56afc0ecf942ba9169c24 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 22 Jun 2008 20:38:16 +0000 Subject: - Eduard Bloch filed the debian bug report #487567 (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=487567) pointing out that libcurl used Content-Range: instead of Range when doing a range request with --head (CURLOPT_NOBODY). This is now fixed and test case 1032 was added to verify. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index acb0f94d7..280cccecb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2298,7 +2298,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * or uploading and we always let customized headers override our internal * ones if any such are specified. */ - if((httpreq == HTTPREQ_GET) && + if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && !checkheaders(data, "Range:")) { /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) -- cgit v1.2.1 From 82412f218fe6809288c718c5b43b9675eb2856f5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Jul 2008 08:47:53 +0000 Subject: Phil Blundell provided a fix for libcurl's treatment of unexpected 1xx response codes. Previously libcurl would hang on such occurances. I added test case 1033 to verify. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 280cccecb..c65b0cf1f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -369,7 +369,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) bool pickproxy = FALSE; CURLcode code = CURLE_OK; - if(100 == data->req.httpcode) + if(100 <= data->req.httpcode && 199 >= data->req.httpcode) /* this is a transient response code, ignore */ return CURLE_OK; -- cgit v1.2.1 From cc0285da7f99fd4cb87db7059552db929b6f24f2 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 30 Jul 2008 20:11:51 +0000 Subject: Factored out Curl_copy_header_value --- lib/http.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 16 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c65b0cf1f..0da7156e3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -180,6 +180,60 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) return NULL; } +/* + * Strip off leading and trailing whitespace from the value in the + * given HTTP header line and return a strdupped copy. Returns NULL in + * case of allocation failure. Returns an empty string if the header value + * consists entirely of whitespace. + */ +char *Curl_copy_header_value(const char *h) +{ + const char *start; + const char *end; + char *value; + size_t len; + + DEBUGASSERT(h); + + /* Find the end of the header name */ + while (*h && (*h != ':')) + ++h; + + if (*h) + /* Skip over colon */ + ++h; + + /* Find the first non-space letter */ + for(start=h; + *start && ISSPACE(*start); + start++) + ; /* empty loop */ + + /* data is in the host encoding so + use '\r' and '\n' instead of 0x0d and 0x0a */ + end = strchr(start, '\r'); + if(!end) + end = strchr(start, '\n'); + if(!end) + end = strchr(start, '\0'); + + /* skip all trailing space letters */ + for(; ISSPACE(*end) && (end > start); end--) + ; /* empty loop */ + + /* get length of the type */ + len = end-start+1; + + value = malloc(len + 1); + if(!value) + return NULL; + + memcpy(value, start, len); + value[len] = 0; /* zero terminate */ + + return value; +} + /* * http_output_basic() sets up an Authorization: header (or the proxy version) * for HTTP Basic authentication. @@ -668,6 +722,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* if exactly this is wanted, go */ int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); if(neg == 0) { + DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->change.url); data->state.authproblem = (data->req.newurl == NULL); } @@ -2094,23 +2149,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) custom Host: header if this is NOT a redirect, as setting Host: in the redirected request is being out on thin ice. Except if the host name is the same as the first one! */ - char *start = ptr+strlen("Host:"); - while(*start && ISSPACE(*start )) - start++; - ptr = start; /* start host-scanning here */ - - /* scan through the string to find the end (space or colon) */ - while(*ptr && !ISSPACE(*ptr) && !(':'==*ptr)) - ptr++; - - if(ptr != start) { - size_t len=ptr-start; + char *cookiehost = Curl_copy_header_value(ptr); + if (!cookiehost) + return CURLE_OUT_OF_MEMORY; + if (!*cookiehost) + /* ignore empty data */ + free(cookiehost); + else { + char *colon = strchr(cookiehost, ':'); + if (colon) + *colon = 0; /* The host must not include an embedded port number */ Curl_safefree(conn->allocptr.cookiehost); - conn->allocptr.cookiehost = malloc(len+1); - if(!conn->allocptr.cookiehost) - return CURLE_OUT_OF_MEMORY; - memcpy(conn->allocptr.cookiehost, start, len); - conn->allocptr.cookiehost[len]=0; + conn->allocptr.cookiehost = cookiehost; } #endif -- cgit v1.2.1 From 8d012181b01aae80b46c90755a55126bc9731f7d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Aug 2008 22:20:58 +0000 Subject: - Test case 1041 (added by Daniel Fandrich April 14th) proved a bug where PUT with -C - sent garbage in the Content-Range: header. I fixed this problem by making sure libcurl always sets the size of the _entire_ upload if an app attemps to do resumed uploads since libcurl simply cannot know the size of what is currently at the server end. Test 1041 is no longer disabled. --- lib/http.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0da7156e3..195d661d6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2363,7 +2363,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); - if(data->state.resume_from) { + if(data->set.set_resume_from < 0) { + /* Upload resume was asked for, but we don't know the size of the + remote part so we tell the server (and act accordingly) that we + upload the whole file (again) */ + conn->allocptr.rangeline = + aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T + "/%" FORMAT_OFF_T "\r\n", + data->set.infilesize - 1, data->set.infilesize); + + } + else if(data->state.resume_from) { /* This is because "resume" was selected */ curl_off_t total_expected_size= data->state.resume_from + data->set.infilesize; -- cgit v1.2.1 From 3a499099af52ddc69a3647767521c99c9e9c42e4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Aug 2008 22:00:22 +0000 Subject: - Test cases 1051, 1052 and 1055 were added by Daniel Fandrich on July 30 and proved how PUT and POST with a redirect could lead to a "hang" due to the data stream not being rewound properly when it had to in order to get sent properly (again) to the subsequent URL. This is now fixed and these test cases are no longer disabled. --- lib/http.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 195d661d6..173de8edc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -309,7 +309,7 @@ static bool pickoneauth(struct auth *pick) } /* - * perhapsrewind() + * Curl_http_perhapsrewind() * * If we are doing POST or PUT { * If we have more data to send { @@ -331,18 +331,29 @@ static bool pickoneauth(struct auth *pick) * } * } */ -static CURLcode perhapsrewind(struct connectdata *conn) +CURLcode Curl_http_perhapsrewind(struct connectdata *conn) { struct SessionHandle *data = conn->data; struct HTTP *http = data->state.proto.http; curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ - if(!http) + if(!http || !(conn->protocol & PROT_HTTP)) /* If this is still NULL, we have not reach very far and we can - safely skip this rewinding stuff */ + safely skip this rewinding stuff, or this is attempted to get used + when HTTP isn't activated */ return CURLE_OK; + infof(data, "now in %s\n", __func__); + + switch(data->set.httpreq) { + case HTTPREQ_GET: + case HTTPREQ_HEAD: + return CURLE_OK; + default: + break; + } + bytessent = http->writebytecount; if(conn->bits.authneg) @@ -453,7 +464,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD) && !conn->bits.rewindaftersend) { - code = perhapsrewind(conn); + code = Curl_http_perhapsrewind(conn); if(code) return code; } -- cgit v1.2.1 From ed50e3f1b4bfafa9f0cb16626f6edd93e06cd14c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Aug 2008 22:07:50 +0000 Subject: - Yehoshua Hershberg found a problem that would make libcurl re-use a connection with the multi interface even if a previous use of it caused a CURLE_PEER_FAILED_VERIFICATION to get returned. I now make sure that failed SSL connections properly close the connections. --- lib/http.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 173de8edc..a2a5cd1f5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1815,8 +1815,11 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); - if(result) + if(result) { + conn->bits.close = TRUE; /* a failed connection is marked for closure + to prevent (bad) re-use or similar */ return result; + } return CURLE_OK; } -- cgit v1.2.1 From b0685b357607772084b05eab988fea0b6d319fc9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 6 Aug 2008 09:54:34 +0000 Subject: remove debug code I accidentally left in here --- lib/http.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a2a5cd1f5..fdaf6f82f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -344,8 +344,6 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) when HTTP isn't activated */ return CURLE_OK; - infof(data, "now in %s\n", __func__); - switch(data->set.httpreq) { case HTTPREQ_GET: case HTTPREQ_HEAD: -- cgit v1.2.1 From 7eab7fa3534c9ba82b45752e3726a7f1a4645e0d Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 12 Aug 2008 20:07:52 +0000 Subject: Fixed a buffer overflow problem in Curl_proxyCONNECT that could occur when a server responded with long headers and data. Luckily, the buffer overflowed into another unused buffer, so no actual harm was done. Added test cases 1060 and 1061 to verify. --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fdaf6f82f..42aa45718 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1474,6 +1474,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, case 0: /* timeout */ break; default: + DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); if(res< 0) /* EWOULDBLOCK */ @@ -1506,6 +1507,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* This means we are currently ignoring a response-body */ nread = 0; /* make next read start over in the read buffer */ + ptr=data->state.buffer; if(cl) { /* A Content-Length based body: simply count down the counter and make sure to break out of the loop when we're done! */ @@ -1565,6 +1567,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* end of response-headers from the proxy */ nread = 0; /* make next read start over in the read buffer */ + ptr=data->state.buffer; if((407 == k->httpcode) && !data->state.authproblem) { /* If we get a 407 response code with content length when we have no auth problem, we must ignore the -- cgit v1.2.1 From 66fb9ca5f6de6eb74c2c3ade7ee651a299247749 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 15 Aug 2008 02:58:15 +0000 Subject: For congruency sake with the naming of other CURL_XXXXXX_CURL_OFF_T macros, the names of the curl_off_t formatting string directives now become CURL_FORMAT_CURL_OFF_T and CURL_FORMAT_CURL_OFF_TU. CURL_FMT_OFF_T -> CURL_FORMAT_CURL_OFF_T CURL_FMT_OFF_TU -> CURL_FORMAT_CURL_OFF_TU Remove the use of an internal name for the curl_off_t formatting string directives and use the common one available from the inside and outside of the library. FORMAT_OFF_T -> CURL_FORMAT_CURL_OFF_T FORMAT_OFF_TU -> CURL_FORMAT_CURL_OFF_TU --- lib/http.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 42aa45718..20d0e388a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -398,7 +398,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) /* this is already marked to get closed */ return CURLE_OK; - infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T + infof(data, "NTLM send, close instead of sending %" CURL_FORMAT_CURL_OFF_T " bytes\n", (curl_off_t)(expectsend - bytessent)); } @@ -1576,7 +1576,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(cl) { - infof(data, "Ignore %" FORMAT_OFF_T + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T " bytes of response-body\n", cl); /* remove the remaining chunk of what we already read */ @@ -2337,7 +2337,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read %" FORMAT_OFF_T + failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T " bytes from the input", passed); return CURLE_READ_ERROR; @@ -2383,8 +2383,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) remote part so we tell the server (and act accordingly) that we upload the whole file (again) */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T - "/%" FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", data->set.infilesize - 1, data->set.infilesize); } @@ -2393,8 +2393,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t total_expected_size= data->state.resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%" FORMAT_OFF_T - "/%" FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T + "/%" CURL_FORMAT_CURL_OFF_T "\r\n", data->state.range, total_expected_size-1, total_expected_size); } @@ -2402,7 +2402,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", + aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", data->state.range, data->set.infilesize); } if(!conn->allocptr.rangeline) @@ -2629,7 +2629,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", http->postsize); if(result) return result; @@ -2701,7 +2701,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if((postsize != -1) && !data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", postsize ); if(result) return result; @@ -2753,7 +2753,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we allow replacing this header, although it isn't very wise to actually set your own */ result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", postsize); if(result) return result; -- cgit v1.2.1 From ad638da2c29a61babb50fdced0333393416a199a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 16 Aug 2008 01:33:59 +0000 Subject: Library internal only C preprocessor macros FORMAT_OFF_T and FORMAT_OFF_TU remain in use as internal curl_off_t print formatting strings for the internal *printf functions which still cannot handle print formatting string directives such as "I64d", "I64u", and others available on MSVC, MinGW, Intel's ICC, and other DOS/Windows compilers. This reverts previous commit part which did: FORMAT_OFF_T -> CURL_FORMAT_CURL_OFF_T FORMAT_OFF_TU -> CURL_FORMAT_CURL_OFF_TU --- lib/http.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 20d0e388a..42aa45718 100644 --- a/lib/http.c +++ b/lib/http.c @@ -398,7 +398,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) /* this is already marked to get closed */ return CURLE_OK; - infof(data, "NTLM send, close instead of sending %" CURL_FORMAT_CURL_OFF_T + infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T " bytes\n", (curl_off_t)(expectsend - bytessent)); } @@ -1576,7 +1576,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(cl) { - infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + infof(data, "Ignore %" FORMAT_OFF_T " bytes of response-body\n", cl); /* remove the remaining chunk of what we already read */ @@ -2337,7 +2337,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) passed += actuallyread; if(actuallyread != readthisamountnow) { - failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T + failf(data, "Could only read %" FORMAT_OFF_T " bytes from the input", passed); return CURLE_READ_ERROR; @@ -2383,8 +2383,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) remote part so we tell the server (and act accordingly) that we upload the whole file (again) */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T + "/%" FORMAT_OFF_T "\r\n", data->set.infilesize - 1, data->set.infilesize); } @@ -2393,8 +2393,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t total_expected_size= data->state.resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T "\r\n", + aprintf("Content-Range: bytes %s%" FORMAT_OFF_T + "/%" FORMAT_OFF_T "\r\n", data->state.range, total_expected_size-1, total_expected_size); } @@ -2402,7 +2402,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", + aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", data->state.range, data->set.infilesize); } if(!conn->allocptr.rangeline) @@ -2629,7 +2629,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, - "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + "Content-Length: %" FORMAT_OFF_T "\r\n", http->postsize); if(result) return result; @@ -2701,7 +2701,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if((postsize != -1) && !data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ result = add_bufferf(req_buffer, - "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + "Content-Length: %" FORMAT_OFF_T "\r\n", postsize ); if(result) return result; @@ -2753,7 +2753,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we allow replacing this header, although it isn't very wise to actually set your own */ result = add_bufferf(req_buffer, - "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", + "Content-Length: %" FORMAT_OFF_T"\r\n", postsize); if(result) return result; -- cgit v1.2.1 From ac18b471d253f8d5c69d1044a59753f32bcd663f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 17 Aug 2008 00:25:38 +0000 Subject: libcurl internal base64.h header file renamed to curl_base64.h --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 42aa45718..fde46dd0e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -81,7 +81,7 @@ #include "easyif.h" /* for Curl_convert_... prototypes */ #include "formdata.h" #include "progress.h" -#include "base64.h" +#include "curl_base64.h" #include "cookie.h" #include "strequal.h" #include "sslgen.h" -- cgit v1.2.1 From 934708d950617688c7d294ea1ab583667f383ab1 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 2 Sep 2008 17:41:20 +0000 Subject: Made some variables const which eliminated some casts --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fde46dd0e..ab25573bf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1337,7 +1337,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } /* Setup the proxy-authorization header, if any */ - result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); + result = http_output_auth(conn, "CONNECT", host_port, TRUE); if(CURLE_OK == result) { char *host=(char *)""; @@ -2027,7 +2027,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ char *ptr; - char *request; + const char *request; Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; curl_off_t included_body = 0; @@ -2066,23 +2066,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) request = data->set.str[STRING_CUSTOMREQUEST]; else { if(data->set.opt_no_body) - request = (char *)"HEAD"; + request = "HEAD"; else { DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); switch(httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: - request = (char *)"POST"; + request = "POST"; break; case HTTPREQ_PUT: - request = (char *)"PUT"; + request = "PUT"; break; default: /* this should never happen */ case HTTPREQ_GET: - request = (char *)"GET"; + request = "GET"; break; case HTTPREQ_HEAD: - request = (char *)"HEAD"; + request = "HEAD"; break; } } -- cgit v1.2.1 From 91ff93803512e3438ce165b23bb5b9fb404df288 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 5 Sep 2008 17:58:53 +0000 Subject: Improved the logic the decides whether to use HTTP 1.1 features or not in a request. Detect cases where an upload must be sent chunked and the server supports only HTTP 1.0 and return CURLE_UPLOAD_FAILED. --- lib/http.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ab25573bf..77a99cc6a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1950,15 +1950,30 @@ CURLcode Curl_http_done(struct connectdata *conn, return CURLE_OK; } + +/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it +are if the user specifically requested HTTP 1.0, if the server we are +connected to only supports 1.0, or if any server previously contacted to +handle this request only supports 1.0. */ +static bool use_http_1_1(const struct SessionHandle *data, + const struct connectdata *conn) +{ + return (data->set.httpversion == CURL_HTTP_VERSION_1_1) || + ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && + ((conn->httpversion == 11) || + ((conn->httpversion != 10) && + (data->state.httpversion != 10)))); +} + /* check and possibly add an Expect: header */ static CURLcode expect100(struct SessionHandle *data, + struct connectdata *conn, send_buffer *req_buffer) { CURLcode result = CURLE_OK; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - !checkheaders(data, "Expect:")) { + if(use_http_1_1(data, conn) && !checkheaders(data, "Expect:")) { /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web @@ -2139,10 +2154,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else { if((conn->protocol&PROT_HTTP) && data->set.upload && - (data->set.infilesize == -1) && - (data->set.httpversion != CURL_HTTP_VERSION_1_0)) { - /* HTTP, upload, unknown file size and not HTTP 1.0 */ - data->req.upload_chunky = TRUE; + (data->set.infilesize == -1)) { + if (use_http_1_1(data, conn)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } else { + failf(data, "Chunky upload is not supported by HTTP 1.0"); + return CURLE_UPLOAD_FAILED; + } } else { /* else, no chunky upload */ @@ -2410,8 +2429,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - /* Use 1.1 unless the use specificly asked for 1.0 */ - httpstring= data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1"; + /* Use 1.1 unless the user specifically asked for 1.0 or the server only + supports 1.0 */ + httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; /* initialize a dynamic send-buffer */ req_buffer = add_buffer_init(); @@ -2635,7 +2655,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - result = expect100(data, req_buffer); + result = expect100(data, conn, req_buffer); if(result) return result; @@ -2707,7 +2727,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - result = expect100(data, req_buffer); + result = expect100(data, conn, req_buffer); if(result) return result; @@ -2772,7 +2792,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) sure that the expect100header is always set to the preferred value here. */ if(postsize > TINY_INITIAL_POST_SIZE) { - result = expect100(data, req_buffer); + result = expect100(data, conn, req_buffer); if(result) return result; } -- cgit v1.2.1 From 861b647e7b1da564b831a5b07312a30feb7b6c58 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 6 Sep 2008 04:28:43 +0000 Subject: remove unnecessary typecasting of realloc() --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 77a99cc6a..3b05184ad 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1190,7 +1190,7 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) if(in->buffer) /* we have a buffer, enlarge the existing one */ - new_rb = (char *)realloc(in->buffer, new_size); + new_rb = realloc(in->buffer, new_size); else /* create a new buffer */ new_rb = (char *)malloc(new_size); -- cgit v1.2.1 From a622fd90b4c563a4fced20c5b88cb57537e809b0 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 6 Sep 2008 04:47:14 +0000 Subject: remove unnecessary typecasting of calloc() --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3b05184ad..6b22c2c10 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2063,7 +2063,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->state.proto.http) { /* Only allocate this struct if we don't already have it! */ - http = (struct HTTP *)calloc(sizeof(struct HTTP), 1); + http = calloc(sizeof(struct HTTP), 1); if(!http) return CURLE_OUT_OF_MEMORY; data->state.proto.http = http; -- cgit v1.2.1 From 59e378f48fed849e8e41f0bc6a10bf7a1732ae8a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 6 Sep 2008 05:29:05 +0000 Subject: remove unnecessary typecasting of malloc() --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6b22c2c10..e223c1f92 100644 --- a/lib/http.c +++ b/lib/http.c @@ -971,7 +971,7 @@ static send_buffer *add_buffer_init(void) { send_buffer *blonk; - blonk=(send_buffer *)malloc(sizeof(send_buffer)); + blonk = malloc(sizeof(send_buffer)); if(blonk) { memset(blonk, 0, sizeof(send_buffer)); return blonk; @@ -1193,7 +1193,7 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) new_rb = realloc(in->buffer, new_size); else /* create a new buffer */ - new_rb = (char *)malloc(new_size); + new_rb = malloc(new_size); if(!new_rb) { /* If we failed, we cleanup the whole buffer and return error */ -- cgit v1.2.1 From 2ef72f7abb0f955d08a7f26d1a65a21be26b1af9 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 8 Sep 2008 19:34:58 +0000 Subject: fix compiler warning --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e223c1f92..b57d9b592 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1958,11 +1958,11 @@ handle this request only supports 1.0. */ static bool use_http_1_1(const struct SessionHandle *data, const struct connectdata *conn) { - return (data->set.httpversion == CURL_HTTP_VERSION_1_1) || + return (bool)((data->set.httpversion == CURL_HTTP_VERSION_1_1) || ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && ((conn->httpversion == 11) || ((conn->httpversion != 10) && - (data->state.httpversion != 10)))); + (data->state.httpversion != 10))))); } /* check and possibly add an Expect: header */ -- cgit v1.2.1 From c4a694862c69f2b63c6b775cd6fdf1a7afcc0a52 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 22 Sep 2008 20:42:13 +0000 Subject: - Michael Goffioul filed bug report #2107377 "Problem with mutli + GnuTLS + proxy" (http://curl.haxx.se/bug/view.cgi?id=2107377) that showed how a multi interface using program didn't work when built with GnuTLS and a CONNECT request was done over a proxy (basically test 502 over a proxy to a HTTPS site). It turned out the ssl connect function would get called twice which caused the second call to fail. --- lib/http.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b57d9b592..b60345b08 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1814,6 +1814,13 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) CURLcode result; DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); + if(conn->ssl[FIRSTSOCKET].use) { + /* in some circumstances, this already has SSL enabled and then we don't + need to connect SSL again */ + *done = TRUE; + return CURLE_OK; + } + /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); if(result) { -- cgit v1.2.1 From 426ec2d3994886fc5c439af477858acc8969147e Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 26 Sep 2008 19:55:12 +0000 Subject: Fixed a few comment typos --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b60345b08..65a42bb2e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -290,7 +290,7 @@ static bool pickoneauth(struct auth *pick) picked = TRUE; /* The order of these checks is highly relevant, as this will be the order - of preference in case of the existance of multiple accepted types. */ + of preference in case of the existence of multiple accepted types. */ if(avail & CURLAUTH_GSSNEGOTIATE) pick->picked = CURLAUTH_GSSNEGOTIATE; else if(avail & CURLAUTH_DIGEST) @@ -419,9 +419,9 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) } /* - * Curl_http_auth_act() gets called when a all HTTP headers have been received + * Curl_http_auth_act() gets called when all HTTP headers have been received * and it checks what authentication methods that are available and decides - * which one (if any) to use. It will set 'newurl' if an auth metod was + * which one (if any) to use. It will set 'newurl' if an auth method was * picked. */ @@ -791,7 +791,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, authp->avail |= CURLAUTH_BASIC; if(authp->picked == CURLAUTH_BASIC) { /* We asked for Basic authentication but got a 40X back - anyway, which basicly means our name+password isn't + anyway, which basically means our name+password isn't valid. */ authp->avail = CURLAUTH_NONE; infof(data, "Authentication problem. Ignoring this.\n"); -- cgit v1.2.1 From 8f467b4288b69e0cd2355cdb8d4dd8356950e447 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 29 Sep 2008 21:44:50 +0000 Subject: Removed unneeded includes of signal.h and setjmp.h --- lib/http.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 65a42bb2e..86006a824 100644 --- a/lib/http.c +++ b/lib/http.c @@ -66,7 +66,6 @@ #ifdef HAVE_SYS_IOCTL_H #include #endif -#include #ifdef HAVE_SYS_PARAM_H #include -- cgit v1.2.1 From 88513d2d1ad60767b2d4e41a0e3a7b42894ff973 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 1 Oct 2008 17:34:24 +0000 Subject: Fixed some compiler warnings with gcc --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 86006a824..c52b1038f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -591,6 +591,9 @@ http_output_auth(struct connectdata *conn, if(result) return result; } +#else + (void)request; + (void)path; #endif if(auth) { infof(data, "Proxy auth using %s with user '%s'\n", -- cgit v1.2.1 From 95456b8e78d3dcee0c1d79760bcb2dfcb0d7db09 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 8 Oct 2008 01:17:51 +0000 Subject: Added const to some pointer variables --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c52b1038f..9535c7633 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2046,11 +2046,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; - char *ppath = data->state.path; + const char *ppath = data->state.path; char ftp_typecode[sizeof(";type=?")] = ""; - char *host = conn->host.name; + const char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ - char *ptr; + const char *ptr; const char *request; Curl_HttpReq httpreq = data->set.httpreq; char *addcookies = NULL; -- cgit v1.2.1 From a579d6706436615845f57692921e0891fb6e3719 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Oct 2008 21:43:48 +0000 Subject: - Pascal Terjan filed bug #2154627 (http://curl.haxx.se/bug/view.cgi?id=2154627) which pointed out that libcurl uses strcasecmp() in multiple places where it causes failures when the Turkish locale is used. This is because 'i' and 'I' isn't the same letter so strcasecmp() on those letters are different in Turkish than in English (or just about all other languages). I thus introduced a totally new internal function in libcurl (called Curl_ascii_equal) for doing case insentive comparisons for english-(ascii?) style strings that thus will make "file" and "FILE" match even if the Turkish locale is selected. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9535c7633..da7972459 100644 --- a/lib/http.c +++ b/lib/http.c @@ -613,7 +613,7 @@ http_output_auth(struct connectdata *conn, if(!data->state.this_is_a_follow || conn->bits.netrc || !data->state.first_host || - curl_strequal(data->state.first_host, conn->host.name) || + Curl_ascii_equal(data->state.first_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { /* Send web authentication header if needed */ @@ -2185,7 +2185,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ptr = checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || - curl_strequal(data->state.first_host, conn->host.name))) { + Curl_ascii_equal(data->state.first_host, conn->host.name))) { #if !defined(CURL_DISABLE_COOKIES) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the -- cgit v1.2.1 From 9d16b4081ed011c11f9876ae2685076e92113593 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Oct 2008 08:23:48 +0000 Subject: Renamed Curl_ascii_equal to Curl_raw_equal and bugfixed the my_toupper function used in strequal.c so now all test cases run fine for me again. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index da7972459..95ba8d0db 100644 --- a/lib/http.c +++ b/lib/http.c @@ -613,7 +613,7 @@ http_output_auth(struct connectdata *conn, if(!data->state.this_is_a_follow || conn->bits.netrc || !data->state.first_host || - Curl_ascii_equal(data->state.first_host, conn->host.name) || + Curl_raw_equal(data->state.first_host, conn->host.name) || data->set.http_disable_hostname_check_before_authentication) { /* Send web authentication header if needed */ @@ -2185,7 +2185,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ptr = checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || - Curl_ascii_equal(data->state.first_host, conn->host.name))) { + Curl_raw_equal(data->state.first_host, conn->host.name))) { #if !defined(CURL_DISABLE_COOKIES) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the -- cgit v1.2.1 From 4acbe8f20c45ed43768ff4d25ec6718c2f1dd6dd Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 17 Oct 2008 12:53:53 +0000 Subject: fix compiler warning --- lib/http.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 95ba8d0db..dd12e964a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -203,10 +203,9 @@ char *Curl_copy_header_value(const char *h) ++h; /* Find the first non-space letter */ - for(start=h; - *start && ISSPACE(*start); - start++) - ; /* empty loop */ + start = h; + while(*start && ISSPACE(*start)) + start++; /* data is in the host encoding so use '\r' and '\n' instead of 0x0d and 0x0a */ @@ -215,10 +214,12 @@ char *Curl_copy_header_value(const char *h) end = strchr(start, '\n'); if(!end) end = strchr(start, '\0'); + if(!end) + return NULL; /* skip all trailing space letters */ - for(; ISSPACE(*end) && (end > start); end--) - ; /* empty loop */ + while((end > start) && ISSPACE(*end)) + end--; /* get length of the type */ len = end-start+1; -- cgit v1.2.1 From 4198bb88b64383509a7267411282e20cd867d3e0 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 21 Oct 2008 23:15:19 +0000 Subject: Compile away some more code in the CURL_DISABLE_PROXY case. --- lib/http.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dd12e964a..89ddaca98 100644 --- a/lib/http.c +++ b/lib/http.c @@ -545,6 +545,7 @@ http_output_auth(struct connectdata *conn, and if this is one single bit it'll be used instantly. */ authproxy->picked = authproxy->want; +#ifndef CURL_DISABLE_PROXY /* Send proxy authentication header if needed */ if(conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { @@ -605,6 +606,7 @@ http_output_auth(struct connectdata *conn, authproxy->multi = FALSE; } else +#endif /* CURL_DISABLE_PROXY */ /* we have no proxy so let's pretend we're done authenticating with it */ authproxy->done = TRUE; @@ -1273,6 +1275,7 @@ Curl_compareheader(const char *headerline, /* line to check */ return FALSE; /* no match */ } +#ifndef CURL_DISABLE_PROXY /* * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This * function will issue the necessary commands to get a seamless tunnel through @@ -1729,6 +1732,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ return CURLE_OK; } +#endif /* CURL_DISABLE_PROXY */ /* * Curl_http_connect() performs HTTP stuff to do at connect-time, called from @@ -1745,12 +1749,12 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) function to make the re-use checks properly be able to check this bit. */ conn->bits.close = FALSE; +#ifndef CURL_DISABLE_PROXY /* If we are not using a proxy and we want a secure connection, perform SSL * initialization & connection now. If using a proxy with https, then we * must tell the proxy to CONNECT to the host we want to talk to. Only * after the connect has occurred, can we start talking SSL */ - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* either SSL over proxy, or explicitly asked for */ @@ -1765,6 +1769,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; } +#endif /* CURL_DISABLE_PROXY */ if(!data->state.this_is_a_follow) { /* this is not a followed location, get the original host name */ @@ -2234,6 +2239,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } +#ifndef CURL_DISABLE_PROXY if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { /* Using a proxy but does not tunnel through it */ @@ -2295,6 +2301,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } } +#endif /* CURL_DISABLE_PROXY */ + if(HTTPREQ_POST_FORM == httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ -- cgit v1.2.1 From d22b2d181f4409846161d858d9563a8d2178f51d Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 22 Oct 2008 17:36:48 +0000 Subject: Fixed a compiler warning with --disable-proxy --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 89ddaca98..b1b70ce4e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -606,6 +606,10 @@ http_output_auth(struct connectdata *conn, authproxy->multi = FALSE; } else +#else + (void)request; + (void)path; + (void)proxytunnel; #endif /* CURL_DISABLE_PROXY */ /* we have no proxy so let's pretend we're done authenticating with it */ -- cgit v1.2.1 From bab5183820dbd2e0ea9ee4f0442844291d05c90e Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 23 Oct 2008 01:20:57 +0000 Subject: Created Curl_raw_nequal() which does a C-locale string case comparison. Changed checkprefix() to use it and those instances of strnequal() that compare host names or other protocol strings that are defined to be independent of case in the C locale. This should fix a few more Turkish locale problems. --- lib/http.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b1b70ce4e..503ceb0c1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -173,7 +173,7 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) size_t thislen = strlen(thisheader); for(head = data->set.headers; head; head=head->next) { - if(strnequal(head->data, thisheader, thislen)) + if(Curl_raw_nequal(head->data, thisheader, thislen)) return head->data; } return NULL; @@ -1246,7 +1246,7 @@ Curl_compareheader(const char *headerline, /* line to check */ const char *start; const char *end; - if(!strnequal(headerline, header, hlen)) + if(!Curl_raw_nequal(headerline, header, hlen)) return FALSE; /* doesn't start with header */ /* pass the header */ @@ -1272,7 +1272,7 @@ Curl_compareheader(const char *headerline, /* line to check */ /* find the content string in the rest of the line */ for(;len>=clen;len--, start++) { - if(strnequal(start, content, clen)) + if(Curl_raw_nequal(start, content, clen)) return TRUE; /* match! */ } @@ -2026,12 +2026,11 @@ static CURLcode add_custom_headers(struct connectdata *conn, if(conn->allocptr.host && /* a Host: header was sent already, don't pass on any custom Host: header as that will produce *two* in the same request! */ - curl_strnequal("Host:", headers->data, 5)) + checkprefix("Host:", headers->data)) ; else if(conn->data->set.httpreq == HTTPREQ_POST_FORM && /* this header (extended by formdata.c) is sent later */ - curl_strnequal("Content-Type:", headers->data, - strlen("Content-Type:"))) + checkprefix("Content-Type:", headers->data)) ; else { CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data); -- cgit v1.2.1 From b701ea36a723b2d7700e23ae53e2c3145dfe7bda Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 23 Oct 2008 11:49:19 +0000 Subject: moved the Curl_raw_ functions into the new lib/rawstr.c file for easier curlx_ inclusion by the curl tool without colliding with the curl_strequal functions. --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 503ceb0c1..068748c3c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -96,6 +96,7 @@ #include "parsedate.h" /* for the week day and month names */ #include "strtoofft.h" #include "multiif.h" +#include "rawstr.h" #define _MPRINTF_REPLACE /* use our functions only */ #include -- cgit v1.2.1 From 6ea91af2f8f787f16b1bde88ae2293adcc961986 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 24 Oct 2008 01:27:00 +0000 Subject: fix compiler warning --- lib/http.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 068748c3c..b6609c818 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1836,13 +1836,10 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); - if(result) { + if(result) conn->bits.close = TRUE; /* a failed connection is marked for closure to prevent (bad) re-use or similar */ - return result; - } - - return CURLE_OK; + return result; } #ifdef USE_SSLEAY -- cgit v1.2.1 From f0bb9c7d8dcce50ea5ee544b8c5ad1743e07b6e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 28 Oct 2008 23:34:19 +0000 Subject: added an extra set of braces to unconfuse emacs and then I re-indented a section of the code that was odd-looking previously --- lib/http.c | 216 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 108 insertions(+), 108 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b6609c818..8869a5daf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2777,133 +2777,133 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->bits.authneg) postsize = 0; - else + else { /* figure out the size of the postfields */ postsize = (data->set.postfieldsize != -1)? data->set.postfieldsize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + } + if(!data->req.upload_chunky) { + /* We only set Content-Length and allow a custom Content-Length if + we don't upload data chunked, as RFC2616 forbids us to set both + kinds of headers (Transfer-Encoding: chunked and Content-Length) */ + + if(!checkheaders(data, "Content-Length:")) { + /* we allow replacing this header, although it isn't very wise to + actually set your own */ + result = add_bufferf(req_buffer, + "Content-Length: %" FORMAT_OFF_T"\r\n", + postsize); + if(result) + return result; + } + } - if(!data->req.upload_chunky) { - /* We only set Content-Length and allow a custom Content-Length if - we don't upload data chunked, as RFC2616 forbids us to set both - kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - - if(!checkheaders(data, "Content-Length:")) { - /* we allow replacing this header, although it isn't very wise to - actually set your own */ - result = add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", - postsize); - if(result) - return result; - } - } - - if(!checkheaders(data, "Content-Type:")) { - result = add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); - if(result) - return result; - } + if(!checkheaders(data, "Content-Type:")) { + result = add_bufferf(req_buffer, + "Content-Type: application/x-www-form-urlencoded\r\n"); + if(result) + return result; + } - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - if(postsize > TINY_INITIAL_POST_SIZE) { - result = expect100(data, conn, req_buffer); - if(result) - return result; - } - else - data->state.expect100header = FALSE; + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + if(postsize > TINY_INITIAL_POST_SIZE) { + result = expect100(data, conn, req_buffer); + if(result) + return result; + } + else + data->state.expect100header = FALSE; - if(data->set.postfields) { + if(data->set.postfields) { - if(!data->state.expect100header && - (postsize < MAX_INITIAL_POST_SIZE)) { - /* if we don't use expect: 100 AND - postsize is less than MAX_INITIAL_POST_SIZE + if(!data->state.expect100header && + (postsize < MAX_INITIAL_POST_SIZE)) { + /* if we don't use expect: 100 AND + postsize is less than MAX_INITIAL_POST_SIZE - then append the post data to the HTTP request header. This limit - is no magic limit but only set to prevent really huge POSTs to - get the data duplicated with malloc() and family. */ + then append the post data to the HTTP request header. This limit + is no magic limit but only set to prevent really huge POSTs to + get the data duplicated with malloc() and family. */ - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; - if(!data->req.upload_chunky) { - /* We're not sending it 'chunked', append it to the request - already now to reduce the number if send() calls */ - result = add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - included_body = postsize; - } - else { - /* Append the POST data chunky-style */ - result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); - if(CURLE_OK == result) - result = add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - if(CURLE_OK == result) - result = add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ - included_body = postsize + 7; - } - if(result) - return result; - } - else { - /* A huge POST coming up, do data separate from the request */ - http->postsize = postsize; - http->postdata = data->set.postfields; + if(!data->req.upload_chunky) { + /* We're not sending it 'chunked', append it to the request + already now to reduce the number if send() calls */ + result = add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + included_body = postsize; + } + else { + /* Append the POST data chunky-style */ + result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + if(CURLE_OK == result) + result = add_buffer(req_buffer, + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + /* CR LF 0 CR LF CR LF */ + included_body = postsize + 7; + } + if(result) + return result; + } + else { + /* A huge POST coming up, do data separate from the request */ + http->postsize = postsize; + http->postdata = data->set.postfields; - http->sending = HTTPSEND_BODY; + http->sending = HTTPSEND_BODY; - conn->fread_func = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; + conn->fread_func = (curl_read_callback)readmoredata; + conn->fread_in = (void *)conn; - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; - } - } - else { - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; + } + } + else { + result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(result) + return result; - if(data->set.postfieldsize) { - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize?postsize:-1); + if(data->set.postfieldsize) { + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, postsize?postsize:-1); - /* set the pointer to mark that we will send the post body using the - read callback, but only if we're not in authenticate - negotiation */ - if(!conn->bits.authneg) { - http->postdata = (char *)&http->postdata; - http->postsize = postsize; - } - } + /* set the pointer to mark that we will send the post body using the + read callback, but only if we're not in authenticate + negotiation */ + if(!conn->bits.authneg) { + http->postdata = (char *)&http->postdata; + http->postsize = postsize; } - /* issue the request */ - result = add_buffer_send(req_buffer, conn, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); + } + } + /* issue the request */ + result = add_buffer_send(req_buffer, conn, &data->info.request_size, + (size_t)included_body, FIRSTSOCKET); - if(result) - failf(data, "Failed sending HTTP POST request"); - else - result = - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); - break; + if(result) + failf(data, "Failed sending HTTP POST request"); + else + result = + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); + break; default: result = add_buffer(req_buffer, "\r\n", 2); -- cgit v1.2.1 From 5e3c2af2361fbf0b3f1641945b77fc93fedfec38 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 6 Nov 2008 00:01:13 +0000 Subject: Factored out some common code into a new function output_auth_headers --- lib/http.c | 213 ++++++++++++++++++++++++++----------------------------------- 1 file changed, 92 insertions(+), 121 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8869a5daf..370e07a66 100644 --- a/lib/http.c +++ b/lib/http.c @@ -246,8 +246,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) char *authorization; struct SessionHandle *data=conn->data; char **userp; - char *user; - char *pwd; + const char *user; + const char *pwd; if(proxy) { userp = &conn->allocptr.proxyuserpwd; @@ -493,6 +493,89 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) return code; } + +/* + * Output the correct authentication header depending on the auth type + * and whether or not it is to a proxy. + */ +static CURLcode +output_auth_headers(struct connectdata *conn, + struct auth *authstatus, + const char *request, + const char *path, + bool proxy) +{ + struct SessionHandle *data = conn->data; + const char *auth=NULL; + CURLcode result = CURLE_OK; + +#ifndef CURL_DISABLE_CRYPTO_AUTH + (void)request; + (void)path; +#endif + +#ifdef HAVE_GSSAPI + if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && + data->state.negotiate.context && + !GSS_ERROR(data->state.negotiate.status)) { + auth="GSS-Negotiate"; + result = Curl_output_negotiate(conn, proxy); + if(result) + return result; + authstatus->done = TRUE; + } + else +#endif +#ifdef USE_NTLM + if(authstatus->picked == CURLAUTH_NTLM) { + auth="NTLM"; + result = Curl_output_ntlm(conn, proxy); + if(result) + return result; + } + else +#endif +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(authstatus->picked == CURLAUTH_DIGEST) { + auth="Digest"; + result = Curl_output_digest(conn, + proxy, + (const unsigned char *)request, + (const unsigned char *)path); + if(result) + return result; + } + else +#endif + if(authstatus->picked == CURLAUTH_BASIC) { + /* Basic */ + if((proxy && conn->bits.proxy_user_passwd && + !checkheaders(data, "Proxy-authorization:")) || + (!proxy && conn->bits.user_passwd && + !checkheaders(data, "Authorization:"))) { + auth="Basic"; + result = http_output_basic(conn, proxy); + if(result) + return result; + } + /* NOTE: this function should set 'done' TRUE, as the other auth + functions work that way */ + authstatus->done = TRUE; + } + + if(auth) { + infof(data, "%s auth using %s with user '%s'\n", + proxy?"Proxy":"Server", auth, + proxy?(conn->proxyuser?conn->proxyuser:""): + (conn->user?conn->user:"")); + authstatus->multi = (bool)(!authstatus->done); + } + else + authstatus->multi = FALSE; + + return CURLE_OK; +} + /** * Curl_http_output_auth() setups the authentication headers for the * host/proxy and the correct authentication @@ -516,7 +599,6 @@ http_output_auth(struct connectdata *conn, { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; - const char *auth=NULL; struct auth *authhost; struct auth *authproxy; @@ -550,66 +632,12 @@ http_output_auth(struct connectdata *conn, /* Send proxy authentication header if needed */ if(conn->bits.httpproxy && (conn->bits.tunnel_proxy == proxytunnel)) { -#ifdef HAVE_GSSAPI - if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { - auth="GSS-Negotiate"; - result = Curl_output_negotiate(conn, TRUE); - if(result) - return result; - authproxy->done = TRUE; - } - else -#endif -#ifdef USE_NTLM - if(authproxy->picked == CURLAUTH_NTLM) { - auth="NTLM"; - result = Curl_output_ntlm(conn, TRUE); - if(result) - return result; - } - else -#endif - if(authproxy->picked == CURLAUTH_BASIC) { - /* Basic */ - if(conn->bits.proxy_user_passwd && - !checkheaders(data, "Proxy-authorization:")) { - auth="Basic"; - result = http_output_basic(conn, TRUE); - if(result) - return result; - } - /* NOTE: http_output_basic() should set 'done' TRUE, as the other auth - functions work that way */ - authproxy->done = TRUE; - } -#ifndef CURL_DISABLE_CRYPTO_AUTH - else if(authproxy->picked == CURLAUTH_DIGEST) { - auth="Digest"; - result = Curl_output_digest(conn, - TRUE, /* proxy */ - (const unsigned char *)request, - (const unsigned char *)path); - if(result) - return result; - } -#else - (void)request; - (void)path; -#endif - if(auth) { - infof(data, "Proxy auth using %s with user '%s'\n", - auth, conn->proxyuser?conn->proxyuser:""); - authproxy->multi = (bool)(!authproxy->done); - } - else - authproxy->multi = FALSE; - } + result = output_auth_headers(conn, authproxy, request, path, TRUE); + if(result) + return result; + } else #else - (void)request; - (void)path; (void)proxytunnel; #endif /* CURL_DISABLE_PROXY */ /* we have no proxy so let's pretend we're done authenticating @@ -621,66 +649,9 @@ http_output_auth(struct connectdata *conn, if(!data->state.this_is_a_follow || conn->bits.netrc || !data->state.first_host || - Curl_raw_equal(data->state.first_host, conn->host.name) || - data->set.http_disable_hostname_check_before_authentication) { - - /* Send web authentication header if needed */ - { - auth = NULL; -#ifdef HAVE_GSSAPI - if((authhost->picked == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { - auth="GSS-Negotiate"; - result = Curl_output_negotiate(conn, FALSE); - if(result) - return result; - authhost->done = TRUE; - } - else -#endif -#ifdef USE_NTLM - if(authhost->picked == CURLAUTH_NTLM) { - auth="NTLM"; - result = Curl_output_ntlm(conn, FALSE); - if(result) - return result; - } - else -#endif - { -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(authhost->picked == CURLAUTH_DIGEST) { - auth="Digest"; - result = Curl_output_digest(conn, - FALSE, /* not a proxy */ - (const unsigned char *)request, - (const unsigned char *)path); - if(result) - return result; - } else -#endif - if(authhost->picked == CURLAUTH_BASIC) { - if(conn->bits.user_passwd && - !checkheaders(data, "Authorization:")) { - auth="Basic"; - result = http_output_basic(conn, FALSE); - if(result) - return result; - } - /* basic is always ready */ - authhost->done = TRUE; - } - } - if(auth) { - infof(data, "Server auth using %s with user '%s'\n", - auth, conn->user); - - authhost->multi = (bool)(!authhost->done); - } - else - authhost->multi = FALSE; - } + data->set.http_disable_hostname_check_before_authentication || + Curl_raw_equal(data->state.first_host, conn->host.name)) { + result = output_auth_headers(conn, authhost, request, path, FALSE); } else authhost->done = TRUE; -- cgit v1.2.1 From 4cbc0f6c2e9557e7aad07abd62e6b836f78134e1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Nov 2008 22:19:27 +0000 Subject: - Rainer Canavan filed bug #2255627 (http://curl.haxx.se/bug/view.cgi?id=2255627) which pointed out that a program using libcurl's multi interface to download a HTTPS page with a libcurl built powered by OpenSSL, would easily get silly and instead hand over SSL details as data instead of the actual HTTP headers and body. This happened because libcurl would consider the connection handshake done too early. This problem was introduced at September 22nd 2008 with my fix of the bug #2107377 The correct fix is now instead done within the GnuTLS-handling code, as both the OpenSSL and the NSS code already deal with this situation in similar fashion. I added test case 560 in an attempt to verify this fix, but unfortunately it didn't trigger it even before this fix! --- lib/http.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 370e07a66..85d99a057 100644 --- a/lib/http.c +++ b/lib/http.c @@ -114,11 +114,13 @@ static int http_getsock_do(struct connectdata *conn, curl_socket_t *socks, int numsocks); -static CURLcode https_connecting(struct connectdata *conn, bool *done); #ifdef USE_SSL +static CURLcode https_connecting(struct connectdata *conn, bool *done); static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks); +#else +#define https_connecting(x,y) CURLE_COULDNT_CONNECT #endif /* @@ -1793,18 +1795,12 @@ static int http_getsock_do(struct connectdata *conn, return GETSOCK_WRITESOCK(0); } +#ifdef USE_SSL static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); - if(conn->ssl[FIRSTSOCKET].use) { - /* in some circumstances, this already has SSL enabled and then we don't - need to connect SSL again */ - *done = TRUE; - return CURLE_OK; - } - /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); if(result) @@ -1812,6 +1808,7 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) to prevent (bad) re-use or similar */ return result; } +#endif #ifdef USE_SSLEAY /* This function is OpenSSL-specific. It should be made to query the generic -- cgit v1.2.1 From 4b3ae5e1575fd40d3ca969fda2f23e46182cf0b8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 19 Nov 2008 14:22:01 +0000 Subject: - Christian Krause reported and fixed a memory leak that would occur with HTTP GSS/kerberos authentication (http://curl.haxx.se/bug/view.cgi?id=2284386) --- lib/http.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 85d99a057..1b20c37e7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -458,6 +458,10 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } if(pickhost || pickproxy) { + /* In case this is GSS auth, the newurl field is already allocated so + we must make sure to free it before allocating a new one. As figured + out in bug #2284386 */ + Curl_safefree(data->req.newurl); data->req.newurl = strdup(data->change.url); /* clone URL */ if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; -- cgit v1.2.1 From 40e8b4e5277c7ad726b50ec904fa573b656184b3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 19 Nov 2008 22:00:14 +0000 Subject: - I removed the default use of "Pragma: no-cache" from libcurl when a proxy is used. It has been used since forever but it was never a good idea to use unless explicitly asked for. --- lib/http.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1b20c37e7..70bf61e39 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2290,11 +2290,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } - http->p_pragma = - (!checkheaders(data, "Pragma:") && - (conn->bits.httpproxy && !conn->bits.tunnel_proxy) )? - "Pragma: no-cache\r\n":NULL; - http->p_accept = checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; if(( (HTTPREQ_POST == httpreq) || @@ -2440,7 +2435,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) "%s" /* range */ "%s" /* user agent */ "%s" /* host */ - "%s" /* pragma */ "%s" /* accept */ "%s" /* accept-encoding */ "%s" /* referer */ @@ -2460,7 +2454,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? conn->allocptr.uagent:"", (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ - http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", (data->set.str[STRING_ENCODING] && *data->set.str[STRING_ENCODING] && -- cgit v1.2.1 From 42365aa7ef58f0a466f2e4ee42718c358b5a9937 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 8 Dec 2008 13:52:20 +0000 Subject: - Christian Krause filed bug #2221237 (http://curl.haxx.se/bug/view.cgi?id=2221237) that identified an infinite loop during GSS authentication given some specific conditions. With his patience and great feedback I managed to narrow down the problem and eventually fix it although I can't test any of this myself! --- lib/http.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 70bf61e39..f7b3610c6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -507,8 +507,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) static CURLcode output_auth_headers(struct connectdata *conn, struct auth *authstatus, - const char *request, - const char *path, + const char *request, + const char *path, bool proxy) { struct SessionHandle *data = conn->data; @@ -529,6 +529,7 @@ output_auth_headers(struct connectdata *conn, if(result) return result; authstatus->done = TRUE; + data->state.negotiate.state = GSS_AUTHSENT; } else #endif @@ -545,9 +546,9 @@ output_auth_headers(struct connectdata *conn, if(authstatus->picked == CURLAUTH_DIGEST) { auth="Digest"; result = Curl_output_digest(conn, - proxy, - (const unsigned char *)request, - (const unsigned char *)path); + proxy, + (const unsigned char *)request, + (const unsigned char *)path); if(result) return result; } @@ -562,7 +563,7 @@ output_auth_headers(struct connectdata *conn, auth="Basic"; result = http_output_basic(conn, proxy); if(result) - return result; + return result; } /* NOTE: this function should set 'done' TRUE, as the other auth functions work that way */ @@ -571,9 +572,9 @@ output_auth_headers(struct connectdata *conn, if(auth) { infof(data, "%s auth using %s with user '%s'\n", - proxy?"Proxy":"Server", auth, - proxy?(conn->proxyuser?conn->proxyuser:""): - (conn->user?conn->user:"")); + proxy?"Proxy":"Server", auth, + proxy?(conn->proxyuser?conn->proxyuser:""): + (conn->user?conn->user:"")); authstatus->multi = (bool)(!authstatus->done); } else @@ -707,24 +708,39 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, * If the provided authentication is wanted as one out of several accepted * types (using &), we OR this authentication type to the authavail * variable. + * + * Note: + * + * ->picked is first set to the 'want' value (one or more bits) before the + * request is sent, and then it is again set _after_ all response 401/407 + * headers have been received but then only to a single preferred method + * (bit). + * */ #ifdef HAVE_GSSAPI if(checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { + int neg; *availp |= CURLAUTH_GSSNEGOTIATE; authp->avail |= CURLAUTH_GSSNEGOTIATE; - if(authp->picked == CURLAUTH_GSSNEGOTIATE) { - /* if exactly this is wanted, go */ - int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); + + if(data->state.negotiate.state == GSS_AUTHSENT) { + /* if we sent GSS authentication in the outgoing request and we get this + back, we're in trouble */ + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + else { + neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); if(neg == 0) { DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->change.url); - data->state.authproblem = (data->req.newurl == NULL); - } - else { - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received GSS auth info and we dealt with it fine */ + data->state.negotiate.state = GSS_AUTHRECV; } } } -- cgit v1.2.1 From 07416b61e3c403ea56370858a618f877dcaee57d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 19 Dec 2008 21:14:52 +0000 Subject: - Using the libssh2 0.19 function libssh2_session_block_directions(), libcurl now has an improved ability to do right when the multi interface (both "regular" and multi_socket) is used for SCP and SFTP transfers. This should result in (much) less busy-loop situations and thus less CPU usage with no speed loss. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f7b3610c6..560d2e9d8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -137,6 +137,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTP, /* defport */ PROT_HTTP, /* protocol */ @@ -157,6 +158,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* doing */ https_getsock, /* proto_getsock */ http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */ -- cgit v1.2.1 From 5be7d88b34873ef6e16ace91ba6d89f4b3203e61 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 20 Dec 2008 22:47:49 +0000 Subject: same procedure, simpler code --- lib/http.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 560d2e9d8..eaa50eeef 100644 --- a/lib/http.c +++ b/lib/http.c @@ -975,13 +975,7 @@ static CURLcode static send_buffer *add_buffer_init(void) { - send_buffer *blonk; - blonk = malloc(sizeof(send_buffer)); - if(blonk) { - memset(blonk, 0, sizeof(send_buffer)); - return blonk; - } - return NULL; /* failed, go home */ + return calloc(sizeof(send_buffer), 1); } /* -- cgit v1.2.1 From 5591550167092c0e5f307b3c2c87f44518e7159f Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 21 Jan 2009 04:42:47 +0000 Subject: Fixed a couple more locale-dependent toupper conversions, mainly for clarity. This does fix one problem that causes ;type=i FTP URLs to fail in the Turkish locale when CURLOPT_PROXY_TRANSFER_MODE is used (test case 561) Added tests 561 and 1092 through 1094 to test various combinations of ;type= and ;mode= URLs that could potentially fail in the Turkish locale. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index eaa50eeef..b96d51d78 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2271,7 +2271,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { char *p = strstr(ppath, ";type="); if(p && p[6] && p[7] == 0) { - switch (toupper((int)((unsigned char)p[6]))) { + switch (Curl_raw_toupper(p[6])) { case 'A': case 'D': case 'I': -- cgit v1.2.1 From bdd4294e79eea15cb6f312f7ee7d388ad40a65e3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Feb 2009 16:19:23 +0000 Subject: - Craig A West brought us: libcurl now defaults to do CONNECT with HTTP version 1.1 instead of 1.0 like before. This change also introduces the new proxy type for libcurl called 'CURLPROXY_HTTP_1_0' that then allows apps to switch (back) to CONNECT 1.0 requests. The curl tool also got a --proxy1.0 option that works exactly like --proxy but sets CURLPROXY_HTTP_1_0. I updated all test cases cases that use CONNECT and I tried to do some using --proxy1.0 and some updated to do CONNECT 1.1 to get both versions run. --- lib/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b96d51d78..dc5066f8a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1343,6 +1343,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, char *host=(char *)""; const char *proxyconn=""; const char *useragent=""; + const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? + "1.0" : "1.1"; if(!checkheaders(data, "Host:")) { host = aprintf("Host: %s\r\n", host_port); @@ -1363,12 +1365,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* BLOCKING */ result = add_bufferf(req_buffer, - "CONNECT %s:%d HTTP/1.0\r\n" + "CONNECT %s:%d HTTP/%s\r\n" "%s" /* Host: */ "%s" /* Proxy-Authorization */ "%s" /* User-Agent */ "%s", /* Proxy-Connection */ - hostname, remote_port, + hostname, remote_port, http, host, conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", -- cgit v1.2.1 From ea6531cf32a7c46d2c919f02c6b650e31a458052 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 24 Feb 2009 08:30:09 +0000 Subject: - Brian J. Murrell found out that Negotiate proxy authentication didn't work. It happened because the code used the struct for server-based auth all the time for both proxy and server auth which of course was wrong. --- lib/http.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dc5066f8a..dfd19dd86 100644 --- a/lib/http.c +++ b/lib/http.c @@ -516,6 +516,10 @@ output_auth_headers(struct connectdata *conn, struct SessionHandle *data = conn->data; const char *auth=NULL; CURLcode result = CURLE_OK; +#ifdef HAVE_GSSAPI + struct negotiatedata *negdata = proxy? + &data->state.proxyneg:&data->state.negotiate; +#endif #ifndef CURL_DISABLE_CRYPTO_AUTH (void)request; @@ -524,14 +528,13 @@ output_auth_headers(struct connectdata *conn, #ifdef HAVE_GSSAPI if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && - data->state.negotiate.context && - !GSS_ERROR(data->state.negotiate.status)) { + negdata->context && !GSS_ERROR(negdata->status)) { auth="GSS-Negotiate"; result = Curl_output_negotiate(conn, proxy); if(result) return result; authstatus->done = TRUE; - data->state.negotiate.state = GSS_AUTHSENT; + negdata->state = GSS_AUTHSENT; } else #endif -- cgit v1.2.1 From 33a3753c3f41d546ebf3350685eb7201d25783f4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 21 Apr 2009 11:46:16 +0000 Subject: libcurl's memory.h renamed to curl_memory.h --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index dfd19dd86..2e3798f65 100644 --- a/lib/http.c +++ b/lib/http.c @@ -91,7 +91,7 @@ #include "share.h" #include "hostip.h" #include "http.h" -#include "memory.h" +#include "curl_memory.h" #include "select.h" #include "parsedate.h" /* for the week day and month names */ #include "strtoofft.h" -- cgit v1.2.1 From e01b7c1ede6f8b91f458259dbed96acce7bf3779 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 28 Apr 2009 11:19:10 +0000 Subject: - Bug report #2709004 (http://curl.haxx.se/bug/view.cgi?id=2709004) by Tim Chen pointed out how curl couldn't upload with resume when reading from a pipe. This ended up with the introduction of a new return code for the CURLOPT_SEEKFUNCTION callback that basically says that the seek failed but that libcurl may try to resolve the situation anyway. In our case this means libcurl will attempt to instead read that much data from the stream instead of seeking and that way curl can now upload with resume when data is read from a stream! --- lib/http.c | 58 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2e3798f65..c6ff5f50f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2054,7 +2054,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) const char *httpstring; send_buffer *req_buffer; curl_off_t postsize; /* off_t type to be able to hold a large file size */ - + int seekerr = CURL_SEEKFUNC_OK; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with @@ -2335,36 +2335,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Now, let's read off the proper amount of bytes from the input. */ if(conn->seek_func) { - curl_off_t readthisamountnow = data->state.resume_from; + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + } - if(conn->seek_func(conn->seek_client, - readthisamountnow, SEEK_SET) != 0) { + if(seekerr != CURL_SEEKFUNC_OK) { + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { failf(data, "Could not seek stream"); return CURLE_READ_ERROR; } - } - else { - curl_off_t passed=0; - - do { - size_t readthisamountnow = (size_t)(data->state.resume_from - passed); - size_t actuallyread; - - if(readthisamountnow > BUFSIZE) - readthisamountnow = BUFSIZE; - - actuallyread = data->set.fread_func(data->state.buffer, 1, - (size_t)readthisamountnow, - data->set.in); - - passed += actuallyread; - if(actuallyread != readthisamountnow) { - failf(data, "Could only read %" FORMAT_OFF_T - " bytes from the input", - passed); - return CURLE_READ_ERROR; - } - } while(passed != data->state.resume_from); /* loop until done */ + /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + else { + curl_off_t passed=0; + + do { + size_t readthisamountnow = (size_t)(data->state.resume_from - + passed); + size_t actuallyread; + + if(readthisamountnow > BUFSIZE) + readthisamountnow = BUFSIZE; + + actuallyread = data->set.fread_func(data->state.buffer, 1, + (size_t)readthisamountnow, + data->set.in); + + passed += actuallyread; + if(actuallyread != readthisamountnow) { + failf(data, "Could only read %" FORMAT_OFF_T + " bytes from the input", + passed); + return CURLE_READ_ERROR; + } + } while(passed != data->state.resume_from); /* loop until done */ + } } /* now, decrease the size of the read */ -- cgit v1.2.1 From 0569c9c1be11590c36799518565eb760eaaca539 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 1 May 2009 13:00:38 +0000 Subject: David McCreedy's "http.c fix to Curl_proxyCONNECT for non-ASCII platforms" patch --- lib/http.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c6ff5f50f..349b81da6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1544,10 +1544,18 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, else for(i = 0; i < gotbytes; ptr++, i++) { perline++; /* amount of bytes in this line so far */ - if(*ptr=='\n') { + if(*ptr=='\x0a') { char letter; int writetype; +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding */ + result = Curl_convert_from_network(data, line_start, perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; +#endif /* CURL_DOES_CONVERSIONS */ + /* output debug if that is requested */ if(data->set.verbose) Curl_debug(data, CURLINFO_HEADER_IN, -- cgit v1.2.1 From a1708730c3b06e33f595c9d76896c1d82231c22b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 5 May 2009 13:04:33 +0000 Subject: fix compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 349b81da6..a31e0f879 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1544,7 +1544,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, else for(i = 0; i < gotbytes; ptr++, i++) { perline++; /* amount of bytes in this line so far */ - if(*ptr=='\x0a') { + if(*ptr == 0x0a) { char letter; int writetype; -- cgit v1.2.1 From 56dab605f1f1010d7a97b29532d294ad5a6a83a9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 May 2009 08:55:58 +0000 Subject: - I fixed the problem with doing NTLM, POST and then following a 302 redirect, as reported by Ebenezer Ikonne (on curl-users) and Laurent Rabret (on curl-library). The transfer was mistakenly marked to get more data to send but since it didn't actually have that, it just hung there... --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a31e0f879..9c020396c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -369,6 +369,8 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) case HTTPREQ_POST: if(data->set.postfieldsize != -1) expectsend = data->set.postfieldsize; + else if(data->set.postfields) + expectsend = (curl_off_t)strlen(data->set.postfields); break; case HTTPREQ_PUT: if(data->set.infilesize != -1) -- cgit v1.2.1 From 242a17b9e0e430ba5933f7b2ae5586233ec35f33 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 May 2009 09:55:28 +0000 Subject: - Balint Szilakszi reported a memory leak when libcurl did gzip decompression of streams that had some parts (legitimately) missing. We now provide and use a proper cleanup function for the content encoding submodule. http://curl.haxx.se/mail/lib-2009-05/0092.html --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9c020396c..a17c6eba9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -97,6 +97,7 @@ #include "strtoofft.h" #include "multiif.h" #include "rawstr.h" +#include "content_encoding.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1917,6 +1918,8 @@ CURLcode Curl_http_done(struct connectdata *conn, struct HTTP *http =data->state.proto.http; (void)premature; /* not used */ + Curl_unencode_cleanup(conn); + /* set the proper values (possibly modified on POST) */ conn->fread_func = data->set.fread_func; /* restore */ conn->fread_in = data->set.in; /* restore */ -- cgit v1.2.1 From f13cbcf17568fcfdd4160448ceb84e2e0a0704ee Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 28 May 2009 16:18:25 +0000 Subject: fix compiler warning: unused parameter --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a17c6eba9..466d9539a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -524,7 +524,7 @@ output_auth_headers(struct connectdata *conn, &data->state.proxyneg:&data->state.negotiate; #endif -#ifndef CURL_DISABLE_CRYPTO_AUTH +#ifdef CURL_DISABLE_CRYPTO_AUTH (void)request; (void)path; #endif -- cgit v1.2.1 From 1012c5705aedc6730244c22cd9d2bcb3c5c13212 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Jun 2009 06:18:42 +0000 Subject: - Setting the Content-Length: header from your app when you do a POST or PUT is almost always a VERY BAD IDEA. Yet there are still apps out there doing this, and now recently it triggered a bug/side-effect in libcurl as when libcurl sends a POST or PUT with NTLM, it sends an empty post first when it knows it will just get a 401/407 back. If the app then replaced the Content-Length header, it caused the server to wait for input that libcurl wouldn't send. Aaron Oneal reported this problem in bug report #2799008 http://curl.haxx.se/bug/view.cgi?id=2799008) and helped us verify the fix. --- lib/http.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 466d9539a..ccbec227f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2032,6 +2032,11 @@ static CURLcode add_custom_headers(struct connectdata *conn, /* this header (extended by formdata.c) is sent later */ checkprefix("Content-Type:", headers->data)) ; + else if(conn->bits.authneg && + /* while doing auth neg, don't allow the custom length since + we will force length zero then */ + checkprefix("Content-Length", headers->data)) + ; else { CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data); if(result) @@ -2787,9 +2792,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) we don't upload data chunked, as RFC2616 forbids us to set both kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - if(!checkheaders(data, "Content-Length:")) { - /* we allow replacing this header, although it isn't very wise to - actually set your own */ + if(conn->bits.authneg || !checkheaders(data, "Content-Length:")) { + /* we allow replacing this header if not during auth negotiation, + although it isn't very wise to actually set your own */ result = add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T"\r\n", postsize); -- cgit v1.2.1 From 352177090f710fd155d22a79d11f621482c09640 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Jun 2009 21:26:11 +0000 Subject: - Fabian Keil ran clang on the (lib)curl code, found a bunch of warnings and contributed a range of patches to fix them. --- lib/http.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ccbec227f..8457b51f4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1417,10 +1417,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* if timeout is requested, find out how much remaining time we have */ check = timeout - /* timeout time */ Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - if(check <=0 ) { + if(check <= 0) { failf(data, "Proxy CONNECT aborted due to timeout"); - error = SELECT_TIMEOUT; /* already too little time */ - break; + return CURLE_RECV_ERROR; } /* if we're in multi-mode and we would block, return instead for a retry */ -- cgit v1.2.1 From 0b317b72ae6f23eb4dbd0a22509a20ff5acb2958 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 16 Jun 2009 13:16:28 +0000 Subject: - When doing non-anonymous ftp via http proxies and the password is not provided in the url, add it there (squid needs this). --- lib/http.c | 58 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 22 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8457b51f4..f69c5aaaf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2060,6 +2060,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) CURLcode result=CURLE_OK; struct HTTP *http; const char *ppath = data->state.path; + bool paste_ftp_userpwd = FALSE; char ftp_typecode[sizeof(";type=?")] = ""; const char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ @@ -2288,24 +2289,26 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } ppath = data->change.url; - if (data->set.proxy_transfer_mode) { - /* when doing ftp, append ;type= if not present */ - if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { - char *p = strstr(ppath, ";type="); - if(p && p[6] && p[7] == 0) { - switch (Curl_raw_toupper(p[6])) { - case 'A': - case 'D': - case 'I': - break; - default: - p = NULL; + if(checkprefix("ftp://", ppath)) { + if (data->set.proxy_transfer_mode) { + /* when doing ftp, append ;type= if not present */ + char *p = strstr(ppath, ";type="); + if(p && p[6] && p[7] == 0) { + switch (Curl_raw_toupper(p[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + p = NULL; + } } - } - if(!p) - snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); + if(!p) + snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); } + if (conn->bits.user_passwd && !conn->bits.userpwd_in_url) + paste_ftp_userpwd = TRUE; } } #endif /* CURL_DISABLE_PROXY */ @@ -2464,10 +2467,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; /* add the main request stuff */ - result = - add_bufferf(req_buffer, - "%s " /* GET/HEAD/POST/PUT */ - "%s%s HTTP/%s\r\n" /* path + HTTP version */ + /* GET/HEAD/POST/PUT */ + result = add_bufferf(req_buffer, "%s ", request); + if (result) + return result; + + /* url */ + if (paste_ftp_userpwd) + result = add_bufferf(req_buffer, "ftp://%s:%s@%s", + conn->user, conn->passwd, ppath + sizeof("ftp://") - 1); + else + result = add_buffer(req_buffer, ppath, strlen(ppath)); + if (result) + return result; + + result = add_bufferf(req_buffer, + "%s" /* ftp typecode (;type=x) */ + " HTTP/%s\r\n" /* HTTP version */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ "%s" /* range */ @@ -2479,8 +2495,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) "%s" /* Proxy-Connection */ "%s",/* transfer-encoding */ - request, - ppath, ftp_typecode, httpstring, conn->allocptr.proxyuserpwd? -- cgit v1.2.1 From ad1bfc54689060326c076bb7c18d805c955101b6 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Fri, 19 Jun 2009 10:20:28 +0000 Subject: fix indentation. --- lib/http.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f69c5aaaf..9523da38f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2292,20 +2292,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(checkprefix("ftp://", ppath)) { if (data->set.proxy_transfer_mode) { /* when doing ftp, append ;type= if not present */ - char *p = strstr(ppath, ";type="); - if(p && p[6] && p[7] == 0) { - switch (Curl_raw_toupper(p[6])) { - case 'A': - case 'D': - case 'I': - break; - default: - p = NULL; - } + char *p = strstr(ppath, ";type="); + if(p && p[6] && p[7] == 0) { + switch (Curl_raw_toupper(p[6])) { + case 'A': + case 'D': + case 'I': + break; + default: + p = NULL; } - if(!p) - snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); + } + if(!p) + snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", + data->set.prefer_ascii ? 'a' : 'i'); } if (conn->bits.user_passwd && !conn->bits.userpwd_in_url) paste_ftp_userpwd = TRUE; -- cgit v1.2.1 From 5cf78472e1195be215df3831ca11cb532ac75466 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 8 Jul 2009 07:00:40 +0000 Subject: - Constantine Sapuntzakis posted bug report #2813123 (http://curl.haxx.se/bug/view.cgi?id=2813123) and an a patch that fixes the problem: Url A is accessed using auth. Url A redirects to Url B (on a different server0. Url B reuses a persistent connection. Url B has auth, even though it's on a different server. Note: if Url B does not reuse a persistent connection, auth is not sent. --- lib/http.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9523da38f..227675ed7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1780,17 +1780,6 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(!data->state.this_is_a_follow) { - /* this is not a followed location, get the original host name */ - if(data->state.first_host) - /* Free to avoid leaking memory on multiple requests*/ - free(data->state.first_host); - - data->state.first_host = strdup(conn->host.name); - if(!data->state.first_host) - return CURLE_OUT_OF_MEMORY; - } - if(conn->protocol & PROT_HTTPS) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { @@ -2094,6 +2083,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else http = data->state.proto.http; + if(!data->state.this_is_a_follow) { + /* this is not a followed location, get the original host name */ + if(data->state.first_host) + /* Free to avoid leaking memory on multiple requests*/ + free(data->state.first_host); + + data->state.first_host = strdup(conn->host.name); + if(!data->state.first_host) + return CURLE_OUT_OF_MEMORY; + } + if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && data->set.upload) { httpreq = HTTPREQ_PUT; -- cgit v1.2.1 From 10f2fa9c72d7050eaed70474ecad1dd02574e72d Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Fri, 21 Aug 2009 12:15:35 +0000 Subject: With CURLOPT_PROXY_TRANSFER_MODE, avoid sending invalid URLs like ftp://example.com;type=i if the user specified ftp://example.com without the slash. --- lib/http.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 227675ed7..7cc7a9307 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2050,7 +2050,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) struct HTTP *http; const char *ppath = data->state.path; bool paste_ftp_userpwd = FALSE; - char ftp_typecode[sizeof(";type=?")] = ""; + char ftp_typecode[sizeof("/;type=?")] = ""; const char *host = conn->host.name; const char *te = ""; /* transfer-encoding */ const char *ptr; @@ -2292,20 +2292,27 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(checkprefix("ftp://", ppath)) { if (data->set.proxy_transfer_mode) { /* when doing ftp, append ;type= if not present */ - char *p = strstr(ppath, ";type="); - if(p && p[6] && p[7] == 0) { - switch (Curl_raw_toupper(p[6])) { + char *type = strstr(ppath, ";type="); + if(type && type[6] && type[7] == 0) { + switch (Curl_raw_toupper(type[6])) { case 'A': case 'D': case 'I': break; default: - p = NULL; + type = NULL; } } - if(!p) - snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c", + if(!type) { + char *p = ftp_typecode; + /* avoid sending invalid URLs like ftp://example.com;type=i if the + * user specified ftp://example.com without the slash */ + if (!*data->state.path && ppath[strlen(ppath) - 1] != '/') { + *p++ = '/'; + } + snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", data->set.prefer_ascii ? 'a' : 'i'); + } } if (conn->bits.user_passwd && !conn->bits.userpwd_in_url) paste_ftp_userpwd = TRUE; -- cgit v1.2.1 From e5ee82274535366632343f80ea5ca5556b056486 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 18 Oct 2009 00:18:27 +0000 Subject: John Dennis filed bug report #2873666 (http://curl.haxx.se/bug/view.cgi?id=2873666) which identified a problem which made libcurl loop infinitely when given incorrect credentials when using HTTP GSS negotiate authentication. --- lib/http.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7cc7a9307..5471f377f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -750,6 +750,9 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* we received GSS auth info and we dealt with it fine */ data->state.negotiate.state = GSS_AUTHRECV; } + else { + data->state.authproblem = TRUE; + } } } else -- cgit v1.2.1 From d68f215f037febf1850ad6a169d4a69bd9d132a1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 30 Oct 2009 22:24:48 +0000 Subject: - "Tom" posted a bug report that mentioned how libcurl did wrong when doing a POST using a read callback, with Digest authentication and "Transfer-Encoding: chunked" enforced. I would then cause the first request to be wrongly sent and then basically hang until the server closed the connection. I fixed the problem and added test case 565 to verify it. --- lib/http.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5471f377f..832a6d507 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2905,7 +2905,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - if(data->set.postfieldsize) { + if(data->req.upload_chunky && conn->bits.authneg) { + /* Chunky upload is selected and we're negotiating auth still, send + end-of-data only */ + result = add_buffer(req_buffer, + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + /* CR LF 0 CR LF CR LF */ + if(result) + return result; + } + + else if(data->set.postfieldsize) { /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, postsize?postsize:-1); -- cgit v1.2.1 From 59939313f8452a9d817c178425c2ba3b91798ea9 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 18 Nov 2009 10:33:54 +0000 Subject: Make usage of calloc()'s arguments consistent with rest of code base --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 832a6d507..7e4e58795 100644 --- a/lib/http.c +++ b/lib/http.c @@ -984,7 +984,7 @@ static CURLcode static send_buffer *add_buffer_init(void) { - return calloc(sizeof(send_buffer), 1); + return calloc(1, sizeof(send_buffer)); } /* @@ -2078,7 +2078,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->state.proto.http) { /* Only allocate this struct if we don't already have it! */ - http = calloc(sizeof(struct HTTP), 1); + http = calloc(1, sizeof(struct HTTP)); if(!http) return CURLE_OUT_OF_MEMORY; data->state.proto.http = http; -- cgit v1.2.1 From f0826974f225b71a9b95f76f8ac68ea0d72706d5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 1 Dec 2009 12:04:54 +0000 Subject: - If the Expect: 100-continue header has been set by the application through curl_easy_setopt with CURLOPT_HTTPHEADER, the library should set data->state.expect100header accordingly - the current code (in 7.19.7 at least) doesn't handle this properly. Martin Storsjo provided the fix! --- lib/http.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7e4e58795..d67a001b2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1981,17 +1981,24 @@ static CURLcode expect100(struct SessionHandle *data, send_buffer *req_buffer) { CURLcode result = CURLE_OK; + const char *ptr; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if(use_http_1_1(data, conn) && !checkheaders(data, "Expect:")) { + if(use_http_1_1(data, conn)) { /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: - 100-continue to the headers which actually speeds up post - operations (as there is one packet coming back from the web - server) */ - result = add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); - if(result == CURLE_OK) - data->state.expect100header = TRUE; + 100-continue to the headers which actually speeds up post operations + (as there is one packet coming back from the web server) */ + ptr = checkheaders(data, "Expect:"); + if (ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else { + result = add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + if(result == CURLE_OK) + data->state.expect100header = TRUE; + } } return result; } @@ -2837,7 +2844,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) the somewhat bigger ones we allow the app to disable it. Just make sure that the expect100header is always set to the preferred value here. */ - if(postsize > TINY_INITIAL_POST_SIZE) { + ptr = checkheaders(data, "Expect:"); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, "Expect:", "100-continue"); + } + else if(postsize > TINY_INITIAL_POST_SIZE) { result = expect100(data, conn, req_buffer); if(result) return result; -- cgit v1.2.1 From ebe5339003df6b4247f3637c4df5272a8dd69909 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Dec 2009 20:25:17 +0000 Subject: - Martin Storsjo made libcurl use the Expect: 100-continue header for posts with unknown size. Previously it was only used for posts with a known size larger than 1024 bytes. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d67a001b2..6ac2d7331 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2815,7 +2815,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* figure out the size of the postfields */ postsize = (data->set.postfieldsize != -1)? data->set.postfieldsize: - (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); + (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); } if(!data->req.upload_chunky) { /* We only set Content-Length and allow a custom Content-Length if @@ -2849,7 +2849,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->state.expect100header = Curl_compareheader(ptr, "Expect:", "100-continue"); } - else if(postsize > TINY_INITIAL_POST_SIZE) { + else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) { result = expect100(data, conn, req_buffer); if(result) return result; -- cgit v1.2.1 From 1e9a946e6d2714a5e3f143f500fca45a2011e5f1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Dec 2009 21:45:02 +0000 Subject: move HTTP-specific functions to http.c where they belong --- lib/http.c | 756 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 756 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6ac2d7331..76738b880 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2985,4 +2985,760 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } + +/* + * checkhttpprefix() + * + * Returns TRUE if member of the list matches prefix of string + */ +static bool +checkhttpprefix(struct SessionHandle *data, + const char *s) +{ + struct curl_slist *head = data->set.http200aliases; + bool rc = FALSE; +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = calloc(1, strlen(s)+1); + if(NULL == scratch) { + failf (data, "Failed to calloc memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + strcpy(scratch, s); + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#endif /* CURL_DOES_CONVERSIONS */ + + while(head) { + if(checkprefix(head->data, s)) { + rc = TRUE; + break; + } + head = head->next; + } + + if((rc != TRUE) && (checkprefix("HTTP/", s))) { + rc = TRUE; + } + +#ifdef CURL_DOES_CONVERSIONS + free(scratch); +#endif /* CURL_DOES_CONVERSIONS */ + return rc; +} + +/* + * header_append() copies a chunk of data to the end of the already received + * header. We make sure that the full string fit in the allocated header + * buffer, or else we enlarge it. + */ +static CURLcode header_append(struct SessionHandle *data, + struct SingleRequest *k, + size_t length) +{ + if(k->hbuflen + length >= data->state.headersize) { + /* We enlarge the header buffer as it is too small */ + char *newbuff; + size_t hbufp_index; + size_t newsize; + + if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) { + /* The reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause + reallocs infinitely */ + failf (data, "Avoided giant realloc for header (max is %d)!", + CURL_MAX_HTTP_HEADER); + return CURLE_OUT_OF_MEMORY; + } + + newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2); + hbufp_index = k->hbufp - data->state.headerbuff; + newbuff = realloc(data->state.headerbuff, newsize); + if(!newbuff) { + failf (data, "Failed to alloc memory for big header!"); + return CURLE_OUT_OF_MEMORY; + } + data->state.headersize=newsize; + data->state.headerbuff = newbuff; + k->hbufp = data->state.headerbuff + hbufp_index; + } + memcpy(k->hbufp, k->str_start, length); + k->hbufp += length; + k->hbuflen += length; + *k->hbufp = 0; + + return CURLE_OK; +} + + +/* + * Read any HTTP header lines from the server and pass them to the client app. + */ +CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, + struct connectdata *conn, + struct SingleRequest *k, + ssize_t *nread, + bool *stop_reading) +{ + CURLcode result; + + /* header line within buffer loop */ + do { + size_t rest_length; + size_t full_length; + int writetype; + + /* str_start is start of line within buf */ + k->str_start = k->str; + + /* data is in network encoding so use 0x0a instead of '\n' */ + k->end_ptr = memchr(k->str_start, 0x0a, *nread); + + if(!k->end_ptr) { + /* Not a complete header line within buffer, append the data to + the end of the headerbuff. */ + result = header_append(data, k, *nread); + if(result) + return result; + + if(!k->headerline && (k->hbuflen>5)) { + /* make a first check that this looks like a HTTP header */ + if(!checkhttpprefix(data, data->state.headerbuff)) { + /* this is not the beginning of a HTTP first header line */ + k->header = FALSE; + k->badheader = HEADER_ALLBAD; + break; + } + } + + break; /* read more and try again */ + } + + /* decrease the size of the remaining (supposed) header line */ + rest_length = (k->end_ptr - k->str)+1; + *nread -= (ssize_t)rest_length; + + k->str = k->end_ptr + 1; /* move past new line */ + + full_length = k->str - k->str_start; + + result = header_append(data, k, full_length); + if(result) + return result; + + k->end_ptr = k->hbufp; + k->p = data->state.headerbuff; + + /**** + * We now have a FULL header line that p points to + *****/ + + if(!k->headerline) { + /* the first read header */ + if((k->hbuflen>5) && + !checkhttpprefix(data, data->state.headerbuff)) { + /* this is not the beginning of a HTTP first header line */ + k->header = FALSE; + if(*nread) + /* since there's more, this is a partial bad header */ + k->badheader = HEADER_PARTHEADER; + else { + /* this was all we read so it's all a bad header */ + k->badheader = HEADER_ALLBAD; + *nread = (ssize_t)rest_length; + } + break; + } + } + + /* headers are in network encoding so + use 0x0a and 0x0d instead of '\n' and '\r' */ + if((0x0a == *k->p) || (0x0d == *k->p)) { + size_t headerlen; + /* Zero-length header line means end of headers! */ + +#ifdef CURL_DOES_CONVERSIONS + if(0x0d == *k->p) { + *k->p = '\r'; /* replace with CR in host encoding */ + k->p++; /* pass the CR byte */ + } + if(0x0a == *k->p) { + *k->p = '\n'; /* replace with LF in host encoding */ + k->p++; /* pass the LF byte */ + } +#else + if('\r' == *k->p) + k->p++; /* pass the \r byte */ + if('\n' == *k->p) + k->p++; /* pass the \n byte */ +#endif /* CURL_DOES_CONVERSIONS */ + + if(100 <= k->httpcode && 199 >= k->httpcode) { + /* + * We have made a HTTP PUT or POST and this is 1.1-lingo + * that tells us that the server is OK with this and ready + * to receive the data. + * However, we'll get more headers now so we must get + * back into the header-parsing state! + */ + k->header = TRUE; + k->headerline = 0; /* restart the header line counter */ + + /* if we did wait for this do enable write now! */ + if(k->exp100) { + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + } + } + else { + k->header = FALSE; /* no more header to parse! */ + + if((k->size == -1) && !k->chunk && !conn->bits.close && + (conn->httpversion >= 11) ) { + /* On HTTP 1.1, when connection is not to get closed, but no + Content-Length nor Content-Encoding chunked have been + received, according to RFC2616 section 4.4 point 5, we + assume that the server will close the connection to + signal the end of the document. */ + infof(data, "no chunk, no close, no size. Assume close to " + "signal end\n"); + conn->bits.close = TRUE; + } + } + + if(417 == k->httpcode) { + /* + * we got: "417 Expectation Failed" this means: + * we have made a HTTP call and our Expect Header + * seems to cause a problem => abort the write operations + * (or prevent them from starting). + */ + k->exp100 = EXP100_FAILED; + k->keepon &= ~KEEP_SEND; + } + + /* + * When all the headers have been parsed, see if we should give + * up and return an error. + */ + if(Curl_http_should_fail(conn)) { + failf (data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + + /* now, only output this if the header AND body are requested: + */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + headerlen = k->p - data->state.headerbuff; + + result = Curl_client_write(conn, writetype, + data->state.headerbuff, + headerlen); + if(result) + return result; + + data->info.header_size += (long)headerlen; + data->req.headerbytecount += (long)headerlen; + + data->req.deductheadercount = + (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; + + if(data->state.resume_from && + (data->set.httpreq==HTTPREQ_GET) && + (k->httpcode == 416)) { + /* "Requested Range Not Satisfiable" */ + *stop_reading = TRUE; + } + + if(!*stop_reading) { + /* Curl_http_auth_act() checks what authentication methods + * that are available and decides which one (if any) to + * use. It will set 'newurl' if an auth method was picked. */ + result = Curl_http_auth_act(conn); + + if(result) + return result; + + if(conn->bits.rewindaftersend) { + /* We rewind after a complete send, so thus we continue + sending now */ + infof(data, "Keep sending data to get tossed away!\n"); + k->keepon |= KEEP_SEND; + } + } + + if(!k->header) { + /* + * really end-of-headers. + * + * If we requested a "no body", this is a good time to get + * out and return home. + */ + if(data->set.opt_no_body) + *stop_reading = TRUE; + else { + /* If we know the expected size of this document, we set the + maximum download size to the size of the expected + document or else, we won't know when to stop reading! + + Note that we set the download maximum even if we read a + "Connection: close" header, to make sure that + "Content-Length: 0" still prevents us from attempting to + read the (missing) response-body. + */ + /* According to RFC2616 section 4.4, we MUST ignore + Content-Length: headers if we are now receiving data + using chunked Transfer-Encoding. + */ + if(k->chunk) + k->size=-1; + + } + if(-1 != k->size) { + /* We do this operation even if no_body is true, since this + data might be retrieved later with curl_easy_getinfo() + and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ + + Curl_pgrsSetDownloadSize(data, k->size); + k->maxdownload = k->size; + } + /* If max download size is *zero* (nothing) we already + have nothing and can safely return ok now! */ + if(0 == k->maxdownload) + *stop_reading = TRUE; + + if(*stop_reading) { + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + } + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->str_start, headerlen, conn); + break; /* exit header line loop */ + } + + /* We continue reading headers, so reset the line-based + header parsing variables hbufp && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + continue; + } + + /* + * Checks for special headers coming up. + */ + + if(!k->headerline++) { + /* This is the first header, it MUST be the error code line + or else we consider this to be the body right away! */ + int httpversion_major; + int nc; +#ifdef CURL_DOES_CONVERSIONS +#define HEADER1 scratch +#define SCRATCHSIZE 21 + CURLcode res; + char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */ + /* We can't really convert this yet because we + don't know if it's the 1st header line or the body. + So we do a partial conversion into a scratch area, + leaving the data at k->p as-is. + */ + strncpy(&scratch[0], k->p, SCRATCHSIZE); + scratch[SCRATCHSIZE] = 0; /* null terminate */ + res = Curl_convert_from_network(data, + &scratch[0], + SCRATCHSIZE); + if(CURLE_OK != res) { + /* Curl_convert_from_network calls failf if unsuccessful */ + return res; + } +#else +#define HEADER1 k->p /* no conversion needed, just use k->p */ +#endif /* CURL_DOES_CONVERSIONS */ + + nc = sscanf(HEADER1, + " HTTP/%d.%d %3d", + &httpversion_major, + &conn->httpversion, + &k->httpcode); + if(nc==3) { + conn->httpversion += 10 * httpversion_major; + } + else { + /* this is the real world, not a Nirvana + NCSA 1.5.x returns this crap when asked for HTTP/1.1 + */ + nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); + conn->httpversion = 10; + + /* If user has set option HTTP200ALIASES, + compare header line against list of aliases + */ + if(!nc) { + if(checkhttpprefix(data, k->p)) { + nc = 1; + k->httpcode = 200; + conn->httpversion = 10; + } + } + } + + if(nc) { + data->info.httpcode = k->httpcode; + data->info.httpversion = conn->httpversion; + if (!data->state.httpversion || + data->state.httpversion > conn->httpversion) + /* store the lowest server version we encounter */ + data->state.httpversion = conn->httpversion; + + /* + * This code executes as part of processing the header. As a + * result, it's not totally clear how to interpret the + * response code yet as that depends on what other headers may + * be present. 401 and 407 may be errors, but may be OK + * depending on how authentication is working. Other codes + * are definitely errors, so give up here. + */ + if(data->set.http_fail_on_error && (k->httpcode >= 400) && + ((k->httpcode != 401) || !conn->bits.user_passwd) && + ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { + + if(data->state.resume_from && + (data->set.httpreq==HTTPREQ_GET) && + (k->httpcode == 416)) { + /* "Requested Range Not Satisfiable", just proceed and + pretend this is no error */ + } + else { + /* serious error, go home! */ + failf (data, "The requested URL returned error: %d", + k->httpcode); + return CURLE_HTTP_RETURNED_ERROR; + } + } + + if(conn->httpversion == 10) { + /* Default action for HTTP/1.0 must be to close, unless + we get one of those fancy headers that tell us the + server keeps it open for us! */ + infof(data, "HTTP 1.0, assume close after body\n"); + conn->bits.close = TRUE; + } + else if(conn->httpversion >= 11 && + !conn->bits.close) { + /* If HTTP version is >= 1.1 and connection is persistent + server supports pipelining. */ + DEBUGF(infof(data, + "HTTP 1.1 or later with persistent connection, " + "pipelining supported\n")); + conn->server_supports_pipelining = TRUE; + } + + switch(k->httpcode) { + case 204: + /* (quote from RFC2616, section 10.2.5): The server has + * fulfilled the request but does not need to return an + * entity-body ... The 204 response MUST NOT include a + * message-body, and thus is always terminated by the first + * empty line after the header fields. */ + /* FALLTHROUGH */ + case 416: /* Requested Range Not Satisfiable, it has the + Content-Length: set as the "real" document but no + actual response is sent. */ + case 304: + /* (quote from RFC2616, section 10.3.5): The 304 response + * MUST NOT contain a message-body, and thus is always + * terminated by the first empty line after the header + * fields. */ + if(data->set.timecondition) + data->info.timecond = TRUE; + k->size=0; + k->maxdownload=0; + k->ignorecl = TRUE; /* ignore Content-Length headers */ + break; + default: + /* nothing */ + break; + } + } + else { + k->header = FALSE; /* this is not a header line */ + break; + } + } + +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding */ + result = Curl_convert_from_network(data, k->p, strlen(k->p)); + if(CURLE_OK != result) { + return(result); + } + /* Curl_convert_from_network calls failf if unsuccessful */ +#endif /* CURL_DOES_CONVERSIONS */ + + /* Check for Content-Length: header lines to get size. Ignore + the header completely if we get a 416 response as then we're + resuming a document that we don't get, and this header contains + info about the true size of the document we didn't get now. */ + if(!k->ignorecl && !data->set.ignorecl && + checkprefix("Content-Length:", k->p)) { + curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10); + if(data->set.max_filesize && + contentlength > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + if(contentlength >= 0) { + k->size = contentlength; + k->maxdownload = k->size; + /* we set the progress download size already at this point + just to make it easier for apps/callbacks to extract this + info as soon as possible */ + Curl_pgrsSetDownloadSize(data, k->size); + } + else { + /* Negative Content-Length is really odd, and we know it + happens for example when older Apache servers send large + files */ + conn->bits.close = TRUE; + infof(data, "Negative content-length: %" FORMAT_OFF_T + ", closing after transfer\n", contentlength); + } + } + /* check for Content-Type: header lines to get the MIME-type */ + else if(checkprefix("Content-Type:", k->p)) { + char *contenttype = Curl_copy_header_value(k->p); + if (!contenttype) + return CURLE_OUT_OF_MEMORY; + if (!*contenttype) + /* ignore empty data */ + free(contenttype); + else { + Curl_safefree(data->info.contenttype); + data->info.contenttype = contenttype; + } + } + else if((conn->httpversion == 10) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "keep-alive")) { + /* + * When a HTTP/1.0 reply comes when using a proxy, the + * 'Proxy-Connection: keep-alive' line tells us the + * connection will be kept alive for our pleasure. + * Default action for 1.0 is to close. + */ + conn->bits.close = FALSE; /* don't close when done */ + infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + } + else if((conn->httpversion == 11) && + conn->bits.httpproxy && + Curl_compareheader(k->p, + "Proxy-Connection:", "close")) { + /* + * We get a HTTP/1.1 response from a proxy and it says it'll + * close down after this transfer. + */ + conn->bits.close = TRUE; /* close when done */ + infof(data, "HTTP/1.1 proxy connection set close!\n"); + } + else if((conn->httpversion == 10) && + Curl_compareheader(k->p, "Connection:", "keep-alive")) { + /* + * A HTTP/1.0 reply with the 'Connection: keep-alive' line + * tells us the connection will be kept alive for our + * pleasure. Default action for 1.0 is to close. + * + * [RFC2068, section 19.7.1] */ + conn->bits.close = FALSE; /* don't close when done */ + infof(data, "HTTP/1.0 connection set to keep alive!\n"); + } + else if(Curl_compareheader(k->p, "Connection:", "close")) { + /* + * [RFC 2616, section 8.1.2.1] + * "Connection: close" is HTTP/1.1 language and means that + * the connection will close when this request has been + * served. + */ + conn->bits.close = TRUE; /* close when done */ + } + else if(Curl_compareheader(k->p, + "Transfer-Encoding:", "chunked")) { + /* + * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding + * means that the server will send a series of "chunks". Each + * chunk starts with line with info (including size of the + * coming block) (terminated with CRLF), then a block of data + * with the previously mentioned size. There can be any amount + * of chunks, and a chunk-data set to zero signals the + * end-of-chunks. */ + k->chunk = TRUE; /* chunks coming our way */ + + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + + else if(checkprefix("Trailer:", k->p) || + checkprefix("Trailers:", k->p)) { + /* + * This test helps Curl_httpchunk_read() to determine to look + * for well formed trailers after the zero chunksize record. In + * this case a CRLF is required after the zero chunksize record + * when no trailers are sent, or after the last trailer record. + * + * It seems both Trailer: and Trailers: occur in the wild. + */ + k->trailerhdrpresent = TRUE; + } + + else if(checkprefix("Content-Encoding:", k->p) && + data->set.str[STRING_ENCODING]) { + /* + * Process Content-Encoding. Look for the values: identity, + * gzip, deflate, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress. However, errors are + * handled further down when the response body is processed + */ + char *start; + + /* Find the first non-space letter */ + start = k->p + 17; + while(*start && ISSPACE(*start)) + start++; + + /* Record the content-encoding for later use */ + if(checkprefix("identity", start)) + k->content_encoding = IDENTITY; + else if(checkprefix("deflate", start)) + k->content_encoding = DEFLATE; + else if(checkprefix("gzip", start) + || checkprefix("x-gzip", start)) + k->content_encoding = GZIP; + else if(checkprefix("compress", start) + || checkprefix("x-compress", start)) + k->content_encoding = COMPRESS; + } + else if(checkprefix("Content-Range:", k->p)) { + /* Content-Range: bytes [num]- + Content-Range: bytes: [num]- + Content-Range: [num]- + + The second format was added since Sun's webserver + JavaWebServer/1.1.1 obviously sends the header this way! + The third added since some servers use that! + */ + + char *ptr = k->p + 14; + + /* Move forward until first digit */ + while(*ptr && !ISDIGIT(*ptr)) + ptr++; + + k->offset = curlx_strtoofft(ptr, NULL, 10); + + if(data->state.resume_from == k->offset) + /* we asked for a resume and we got it */ + k->content_range = TRUE; + } +#if !defined(CURL_DISABLE_COOKIES) + else if(data->cookies && + checkprefix("Set-Cookie:", k->p)) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, + CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_add(data, + data->cookies, TRUE, k->p+11, + /* If there is a custom-set Host: name, use it + here, or else use real peer host name. */ + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:conn->host.name, + data->state.path); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +#endif + else if(checkprefix("Last-Modified:", k->p) && + (data->set.timecondition || data->set.get_filetime) ) { + time_t secs=time(NULL); + k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), + &secs); + if(data->set.get_filetime) + data->info.filetime = (long)k->timeofdoc; + } + else if((checkprefix("WWW-Authenticate:", k->p) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", k->p) && + (407 == k->httpcode))) { + result = Curl_http_input_auth(conn, k->httpcode, k->p); + if(result) + return result; + } + else if((k->httpcode >= 300 && k->httpcode < 400) && + checkprefix("Location:", k->p)) { + /* this is the URL that the server advises us to use instead */ + char *location = Curl_copy_header_value(k->p); + if (!location) + return CURLE_OUT_OF_MEMORY; + if (!*location) + /* ignore empty data */ + free(location); + else { + DEBUGASSERT(!data->req.location); + data->req.location = location; + + if(data->set.http_follow_location) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = Curl_http_perhapsrewind(conn); + if(result) + return result; + } + } + } + + /* + * End of header-checks. Write them to the client. + */ + + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->p, (size_t)k->hbuflen, conn); + + result = Curl_client_write(conn, writetype, k->p, k->hbuflen); + if(result) + return result; + + data->info.header_size += (long)k->hbuflen; + data->req.headerbytecount += (long)k->hbuflen; + + /* reset hbufp pointer && hbuflen */ + k->hbufp = data->state.headerbuff; + k->hbuflen = 0; + } + while(!*stop_reading && *k->str); /* header line within buffer */ + + /* We might have reached the end of the header part here, but + there might be a non-header part left in the end of the read + buffer. */ + + return CURLE_OK; +} + #endif -- cgit v1.2.1 From 8524c04ca98d9c0b5f90d685135e0466e0d8b386 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Jan 2010 22:48:28 +0000 Subject: removed a parameter from the Curl_http_readwrite_headers() prototype to remove the need for the struct forward declaration from http.h which caused problems with gcc 2.96 and quite frankly the parameter wasn't necessary anyway --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 76738b880..2cc1154fc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -3080,11 +3080,11 @@ static CURLcode header_append(struct SessionHandle *data, */ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, struct connectdata *conn, - struct SingleRequest *k, ssize_t *nread, bool *stop_reading) { CURLcode result; + struct SingleRequest *k = &data->req; /* header line within buffer loop */ do { -- cgit v1.2.1 From bc4582b68a673d3b0f5a2e7d971605de2c8b3730 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 21 Jan 2010 13:58:30 +0000 Subject: Chris Conroy brought support for RTSP transfers, and with it comes 8(!) new libcurl options for controlling what to get and how to receive posssibly interleaved RTP data. Initial commit. --- lib/http.c | 429 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 246 insertions(+), 183 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2cc1154fc..deade9183 100644 --- a/lib/http.c +++ b/lib/http.c @@ -98,6 +98,7 @@ #include "multiif.h" #include "rawstr.h" #include "content_encoding.h" +#include "rtsp.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -173,7 +174,7 @@ const struct Curl_handler Curl_handler_https = { * * Returns a pointer to the first matching header or NULL if none matched. */ -static char *checkheaders(struct SessionHandle *data, const char *thisheader) +char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader) { struct curl_slist *head; size_t thislen = strlen(thisheader); @@ -565,9 +566,9 @@ output_auth_headers(struct connectdata *conn, if(authstatus->picked == CURLAUTH_BASIC) { /* Basic */ if((proxy && conn->bits.proxy_user_passwd && - !checkheaders(data, "Proxy-authorization:")) || + !Curl_checkheaders(data, "Proxy-authorization:")) || (!proxy && conn->bits.user_passwd && - !checkheaders(data, "Authorization:"))) { + !Curl_checkheaders(data, "Authorization:"))) { auth="Basic"; result = http_output_basic(conn, proxy); if(result) @@ -960,41 +961,23 @@ static size_t readmoredata(char *buffer, } /* ------------------------------------------------------------------------- */ -/* - * The add_buffer series of functions are used to build one large memory chunk - * from repeated function invokes. Used so that the entire HTTP request can - * be sent in one go. - */ - -struct send_buffer { - char *buffer; - size_t size_max; - size_t size_used; -}; -typedef struct send_buffer send_buffer; - -static CURLcode add_custom_headers(struct connectdata *conn, - send_buffer *req_buffer); -static CURLcode - add_buffer(send_buffer *in, const void *inptr, size_t size); +/* add_buffer functions */ /* - * add_buffer_init() sets up and returns a fine buffer struct + * Curl_add_buffer_init() sets up and returns a fine buffer struct */ -static -send_buffer *add_buffer_init(void) +Curl_send_buffer *Curl_add_buffer_init(void) { - return calloc(1, sizeof(send_buffer)); + return calloc(1, sizeof(Curl_send_buffer)); } /* - * add_buffer_send() sends a header buffer and frees all associated memory. + * Curl_add_buffer_send() sends a header buffer and frees all associated memory. * Body data may be appended to the header data if desired. * * Returns CURLcode */ -static -CURLcode add_buffer_send(send_buffer *in, +CURLcode Curl_add_buffer_send(Curl_send_buffer *in, struct connectdata *conn, long *bytes_written, /* add the number of sent bytes to this counter */ @@ -1144,8 +1127,7 @@ CURLcode add_buffer_send(send_buffer *in, /* * add_bufferf() add the formatted input to the buffer. */ -static -CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) +CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) { char *s; va_list ap; @@ -1154,7 +1136,7 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) va_end(ap); if(s) { - CURLcode result = add_buffer(in, s, strlen(s)); + CURLcode result = Curl_add_buffer(in, s, strlen(s)); free(s); return result; } @@ -1168,8 +1150,7 @@ CURLcode add_bufferf(send_buffer *in, const char *fmt, ...) /* * add_buffer() appends a memory chunk to the existing buffer */ -static -CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) +CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) { char *new_rb; size_t new_size; @@ -1223,6 +1204,8 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) /* end of the add_buffer functions */ /* ------------------------------------------------------------------------- */ + + /* * Curl_compareheader() * @@ -1320,7 +1303,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, do { if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ char *host_port; - send_buffer *req_buffer; + Curl_send_buffer *req_buffer; infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); @@ -1334,7 +1317,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } /* initialize a dynamic send-buffer */ - req_buffer = add_buffer_init(); + req_buffer = Curl_add_buffer_init(); if(!req_buffer) return CURLE_OUT_OF_MEMORY; @@ -1355,7 +1338,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; - if(!checkheaders(data, "Host:")) { + if(!Curl_checkheaders(data, "Host:")) { host = aprintf("Host: %s\r\n", host_port); if(!host) { free(req_buffer); @@ -1363,17 +1346,17 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } } - if(!checkheaders(data, "Proxy-Connection:")) + if(!Curl_checkheaders(data, "Proxy-Connection:")) proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - if(!checkheaders(data, "User-Agent:") && + if(!Curl_checkheaders(data, "User-Agent:") && data->set.str[STRING_USERAGENT]) useragent = conn->allocptr.uagent; /* Send the connect request to the proxy */ /* BLOCKING */ result = - add_bufferf(req_buffer, + Curl_add_bufferf(req_buffer, "CONNECT %s:%d HTTP/%s\r\n" "%s" /* Host: */ "%s" /* Proxy-Authorization */ @@ -1390,15 +1373,15 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, free(host); if(CURLE_OK == result) - result = add_custom_headers(conn, req_buffer); + result = Curl_add_custom_headers(conn, req_buffer); if(CURLE_OK == result) /* CRLF terminate the request */ - result = add_bufferf(req_buffer, "\r\n"); + result = Curl_add_bufferf(req_buffer, "\r\n"); if(CURLE_OK == result) { /* Now send off the request */ - result = add_buffer_send(req_buffer, conn, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, sockindex); } req_buffer = NULL; @@ -1921,7 +1904,7 @@ CURLcode Curl_http_done(struct connectdata *conn, return CURLE_OK; if(http->send_buffer) { - send_buffer *buff = http->send_buffer; + Curl_send_buffer *buff = http->send_buffer; free(buff->buffer); free(buff); @@ -1962,9 +1945,9 @@ CURLcode Curl_http_done(struct connectdata *conn, /* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it -are if the user specifically requested HTTP 1.0, if the server we are -connected to only supports 1.0, or if any server previously contacted to -handle this request only supports 1.0. */ + are if the user specifically requested HTTP 1.0, if the server we are + connected to only supports 1.0, or if any server previously contacted to + handle this request only supports 1.0. */ static bool use_http_1_1(const struct SessionHandle *data, const struct connectdata *conn) { @@ -1978,7 +1961,7 @@ static bool use_http_1_1(const struct SessionHandle *data, /* check and possibly add an Expect: header */ static CURLcode expect100(struct SessionHandle *data, struct connectdata *conn, - send_buffer *req_buffer) + Curl_send_buffer *req_buffer) { CURLcode result = CURLE_OK; const char *ptr; @@ -1988,14 +1971,14 @@ static CURLcode expect100(struct SessionHandle *data, /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ - ptr = checkheaders(data, "Expect:"); + ptr = Curl_checkheaders(data, "Expect:"); if (ptr) { data->state.expect100header = Curl_compareheader(ptr, "Expect:", "100-continue"); } else { - result = add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); + result = Curl_add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); if(result == CURLE_OK) data->state.expect100header = TRUE; } @@ -2003,8 +1986,8 @@ static CURLcode expect100(struct SessionHandle *data, return result; } -static CURLcode add_custom_headers(struct connectdata *conn, - send_buffer *req_buffer) +CURLcode Curl_add_custom_headers(struct connectdata *conn, + Curl_send_buffer *req_buffer) { char *ptr; struct curl_slist *headers=conn->data->set.headers; @@ -2036,7 +2019,8 @@ static CURLcode add_custom_headers(struct connectdata *conn, checkprefix("Content-Length", headers->data)) ; else { - CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data); + CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); if(result) return result; } @@ -2047,6 +2031,58 @@ static CURLcode add_custom_headers(struct connectdata *conn, return CURLE_OK; } +CURLcode Curl_add_timecondition(struct SessionHandle *data, + Curl_send_buffer *req_buffer) +{ + struct tm *tm; + char *buf = data->state.buffer; + CURLcode result = CURLE_OK; + + /* The If-Modified-Since header family should have their times set in + * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be + * represented in Greenwich Mean Time (GMT), without exception. For the + * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal + * Time)." (see page 20 of RFC2616). + */ + +#ifdef HAVE_GMTIME_R + /* thread-safe version */ + struct tm keeptime; + tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); +#else + tm = gmtime(&data->set.timevalue); +#endif + + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + snprintf(buf, BUFSIZE-1, + "%s, %02d %s %4d %02d:%02d:%02d GMT", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + result = Curl_add_bufferf(req_buffer, + "If-Modified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_IFUNMODSINCE: + result = Curl_add_bufferf(req_buffer, + "If-Unmodified-Since: %s\r\n", buf); + break; + case CURL_TIMECOND_LASTMOD: + result = Curl_add_bufferf(req_buffer, + "Last-Modified: %s\r\n", buf); + break; + } + + return result; +} + /* * Curl_http() gets called from the generic Curl_do() function when a HTTP * request is to be performed. This creates and sends a properly constructed @@ -2055,7 +2091,6 @@ static CURLcode add_custom_headers(struct connectdata *conn, CURLcode Curl_http(struct connectdata *conn, bool *done) { struct SessionHandle *data=conn->data; - char *buf = data->state.buffer; /* this is a short cut to the buffer */ CURLcode result=CURLE_OK; struct HTTP *http; const char *ppath = data->state.path; @@ -2069,7 +2104,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *addcookies = NULL; curl_off_t included_body = 0; const char *httpstring; - send_buffer *req_buffer; + Curl_send_buffer *req_buffer; curl_off_t postsize; /* off_t type to be able to hold a large file size */ int seekerr = CURL_SEEKFUNC_OK; @@ -2140,7 +2175,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ - if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { + if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { free(conn->allocptr.uagent); conn->allocptr.uagent=NULL; } @@ -2161,15 +2196,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->bits.authneg = FALSE; Curl_safefree(conn->allocptr.ref); - if(data->change.referer && !checkheaders(data, "Referer:")) + if(data->change.referer && !Curl_checkheaders(data, "Referer:")) conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); else conn->allocptr.ref = NULL; - if(data->set.str[STRING_COOKIE] && !checkheaders(data, "Cookie:")) + if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:")) addcookies = data->set.str[STRING_COOKIE]; - if(!checkheaders(data, "Accept-Encoding:") && + if(!Curl_checkheaders(data, "Accept-Encoding:") && data->set.str[STRING_ENCODING]) { Curl_safefree(conn->allocptr.accept_encoding); conn->allocptr.accept_encoding = @@ -2178,7 +2213,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - ptr = checkheaders(data, "Transfer-Encoding:"); + ptr = Curl_checkheaders(data, "Transfer-Encoding:"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ data->req.upload_chunky = @@ -2191,7 +2226,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if (use_http_1_1(data, conn)) { /* HTTP, upload, unknown file size and not HTTP 1.0 */ data->req.upload_chunky = TRUE; - } else { + } + else { failf(data, "Chunky upload is not supported by HTTP 1.0"); return CURLE_UPLOAD_FAILED; } @@ -2207,7 +2243,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_safefree(conn->allocptr.host); - ptr = checkheaders(data, "Host:"); + ptr = Curl_checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || Curl_raw_equal(data->state.first_host, conn->host.name))) { #if !defined(CURL_DISABLE_COOKIES) @@ -2334,7 +2370,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ result = Curl_getFormData(&http->sendit, data->set.httppost, - checkheaders(data, "Content-Type:"), + Curl_checkheaders(data, "Content-Type:"), &http->postsize); if(CURLE_OK != result) { /* Curl_getFormData() doesn't use failf() */ @@ -2344,7 +2380,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } - http->p_accept = checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; + http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; if(( (HTTPREQ_POST == httpreq) || (HTTPREQ_POST_FORM == httpreq) || @@ -2427,7 +2463,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * ones if any such are specified. */ if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && - !checkheaders(data, "Range:")) { + !Curl_checkheaders(data, "Range:")) { /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); @@ -2435,7 +2471,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->state.range); } else if((httpreq != HTTPREQ_GET) && - !checkheaders(data, "Content-Range:")) { + !Curl_checkheaders(data, "Content-Range:")) { /* if a line like this was already allocated, free the previous one */ if(conn->allocptr.rangeline) @@ -2478,27 +2514,27 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; /* initialize a dynamic send-buffer */ - req_buffer = add_buffer_init(); + req_buffer = Curl_add_buffer_init(); if(!req_buffer) return CURLE_OUT_OF_MEMORY; /* add the main request stuff */ /* GET/HEAD/POST/PUT */ - result = add_bufferf(req_buffer, "%s ", request); + result = Curl_add_bufferf(req_buffer, "%s ", request); if (result) return result; /* url */ if (paste_ftp_userpwd) - result = add_bufferf(req_buffer, "ftp://%s:%s@%s", + result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", conn->user, conn->passwd, ppath + sizeof("ftp://") - 1); else - result = add_buffer(req_buffer, ppath, strlen(ppath)); + result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); if (result) return result; - result = add_bufferf(req_buffer, + result = Curl_add_bufferf(req_buffer, "%s" /* ftp typecode (;type=x) */ " HTTP/%s\r\n" /* HTTP version */ "%s" /* proxyuserpwd */ @@ -2532,7 +2568,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.ref:"" /* Referer: */, (conn->bits.httpproxy && !conn->bits.tunnel_proxy && - !checkheaders(data, "Proxy-Connection:"))? + !Curl_checkheaders(data, "Proxy-Connection:"))? "Proxy-Connection: Keep-Alive\r\n":"", te ); @@ -2568,11 +2604,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) while(co) { if(co->value) { if(0 == count) { - result = add_bufferf(req_buffer, "Cookie: "); + result = Curl_add_bufferf(req_buffer, "Cookie: "); if(result) break; } - result = add_bufferf(req_buffer, + result = Curl_add_bufferf(req_buffer, "%s%s=%s", count?"; ":"", co->name, co->value); if(result) @@ -2585,16 +2621,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } if(addcookies && (CURLE_OK == result)) { if(!count) - result = add_bufferf(req_buffer, "Cookie: "); + result = Curl_add_bufferf(req_buffer, "Cookie: "); if(CURLE_OK == result) { - result = add_bufferf(req_buffer, "%s%s", + result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"", addcookies); count++; } } if(count && (CURLE_OK == result)) - result = add_buffer(req_buffer, "\r\n", 2); + result = Curl_add_buffer(req_buffer, "\r\n", 2); if(result) return result; @@ -2602,54 +2638,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #endif if(data->set.timecondition) { - struct tm *tm; - - /* The If-Modified-Since header family should have their times set in - * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be - * represented in Greenwich Mean Time (GMT), without exception. For the - * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal - * Time)." (see page 20 of RFC2616). - */ - -#ifdef HAVE_GMTIME_R - /* thread-safe version */ - struct tm keeptime; - tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); -#else - tm = gmtime(&data->set.timevalue); -#endif - - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - - switch(data->set.timecondition) { - case CURL_TIMECOND_IFMODSINCE: - default: - result = add_bufferf(req_buffer, - "If-Modified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_IFUNMODSINCE: - result = add_bufferf(req_buffer, - "If-Unmodified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_LASTMOD: - result = add_bufferf(req_buffer, - "Last-Modified: %s\r\n", buf); - break; - } + result = Curl_add_timecondition(data, req_buffer); if(result) return result; } - result = add_custom_headers(conn, req_buffer); + result = Curl_add_custom_headers(conn, req_buffer); if(result) return result; @@ -2665,11 +2659,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) case HTTPREQ_POST_FORM: if(!http->sendit || conn->bits.authneg) { /* nothing to post! */ - result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); + result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); if(result) return result; - result = add_buffer_send(req_buffer, conn, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); @@ -2701,7 +2695,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ - result = add_bufferf(req_buffer, + result = Curl_add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T "\r\n", http->postsize); if(result) @@ -2725,13 +2719,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_HTTP_POST_ERROR; } - result = add_buffer(req_buffer, contentType, linelength); + result = Curl_add_buffer(req_buffer, contentType, linelength); if(result) return result; } /* make the request end in a true CRLF */ - result = add_buffer(req_buffer, "\r\n", 2); + result = Curl_add_buffer(req_buffer, "\r\n", 2); if(result) return result; @@ -2739,7 +2733,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_pgrsSetUploadSize(data, http->postsize); /* fire away the whole request to the server */ - result = add_buffer_send(req_buffer, conn, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); @@ -2773,7 +2767,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if((postsize != -1) && !data->req.upload_chunky) { /* only add Content-Length if not uploading chunked */ - result = add_bufferf(req_buffer, + result = Curl_add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T "\r\n", postsize ); if(result) @@ -2784,7 +2778,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */ if(result) return result; @@ -2792,7 +2786,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_pgrsSetUploadSize(data, postsize); /* this sends the buffer and frees all the buffer resources */ - result = add_buffer_send(req_buffer, conn, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending PUT request"); @@ -2822,10 +2816,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) we don't upload data chunked, as RFC2616 forbids us to set both kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - if(conn->bits.authneg || !checkheaders(data, "Content-Length:")) { + if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) { /* we allow replacing this header if not during auth negotiation, although it isn't very wise to actually set your own */ - result = add_bufferf(req_buffer, + result = Curl_add_bufferf(req_buffer, "Content-Length: %" FORMAT_OFF_T"\r\n", postsize); if(result) @@ -2833,8 +2827,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - if(!checkheaders(data, "Content-Type:")) { - result = add_bufferf(req_buffer, + if(!Curl_checkheaders(data, "Content-Type:")) { + result = Curl_add_bufferf(req_buffer, "Content-Type: application/x-www-form-urlencoded\r\n"); if(result) return result; @@ -2844,7 +2838,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) the somewhat bigger ones we allow the app to disable it. Just make sure that the expect100header is always set to the preferred value here. */ - ptr = checkheaders(data, "Expect:"); + ptr = Curl_checkheaders(data, "Expect:"); if(ptr) { data->state.expect100header = Curl_compareheader(ptr, "Expect:", "100-continue"); @@ -2868,25 +2862,25 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) return result; if(!data->req.upload_chunky) { /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ - result = add_buffer(req_buffer, data->set.postfields, + result = Curl_add_buffer(req_buffer, data->set.postfields, (size_t)postsize); included_body = postsize; } else { /* Append the POST data chunky-style */ - result = add_bufferf(req_buffer, "%x\r\n", (int)postsize); + result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); if(CURLE_OK == result) - result = add_buffer(req_buffer, data->set.postfields, + result = Curl_add_buffer(req_buffer, data->set.postfields, (size_t)postsize); if(CURLE_OK == result) - result = add_buffer(req_buffer, + result = Curl_add_buffer(req_buffer, "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); /* CR LF 0 CR LF CR LF */ included_body = postsize + 7; @@ -2907,20 +2901,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) return result; } } else { - result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ if(result) return result; if(data->req.upload_chunky && conn->bits.authneg) { /* Chunky upload is selected and we're negotiating auth still, send end-of-data only */ - result = add_buffer(req_buffer, + result = Curl_add_buffer(req_buffer, "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); /* CR LF 0 CR LF CR LF */ if(result) @@ -2941,7 +2935,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } /* issue the request */ - result = add_buffer_send(req_buffer, conn, &data->info.request_size, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, (size_t)included_body, FIRSTSOCKET); if(result) @@ -2955,12 +2949,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) break; default: - result = add_buffer(req_buffer, "\r\n", 2); + result = Curl_add_buffer(req_buffer, "\r\n", 2); if(result) return result; /* issue the request */ - result = add_buffer_send(req_buffer, conn, + result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, FIRSTSOCKET); if(result) @@ -2999,12 +2993,11 @@ checkhttpprefix(struct SessionHandle *data, bool rc = FALSE; #ifdef CURL_DOES_CONVERSIONS /* convert from the network encoding using a scratch area */ - char *scratch = calloc(1, strlen(s)+1); + char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to calloc memory for conversion!"); + failf (data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } - strcpy(scratch, s); if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { /* Curl_convert_from_network calls failf if unsuccessful */ free(scratch); @@ -3031,6 +3024,51 @@ checkhttpprefix(struct SessionHandle *data, return rc; } +#ifndef CURL_DISABLE_RTSP +static bool +checkrtspprefix(struct SessionHandle *data, + const char *s) +{ + +#ifdef CURL_DOES_CONVERSIONS + /* convert from the network encoding using a scratch area */ + char *scratch = strdup(s); + if(NULL == scratch) { + failf (data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + } + if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ + } + s = scratch; +#else + (void)data; /* unused */ +#endif /* CURL_DOES_CONVERSIONS */ + if(checkprefix("RTSP/", s)) + return TRUE; + else + return FALSE; +} +#endif /* CURL_DISABLE_RTSP */ + +static bool +checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, + const char *s) +{ +#ifndef CURL_DISABLE_RTSP + if(conn->protocol & PROT_RTSP) + return checkrtspprefix(data, s); +#endif /* CURL_DISABLE_RTSP */ + + return checkhttpprefix(data, s); +} + +#endif + + + /* * header_append() copies a chunk of data to the end of the already received * header. We make sure that the full string fit in the allocated header @@ -3079,9 +3117,9 @@ static CURLcode header_append(struct SessionHandle *data, * Read any HTTP header lines from the server and pass them to the client app. */ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, - struct connectdata *conn, - ssize_t *nread, - bool *stop_reading) + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading) { CURLcode result; struct SingleRequest *k = &data->req; @@ -3106,9 +3144,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, return result; if(!k->headerline && (k->hbuflen>5)) { - /* make a first check that this looks like a HTTP header */ - if(!checkhttpprefix(data, data->state.headerbuff)) { - /* this is not the beginning of a HTTP first header line */ + /* make a first check that this looks like a protocol header */ + if(!checkprotoprefix(data, conn, data->state.headerbuff)) { + /* this is not the beginning of a protocol first header line */ k->header = FALSE; k->badheader = HEADER_ALLBAD; break; @@ -3140,8 +3178,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, if(!k->headerline) { /* the first read header */ if((k->hbuflen>5) && - !checkhttpprefix(data, data->state.headerbuff)) { - /* this is not the beginning of a HTTP first header line */ + !checkprotoprefix(data, conn, data->state.headerbuff)) { + /* this is not the beginning of a protocol first header line */ k->header = FALSE; if(*nread) /* since there's more, this is a partial bad header */ @@ -3198,7 +3236,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, k->header = FALSE; /* no more header to parse! */ if((k->size == -1) && !k->chunk && !conn->bits.close && - (conn->httpversion >= 11) ) { + (conn->httpversion >= 11) && !(conn->protocol & PROT_RTSP)) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Content-Encoding chunked have been received, according to RFC2616 section 4.4 point 5, we @@ -3310,6 +3348,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, Curl_pgrsSetDownloadSize(data, k->size); k->maxdownload = k->size; } + /* If max download size is *zero* (nothing) we already have nothing and can safely return ok now! */ if(0 == k->maxdownload) @@ -3341,6 +3380,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* This is the first header, it MUST be the error code line or else we consider this to be the body right away! */ int httpversion_major; + int rtspversion_major; int nc; #ifdef CURL_DOES_CONVERSIONS #define HEADER1 scratch @@ -3365,35 +3405,53 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, #define HEADER1 k->p /* no conversion needed, just use k->p */ #endif /* CURL_DOES_CONVERSIONS */ - nc = sscanf(HEADER1, - " HTTP/%d.%d %3d", - &httpversion_major, - &conn->httpversion, - &k->httpcode); - if(nc==3) { - conn->httpversion += 10 * httpversion_major; - } - else { - /* this is the real world, not a Nirvana - NCSA 1.5.x returns this crap when asked for HTTP/1.1 - */ - nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); - conn->httpversion = 10; + if(conn->protocol & PROT_HTTP) { + nc = sscanf(HEADER1, + " HTTP/%d.%d %3d", + &httpversion_major, + &conn->httpversion, + &k->httpcode); + if(nc==3) { + conn->httpversion += 10 * httpversion_major; + } + else { + /* this is the real world, not a Nirvana + NCSA 1.5.x returns this crap when asked for HTTP/1.1 + */ + nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); + conn->httpversion = 10; - /* If user has set option HTTP200ALIASES, - compare header line against list of aliases - */ - if(!nc) { - if(checkhttpprefix(data, k->p)) { - nc = 1; - k->httpcode = 200; - conn->httpversion = 10; + /* If user has set option HTTP200ALIASES, + compare header line against list of aliases + */ + if(!nc) { + if(checkhttpprefix(data, k->p)) { + nc = 1; + k->httpcode = 200; + conn->httpversion = 10; + } } } } + else if(conn->protocol & PROT_RTSP) { + nc = sscanf(HEADER1, + " RTSP/%d.%d %3d", + &rtspversion_major, + &conn->rtspversion, + &k->httpcode); + if(nc==3) { + conn->rtspversion += 10 * rtspversion_major; + conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ + } + else { + /* TODO: do we care about the other cases here? */ + nc = 0; + } + } if(nc) { data->info.httpcode = k->httpcode; + data->info.httpversion = conn->httpversion; if (!data->state.httpversion || data->state.httpversion > conn->httpversion) @@ -3571,8 +3629,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, */ conn->bits.close = TRUE; /* close when done */ } - else if(Curl_compareheader(k->p, - "Transfer-Encoding:", "chunked")) { + else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") && + !(conn->protocol & PROT_RTSP)) { /* * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding * means that the server will send a series of "chunks". Each @@ -3708,7 +3766,13 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } } - +#ifndef CURL_DISABLE_RTSP + else if(conn->protocol & PROT_RTSP) { + result = Curl_rtsp_parseheader(conn, k->p); + if(result) + return result; + } +#endif /* * End of header-checks. Write them to the client. */ @@ -3741,4 +3805,3 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, return CURLE_OK; } -#endif -- cgit v1.2.1 From bd7430c1eec70f0a0ffd7296a21396ea45d92359 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 21 Jan 2010 19:27:32 +0000 Subject: fix compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index deade9183..fc533bfe3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3381,7 +3381,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, or else we consider this to be the body right away! */ int httpversion_major; int rtspversion_major; - int nc; + int nc = 0; #ifdef CURL_DOES_CONVERSIONS #define HEADER1 scratch #define SCRATCHSIZE 21 -- cgit v1.2.1 From 0032ce762eed505905d7e5ef766134ffa6d69b5c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 22 Jan 2010 14:20:56 +0000 Subject: fix compilation when http is disabled --- lib/http.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fc533bfe3..53e991b20 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3065,10 +3065,6 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, return checkhttpprefix(data, s); } -#endif - - - /* * header_append() copies a chunk of data to the end of the already received * header. We make sure that the full string fit in the allocated header @@ -3805,3 +3801,4 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, return CURLE_OK; } +#endif /* CURL_DISABLE_HTTP */ -- cgit v1.2.1 From 33ce0ec1f1951bc1a8f4d475381c1b7c95d4a03a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Jan 2010 23:21:39 +0000 Subject: wrap long lines and do some indent policing --- lib/http.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 53e991b20..15943202e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -972,8 +972,8 @@ Curl_send_buffer *Curl_add_buffer_init(void) } /* - * Curl_add_buffer_send() sends a header buffer and frees all associated memory. - * Body data may be appended to the header data if desired. + * Curl_add_buffer_send() sends a header buffer and frees all associated + * memory. Body data may be appended to the header data if desired. * * Returns CURLcode */ @@ -1420,7 +1420,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } } else { - DEBUGF(infof(data, "Easy mode waiting for response from proxy CONNECT.")); + DEBUGF(infof(data, "Easy mode waiting response from proxy CONNECT.")); } /* at this point, either: @@ -1538,7 +1538,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, #ifdef CURL_DOES_CONVERSIONS /* convert from the network encoding */ - result = Curl_convert_from_network(data, line_start, perline); + result = Curl_convert_from_network(data, line_start, + perline); /* Curl_convert_from_network calls failf if unsuccessful */ if(result) return result; @@ -1642,14 +1643,15 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, return result; } else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + strlen("Content-Length:"), - NULL, 10); + cl = curlx_strtoofft(line_start + + strlen("Content-Length:"), NULL, 10); } else if(Curl_compareheader(line_start, "Connection:", "close")) closeConnection = TRUE; else if(Curl_compareheader(line_start, - "Transfer-Encoding:", "chunked")) { + "Transfer-Encoding:", + "chunked")) { infof(data, "CONNECT responded chunked\n"); chunked_encoding = TRUE; /* init our chunky engine */ @@ -2829,7 +2831,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!Curl_checkheaders(data, "Content-Type:")) { result = Curl_add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); + "Content-Type: application/" + "x-www-form-urlencoded\r\n"); if(result) return result; } -- cgit v1.2.1 From 7aef172a347a0422a0968fde9c487639ff673383 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 4 Feb 2010 19:44:31 +0000 Subject: fix printf-style format strings --- lib/http.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 15943202e..9820b8f62 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1305,7 +1305,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, char *host_port; Curl_send_buffer *req_buffer; - infof(data, "Establish HTTP proxy tunnel to %s:%d\n", + infof(data, "Establish HTTP proxy tunnel to %s:%hu\n", hostname, remote_port); if(data->req.newurl) { @@ -1322,7 +1322,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(!req_buffer) return CURLE_OUT_OF_MEMORY; - host_port = aprintf("%s:%d", hostname, remote_port); + host_port = aprintf("%s:%hu", hostname, remote_port); if(!host_port) { free(req_buffer); return CURLE_OUT_OF_MEMORY; @@ -1357,7 +1357,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* BLOCKING */ result = Curl_add_bufferf(req_buffer, - "CONNECT %s:%d HTTP/%s\r\n" + "CONNECT %s:%hu HTTP/%s\r\n" "%s" /* Host: */ "%s" /* Proxy-Authorization */ "%s" /* User-Agent */ @@ -1525,7 +1525,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, keepon = FALSE; } else - infof(data, "Read %d bytes of chunk, continue\n", + infof(data, "Read %zd bytes of chunk, continue\n", tookcareof); } } @@ -1596,7 +1596,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, attention so that this is cleared again when this function returns! */ k->ignorebody = TRUE; - infof(data, "%d bytes of chunk left\n", gotbytes-i); + infof(data, "%zd bytes of chunk left\n", gotbytes-i); if(line_start[1] == '\n') { /* this can only be a LF if the letter at index 0 @@ -1615,7 +1615,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, keepon = FALSE; } else - infof(data, "Read %d bytes of chunk, continue\n", + infof(data, "Read %zd bytes of chunk, continue\n", gotbytes); } else { @@ -2284,7 +2284,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) host, conn->bits.ipv6_ip?"]":""); else - conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n", conn->bits.ipv6_ip?"[":"", host, conn->bits.ipv6_ip?"]":"", -- cgit v1.2.1 From 01fb0d8497af5465b4213fb5a6eddeab351ba8ec Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 25 Feb 2010 08:09:05 +0000 Subject: fix compiler warning --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9820b8f62..b6c01395a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3063,6 +3063,8 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, #ifndef CURL_DISABLE_RTSP if(conn->protocol & PROT_RTSP) return checkrtspprefix(data, s); +#else + (void)conn; #endif /* CURL_DISABLE_RTSP */ return checkhttpprefix(data, s); -- cgit v1.2.1 From 7fd32ce73d7e253df1e8067d45d50ef9d5290cbd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Mar 2010 15:26:45 +0100 Subject: chunked-encoding with Content-Length: header problem Akos Pasztory filed debian bug report #572276 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572276 mentioning a problem with a resource that returns chunked-encoded _and_ with a Content-Length and libcurl failed to properly ignore the latter information. --- lib/http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b6c01395a..d4b99fd58 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3338,8 +3338,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, using chunked Transfer-Encoding. */ if(k->chunk) - k->size=-1; - + k->maxdownload = k->size = -1; } if(-1 != k->size) { /* We do this operation even if no_body is true, since this -- cgit v1.2.1 From 2309b4e330b96bc2e1f8e36b6184015e59544037 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2010 11:02:54 +0100 Subject: remove the CVSish $Id$ lines --- lib/http.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d4b99fd58..7ffc34d49 100644 --- a/lib/http.c +++ b/lib/http.c @@ -18,7 +18,6 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ #include "setup.h" -- cgit v1.2.1 From c2888604d7ead19473b5621f8f2edab60fc418de Mon Sep 17 00:00:00 2001 From: Jerome Vouillon Date: Fri, 16 Apr 2010 22:43:01 +0200 Subject: GnuTLS: make the connection phase non-blocking When multi interface is used, the SSL handshake is no longer blocking when GnuTLS is used. --- lib/http.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7ffc34d49..99d34e661 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1817,9 +1817,9 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) } #endif -#ifdef USE_SSLEAY -/* This function is OpenSSL-specific. It should be made to query the generic - SSL layer instead. */ +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) +/* This function is for OpenSSL and GnuTLS only. It should be made to query + the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -1844,17 +1844,6 @@ static int https_getsock(struct connectdata *conn, return CURLE_OK; } #else -#ifdef USE_GNUTLS -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; - return GETSOCK_BLANK; -} -#else #ifdef USE_NSS static int https_getsock(struct connectdata *conn, curl_socket_t *socks, @@ -1879,7 +1868,6 @@ static int https_getsock(struct connectdata *conn, #endif #endif #endif -#endif /* * Curl_http_done() gets called from Curl_done() after a single HTTP request -- cgit v1.2.1 From c0111460b0689d74731cc56ff019cc869a0d16a8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 16 Apr 2010 23:43:04 +0200 Subject: Curl_setup_transfer: no longer returns anything This function could only return CURLE_OK and by changing it to a void instead, we can simplify code all over. --- lib/http.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 99d34e661..cfc09cd5e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2653,14 +2653,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - -1, NULL); + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, + -1, NULL); break; } @@ -2728,10 +2727,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, FIRSTSOCKET, + &http->writebytecount); if(result) { Curl_formclean(&http->sendit); /* free that whole lot */ @@ -2781,10 +2779,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending PUT request"); else /* prepare for transfer */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, postsize?FIRSTSOCKET:-1, + postsize?&http->writebytecount:NULL); if(result) return result; break; @@ -2931,11 +2928,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) failf(data, "Failed sending HTTP POST request"); else - result = - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, + &http->readbytecount, http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); break; default: @@ -2951,10 +2946,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, + http->postdata?FIRSTSOCKET:-1, + http->postdata?&http->writebytecount:NULL); } if(result) return result; -- cgit v1.2.1 From 51427e1947ddc07b4ce8ad9dcb04846125170f83 Mon Sep 17 00:00:00 2001 From: Hoi-Ho Chan Date: Wed, 5 May 2010 22:30:46 +0200 Subject: PolarSSL: initial support added This is Hoi-Ho Chan's patch with some minor fixes by me. There are some potential issues in this, but none worse than we can sort out on the list and over time. --- lib/http.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cfc09cd5e..fc01ee889 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1865,6 +1865,18 @@ static int https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } +#else +#ifdef USE_POLARSSL +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif #endif #endif #endif -- cgit v1.2.1 From d64bd82bdcb169d0647a80f00068cedd761f8163 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 7 May 2010 15:05:34 +0200 Subject: sendrecv: split the I/O handling into private handler Howard Chu brought the bulk work of this patch that properly moves out the sending and recving of data to the parts of the code that are properly responsible for the various ways of doing so. Daniel Stenberg assisted with polishing a few bits and fixed some minor flaws in the original patch. Another upside of this patch is that we now abuse CURLcodes less with the "magic" -1 return codes and instead use CURLE_AGAIN more consistently. --- lib/http.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fc01ee889..d510e6a9e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1283,7 +1283,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, struct SessionHandle *data=conn->data; struct SingleRequest *k = &data->req; CURLcode result; - int res; long timeout = data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ curl_socket_t tunnelsocket = conn->sock[sockindex]; @@ -1467,11 +1466,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, break; default: DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); - res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); - if(res< 0) - /* EWOULDBLOCK */ + result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); + if(result==CURLE_AGAIN) continue; /* go loop yourself */ - else if(res) + else if(result) keepon = FALSE; else if(gotbytes <= 0) { keepon = FALSE; -- cgit v1.2.1 From e01cc7737c92897fb8286e3df6392ab434cdced6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 6 Jul 2010 22:50:21 +0200 Subject: http: don't enable chunked during authentication negotiations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As mentioned in bug report #2956968, the HTTP code wouldn't send the first empty chunk during the auth negotiation phase of the HTTP request sending, so the server would wait for data to come and libcurl would wait for data to arrive... I've made the code not enable chunked encoding until the auth negotiation is done and thus this scenario doesn't occur anymore. Reported by: Sidney San Martín Bug: http://curl.haxx.se/bug/view.cgi?id=2956968 --- lib/http.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d510e6a9e..93a5e3e33 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2222,7 +2222,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if((conn->protocol&PROT_HTTP) && data->set.upload && (data->set.infilesize == -1)) { - if (use_http_1_1(data, conn)) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ + ; + else if(use_http_1_1(data, conn)) { /* HTTP, upload, unknown file size and not HTTP 1.0 */ data->req.upload_chunky = TRUE; } -- cgit v1.2.1 From 6d2ccfed48558f171c2840c3aa479261050d084a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 24 Jul 2010 22:52:35 +0200 Subject: add_buffer_send: fix compiler warning Win64's 32 bit long but 64 bit size_t caused a warning that we avoid with a typecast. A small whitespace indent fix was also applied. Reported by: Adam Light --- lib/http.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 93a5e3e33..ddec280f4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -977,12 +977,15 @@ Curl_send_buffer *Curl_add_buffer_init(void) * Returns CURLcode */ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, - struct connectdata *conn, - long *bytes_written, /* add the number of sent bytes - to this counter */ - size_t included_body_bytes, /* how much of the buffer - contains body data */ - int socketindex) + struct connectdata *conn, + + /* add the number of sent bytes to this + counter */ + long *bytes_written, + + /* how much of the buffer contains body data */ + size_t included_body_bytes, + int socketindex) { ssize_t amount; @@ -1069,7 +1072,10 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, accordingly */ http->writebytecount += bodylen; - *bytes_written += amount; + /* 'amount' can never be a very large value here so typecasting it so a + signed 31 bit value should not cause problems even if ssize_t is + 64bit */ + *bytes_written += (long)amount; if(http) { if((size_t)amount != size) { @@ -1380,7 +1386,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(CURLE_OK == result) { /* Now send off the request */ result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); + &data->info.request_size, 0, sockindex); } req_buffer = NULL; if(result) -- cgit v1.2.1 From 5d5dd08e775732beec24a1041f8cb9b62e311188 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Aug 2010 00:07:06 +0200 Subject: indent: white space fixes only --- lib/http.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ddec280f4..926d51f2b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2536,7 +2536,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* url */ if (paste_ftp_userpwd) result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", - conn->user, conn->passwd, ppath + sizeof("ftp://") - 1); + conn->user, conn->passwd, + ppath + sizeof("ftp://") - 1); else result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); if (result) @@ -2741,7 +2742,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* fire away the whole request to the server */ result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); else @@ -2793,7 +2794,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* this sends the buffer and frees all the buffer resources */ result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending PUT request"); else @@ -2942,7 +2943,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* issue the request */ result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); + (size_t)included_body, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP POST request"); @@ -2959,7 +2960,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* issue the request */ result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP request"); -- cgit v1.2.1 From 6b490ed33c3ffc4ac96719df7f8c5df46476579a Mon Sep 17 00:00:00 2001 From: Julien Chaffraix Date: Mon, 16 Aug 2010 22:54:19 +0200 Subject: progress: callback for POSTs less than MAX_INITIAL_POST_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a call to Curl_pgrsSetUploadSize in this case valided by a test case. Reported by: Ðикита Дорохин. Bug: http://curl.haxx.se/mail/lib-2010-04/0173.html --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 926d51f2b..2d0e78af3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2894,6 +2894,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } if(result) return result; + /* Make sure the progress information is accurate */ + Curl_pgrsSetUploadSize(data, postsize); } else { /* A huge POST coming up, do data separate from the request */ -- cgit v1.2.1 From 6b6a3bcb61f2d8f4e80a1e2a5bc62e78904256ed Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 25 Aug 2010 13:42:14 +0200 Subject: http: handle trailer headers in all chunked responses HTTP allows that a server sends trailing headers after all the chunks have been sent WITHOUT signalling their presence in the first response headers. The "Trailer:" header is only a SHOULD there and as we need to handle the situation even without that header I made libcurl ignore Trailer: completely. Test case 1116 was added to verify this and to make sure we handle more than one trailer header properly. Reported by: Patrick McManus Bug: http://curl.haxx.se/bug/view.cgi?id=3052450 --- lib/http.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2d0e78af3..3d6f977ea 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3647,20 +3647,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* init our chunky engine */ Curl_httpchunk_init(conn); } - - else if(checkprefix("Trailer:", k->p) || - checkprefix("Trailers:", k->p)) { - /* - * This test helps Curl_httpchunk_read() to determine to look - * for well formed trailers after the zero chunksize record. In - * this case a CRLF is required after the zero chunksize record - * when no trailers are sent, or after the last trailer record. - * - * It seems both Trailer: and Trailers: occur in the wild. - */ - k->trailerhdrpresent = TRUE; - } - else if(checkprefix("Content-Encoding:", k->p) && data->set.str[STRING_ENCODING]) { /* -- cgit v1.2.1 From 2ae6c47d5dfdff2d6d884284beb6b0322e8ac671 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 2 Oct 2010 00:22:48 +0200 Subject: HTTP: remove special case for 416 It was pointed out that the special case libcurl did for 416 was incorrect and wrong. 416 is not really different to other errors so the response body must be handled like for other errors/http responses. Reported by: Chris Smowton Bug: http://curl.haxx.se/bug/view.cgi?id=3076808 --- lib/http.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3d6f977ea..413ef3d89 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3293,13 +3293,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, data->req.deductheadercount = (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; - if(data->state.resume_from && - (data->set.httpreq==HTTPREQ_GET) && - (k->httpcode == 416)) { - /* "Requested Range Not Satisfiable" */ - *stop_reading = TRUE; - } - if(!*stop_reading) { /* Curl_http_auth_act() checks what authentication methods * that are available and decides which one (if any) to @@ -3512,9 +3505,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, * message-body, and thus is always terminated by the first * empty line after the header fields. */ /* FALLTHROUGH */ - case 416: /* Requested Range Not Satisfiable, it has the - Content-Length: set as the "real" document but no - actual response is sent. */ case 304: /* (quote from RFC2616, section 10.3.5): The 304 response * MUST NOT contain a message-body, and thus is always @@ -3546,10 +3536,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* Curl_convert_from_network calls failf if unsuccessful */ #endif /* CURL_DOES_CONVERSIONS */ - /* Check for Content-Length: header lines to get size. Ignore - the header completely if we get a 416 response as then we're - resuming a document that we don't get, and this header contains - info about the true size of the document we didn't get now. */ + /* Check for Content-Length: header lines to get size */ if(!k->ignorecl && !data->set.ignorecl && checkprefix("Content-Length:", k->p)) { curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10); -- cgit v1.2.1 From e8c442952d53d493e347a784d53d602359b4331c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Oct 2010 14:57:43 +0200 Subject: formdata: provide error message When failing to build form post due to an error, the code now does a proper failf(). Previously libcurl would report an error like "failed creating formpost data" when a file wasn't possible to open which was not easy for users to figure out. I also lower cased a function name to be named more curl-style and removed some unnecessary code. --- lib/http.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 413ef3d89..ed0730c0a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2375,19 +2375,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #endif /* CURL_DISABLE_PROXY */ if(HTTPREQ_POST_FORM == httpreq) { - /* we must build the whole darned post sequence first, so that we have - a size of the whole shebang before we start to send it */ - result = Curl_getFormData(&http->sendit, data->set.httppost, - Curl_checkheaders(data, "Content-Type:"), - &http->postsize); - if(CURLE_OK != result) { - /* Curl_getFormData() doesn't use failf() */ - failf(data, "failed creating formpost data"); - return result; - } + /* we must build the whole post sequence first, so that we have a size of + the whole transfer before we start to send it */ + result = Curl_getformdata(data, &http->sendit, data->set.httppost, + Curl_checkheaders(data, "Content-Type:"), + &http->postsize); + if(result) + return result; } - http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; if(( (HTTPREQ_POST == httpreq) || -- cgit v1.2.1 From afecd1aa13b4f40c54d195514af113715b0e0f9f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 4 Nov 2010 14:58:15 +0100 Subject: host: get the custom Host: name more genericly When given a custom host name in a Host: header, we can use it for several different purposes other than just cookies, so we rename it and use it for SSL SNI etc. --- lib/http.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ed0730c0a..0804ce050 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2254,26 +2254,25 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ptr = Curl_checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || Curl_raw_equal(data->state.first_host, conn->host.name))) { -#if !defined(CURL_DISABLE_COOKIES) + /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the custom Host: header if this is NOT a redirect, as setting Host: in the redirected request is being out on thin ice. Except if the host name is the same as the first one! */ - char *cookiehost = Curl_copy_header_value(ptr); - if (!cookiehost) + char *chost = Curl_copy_header_value(ptr); + if (!chost) return CURLE_OUT_OF_MEMORY; - if (!*cookiehost) + if (!*chost) /* ignore empty data */ - free(cookiehost); + free(chost); else { - char *colon = strchr(cookiehost, ':'); + char *colon = strchr(chost, ':'); if (colon) *colon = 0; /* The host must not include an embedded port number */ - Curl_safefree(conn->allocptr.cookiehost); - conn->allocptr.cookiehost = cookiehost; + Curl_safefree(conn->allocptr.customhost); + conn->allocptr.customhost = chost; } -#endif conn->allocptr.host = NULL; } @@ -2597,8 +2596,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->cookies) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, + conn->allocptr.customhost? + conn->allocptr.customhost:host, data->state.path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); @@ -3689,8 +3688,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, data->cookies, TRUE, k->p+11, /* If there is a custom-set Host: name, use it here, or else use real peer host name. */ - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:conn->host.name, + conn->allocptr.customhost? + conn->allocptr.customhost:conn->host.name, data->state.path); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } -- cgit v1.2.1 From 87374a47c9d22521c8d31f1c4952db5fdb479903 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Nov 2010 10:24:22 +0100 Subject: Revert: use Host: name for SNI and cert name checks This reverts commit b0fd03f5b8d4520dd232a9d13567d16bd0ad8951, 4b2fbe1e97891f, afecd1aa13b4f, 68cde058f66b3 --- lib/http.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0804ce050..ed0730c0a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2254,25 +2254,26 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) ptr = Curl_checkheaders(data, "Host:"); if(ptr && (!data->state.this_is_a_follow || Curl_raw_equal(data->state.first_host, conn->host.name))) { - +#if !defined(CURL_DISABLE_COOKIES) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the custom Host: header if this is NOT a redirect, as setting Host: in the redirected request is being out on thin ice. Except if the host name is the same as the first one! */ - char *chost = Curl_copy_header_value(ptr); - if (!chost) + char *cookiehost = Curl_copy_header_value(ptr); + if (!cookiehost) return CURLE_OUT_OF_MEMORY; - if (!*chost) + if (!*cookiehost) /* ignore empty data */ - free(chost); + free(cookiehost); else { - char *colon = strchr(chost, ':'); + char *colon = strchr(cookiehost, ':'); if (colon) *colon = 0; /* The host must not include an embedded port number */ - Curl_safefree(conn->allocptr.customhost); - conn->allocptr.customhost = chost; + Curl_safefree(conn->allocptr.cookiehost); + conn->allocptr.cookiehost = cookiehost; } +#endif conn->allocptr.host = NULL; } @@ -2596,8 +2597,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->cookies) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); co = Curl_cookie_getlist(data->cookies, - conn->allocptr.customhost? - conn->allocptr.customhost:host, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:host, data->state.path, (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); @@ -3688,8 +3689,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, data->cookies, TRUE, k->p+11, /* If there is a custom-set Host: name, use it here, or else use real peer host name. */ - conn->allocptr.customhost? - conn->allocptr.customhost:conn->host.name, + conn->allocptr.cookiehost? + conn->allocptr.cookiehost:conn->host.name, data->state.path); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } -- cgit v1.2.1 From c1901f7ed0dc43a92e611ff4cfc00ad97425318f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 4 Dec 2010 05:53:07 +0100 Subject: fix compiler warning: conversion may lose significant bits --- lib/http.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ed0730c0a..e35437f1e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -98,6 +98,7 @@ #include "rawstr.h" #include "content_encoding.h" #include "rtsp.h" +#include "warnless.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -2424,27 +2425,25 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ else { curl_off_t passed=0; - do { - size_t readthisamountnow = (size_t)(data->state.resume_from - - passed); - size_t actuallyread; - - if(readthisamountnow > BUFSIZE) - readthisamountnow = BUFSIZE; + size_t readthisamountnow = + (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? + BUFSIZE : curlx_sotouz(data->state.resume_from - passed); - actuallyread = data->set.fread_func(data->state.buffer, 1, - (size_t)readthisamountnow, - data->set.in); + size_t actuallyread = + data->set.fread_func(data->state.buffer, 1, readthisamountnow, + data->set.in); passed += actuallyread; - if(actuallyread != readthisamountnow) { + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ failf(data, "Could only read %" FORMAT_OFF_T " bytes from the input", passed); return CURLE_READ_ERROR; } - } while(passed != data->state.resume_from); /* loop until done */ + } while(passed < data->state.resume_from); } } -- cgit v1.2.1 From 108d7693a443435e39d2278d5dbf842a80c6260c Mon Sep 17 00:00:00 2001 From: Eric Hu Date: Fri, 3 Dec 2010 10:23:45 -0800 Subject: Preparing for axTLS. Actual SSL API functions are only stubbed. Added axTLS to autotool files and glue code to misc other files. axtls.h maps SSL API functions, but may change. axtls.c is just a stub file and will definitely change. --- lib/http.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e35437f1e..2cf4dd2d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1881,10 +1881,22 @@ static int https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -#endif -#endif -#endif -#endif +#else +#ifdef USE_AXTLS +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +#endif /* USE_AXTLS */ +#endif /* USE_POLARSSL */ +#endif /* USE_QSOSSL */ +#endif /* USE_NSS */ +#endif /* USE_SSLEAY || USE_GNUTLS */ /* * Curl_http_done() gets called from Curl_done() after a single HTTP request -- cgit v1.2.1 From 1d28efb9d1759bcbc81d28e462c2e3a5d60a17e4 Mon Sep 17 00:00:00 2001 From: Marcel Roelofs Date: Wed, 5 Jan 2011 17:01:07 +0100 Subject: HTTP: HTTP Negotiate authentication using SSPI Only under Windows --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2cf4dd2d3..b61426ec5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -520,7 +520,7 @@ output_auth_headers(struct connectdata *conn, struct SessionHandle *data = conn->data; const char *auth=NULL; CURLcode result = CURLE_OK; -#ifdef HAVE_GSSAPI +#ifdef USE_HTTP_NEGOTIATE struct negotiatedata *negdata = proxy? &data->state.proxyneg:&data->state.negotiate; #endif @@ -530,7 +530,7 @@ output_auth_headers(struct connectdata *conn, (void)path; #endif -#ifdef HAVE_GSSAPI +#ifdef USE_HTTP_NEGOTIATE if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && negdata->context && !GSS_ERROR(negdata->status)) { auth="GSS-Negotiate"; @@ -727,7 +727,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, * */ -#ifdef HAVE_GSSAPI +#ifdef USE_HTTP_NEGOTIATE if(checkprefix("GSS-Negotiate", start) || checkprefix("Negotiate", start)) { int neg; -- cgit v1.2.1 From dbcaa0065719acc0383307f13d02d3d0c9b5c635 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 25 Jan 2011 12:06:50 +0100 Subject: HTTP: memory leak on multiple Location: The HTTP parser allocated memory on each received Location: header without properly freeing old data. Starting now, the code only considers the first Location: header and will blissfully ignore subsequent ones. Bug: http://curl.haxx.se/bug/view.cgi?id=3165129 Reported by: Martin Lemke --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b61426ec5..40ae6b7db 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3723,7 +3723,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, return result; } else if((k->httpcode >= 300 && k->httpcode < 400) && - checkprefix("Location:", k->p)) { + checkprefix("Location:", k->p) && + !data->req.location) { /* this is the URL that the server advises us to use instead */ char *location = Curl_copy_header_value(k->p); if (!location) @@ -3732,7 +3733,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* ignore empty data */ free(location); else { - DEBUGASSERT(!data->req.location); data->req.location = location; if(data->set.http_follow_location) { -- cgit v1.2.1 From 54d9f060b4b0a8fb5fa006813e4db1ca5c1a07e8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Feb 2011 15:00:48 +0100 Subject: Curl_gmtime: added a portable gmtime Instead of polluting many places with #ifdefs, we create a single place for this function, and also check return code properly so that a NULL pointer returned won't cause problems. --- lib/http.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 40ae6b7db..b2fb7cb28 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2052,9 +2052,17 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, CURLcode Curl_add_timecondition(struct SessionHandle *data, Curl_send_buffer *req_buffer) { - struct tm *tm; + const struct tm *tm; char *buf = data->state.buffer; CURLcode result = CURLE_OK; + struct tm keeptime; + + result = Curl_gmtime(data->set.timevalue, &keeptime); + if(result) { + failf(data, "Invalid TIMEVALUE\n"); + return result; + } + tm = &keeptime; /* The If-Modified-Since header family should have their times set in * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be @@ -2063,14 +2071,6 @@ CURLcode Curl_add_timecondition(struct SessionHandle *data, * Time)." (see page 20 of RFC2616). */ -#ifdef HAVE_GMTIME_R - /* thread-safe version */ - struct tm keeptime; - tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); -#else - tm = gmtime(&data->set.timevalue); -#endif - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ snprintf(buf, BUFSIZE-1, "%s, %02d %s %4d %02d:%02d:%02d GMT", @@ -2654,7 +2654,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) #endif if(data->set.timecondition) { - result = Curl_add_timecondition(data, req_buffer); + result = Curl_add_timecondition(data, req_buffer); if(result) return result; } -- cgit v1.2.1 From d7846237a441985feb8214d0ffa5bb49590855d2 Mon Sep 17 00:00:00 2001 From: Julien Chaffraix Date: Fri, 25 Feb 2011 20:35:16 -0800 Subject: http: removed code duplication for stubbed https_getsock function. --- lib/http.c | 41 +++-------------------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b2fb7cb28..78f6ef1f8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1849,7 +1849,8 @@ static int https_getsock(struct connectdata *conn, return CURLE_OK; } #else -#ifdef USE_NSS +#if defined(USE_NSS) || defined(USE_QSOSSL) || \ + defined(USE_POLARSSL) || defined(USE_AXTLS) static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -1859,43 +1860,7 @@ static int https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -#else -#ifdef USE_QSOSSL -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; - return GETSOCK_BLANK; -} -#else -#ifdef USE_POLARSSL -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; - return GETSOCK_BLANK; -} -#else -#ifdef USE_AXTLS -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; - return GETSOCK_BLANK; -} -#endif /* USE_AXTLS */ -#endif /* USE_POLARSSL */ -#endif /* USE_QSOSSL */ -#endif /* USE_NSS */ +#endif /* USE_AXTLS || USE_POLARSSL || USE_QSOSSL || USE_NSS */ #endif /* USE_SSLEAY || USE_GNUTLS */ /* -- cgit v1.2.1 From 5719e5616805b246128f68bb282b941af949268e Mon Sep 17 00:00:00 2001 From: Julien Chaffraix Date: Fri, 25 Feb 2011 20:37:54 -0800 Subject: http: removed wrong unused comment. |premature| is used in Curl_http_done. --- lib/http.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 78f6ef1f8..121b7b2a9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1873,7 +1873,6 @@ CURLcode Curl_http_done(struct connectdata *conn, { struct SessionHandle *data = conn->data; struct HTTP *http =data->state.proto.http; - (void)premature; /* not used */ Curl_unencode_cleanup(conn); -- cgit v1.2.1 From 9e60d8fd9e9308cd2c79a13710f30a8481f5f1e6 Mon Sep 17 00:00:00 2001 From: Todd A Ouska Date: Tue, 8 Mar 2011 13:54:58 +0100 Subject: SSL: (part 2) Added CyaSSL to SSL abstraction layer This is the modified existing files commit. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 121b7b2a9..807bbeb84 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1850,7 +1850,7 @@ static int https_getsock(struct connectdata *conn, } #else #if defined(USE_NSS) || defined(USE_QSOSSL) || \ - defined(USE_POLARSSL) || defined(USE_AXTLS) + defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL) static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) -- cgit v1.2.1 From 6f0ee717c3752e06144e87b45bb56c24ce8237f7 Mon Sep 17 00:00:00 2001 From: Marcus Sundberg Date: Sun, 13 Mar 2011 00:21:07 +0100 Subject: GSS: handle reuse fix Make GSS authentication work when a curl handle is reused for multiple authenticated requests, by always setting negdata->state in output_auth_headers(). Signed-off-by: Marcus Sundberg --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 807bbeb84..419efc167 100644 --- a/lib/http.c +++ b/lib/http.c @@ -531,6 +531,7 @@ output_auth_headers(struct connectdata *conn, #endif #ifdef USE_HTTP_NEGOTIATE + negdata->state = GSS_AUTHNONE; if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && negdata->context && !GSS_ERROR(negdata->status)) { auth="GSS-Negotiate"; -- cgit v1.2.1 From 8831000bc07de463d277975a3ddfb6a31dcf14b4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Mar 2011 22:22:22 +0100 Subject: protocol handler: added flags field The protocol handler struct got a 'flags' field for special information and characteristics of the given protocol. This now enables us to move away central protocol information such as CLOSEACTION and DUALCHANNEL from single defines in a central place, out to each protocol's definition. It also made us stop abusing the protocol field for other info than the protocol, and we could start cleaning up other protocol-specific things by adding flags bits to set in the handler struct. The "protocol" field connectdata struct was removed as well and the code now refers directly to the conn->handler->protocol field instead. To make things work properly, the code now always store a conn->given pointer that points out the original handler struct so that the code can learn details from the original protocol even if conn->handler is modified along the way - for example when switching to go over a HTTP proxy. --- lib/http.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 419efc167..2a74066b0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -143,6 +143,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* disconnect */ PORT_HTTP, /* defport */ PROT_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ }; #ifdef USE_SSL @@ -163,7 +164,8 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ - PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */ + PROT_HTTP | PROT_HTTPS, /* protocol */ + PROTOPT_SSL /* flags */ }; #endif @@ -345,7 +347,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ - if(!http || !(conn->protocol & PROT_HTTP)) + if(!http || !(conn->handler->protocol & PROT_HTTP)) /* If this is still NULL, we have not reach very far and we can safely skip this rewinding stuff, or this is attempted to get used when HTTP isn't activated */ @@ -1026,7 +1028,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, } #endif /* CURL_DOES_CONVERSIONS */ - if(conn->protocol & PROT_HTTPS) { + if(conn->handler->protocol & PROT_HTTPS) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that @@ -1773,7 +1775,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(conn->protocol & PROT_HTTPS) { + if(conn->handler->protocol & PROT_HTTPS) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { result = https_connecting(conn, done); @@ -1812,7 +1814,7 @@ static int http_getsock_do(struct connectdata *conn, static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; - DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); + DEBUGASSERT((conn) && (conn->handler->protocol & PROT_HTTPS)); /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); @@ -1830,7 +1832,7 @@ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->protocol & PROT_HTTPS) { + if(conn->handler->protocol & PROT_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; if(!numsocks) @@ -2122,8 +2124,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && - data->set.upload) { + if( (conn->handler->protocol&(PROT_HTTP|PROT_FTP)) && + data->set.upload) { httpreq = HTTPREQ_PUT; } @@ -2203,7 +2205,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } else { - if((conn->protocol&PROT_HTTP) && + if((conn->handler->protocol&PROT_HTTP) && data->set.upload && (data->set.infilesize == -1)) { if(conn->bits.authneg) @@ -2259,9 +2261,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* When building Host: headers, we must put the host name within [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ - if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || - (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) - /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include + if(((conn->given->protocol&PROT_HTTPS) && + (conn->remote_port == PORT_HTTPS)) || + ((conn->given->protocol&PROT_HTTP) && + (conn->remote_port == PORT_HTTP)) ) + /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include the port number in the host string */ conn->allocptr.host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip?"[":"", @@ -2576,7 +2580,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.cookiehost? conn->allocptr.cookiehost:host, data->state.path, - (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); + (bool)(conn->handler->protocol&PROT_HTTPS? + TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } if(co) { @@ -3036,7 +3041,7 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, const char *s) { #ifndef CURL_DISABLE_RTSP - if(conn->protocol & PROT_RTSP) + if(conn->handler->protocol & PROT_RTSP) return checkrtspprefix(data, s); #else (void)conn; @@ -3212,7 +3217,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, k->header = FALSE; /* no more header to parse! */ if((k->size == -1) && !k->chunk && !conn->bits.close && - (conn->httpversion >= 11) && !(conn->protocol & PROT_RTSP)) { + (conn->httpversion >= 11) && + !(conn->handler->protocol & PROT_RTSP)) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Content-Encoding chunked have been received, according to RFC2616 section 4.4 point 5, we @@ -3373,7 +3379,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, #define HEADER1 k->p /* no conversion needed, just use k->p */ #endif /* CURL_DOES_CONVERSIONS */ - if(conn->protocol & PROT_HTTP) { + if(conn->handler->protocol & PROT_HTTP) { nc = sscanf(HEADER1, " HTTP/%d.%d %3d", &httpversion_major, @@ -3401,7 +3407,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } } - else if(conn->protocol & PROT_RTSP) { + else if(conn->handler->protocol & PROT_RTSP) { nc = sscanf(HEADER1, " RTSP/%d.%d %3d", &rtspversion_major, @@ -3592,7 +3598,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, conn->bits.close = TRUE; /* close when done */ } else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") && - !(conn->protocol & PROT_RTSP)) { + !(conn->handler->protocol & PROT_RTSP)) { /* * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding * means that the server will send a series of "chunks". Each @@ -3715,7 +3721,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } #ifndef CURL_DISABLE_RTSP - else if(conn->protocol & PROT_RTSP) { + else if(conn->handler->protocol & PROT_RTSP) { result = Curl_rtsp_parseheader(conn, k->p); if(result) return result; -- cgit v1.2.1 From 13b64d75589647f8d151e035bd2c5d340a1c37ee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 14 Mar 2011 22:52:14 +0100 Subject: protocols: use CURLPROTO_ internally The PROT_* set of internal defines for the protocols is no longer used. We now use the same bits internally as we have defined in the public header using the CURLPROTO_ prefix. This is for simplicity and because the PROT_* prefix was already used duplicated internally for a set of KRB4 values. The PROTOPT_* defines were moved up to just below the struct definition within which they are used. --- lib/http.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2a74066b0..01a78a977 100644 --- a/lib/http.c +++ b/lib/http.c @@ -142,7 +142,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTP, /* defport */ - PROT_HTTP, /* protocol */ + CURLPROTO_HTTP, /* protocol */ PROTOPT_NONE /* flags */ }; @@ -164,7 +164,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ PORT_HTTPS, /* defport */ - PROT_HTTP | PROT_HTTPS, /* protocol */ + CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ PROTOPT_SSL /* flags */ }; #endif @@ -347,7 +347,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn) curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ - if(!http || !(conn->handler->protocol & PROT_HTTP)) + if(!http || !(conn->handler->protocol & CURLPROTO_HTTP)) /* If this is still NULL, we have not reach very far and we can safely skip this rewinding stuff, or this is attempted to get used when HTTP isn't activated */ @@ -1028,7 +1028,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, } #endif /* CURL_DOES_CONVERSIONS */ - if(conn->handler->protocol & PROT_HTTPS) { + if(conn->handler->protocol & CURLPROTO_HTTPS) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that @@ -1775,7 +1775,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(conn->handler->protocol & PROT_HTTPS) { + if(conn->handler->protocol & CURLPROTO_HTTPS) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { result = https_connecting(conn, done); @@ -1814,7 +1814,7 @@ static int http_getsock_do(struct connectdata *conn, static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; - DEBUGASSERT((conn) && (conn->handler->protocol & PROT_HTTPS)); + DEBUGASSERT((conn) && (conn->handler->protocol & CURLPROTO_HTTPS)); /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); @@ -1832,7 +1832,7 @@ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->handler->protocol & PROT_HTTPS) { + if(conn->handler->protocol & CURLPROTO_HTTPS) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; if(!numsocks) @@ -2124,7 +2124,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if( (conn->handler->protocol&(PROT_HTTP|PROT_FTP)) && + if( (conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && data->set.upload) { httpreq = HTTPREQ_PUT; } @@ -2205,7 +2205,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } else { - if((conn->handler->protocol&PROT_HTTP) && + if((conn->handler->protocol&CURLPROTO_HTTP) && data->set.upload && (data->set.infilesize == -1)) { if(conn->bits.authneg) @@ -2261,9 +2261,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* When building Host: headers, we must put the host name within [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ - if(((conn->given->protocol&PROT_HTTPS) && + if(((conn->given->protocol&CURLPROTO_HTTPS) && (conn->remote_port == PORT_HTTPS)) || - ((conn->given->protocol&PROT_HTTP) && + ((conn->given->protocol&CURLPROTO_HTTP) && (conn->remote_port == PORT_HTTP)) ) /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include the port number in the host string */ @@ -2580,7 +2580,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.cookiehost? conn->allocptr.cookiehost:host, data->state.path, - (bool)(conn->handler->protocol&PROT_HTTPS? + (bool)(conn->handler->protocol&CURLPROTO_HTTPS? TRUE:FALSE)); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } @@ -3041,7 +3041,7 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, const char *s) { #ifndef CURL_DISABLE_RTSP - if(conn->handler->protocol & PROT_RTSP) + if(conn->handler->protocol & CURLPROTO_RTSP) return checkrtspprefix(data, s); #else (void)conn; @@ -3218,7 +3218,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, if((k->size == -1) && !k->chunk && !conn->bits.close && (conn->httpversion >= 11) && - !(conn->handler->protocol & PROT_RTSP)) { + !(conn->handler->protocol & CURLPROTO_RTSP)) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Content-Encoding chunked have been received, according to RFC2616 section 4.4 point 5, we @@ -3379,7 +3379,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, #define HEADER1 k->p /* no conversion needed, just use k->p */ #endif /* CURL_DOES_CONVERSIONS */ - if(conn->handler->protocol & PROT_HTTP) { + if(conn->handler->protocol & CURLPROTO_HTTP) { nc = sscanf(HEADER1, " HTTP/%d.%d %3d", &httpversion_major, @@ -3407,7 +3407,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } } - else if(conn->handler->protocol & PROT_RTSP) { + else if(conn->handler->protocol & CURLPROTO_RTSP) { nc = sscanf(HEADER1, " RTSP/%d.%d %3d", &rtspversion_major, @@ -3598,7 +3598,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, conn->bits.close = TRUE; /* close when done */ } else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") && - !(conn->handler->protocol & PROT_RTSP)) { + !(conn->handler->protocol & CURLPROTO_RTSP)) { /* * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding * means that the server will send a series of "chunks". Each @@ -3721,7 +3721,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } #ifndef CURL_DISABLE_RTSP - else if(conn->handler->protocol & PROT_RTSP) { + else if(conn->handler->protocol & CURLPROTO_RTSP) { result = Curl_rtsp_parseheader(conn, k->p); if(result) return result; -- cgit v1.2.1 From 02dbfa21921aded6bba292b99dd224fe450e7254 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 4 Apr 2011 16:24:37 +0200 Subject: http-proxy: move proxy code to http_proxy.c The new http_proxy.* files now host HTTP proxy specific code (500+ lines moved out from http.c), and as a consequence there is a macro introduced for the Curl_proxyCONNECT() function so that code can use it without actually supporting proxy (or HTTP) in builds. --- lib/http.c | 486 +------------------------------------------------------------ 1 file changed, 8 insertions(+), 478 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 01a78a977..175ec7be7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -98,6 +98,7 @@ #include "rawstr.h" #include "content_encoding.h" #include "rtsp.h" +#include "http_proxy.h" #include "warnless.h" #define _MPRINTF_REPLACE /* use our functions only */ @@ -106,9 +107,6 @@ /* The last #include file should be: */ #include "memdebug.h" -/* Default proxy timeout in milliseconds */ -#define PROXY_TIMEOUT (3600*1000) - /* * Forward declarations. */ @@ -609,12 +607,12 @@ output_auth_headers(struct connectdata *conn, * * @returns CURLcode */ -static CURLcode -http_output_auth(struct connectdata *conn, - const char *request, - const char *path, - bool proxytunnel) /* TRUE if this is the request setting - up the proxy tunnel */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel) /* TRUE if this is the request setting + up the proxy tunnel */ { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; @@ -1270,474 +1268,6 @@ Curl_compareheader(const char *headerline, /* line to check */ return FALSE; /* no match */ } -#ifndef CURL_DISABLE_PROXY -/* - * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This - * function will issue the necessary commands to get a seamless tunnel through - * this proxy. After that, the socket can be used just as a normal socket. - * - * This badly needs to be rewritten. CONNECT should be sent and dealt with - * like any ordinary HTTP request, and not specially crafted like this. This - * function only remains here like this for now since the rewrite is a bit too - * much work to do at the moment. - * - * This function is BLOCKING which is nasty for all multi interface using apps. - */ - -CURLcode Curl_proxyCONNECT(struct connectdata *conn, - int sockindex, - const char *hostname, - unsigned short remote_port) -{ - int subversion=0; - struct SessionHandle *data=conn->data; - struct SingleRequest *k = &data->req; - CURLcode result; - long timeout = - data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ - curl_socket_t tunnelsocket = conn->sock[sockindex]; - curl_off_t cl=0; - bool closeConnection = FALSE; - bool chunked_encoding = FALSE; - long check; - -#define SELECT_OK 0 -#define SELECT_ERROR 1 -#define SELECT_TIMEOUT 2 - int error = SELECT_OK; - - conn->bits.proxy_connect_closed = FALSE; - - do { - if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ - char *host_port; - Curl_send_buffer *req_buffer; - - infof(data, "Establish HTTP proxy tunnel to %s:%hu\n", - hostname, remote_port); - - if(data->req.newurl) { - /* This only happens if we've looped here due to authentication - reasons, and we don't really use the newly cloned URL here - then. Just free() it. */ - free(data->req.newurl); - data->req.newurl = NULL; - } - - /* initialize a dynamic send-buffer */ - req_buffer = Curl_add_buffer_init(); - - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; - - host_port = aprintf("%s:%hu", hostname, remote_port); - if(!host_port) { - free(req_buffer); - return CURLE_OUT_OF_MEMORY; - } - - /* Setup the proxy-authorization header, if any */ - result = http_output_auth(conn, "CONNECT", host_port, TRUE); - - if(CURLE_OK == result) { - char *host=(char *)""; - const char *proxyconn=""; - const char *useragent=""; - const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? - "1.0" : "1.1"; - - if(!Curl_checkheaders(data, "Host:")) { - host = aprintf("Host: %s\r\n", host_port); - if(!host) { - free(req_buffer); - free(host_port); - return CURLE_OUT_OF_MEMORY; - } - } - if(!Curl_checkheaders(data, "Proxy-Connection:")) - proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - - if(!Curl_checkheaders(data, "User-Agent:") && - data->set.str[STRING_USERAGENT]) - useragent = conn->allocptr.uagent; - - /* Send the connect request to the proxy */ - /* BLOCKING */ - result = - Curl_add_bufferf(req_buffer, - "CONNECT %s:%hu HTTP/%s\r\n" - "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ - hostname, remote_port, http, - host, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - useragent, - proxyconn); - - if(host && *host) - free(host); - - if(CURLE_OK == result) - result = Curl_add_custom_headers(conn, req_buffer); - - if(CURLE_OK == result) - /* CRLF terminate the request */ - result = Curl_add_bufferf(req_buffer, "\r\n"); - - if(CURLE_OK == result) { - /* Now send off the request */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); - } - req_buffer = NULL; - if(result) - failf(data, "Failed sending CONNECT to proxy"); - } - free(host_port); - Curl_safefree(req_buffer); - if(result) - return result; - - conn->bits.tunnel_connecting = TRUE; - } /* END CONNECT PHASE */ - - /* now we've issued the CONNECT and we're waiting to hear back - - we try not to block here in multi-mode because that might be a LONG - wait if the proxy cannot connect-through to the remote host. */ - - /* if timeout is requested, find out how much remaining time we have */ - check = timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - if(check <= 0) { - failf(data, "Proxy CONNECT aborted due to timeout"); - return CURLE_RECV_ERROR; - } - - /* if we're in multi-mode and we would block, return instead for a retry */ - if(Curl_if_multi == data->state.used_interface) { - if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) - /* return so we'll be called again polling-style */ - return CURLE_OK; - else { - DEBUGF(infof(data, - "Multi mode finished polling for response from " - "proxy CONNECT.")); - } - } - else { - DEBUGF(infof(data, "Easy mode waiting response from proxy CONNECT.")); - } - - /* at this point, either: - 1) we're in easy-mode and so it's okay to block waiting for a CONNECT - response - 2) we're in multi-mode and we didn't block - it's either an error or we - now have some data waiting. - In any case, the tunnel_connecting phase is over. */ - conn->bits.tunnel_connecting = FALSE; - - { /* BEGIN NEGOTIATION PHASE */ - size_t nread; /* total size read */ - int perline; /* count bytes per line */ - int keepon=TRUE; - ssize_t gotbytes; - char *ptr; - char *line_start; - - ptr=data->state.buffer; - line_start = ptr; - - nread=0; - perline=0; - keepon=TRUE; - - while((nreadnow); /* spent time */ - if(check <= 0) { - failf(data, "Proxy CONNECT aborted due to timeout"); - error = SELECT_TIMEOUT; /* already too little time */ - break; - } - - /* loop every second at least, less if the timeout is near */ - switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, - check<1000L?(int)check:1000)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select/poll error"); - break; - case 0: /* timeout */ - break; - default: - DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); - result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); - if(result==CURLE_AGAIN) - continue; /* go loop yourself */ - else if(result) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - if(data->set.proxyauth && data->state.authproxy.avail) { - /* proxy auth was requested and there was proxy auth available, - then deem this as "mere" proxy disconnect */ - conn->bits.proxy_connect_closed = TRUE; - } - else { - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); - } - } - else { - /* - * We got a whole chunk of data, which can be anything from one - * byte to a set of lines and possibly just a piece of the last - * line. - */ - int i; - - nread += gotbytes; - - if(keepon > TRUE) { - /* This means we are currently ignoring a response-body */ - - nread = 0; /* make next read start over in the read buffer */ - ptr=data->state.buffer; - if(cl) { - /* A Content-Length based body: simply count down the counter - and make sure to break out of the loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; - } - } - else { - /* chunked-encoded body, so we need to do the chunked dance - properly to know when the end of the body is reached */ - CHUNKcode r; - ssize_t tookcareof=0; - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - tookcareof); - } - } - else - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr == 0x0a) { - char letter; - int writetype; - -#ifdef CURL_DOES_CONVERSIONS - /* convert from the network encoding */ - result = Curl_convert_from_network(data, line_start, - perline); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(result) - return result; -#endif /* CURL_DOES_CONVERSIONS */ - - /* output debug if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - line_start, (size_t)perline, conn); - - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - result = Curl_client_write(conn, writetype, line_start, - perline); - if(result) - return result; - - /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes. Treat a following CR - as end-of-headers as well.*/ - - if(('\r' == line_start[0]) || - ('\n' == line_start[0])) { - /* end of response-headers from the proxy */ - nread = 0; /* make next read start over in the read - buffer */ - ptr=data->state.buffer; - if((407 == k->httpcode) && !data->state.authproblem) { - /* If we get a 407 response code with content length - when we have no auth problem, we must ignore the - whole response-body */ - keepon = 2; - - if(cl) { - - infof(data, "Ignore %" FORMAT_OFF_T - " bytes of response-body\n", cl); - /* remove the remaining chunk of what we already - read */ - cl -= (gotbytes - i); - - if(cl<=0) - /* if the whole thing was already read, we are done! - */ - keepon=FALSE; - } - else if(chunked_encoding) { - CHUNKcode r; - /* We set ignorebody true here since the chunked - decoder function will acknowledge that. Pay - attention so that this is cleared again when this - function returns! */ - k->ignorebody = TRUE; - infof(data, "%zd bytes of chunk left\n", gotbytes-i); - - if(line_start[1] == '\n') { - /* this can only be a LF if the letter at index 0 - was a CR */ - line_start++; - i++; - } - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, line_start+1, - gotbytes -i, &gotbytes); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - gotbytes); - } - else { - /* without content-length or chunked encoding, we - can't keep the connection alive since the close is - the end signal so we bail out at once instead */ - keepon=FALSE; - } - } - else - keepon = FALSE; - break; /* breaks out of for-loop, not switch() */ - } - - /* keep a backup of the position we are about to blank */ - letter = line_start[perline]; - line_start[perline]=0; /* zero terminate the buffer */ - if((checkprefix("WWW-Authenticate:", line_start) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", line_start) && - (407 == k->httpcode))) { - result = Curl_http_input_auth(conn, k->httpcode, - line_start); - if(result) - return result; - } - else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + - strlen("Content-Length:"), NULL, 10); - } - else if(Curl_compareheader(line_start, - "Connection:", "close")) - closeConnection = TRUE; - else if(Curl_compareheader(line_start, - "Transfer-Encoding:", - "chunked")) { - infof(data, "CONNECT responded chunked\n"); - chunked_encoding = TRUE; - /* init our chunky engine */ - Curl_httpchunk_init(conn); - } - else if(Curl_compareheader(line_start, - "Proxy-Connection:", "close")) - closeConnection = TRUE; - else if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &k->httpcode)) { - /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode; - } - /* put back the letter we blanked out before */ - line_start[perline]= letter; - - perline=0; /* line starts over here */ - line_start = ptr+1; /* this skips the zero byte we wrote */ - } - } - } - break; - } /* switch */ - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; - } /* while there's buffer left and loop is requested */ - - if(error) - return CURLE_RECV_ERROR; - - if(data->info.httpproxycode != 200) { - /* Deal with the possibly already received authenticate - headers. 'newurl' is set to a new URL if we must loop. */ - result = Curl_http_auth_act(conn); - if(result) - return result; - - if(conn->bits.close) - /* the connection has been marked for closure, most likely in the - Curl_http_auth_act() function and thus we can kill it at once - below - */ - closeConnection = TRUE; - } - - if(closeConnection && data->req.newurl) { - /* Connection closed by server. Don't use it anymore */ - sclose(conn->sock[sockindex]); - conn->sock[sockindex] = CURL_SOCKET_BAD; - break; - } - } /* END NEGOTIATION PHASE */ - } while(data->req.newurl); - - if(200 != data->req.httpcode) { - failf(data, "Received HTTP code %d from proxy after CONNECT", - data->req.httpcode); - - if(closeConnection && data->req.newurl) - conn->bits.proxy_connect_closed = TRUE; - - return CURLE_RECV_ERROR; - } - - /* If a proxy-authorization header was used for the proxy, then we should - make sure that it isn't accidentally used for the document request - after we've connected. So let's free and clear it here. */ - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = NULL; - - data->state.authproxy.done = TRUE; - - infof (data, "Proxy replied OK to CONNECT request\n"); - data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ - return CURLE_OK; -} -#endif /* CURL_DISABLE_PROXY */ - /* * Curl_http_connect() performs HTTP stuff to do at connect-time, called from * the generic Curl_connect(). @@ -2166,7 +1696,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* setup the authentication headers */ - result = http_output_auth(conn, request, ppath, FALSE); + result = Curl_http_output_auth(conn, request, ppath, FALSE); if(result) return result; -- cgit v1.2.1 From 0790b2791091ca46bed3813dc7d04cd3f30e5dac Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 Apr 2011 23:24:52 +0200 Subject: HTTP: add support for gzip and deflate Transfer-Encoding Transfer-Encoding differs from Content-Encoding in a few subtle ways, but primarily it concerns the transfer only and not the content so when discovered to be compressed we know we have to uncompress it. There will only arrive compressed transfers in a response after we have requested them with the appropriate TE: header. Test case 1122 and 1123 verify. --- lib/http.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 175ec7be7..6b14fab19 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1728,6 +1728,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } +#if 0 + if(!Curl_checkheaders(data, "TE:")) { + Curl_safefree(conn->allocptr.te); + conn->allocptr.te = aprintf("TE: %s\r\n", "gzip"); + if(!conn->allocptr.te) + return CURLE_OUT_OF_MEMORY; + } +#endif + ptr = Curl_checkheaders(data, "Transfer-Encoding:"); if(ptr) { /* Some kind of TE is requested, check if 'chunked' is chosen */ @@ -2058,6 +2067,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) "%s" /* user agent */ "%s" /* host */ "%s" /* accept */ + "%s" /* TE: */ "%s" /* accept-encoding */ "%s" /* referer */ "%s" /* Proxy-Connection */ @@ -2075,6 +2085,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.uagent:"", (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_accept?http->p_accept:"", + conn->allocptr.te?conn->allocptr.te:"", (data->set.str[STRING_ENCODING] && *data->set.str[STRING_ENCODING] && conn->allocptr.accept_encoding)? @@ -3127,8 +3138,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, */ conn->bits.close = TRUE; /* close when done */ } - else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") && - !(conn->handler->protocol & CURLPROTO_RTSP)) { + else if(checkprefix("Transfer-Encoding:", k->p)) { + /* One or more encodings. We check for chunked and/or a compression + algorithm. */ /* * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding * means that the server will send a series of "chunks". Each @@ -3137,10 +3149,60 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, * with the previously mentioned size. There can be any amount * of chunks, and a chunk-data set to zero signals the * end-of-chunks. */ - k->chunk = TRUE; /* chunks coming our way */ - /* init our chunky engine */ - Curl_httpchunk_init(conn); + char *start; + + /* Find the first non-space letter */ + start = k->p + 18; + + do { + /* skip whitespaces and commas */ + while(*start && (ISSPACE(*start) || (*start == ','))) + start++; + + if(checkprefix("chunked", start)) { + k->chunk = TRUE; /* chunks coming our way */ + + /* init our chunky engine */ + Curl_httpchunk_init(conn); + + start += 7; + } + + if(k->content_encoding) + /* TODO: we only support the first mentioned compression for now */ + break; + + if(checkprefix("identity", start)) { + k->content_encoding = IDENTITY; + start += 8; + } + else if(checkprefix("deflate", start)) { + k->content_encoding = DEFLATE; + start += 7; + } + else if(checkprefix("gzip", start)) { + k->content_encoding = GZIP; + start += 4; + } + else if(checkprefix("x-gzip", start)) { + k->content_encoding = GZIP; + start += 6; + } + else if(checkprefix("compress", start)) { + k->content_encoding = COMPRESS; + start += 8; + } + else if(checkprefix("x-compress", start)) { + k->content_encoding = COMPRESS; + start += 10; + } + else + /* unknown! */ + break; + + } while(1); + } else if(checkprefix("Content-Encoding:", k->p) && data->set.str[STRING_ENCODING]) { -- cgit v1.2.1 From 2db6f7e703bda76872a0e05f2d5fe6c5a7ddaf74 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 8 Apr 2011 22:50:40 +0200 Subject: TE: rename struct field content_encoding Since this struct member is used in the code to determine what and how to decode automatically and since it is now also used for compressed Transfer-Encodings, I renamed it to the more suitable 'auto_decoding' --- lib/http.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6b14fab19..c442eebab 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3169,32 +3169,32 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, start += 7; } - if(k->content_encoding) + if(k->auto_decoding) /* TODO: we only support the first mentioned compression for now */ break; if(checkprefix("identity", start)) { - k->content_encoding = IDENTITY; + k->auto_decoding = IDENTITY; start += 8; } else if(checkprefix("deflate", start)) { - k->content_encoding = DEFLATE; + k->auto_decoding = DEFLATE; start += 7; } else if(checkprefix("gzip", start)) { - k->content_encoding = GZIP; + k->auto_decoding = GZIP; start += 4; } else if(checkprefix("x-gzip", start)) { - k->content_encoding = GZIP; + k->auto_decoding = GZIP; start += 6; } else if(checkprefix("compress", start)) { - k->content_encoding = COMPRESS; + k->auto_decoding = COMPRESS; start += 8; } else if(checkprefix("x-compress", start)) { - k->content_encoding = COMPRESS; + k->auto_decoding = COMPRESS; start += 10; } else @@ -3222,15 +3222,15 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* Record the content-encoding for later use */ if(checkprefix("identity", start)) - k->content_encoding = IDENTITY; + k->auto_decoding = IDENTITY; else if(checkprefix("deflate", start)) - k->content_encoding = DEFLATE; + k->auto_decoding = DEFLATE; else if(checkprefix("gzip", start) || checkprefix("x-gzip", start)) - k->content_encoding = GZIP; + k->auto_decoding = GZIP; else if(checkprefix("compress", start) || checkprefix("x-compress", start)) - k->content_encoding = COMPRESS; + k->auto_decoding = COMPRESS; } else if(checkprefix("Content-Range:", k->p)) { /* Content-Range: bytes [num]- -- cgit v1.2.1 From 9d191a6a40c2e90153d4b60cbc78fa34837c07ee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Apr 2011 16:30:14 +0200 Subject: TE: do the Connection: header When TE: is inserted in the request, we must add a "Connection: TE" as well to be HTTP 1.1 compliant. If a custom Connection: header is passed in, we must use that and only append TE to it. Test case 1125 verifies TE: + custom Connection:. --- lib/http.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c442eebab..8d3a085d0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1533,6 +1533,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, we will force length zero then */ checkprefix("Content-Length", headers->data)) ; + else if(conn->allocptr.te && + /* when asking for Transfer-Encoding, don't pass on a custom + Connection: */ + checkprefix("Connection", headers->data)) + ; else { CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data); @@ -1728,14 +1733,21 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } -#if 0 - if(!Curl_checkheaders(data, "TE:")) { + if(Curl_checkheaders(data, "TE:")) { + /* When we insert a TE: header in the request, we must also insert TE in a + Connection: header, so we need to merge the custom provided Connection: + header and prevent the original to get sent */ + char *cptr = Curl_checkheaders(data, "Connection:"); + Curl_safefree(conn->allocptr.te); - conn->allocptr.te = aprintf("TE: %s\r\n", "gzip"); + + /* Create the (updated) Connection: header */ + conn->allocptr.te = cptr? aprintf("%s, TE\r\n", cptr): + strdup("Connection: TE\r\n"); + if(!conn->allocptr.te) return CURLE_OUT_OF_MEMORY; } -#endif ptr = Curl_checkheaders(data, "Transfer-Encoding:"); if(ptr) { -- cgit v1.2.1 From 8e4fb01e64bee1893452f25873758cb856898d84 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 14 Apr 2011 22:45:42 +0200 Subject: transfer-encoding: added new option and cmdline Added CURLOPT_TRANSFER_ENCODING as the option to set to request Transfer Encoding in HTTP requests (if built zlib enabled). I also renamed CURLOPT_ENCODING to CURLOPT_ACCEPT_ENCODING (while keeping the old name around) to reduce the confusion when we have to encoding options for HTTP. --tr-encoding is now the new command line option for curl to request this, and thus I updated the test cases accordingly. --- lib/http.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8d3a085d0..4f2b46a59 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1733,21 +1733,28 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if(Curl_checkheaders(data, "TE:")) { - /* When we insert a TE: header in the request, we must also insert TE in a - Connection: header, so we need to merge the custom provided Connection: - header and prevent the original to get sent */ +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + + if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/hers own TE: header we don't do this magic + but then assume that the user will handle it all! */ char *cptr = Curl_checkheaders(data, "Connection:"); +#define TE_HEADER "TE: gzip\r\n" Curl_safefree(conn->allocptr.te); /* Create the (updated) Connection: header */ - conn->allocptr.te = cptr? aprintf("%s, TE\r\n", cptr): - strdup("Connection: TE\r\n"); + conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr): + strdup("Connection: TE\r\n" TE_HEADER); if(!conn->allocptr.te) return CURLE_OUT_OF_MEMORY; } +#endif ptr = Curl_checkheaders(data, "Transfer-Encoding:"); if(ptr) { -- cgit v1.2.1 From c828646f60b5bffb2bfcf924eba36da767bf08bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 00:48:20 +0200 Subject: CURL_DOES_CONVERSIONS: cleanup Massively reduce #ifdefs all over (23 #ifdef lines less so far) Moved conversion-specific code to non-ascii.c --- lib/http.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4f2b46a59..960bb4279 100644 --- a/lib/http.c +++ b/lib/http.c @@ -76,7 +76,6 @@ #include #include "transfer.h" #include "sendf.h" -#include "easyif.h" /* for Curl_convert_... prototypes */ #include "formdata.h" #include "progress.h" #include "curl_base64.h" @@ -100,6 +99,7 @@ #include "rtsp.h" #include "http_proxy.h" #include "warnless.h" +#include "non-ascii.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1014,17 +1014,15 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, DEBUGASSERT(size > included_body_bytes); -#ifdef CURL_DOES_CONVERSIONS res = Curl_convert_to_network(conn->data, ptr, headersize); /* Curl_convert_to_network calls failf if unsuccessful */ - if(res != CURLE_OK) { + if(res) { /* conversion failed, free memory and return to the caller */ if(in->buffer) free(in->buffer); free(in); return res; } -#endif /* CURL_DOES_CONVERSIONS */ if(conn->handler->protocol & CURLPROTO_HTTPS) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk @@ -2292,14 +2290,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_formclean(&http->sendit); /* free that whole lot */ return result; } -#ifdef CURL_DOES_CONVERSIONS -/* time to convert the form data... */ - result = Curl_formconvert(data, http->sendit); + + /* convert the form data */ + result = Curl_convert_form(data, http->sendit); if(result) { Curl_formclean(&http->sendit); /* free that whole lot */ return result; } -#endif /* CURL_DOES_CONVERSIONS */ + break; case HTTPREQ_PUT: /* Let's PUT the data to the server! */ @@ -2538,13 +2536,13 @@ checkhttpprefix(struct SessionHandle *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); - return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ + failf (data, "Failed to allocate memory for conversion!"); + return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { /* Curl_convert_from_network calls failf if unsuccessful */ - free(scratch); - return FALSE; /* can't return CURLE_foobar so return FALSE */ + free(scratch); + return FALSE; /* can't return CURLE_foobar so return FALSE */ } s = scratch; #endif /* CURL_DOES_CONVERSIONS */ @@ -2557,9 +2555,8 @@ checkhttpprefix(struct SessionHandle *data, head = head->next; } - if((rc != TRUE) && (checkprefix("HTTP/", s))) { + if((rc != TRUE) && (checkprefix("HTTP/", s))) rc = TRUE; - } #ifdef CURL_DOES_CONVERSIONS free(scratch); @@ -2931,10 +2928,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, res = Curl_convert_from_network(data, &scratch[0], SCRATCHSIZE); - if(CURLE_OK != res) { + if(res) /* Curl_convert_from_network calls failf if unsuccessful */ return res; - } #else #define HEADER1 k->p /* no conversion needed, just use k->p */ #endif /* CURL_DOES_CONVERSIONS */ @@ -3065,14 +3061,10 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } -#ifdef CURL_DOES_CONVERSIONS - /* convert from the network encoding */ result = Curl_convert_from_network(data, k->p, strlen(k->p)); - if(CURLE_OK != result) { - return(result); - } /* Curl_convert_from_network calls failf if unsuccessful */ -#endif /* CURL_DOES_CONVERSIONS */ + if(result) + return result; /* Check for Content-Length: header lines to get size */ if(!k->ignorecl && !data->set.ignorecl && -- cgit v1.2.1 From c2c89481909de99e37f4aee46c8bc1b1358a5988 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 22:50:04 +0200 Subject: Curl_http_connect: detect HTTPS properly after CONNECT libcurl failed to check the correct struct for HTTPS after CONNECT was issued to the proxy, so it didn't do the TLS handshake and subsequently failed the connection. A regression released in 7.21.5 (introduced around commit 8831000bc07de). Bug: http://curl.haxx.se/mail/lib-2011-04/0134.html Reported by: Josue Andrade Gomes --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 960bb4279..1e463ee69 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1303,7 +1303,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(conn->handler->protocol & CURLPROTO_HTTPS) { + if(conn->given->protocol & CURLPROTO_HTTPS) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { result = https_connecting(conn, done); -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/http.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 1e463ee69..087c5ddcb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -202,10 +202,10 @@ char *Curl_copy_header_value(const char *h) DEBUGASSERT(h); /* Find the end of the header name */ - while (*h && (*h != ':')) + while(*h && (*h != ':')) ++h; - if (*h) + if(*h) /* Skip over colon */ ++h; @@ -1485,7 +1485,7 @@ static CURLcode expect100(struct SessionHandle *data, 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ ptr = Curl_checkheaders(data, "Expect:"); - if (ptr) { + if(ptr) { data->state.expect100header = Curl_compareheader(ptr, "Expect:", "100-continue"); } @@ -1797,14 +1797,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) redirected request is being out on thin ice. Except if the host name is the same as the first one! */ char *cookiehost = Curl_copy_header_value(ptr); - if (!cookiehost) + if(!cookiehost) return CURLE_OUT_OF_MEMORY; - if (!*cookiehost) + if(!*cookiehost) /* ignore empty data */ free(cookiehost); else { char *colon = strchr(cookiehost, ':'); - if (colon) + if(colon) *colon = 0; /* The host must not include an embedded port number */ Curl_safefree(conn->allocptr.cookiehost); conn->allocptr.cookiehost = cookiehost; @@ -1882,7 +1882,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } ppath = data->change.url; if(checkprefix("ftp://", ppath)) { - if (data->set.proxy_transfer_mode) { + if(data->set.proxy_transfer_mode) { /* when doing ftp, append ;type= if not present */ char *type = strstr(ppath, ";type="); if(type && type[6] && type[7] == 0) { @@ -1899,14 +1899,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) char *p = ftp_typecode; /* avoid sending invalid URLs like ftp://example.com;type=i if the * user specified ftp://example.com without the slash */ - if (!*data->state.path && ppath[strlen(ppath) - 1] != '/') { + if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') { *p++ = '/'; } snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", data->set.prefer_ascii ? 'a' : 'i'); } } - if (conn->bits.user_passwd && !conn->bits.userpwd_in_url) + if(conn->bits.user_passwd && !conn->bits.userpwd_in_url) paste_ftp_userpwd = TRUE; } } @@ -2062,17 +2062,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* add the main request stuff */ /* GET/HEAD/POST/PUT */ result = Curl_add_bufferf(req_buffer, "%s ", request); - if (result) + if(result) return result; /* url */ - if (paste_ftp_userpwd) + if(paste_ftp_userpwd) result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", conn->user, conn->passwd, ppath + sizeof("ftp://") - 1); else result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); - if (result) + if(result) return result; result = Curl_add_bufferf(req_buffer, @@ -2983,8 +2983,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, data->info.httpcode = k->httpcode; data->info.httpversion = conn->httpversion; - if (!data->state.httpversion || - data->state.httpversion > conn->httpversion) + if(!data->state.httpversion || + data->state.httpversion > conn->httpversion) /* store the lowest server version we encounter */ data->state.httpversion = conn->httpversion; @@ -3095,9 +3095,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* check for Content-Type: header lines to get the MIME-type */ else if(checkprefix("Content-Type:", k->p)) { char *contenttype = Curl_copy_header_value(k->p); - if (!contenttype) + if(!contenttype) return CURLE_OUT_OF_MEMORY; - if (!*contenttype) + if(!*contenttype) /* ignore empty data */ free(contenttype); else { @@ -3301,9 +3301,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, !data->req.location) { /* this is the URL that the server advises us to use instead */ char *location = Curl_copy_header_value(k->p); - if (!location) + if(!location) return CURLE_OUT_OF_MEMORY; - if (!*location) + if(!*location) /* ignore empty data */ free(location); else { -- cgit v1.2.1 From 889d1e973fb718a77c5000141d724ce03863af23 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Apr 2011 23:01:30 +0200 Subject: whitespace cleanup: no space first in conditionals "if(a)" is our style, not "if( a )" --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 087c5ddcb..0f7ad14cf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1657,8 +1657,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; } - if( (conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && - data->set.upload) { + if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && + data->set.upload) { httpreq = HTTPREQ_PUT; } -- cgit v1.2.1 From 53ef3493bfd4ddaf71adea051ea530b87abfd5a9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 28 Apr 2011 09:21:20 +0200 Subject: cleanup: remove old unused debug code --- lib/http.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0f7ad14cf..2e1649134 100644 --- a/lib/http.c +++ b/lib/http.c @@ -886,16 +886,6 @@ int Curl_http_should_fail(struct connectdata *conn) ** the client needs to reauthenticate. Once that info is ** available, use it here. */ -#if 0 /* set to 1 when debugging this functionality */ - infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); - infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant); - infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); - infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); - infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); - infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ? - data->req.newurl : "(null)"); - infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); -#endif /* ** Either we're not authenticating, or we're supposed to -- cgit v1.2.1 From 574aecee208f79d391f10d57520b3eb2fcf091e6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 15:18:31 +0200 Subject: http_perhapsrewind: make it static, remove Curl_ prefix --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2e1649134..b05412c96 100644 --- a/lib/http.c +++ b/lib/http.c @@ -338,7 +338,7 @@ static bool pickoneauth(struct auth *pick) * } * } */ -CURLcode Curl_http_perhapsrewind(struct connectdata *conn) +static CURLcode http_perhapsrewind(struct connectdata *conn) { struct SessionHandle *data = conn->data; struct HTTP *http = data->state.proto.http; @@ -475,7 +475,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) if((data->set.httpreq != HTTPREQ_GET) && (data->set.httpreq != HTTPREQ_HEAD) && !conn->bits.rewindaftersend) { - code = Curl_http_perhapsrewind(conn); + code = http_perhapsrewind(conn); if(code) return code; } @@ -3307,7 +3307,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* some cases of POST and PUT etc needs to rewind the data stream at this point */ - result = Curl_http_perhapsrewind(conn); + result = http_perhapsrewind(conn); if(result) return result; } -- cgit v1.2.1 From 335dfa793c239283b0003d3f10739051c10ecb13 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 15:38:01 +0200 Subject: http_perhapsrewind: remove HTTP check No need to check for HTTP as this is now a HTTP-specific function --- lib/http.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b05412c96..f6b6a3e14 100644 --- a/lib/http.c +++ b/lib/http.c @@ -345,10 +345,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) curl_off_t bytessent; curl_off_t expectsend = -1; /* default is unknown */ - if(!http || !(conn->handler->protocol & CURLPROTO_HTTP)) - /* If this is still NULL, we have not reach very far and we can - safely skip this rewinding stuff, or this is attempted to get used - when HTTP isn't activated */ + if(!http) + /* If this is still NULL, we have not reach very far and we can safely + skip this rewinding stuff */ return CURLE_OK; switch(data->set.httpreq) { -- cgit v1.2.1 From e34131db783336aa17fa0aa664635867459b2a85 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 15:49:43 +0200 Subject: SSL: check for SSL, not specific protocols Code cleanup to check less for protocols and more for the specific relevant feature. Like if SSL is required. --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f6b6a3e14..5759a7ff2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1013,7 +1013,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, return res; } - if(conn->handler->protocol & CURLPROTO_HTTPS) { + if(conn->handler->flags & PROTOPT_SSL) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that @@ -1292,7 +1292,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(conn->given->protocol & CURLPROTO_HTTPS) { + if(conn->given->flags & PROTOPT_SSL) { /* perform SSL initialization */ if(data->state.used_interface == Curl_if_multi) { result = https_connecting(conn, done); @@ -1331,7 +1331,7 @@ static int http_getsock_do(struct connectdata *conn, static CURLcode https_connecting(struct connectdata *conn, bool *done) { CURLcode result; - DEBUGASSERT((conn) && (conn->handler->protocol & CURLPROTO_HTTPS)); + DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); /* perform SSL initialization for this socket */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); @@ -1349,7 +1349,7 @@ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->handler->protocol & CURLPROTO_HTTPS) { + if(conn->handler->flags & PROTOPT_SSL) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; if(!numsocks) -- cgit v1.2.1 From f0612f166a5fa51d09498baa19a327c5cf36941f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 16:27:03 +0200 Subject: RTSP: convert protocol-specific checks to generic Add a 'readwrite' function to the protocol handler struct and use that for the extra readwrite functionality RTSP needs. --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5759a7ff2..cc8dcffa5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -139,6 +139,7 @@ const struct Curl_handler Curl_handler_http = { http_getsock_do, /* doing_getsock */ ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ PROTOPT_NONE /* flags */ @@ -161,6 +162,7 @@ const struct Curl_handler Curl_handler_https = { http_getsock_do, /* doing_getsock */ ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ PORT_HTTPS, /* defport */ CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ PROTOPT_SSL /* flags */ -- cgit v1.2.1 From 9c629e534866169b1445bd6614233ded73ff0460 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 May 2011 16:53:05 +0200 Subject: RTSP: cleanups Made several functions static Made one function defined to nothing when RTSP is disabled to avoid the #ifdefs in code. Removed explicit rtsp.h includes --- lib/http.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cc8dcffa5..fe78b6dc3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -96,7 +96,6 @@ #include "multiif.h" #include "rawstr.h" #include "content_encoding.h" -#include "rtsp.h" #include "http_proxy.h" #include "warnless.h" #include "non-ascii.h" @@ -3314,13 +3313,12 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } } -#ifndef CURL_DISABLE_RTSP else if(conn->handler->protocol & CURLPROTO_RTSP) { result = Curl_rtsp_parseheader(conn, k->p); if(result) return result; } -#endif + /* * End of header-checks. Write them to the client. */ -- cgit v1.2.1 From 5d4e5593d5178a716b21c74648077171c7192905 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 3 Jun 2011 19:51:08 +0200 Subject: privatise: make private functions static --- lib/http.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fe78b6dc3..3d9f2f2eb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -113,6 +113,8 @@ static int http_getsock_do(struct connectdata *conn, curl_socket_t *socks, int numsocks); +static int http_should_fail(struct connectdata *conn); + #ifdef USE_SSL static CURLcode https_connecting(struct connectdata *conn, bool *done); static int https_getsock(struct connectdata *conn, @@ -193,7 +195,7 @@ char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader) * case of allocation failure. Returns an empty string if the header value * consists entirely of whitespace. */ -char *Curl_copy_header_value(const char *h) +static char *copy_header_value(const char *h) { const char *start; const char *end; @@ -496,7 +498,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) data->state.authhost.done = TRUE; } } - if(Curl_http_should_fail(conn)) { + if(http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", data->req.httpcode); code = CURLE_HTTP_RETURNED_ERROR; @@ -819,7 +821,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } /** - * Curl_http_should_fail() determines whether an HTTP response has gotten us + * http_should_fail() determines whether an HTTP response has gotten us * into an error state or not. * * @param conn all information about the current connection @@ -828,7 +830,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, * * @retval 1 communications should not continue */ -int Curl_http_should_fail(struct connectdata *conn) +static int http_should_fail(struct connectdata *conn) { struct SessionHandle *data; int httpcode; @@ -1786,7 +1788,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) custom Host: header if this is NOT a redirect, as setting Host: in the redirected request is being out on thin ice. Except if the host name is the same as the first one! */ - char *cookiehost = Curl_copy_header_value(ptr); + char *cookiehost = copy_header_value(ptr); if(!cookiehost) return CURLE_OUT_OF_MEMORY; if(!*cookiehost) @@ -2792,7 +2794,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, * When all the headers have been parsed, see if we should give * up and return an error. */ - if(Curl_http_should_fail(conn)) { + if(http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", k->httpcode); return CURLE_HTTP_RETURNED_ERROR; @@ -3084,7 +3086,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } /* check for Content-Type: header lines to get the MIME-type */ else if(checkprefix("Content-Type:", k->p)) { - char *contenttype = Curl_copy_header_value(k->p); + char *contenttype = copy_header_value(k->p); if(!contenttype) return CURLE_OUT_OF_MEMORY; if(!*contenttype) @@ -3290,7 +3292,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, checkprefix("Location:", k->p) && !data->req.location) { /* this is the URL that the server advises us to use instead */ - char *location = Curl_copy_header_value(k->p); + char *location = copy_header_value(k->p); if(!location) return CURLE_OUT_OF_MEMORY; if(!*location) -- cgit v1.2.1 From 57064e4a0d426eeb0f82e7831214caaf9300bc2a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 21 Jun 2011 16:28:15 +0200 Subject: http: fix compiler warning compiler warning: conditional expression is constant --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 3d9f2f2eb..56d263b91 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3158,7 +3158,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* Find the first non-space letter */ start = k->p + 18; - do { + for(;;) { /* skip whitespaces and commas */ while(*start && (ISSPACE(*start) || (*start == ','))) start++; @@ -3204,7 +3204,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, /* unknown! */ break; - } while(1); + } } else if(checkprefix("Content-Encoding:", k->p) && -- cgit v1.2.1 From bcf50283fc64b126d57b63267be8b6aab451f99a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 1 Jul 2011 22:57:28 +0200 Subject: Curl_http_readwrite_headers: minor indent fix --- lib/http.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 56d263b91..92f7c02a1 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2929,23 +2929,23 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, if(conn->handler->protocol & CURLPROTO_HTTP) { nc = sscanf(HEADER1, - " HTTP/%d.%d %3d", - &httpversion_major, - &conn->httpversion, - &k->httpcode); + " HTTP/%d.%d %3d", + &httpversion_major, + &conn->httpversion, + &k->httpcode); if(nc==3) { conn->httpversion += 10 * httpversion_major; } else { /* this is the real world, not a Nirvana NCSA 1.5.x returns this crap when asked for HTTP/1.1 - */ + */ nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); conn->httpversion = 10; /* If user has set option HTTP200ALIASES, compare header line against list of aliases - */ + */ if(!nc) { if(checkhttpprefix(data, k->p)) { nc = 1; -- cgit v1.2.1 From a6d4807d028eb82f4a99587b0a8851727ca88566 Mon Sep 17 00:00:00 2001 From: Mandy Wu Date: Mon, 18 Jul 2011 23:36:36 +0200 Subject: NTLM single-sign on supported With the use of the 'ntlm_auth' tool from the Samba project --- lib/http.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 92f7c02a1..bb6af2cb4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -307,6 +307,8 @@ static bool pickoneauth(struct auth *pick) pick->picked = CURLAUTH_DIGEST; else if(avail & CURLAUTH_NTLM) pick->picked = CURLAUTH_NTLM; + else if(avail & CURLAUTH_NTLM_SSO) + pick->picked = CURLAUTH_NTLM_SSO; else if(avail & CURLAUTH_BASIC) pick->picked = CURLAUTH_BASIC; else { @@ -393,7 +395,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) if((expectsend == -1) || (expectsend > bytessent)) { /* There is still data left to send */ if((data->state.authproxy.picked == CURLAUTH_NTLM) || - (data->state.authhost.picked == CURLAUTH_NTLM)) { + (data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_SSO) || + (data->state.authhost.picked == CURLAUTH_NTLM_SSO)) { if(((expectsend - bytessent) < 2000) || (conn->ntlm.state != NTLMSTATE_NONE)) { /* The NTLM-negotiation has started *OR* there is just a little (<2K) @@ -554,6 +558,15 @@ output_auth_headers(struct connectdata *conn, } else #endif +#ifdef USE_NTLM_SSO + if(authstatus->picked == CURLAUTH_NTLM_SSO) { + auth="NTLM_SSO"; + result = Curl_output_ntlm_sso(conn, proxy); + if(result) + return result; + } + else +#endif #ifndef CURL_DISABLE_CRYPTO_AUTH if(authstatus->picked == CURLAUTH_DIGEST) { auth="Digest"; @@ -766,13 +779,35 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, if(checkprefix("NTLM", start)) { *availp |= CURLAUTH_NTLM; authp->avail |= CURLAUTH_NTLM; - if(authp->picked == CURLAUTH_NTLM) { + if(authp->picked == CURLAUTH_NTLM || + authp->picked == CURLAUTH_NTLM_SSO) { /* NTLM authentication is picked and activated */ CURLntlm ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - - if(CURLNTLM_BAD != ntlm) + if(CURLNTLM_BAD != ntlm) { data->state.authproblem = FALSE; +#ifdef USE_NTLM_SSO + if(authp->picked == CURLAUTH_NTLM_SSO) { + *availp &= ~CURLAUTH_NTLM; + authp->avail &= ~CURLAUTH_NTLM; + *availp |= CURLAUTH_NTLM_SSO; + authp->avail |= CURLAUTH_NTLM_SSO; + + /* Get the challenge-message which will be passed to + * ntlm_auth for generating the type 3 message later */ + while(*start && ISSPACE(*start)) + start++; + if(checkprefix("NTLM", start)) { + start += strlen("NTLM"); + while(*start && ISSPACE(*start)) + start++; + if(*start) + if((conn->challenge_header = strdup(start)) == NULL) + return CURLE_OUT_OF_MEMORY; + } + } +#endif + } else { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; -- cgit v1.2.1 From 3f9b4afdfd7dd3ea16e07af98bb324b9f4277696 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Jul 2011 23:24:45 +0200 Subject: http error response: stop sending when error is received When libcurl has said to the server that there's a POST or PUT coming (with a content-length and all) it has to either deliver that amount of data or it needs to close the connection before trying a second request. Adds test case 1129, 1130 and 1131 The bug report is about when used with 100-continue, but the change is more generic. Bug: http://curl.haxx.se/mail/lib-2011-06/0191.html Reported by: Steven Parkes --- lib/http.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 12 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bb6af2cb4..5c529231f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -404,8 +404,10 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) data left to send, keep on sending. */ /* rewind data when completely done sending! */ - if(!conn->bits.authneg) + if(!conn->bits.authneg) { conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } return CURLE_OK; } @@ -1683,6 +1685,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!data->state.first_host) return CURLE_OUT_OF_MEMORY; } + http->writebytecount = http->readbytecount = 0; if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && data->set.upload) { @@ -2543,6 +2546,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_pgrsSetUploadCounter(data, http->writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; + + if(http->writebytecount >= postsize) { + /* already sent the entire request body, mark the "upload" as + complete */ + infof(data, "upload completely sent off: %" FORMAT_OFF_T "out of " + "%" FORMAT_OFF_T " bytes\n", + http->writebytecount, postsize); + data->req.upload_done = TRUE; + data->req.keepon &= ~KEEP_SEND; /* we're done writing */ + data->req.exp100 = EXP100_SEND_DATA; /* already sent */ + } } return result; @@ -2814,17 +2828,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } } - if(417 == k->httpcode) { - /* - * we got: "417 Expectation Failed" this means: - * we have made a HTTP call and our Expect Header - * seems to cause a problem => abort the write operations - * (or prevent them from starting). - */ - k->exp100 = EXP100_FAILED; - k->keepon &= ~KEEP_SEND; - } - /* * When all the headers have been parsed, see if we should give * up and return an error. @@ -2864,6 +2867,46 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, if(result) return result; + if(k->httpcode >= 300) { + if((!conn->bits.authneg) && !conn->bits.close && + !conn->bits.rewindaftersend) { + /* + * General treatment of errors when about to send data. Including : + * "417 Expectation Failed", while waiting for 100-continue. + * + * The check for close above is done simply because of something + * else has already deemed the connection to get closed then + * something else should've considered the big picture and we + * avoid this check. + * + * rewindaftersend indicates that something has told libcurl to + * continue sending even if it gets discarded + */ + + switch(data->set.httpreq) { + case HTTPREQ_PUT: + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + /* We got an error response. If this happened before the whole + * request body has been sent we stop sending and mark the + * connection for closure after we've read the entire response. + */ + if(!k->upload_done) { + infof(data, "HTTP error before end of send, stop sending\n"); + conn->bits.close = TRUE; /* close after this */ + k->upload_done = TRUE; + k->keepon &= ~KEEP_SEND; /* don't send */ + if(data->state.expect100header) + k->exp100 = EXP100_FAILED; + } + break; + + default: /* default label present to avoid compiler warnings */ + break; + } + } + } + if(conn->bits.rewindaftersend) { /* We rewind after a complete send, so thus we continue sending now */ -- cgit v1.2.1 From 0337b871975ab515c513d2c5d596feb9a489494d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 25 Jul 2011 04:08:08 +0200 Subject: time.h and sys/time.h inclusion conditionally done in setup_once.h --- lib/http.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5c529231f..cc01636c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -31,7 +31,6 @@ #include #ifdef WIN32 -#include #include #else #ifdef HAVE_SYS_SOCKET_H @@ -40,15 +39,6 @@ #ifdef HAVE_NETINET_IN_H #include #endif -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifdef HAVE_TIME_H -#ifdef TIME_WITH_SYS_TIME -#include -#endif -#endif #ifdef HAVE_UNISTD_H #include -- cgit v1.2.1 From 983f3d70f9610a35f279b656a3322087e272f2a6 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 25 Jul 2011 05:30:14 +0200 Subject: WIN32 io.h and fcntl.h inclusion done in setup_once.h --- lib/http.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index cc01636c2..be0149cb9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -30,9 +30,6 @@ #include #include -#ifdef WIN32 -#include -#else #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -60,8 +57,6 @@ #include #endif -#endif - #include "urldata.h" #include #include "transfer.h" -- cgit v1.2.1 From f1586cb4775681810afd8e6626e7842d459f3b85 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 17:23:27 +0200 Subject: stdio.h, stdlib.h, string.h, stdarg.h and ctype.h inclusion done in setup_once.h --- lib/http.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index be0149cb9..bb4b38793 100644 --- a/lib/http.c +++ b/lib/http.c @@ -23,12 +23,6 @@ #include "setup.h" #ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include #ifdef HAVE_SYS_SOCKET_H #include -- cgit v1.2.1 From 78bbd0eecff23203dd8a1aa2dd76143af9a90b7b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 19:42:16 +0200 Subject: fix compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index bb4b38793..6646d5ed3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1631,7 +1631,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t included_body = 0; const char *httpstring; Curl_send_buffer *req_buffer; - curl_off_t postsize; /* off_t type to be able to hold a large file size */ + curl_off_t postsize = 0; /* off_t type to be able to hold a large file size */ int seekerr = CURL_SEEKFUNC_OK; /* Always consider the DO phase done after this function call, even if there -- cgit v1.2.1 From 41c6c78a0887d8eabf258a8349d537f3d1ede25b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Jul 2011 21:36:35 +0200 Subject: fix compiler warning --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 6646d5ed3..97946f84d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1631,7 +1631,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t included_body = 0; const char *httpstring; Curl_send_buffer *req_buffer; - curl_off_t postsize = 0; /* off_t type to be able to hold a large file size */ + curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ int seekerr = CURL_SEEKFUNC_OK; /* Always consider the DO phase done after this function call, even if there -- cgit v1.2.1 From 10a0bed48536e5a3fe801a5e0d94bd84ad80c559 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 31 Jul 2011 20:44:41 +0200 Subject: NTLM single-sign on adjustments (VIII) Use preprocessor symbols WINBIND_NTLM_AUTH_ENABLED and WINBIND_NTLM_AUTH_FILE for Samba's winbind daemon ntlm_auth helper code implementation and filename. Retain preprocessor symbol USE_NTLM_SSO for NTLM single-sign-on feature availability implementation independent. For test harness, prefix NTLM_AUTH environment vars with CURL_ Refactor and rename configure option --with-ntlm-auth to --enable-wb-ntlm-auth[=FILE] --- lib/http.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 97946f84d..97c904342 100644 --- a/lib/http.c +++ b/lib/http.c @@ -542,9 +542,13 @@ output_auth_headers(struct connectdata *conn, #ifdef USE_NTLM_SSO if(authstatus->picked == CURLAUTH_NTLM_SSO) { auth="NTLM_SSO"; +#ifdef WINBIND_NTLM_AUTH_ENABLED result = Curl_output_ntlm_sso(conn, proxy); if(result) return result; +#else + return CURLE_REMOTE_ACCESS_DENIED; +#endif } else #endif @@ -767,7 +771,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, Curl_input_ntlm(conn, (bool)(httpcode == 407), start); if(CURLNTLM_BAD != ntlm) { data->state.authproblem = FALSE; -#ifdef USE_NTLM_SSO +#ifdef WINBIND_NTLM_AUTH_ENABLED if(authp->picked == CURLAUTH_NTLM_SSO) { *availp &= ~CURLAUTH_NTLM; authp->avail &= ~CURLAUTH_NTLM; -- cgit v1.2.1 From b4d6db83debe4f57a94d23e50764f290c86f753a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 13 Aug 2011 23:58:27 +0200 Subject: http NTLM: change return type of Curl_input_ntlm() to CURLcode Remove CURLntlm enum, no longer required. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 97c904342..4952ddd64 100644 --- a/lib/http.c +++ b/lib/http.c @@ -767,9 +767,9 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, if(authp->picked == CURLAUTH_NTLM || authp->picked == CURLAUTH_NTLM_SSO) { /* NTLM authentication is picked and activated */ - CURLntlm ntlm = + CURLcode ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - if(CURLNTLM_BAD != ntlm) { + if(CURLE_OK == ntlm) { data->state.authproblem = FALSE; #ifdef WINBIND_NTLM_AUTH_ENABLED if(authp->picked == CURLAUTH_NTLM_SSO) { -- cgit v1.2.1 From fd00b382b2d33ef90c6f5c840a32b66c8ceb1662 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 24 Aug 2011 08:07:36 +0200 Subject: base64: fix Curl_base64_encode and Curl_base64_decode interfaces Previous interfaces for these libcurl internal functions did not allow to tell apart a legitimate zero size result from an error condition. These functions now return a CURLcode indicating function success or otherwise specific error. Output size is returned using a pointer argument. All usage of these two functions, and others closely related, has been adapted to the new interfaces. Relative error and OOM handling adapted or added where missing. Unit test 1302 also adapted. --- lib/http.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4952ddd64..edf3e163f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -231,11 +231,13 @@ static char *copy_header_value(const char *h) */ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) { - char *authorization; - struct SessionHandle *data=conn->data; + size_t size = 0; + char *authorization = NULL; + struct SessionHandle *data = conn->data; char **userp; const char *user; const char *pwd; + CURLcode error; if(proxy) { userp = &conn->allocptr.proxyuserpwd; @@ -249,20 +251,24 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) } snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); - if(Curl_base64_encode(data, data->state.buffer, - strlen(data->state.buffer), - &authorization) > 0) { - if(*userp) - free(*userp); - *userp = aprintf( "%sAuthorization: Basic %s\r\n", - proxy?"Proxy-":"", - authorization); - free(authorization); - if(!*userp) - return CURLE_OUT_OF_MEMORY; - } - else + + error = Curl_base64_encode(data, + data->state.buffer, strlen(data->state.buffer), + &authorization, &size); + if(error) + return error; + + if(!authorization) + return CURLE_REMOTE_ACCESS_DENIED; + + Curl_safefree(*userp); + *userp = aprintf("%sAuthorization: Basic %s\r\n", + proxy?"Proxy-":"", + authorization); + free(authorization); + if(!*userp) return CURLE_OUT_OF_MEMORY; + return CURLE_OK; } -- cgit v1.2.1 From 407e08baad45b060e3fa1387190a8b12aca9ab60 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 26 Aug 2011 18:57:50 +0200 Subject: NTLM single-sign on adjustments (X) Functions renamed: Curl_output_ntlm_sso -> Curl_output_ntlm_wb sso_ntlm_close -> wb_ntlm_close sso_ntlm_response -> wb_ntlm_response sso_ntlm_initiate -> wb_ntlm_initiate Preprocessor symbols renamed: CURLAUTH_NTLM_SSO -> CURLAUTH_NTLM_WB CURL_VERSION_NTLM_SSO -> CURL_VERSION_NTLM_WB --- lib/http.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index edf3e163f..fa8c7c39f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -292,8 +292,8 @@ static bool pickoneauth(struct auth *pick) pick->picked = CURLAUTH_DIGEST; else if(avail & CURLAUTH_NTLM) pick->picked = CURLAUTH_NTLM; - else if(avail & CURLAUTH_NTLM_SSO) - pick->picked = CURLAUTH_NTLM_SSO; + else if(avail & CURLAUTH_NTLM_WB) + pick->picked = CURLAUTH_NTLM_WB; else if(avail & CURLAUTH_BASIC) pick->picked = CURLAUTH_BASIC; else { @@ -381,8 +381,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) /* There is still data left to send */ if((data->state.authproxy.picked == CURLAUTH_NTLM) || (data->state.authhost.picked == CURLAUTH_NTLM) || - (data->state.authproxy.picked == CURLAUTH_NTLM_SSO) || - (data->state.authhost.picked == CURLAUTH_NTLM_SSO)) { + (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { if(((expectsend - bytessent) < 2000) || (conn->ntlm.state != NTLMSTATE_NONE)) { /* The NTLM-negotiation has started *OR* there is just a little (<2K) @@ -546,10 +546,10 @@ output_auth_headers(struct connectdata *conn, else #endif #ifdef USE_NTLM_SSO - if(authstatus->picked == CURLAUTH_NTLM_SSO) { + if(authstatus->picked == CURLAUTH_NTLM_WB) { auth="NTLM_SSO"; #ifdef WINBIND_NTLM_AUTH_ENABLED - result = Curl_output_ntlm_sso(conn, proxy); + result = Curl_output_ntlm_wb(conn, proxy); if(result) return result; #else @@ -771,18 +771,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, *availp |= CURLAUTH_NTLM; authp->avail |= CURLAUTH_NTLM; if(authp->picked == CURLAUTH_NTLM || - authp->picked == CURLAUTH_NTLM_SSO) { + authp->picked == CURLAUTH_NTLM_WB) { /* NTLM authentication is picked and activated */ CURLcode ntlm = Curl_input_ntlm(conn, (bool)(httpcode == 407), start); if(CURLE_OK == ntlm) { data->state.authproblem = FALSE; #ifdef WINBIND_NTLM_AUTH_ENABLED - if(authp->picked == CURLAUTH_NTLM_SSO) { + if(authp->picked == CURLAUTH_NTLM_WB) { *availp &= ~CURLAUTH_NTLM; authp->avail &= ~CURLAUTH_NTLM; - *availp |= CURLAUTH_NTLM_SSO; - authp->avail |= CURLAUTH_NTLM_SSO; + *availp |= CURLAUTH_NTLM_WB; + authp->avail |= CURLAUTH_NTLM_WB; /* Get the challenge-message which will be passed to * ntlm_auth for generating the type 3 message later */ -- cgit v1.2.1 From b4f6319cf77ca2642154bdac76d6729dde56dd8e Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 27 Aug 2011 01:32:49 +0200 Subject: NTLM single-sign on adjustments (XI) Feature string literal NTLM_SSO renamed to NTLM_WB. Preprocessor symbol USE_NTLM_SSO renamed to WINBIND_NTLM_AUTH_ENABLED. curl's 'long' option 'ntlm-sso' renamed to 'ntlm-wb'. Fix some comments to make clear that this is actually a NTLM delegation. --- lib/http.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fa8c7c39f..54bb53527 100644 --- a/lib/http.c +++ b/lib/http.c @@ -545,16 +545,12 @@ output_auth_headers(struct connectdata *conn, } else #endif -#ifdef USE_NTLM_SSO - if(authstatus->picked == CURLAUTH_NTLM_WB) { - auth="NTLM_SSO"; #ifdef WINBIND_NTLM_AUTH_ENABLED + if(authstatus->picked == CURLAUTH_NTLM_WB) { + auth="NTLM_WB"; result = Curl_output_ntlm_wb(conn, proxy); if(result) return result; -#else - return CURLE_REMOTE_ACCESS_DENIED; -#endif } else #endif -- cgit v1.2.1 From b976d108f1beecff743f912f190ffc89f1ef9098 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 27 Aug 2011 06:31:18 +0200 Subject: NTLM_WB: final congruency naming adjustments Configure script option --enable-wb-ntlm-auth renamed to --enable-ntlm-wb Configure script option --disable-wb-ntlm-auth renamed to --disable-ntlm-wb Preprocessor symbol WINBIND_NTLM_AUTH_ENABLED renamed to NTLM_WB_ENABLED Preprocessor symbol WINBIND_NTLM_AUTH_FILE renamed to NTLM_WB_FILE Test harness env var CURL_NTLM_AUTH renamed to CURL_NTLM_WB_FILE Static function wb_ntlm_close renamed to ntlm_wb_cleanup Static function wb_ntlm_initiate renamed to ntlm_wb_init Static function wb_ntlm_response renamed to ntlm_wb_response --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 54bb53527..c1a94712e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -545,7 +545,7 @@ output_auth_headers(struct connectdata *conn, } else #endif -#ifdef WINBIND_NTLM_AUTH_ENABLED +#ifdef NTLM_WB_ENABLED if(authstatus->picked == CURLAUTH_NTLM_WB) { auth="NTLM_WB"; result = Curl_output_ntlm_wb(conn, proxy); @@ -773,7 +773,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, Curl_input_ntlm(conn, (bool)(httpcode == 407), start); if(CURLE_OK == ntlm) { data->state.authproblem = FALSE; -#ifdef WINBIND_NTLM_AUTH_ENABLED +#ifdef NTLM_WB_ENABLED if(authp->picked == CURLAUTH_NTLM_WB) { *availp &= ~CURLAUTH_NTLM; authp->avail &= ~CURLAUTH_NTLM; -- cgit v1.2.1 From 260ee6b7bfbc4a49832a1e322d1cc5d9d3c33ddf Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 27 Aug 2011 19:16:10 +0200 Subject: NTLM_WB: move NTLM_WB specifics into curl_ntlm_wb.[ch] --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c1a94712e..36062d7c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -63,6 +63,7 @@ #include "sslgen.h" #include "http_digest.h" #include "http_ntlm.h" +#include "curl_ntlm_wb.h" #include "http_negotiate.h" #include "url.h" #include "share.h" -- cgit v1.2.1 From 662c1d87f3933a7deece63d484f4c0c248a13ded Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 28 Aug 2011 02:00:02 +0200 Subject: NTLM: END of refactoring/splitting/moving First: File curl_ntlm.h renamed curl_ntlm_msgs.h File curl_ntlm.c renamed curl_ntlm_msgs.c Afterwards: File http_ntlm.c renamed curl_ntlm.c File http_ntlm.h renamed curl_ntlm.h --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 36062d7c2..ef3953ec0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -62,7 +62,7 @@ #include "strequal.h" #include "sslgen.h" #include "http_digest.h" -#include "http_ntlm.h" +#include "curl_ntlm.h" #include "curl_ntlm_wb.h" #include "http_negotiate.h" #include "url.h" -- cgit v1.2.1 From a50210710ab6fd772e2762ed36602c15adfb49e1 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 5 Sep 2011 20:46:09 +0200 Subject: fix bool variables checking and assignment --- lib/http.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ef3953ec0..b67329649 100644 --- a/lib/http.c +++ b/lib/http.c @@ -588,7 +588,7 @@ output_auth_headers(struct connectdata *conn, proxy?"Proxy":"Server", auth, proxy?(conn->proxyuser?conn->proxyuser:""): (conn->user?conn->user:"")); - authstatus->multi = (bool)(!authstatus->done); + authstatus->multi = (!authstatus->done) ? TRUE : FALSE; } else authstatus->multi = FALSE; @@ -745,7 +745,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, data->state.authproblem = TRUE; } else { - neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); + neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start); if(neg == 0) { DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->change.url); @@ -771,7 +771,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, authp->picked == CURLAUTH_NTLM_WB) { /* NTLM authentication is picked and activated */ CURLcode ntlm = - Curl_input_ntlm(conn, (bool)(httpcode == 407), start); + Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); if(CURLE_OK == ntlm) { data->state.authproblem = FALSE; #ifdef NTLM_WB_ENABLED @@ -817,7 +817,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, /* We call this function on input Digest headers even if Digest * authentication isn't activated yet, as we need to store the * incoming data from this header in case we are gonna use Digest. */ - dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); + dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); if(CURLDIGEST_FINE != dig) { infof(data, "Authentication problem. Ignoring this.\n"); @@ -946,7 +946,7 @@ static size_t readmoredata(char *buffer, return 0; /* make sure that a HTTP request is never sent away chunked! */ - conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST); + conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); @@ -1479,11 +1479,11 @@ CURLcode Curl_http_done(struct connectdata *conn, static bool use_http_1_1(const struct SessionHandle *data, const struct connectdata *conn) { - return (bool)((data->set.httpversion == CURL_HTTP_VERSION_1_1) || + return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) || ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && ((conn->httpversion == 11) || ((conn->httpversion != 10) && - (data->state.httpversion != 10))))); + (data->state.httpversion != 10))))) ? TRUE : FALSE; } /* check and possibly add an Expect: header */ @@ -2154,8 +2154,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.cookiehost? conn->allocptr.cookiehost:host, data->state.path, - (bool)(conn->handler->protocol&CURLPROTO_HTTPS? - TRUE:FALSE)); + (conn->handler->protocol&CURLPROTO_HTTPS)? + TRUE:FALSE); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } if(co) { @@ -2582,7 +2582,7 @@ checkhttpprefix(struct SessionHandle *data, head = head->next; } - if((rc != TRUE) && (checkprefix("HTTP/", s))) + if(!rc && (checkprefix("HTTP/", s))) rc = TRUE; #ifdef CURL_DOES_CONVERSIONS -- cgit v1.2.1 From aff70e2e9534eecb9e756d2104efa52e5d8b0462 Mon Sep 17 00:00:00 2001 From: warp kawada Date: Thu, 8 Sep 2011 15:39:39 -0700 Subject: Curl_add_custom_headers: support headers with no data A custom HTTP header ending in a semicolon instead of a colon will be treated as a header to be added without any data portion. --- lib/http.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b67329649..993900617 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1559,6 +1559,31 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, } } } + else { + ptr = strchr(headers->data, ';'); + if(ptr) { + + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* this may be used for something else in the future */ + } + else { + if(*(--ptr) == ';') { + CURLcode result; + + /* send no-value custom header if terminated by semicolon */ + *ptr = ':'; + result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); + if(result) + return result; + } + } + } + } headers = headers->next; } return CURLE_OK; -- cgit v1.2.1 From c1057fc9aa9ba0304ea9afae38282ad1e9b3f1d4 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 21 Sep 2011 21:19:29 +0200 Subject: lib/http: add missing whitespace in verbose output Example: * upload completely sent off: 35out of 35 bytes Should be: * upload completely sent off: 35 out of 35 bytes --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 993900617..9f7a5a516 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2561,7 +2561,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(http->writebytecount >= postsize) { /* already sent the entire request body, mark the "upload" as complete */ - infof(data, "upload completely sent off: %" FORMAT_OFF_T "out of " + infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of " "%" FORMAT_OFF_T " bytes\n", http->writebytecount, postsize); data->req.upload_done = TRUE; -- cgit v1.2.1 From 01c172f5e8c78b781397003e22fc462a503d2c24 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 22 Sep 2011 00:24:02 +0200 Subject: NTLM_WB: fix disabling of NTLM_WB when NTLM is disabled --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 9f7a5a516..8c9848a9d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -546,7 +546,7 @@ output_auth_headers(struct connectdata *conn, } else #endif -#ifdef NTLM_WB_ENABLED +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) if(authstatus->picked == CURLAUTH_NTLM_WB) { auth="NTLM_WB"; result = Curl_output_ntlm_wb(conn, proxy); -- cgit v1.2.1 From 5f0764870f5710f58f308f62f46fca7b97d75c2b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 24 Sep 2011 00:05:58 +0200 Subject: http header: allow Content-Length to be replaced In some cases Content-Length: couldn't be replaced by an application Also, indented some code properly --- lib/http.c | 132 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 68 insertions(+), 64 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 8c9848a9d..ee5d6116a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1803,8 +1803,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } else { if((conn->handler->protocol&CURLPROTO_HTTP) && - data->set.upload && - (data->set.infilesize == -1)) { + data->set.upload && + (data->set.infilesize == -1)) { if(conn->bits.authneg) /* don't enable chunked during auth neg */ ; @@ -1982,7 +1982,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * This is meant to get the size of the present remote-file by itself. * We don't support this now. Bail out! */ - data->state.resume_from = 0; + data->state.resume_from = 0; } if(data->state.resume_from && !data->state.this_is_a_follow) { @@ -2073,17 +2073,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) curl_off_t total_expected_size= data->state.resume_from + data->set.infilesize; conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%" FORMAT_OFF_T - "/%" FORMAT_OFF_T "\r\n", - data->state.range, total_expected_size-1, - total_expected_size); + aprintf("Content-Range: bytes %s%" FORMAT_OFF_T + "/%" FORMAT_OFF_T "\r\n", + data->state.range, total_expected_size-1, + total_expected_size); } else { /* Range was selected and then we just pass the incoming range and append total size */ conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", - data->state.range, data->set.infilesize); + aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", + data->state.range, data->set.infilesize); } if(!conn->allocptr.rangeline) return CURLE_OUT_OF_MEMORY; @@ -2116,45 +2116,47 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - result = Curl_add_bufferf(req_buffer, - "%s" /* ftp typecode (;type=x) */ - " HTTP/%s\r\n" /* HTTP version */ - "%s" /* proxyuserpwd */ - "%s" /* userpwd */ - "%s" /* range */ - "%s" /* user agent */ - "%s" /* host */ - "%s" /* accept */ - "%s" /* TE: */ - "%s" /* accept-encoding */ - "%s" /* referer */ - "%s" /* Proxy-Connection */ - "%s",/* transfer-encoding */ - - ftp_typecode, - httpstring, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - conn->allocptr.userpwd?conn->allocptr.userpwd:"", - (data->state.use_range && conn->allocptr.rangeline)? - conn->allocptr.rangeline:"", - (data->set.str[STRING_USERAGENT] && - *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? - conn->allocptr.uagent:"", - (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ - http->p_accept?http->p_accept:"", - conn->allocptr.te?conn->allocptr.te:"", - (data->set.str[STRING_ENCODING] && - *data->set.str[STRING_ENCODING] && - conn->allocptr.accept_encoding)? - conn->allocptr.accept_encoding:"", - (data->change.referer && conn->allocptr.ref)? - conn->allocptr.ref:"" /* Referer: */, - (conn->bits.httpproxy && - !conn->bits.tunnel_proxy && - !Curl_checkheaders(data, "Proxy-Connection:"))? - "Proxy-Connection: Keep-Alive\r\n":"", - te + result = + Curl_add_bufferf(req_buffer, + "%s" /* ftp typecode (;type=x) */ + " HTTP/%s\r\n" /* HTTP version */ + "%s" /* proxyuserpwd */ + "%s" /* userpwd */ + "%s" /* range */ + "%s" /* user agent */ + "%s" /* host */ + "%s" /* accept */ + "%s" /* TE: */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s" /* Proxy-Connection */ + "%s",/* transfer-encoding */ + + ftp_typecode, + httpstring, + conn->allocptr.proxyuserpwd? + conn->allocptr.proxyuserpwd:"", + conn->allocptr.userpwd?conn->allocptr.userpwd:"", + (data->state.use_range && conn->allocptr.rangeline)? + conn->allocptr.rangeline:"", + (data->set.str[STRING_USERAGENT] && + *data->set.str[STRING_USERAGENT] && + conn->allocptr.uagent)? + conn->allocptr.uagent:"", + (conn->allocptr.host?conn->allocptr.host:""), + http->p_accept?http->p_accept:"", + conn->allocptr.te?conn->allocptr.te:"", + (data->set.str[STRING_ENCODING] && + *data->set.str[STRING_ENCODING] && + conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", + (data->change.referer && conn->allocptr.ref)? + conn->allocptr.ref:"" /* Referer: */, + (conn->bits.httpproxy && + !conn->bits.tunnel_proxy && + !Curl_checkheaders(data, "Proxy-Connection:"))? + "Proxy-Connection: Keep-Alive\r\n":"", + te ); /* @@ -2194,8 +2196,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) break; } result = Curl_add_bufferf(req_buffer, - "%s%s=%s", count?"; ":"", - co->name, co->value); + "%s%s=%s", count?"; ":"", + co->name, co->value); if(result) break; count++; @@ -2209,8 +2211,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) result = Curl_add_bufferf(req_buffer, "Cookie: "); if(CURLE_OK == result) { result = Curl_add_bufferf(req_buffer, "%s%s", - count?"; ":"", - addcookies); + count?"; ":"", + addcookies); count++; } } @@ -2277,11 +2279,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) http->sending = HTTPSEND_BODY; - if(!data->req.upload_chunky) { + if(!data->req.upload_chunky && + !Curl_checkheaders(data, "Content-Length:")) { /* only add Content-Length if not uploading chunked */ result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - http->postsize); + "Content-Length: %" FORMAT_OFF_T "\r\n", + http->postsize); if(result) return result; } @@ -2348,11 +2351,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else postsize = data->set.infilesize; - if((postsize != -1) && !data->req.upload_chunky) { + if((postsize != -1) && !data->req.upload_chunky && + !Curl_checkheaders(data, "Content-Length:")) { /* only add Content-Length if not uploading chunked */ result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - postsize ); + "Content-Length: %" FORMAT_OFF_T "\r\n", + postsize ); if(result) return result; } @@ -2402,8 +2406,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* we allow replacing this header if not during auth negotiation, although it isn't very wise to actually set your own */ result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", - postsize); + "Content-Length: %" FORMAT_OFF_T"\r\n", + postsize); if(result) return result; } @@ -2453,7 +2457,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); + (size_t)postsize); included_body = postsize; } else { @@ -2461,10 +2465,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); if(CURLE_OK == result) result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); + (size_t)postsize); if(CURLE_OK == result) result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); /* CR LF 0 CR LF CR LF */ included_body = postsize + 7; } @@ -2500,7 +2504,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Chunky upload is selected and we're negotiating auth still, send end-of-data only */ result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); + "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); /* CR LF 0 CR LF CR LF */ if(result) return result; -- cgit v1.2.1 From bff78cc18e8dc22926d4b0219e6fac08758ed790 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Oct 2011 21:32:10 +0200 Subject: OOM handling/cleanup slight adjustments --- lib/http.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ee5d6116a..5b30f8aa0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1912,8 +1912,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) memcpy(newurl + newlen + (ptr - url), ptr + currlen, /* copy the trailing zero byte too */ urllen - (ptr-url) - currlen + 1); - if(data->change.url_alloc) - free(data->change.url); + if(data->change.url_alloc) { + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } data->change.url = newurl; data->change.url_alloc = TRUE; } -- cgit v1.2.1 From ff0a295cdbc9cf95db0c364ede5cca4063ba2882 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 20 Oct 2011 13:05:09 +0200 Subject: Curl_http_input_auth: handle multiple auths in WWW-Authenticate The fix is pretty much the one Nick Zitzmann provided, just edited to do the right indent levels and with test case 1204 added to verify the fix. Bug: http://curl.haxx.se/mail/lib-2011-10/0190.html Reported by: Nick Zitzmann --- lib/http.c | 186 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 98 insertions(+), 88 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 5b30f8aa0..e41cb7af3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -731,95 +731,73 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, * */ + while(*start) { #ifdef USE_HTTP_NEGOTIATE - if(checkprefix("GSS-Negotiate", start) || - checkprefix("Negotiate", start)) { - int neg; - *availp |= CURLAUTH_GSSNEGOTIATE; - authp->avail |= CURLAUTH_GSSNEGOTIATE; - - if(data->state.negotiate.state == GSS_AUTHSENT) { - /* if we sent GSS authentication in the outgoing request and we get this - back, we're in trouble */ - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - else { - neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start); - if(neg == 0) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authproblem = FALSE; - /* we received GSS auth info and we dealt with it fine */ - data->state.negotiate.state = GSS_AUTHRECV; - } - else { + if(checkprefix("GSS-Negotiate", start) || + checkprefix("Negotiate", start)) { + int neg; + *availp |= CURLAUTH_GSSNEGOTIATE; + authp->avail |= CURLAUTH_GSSNEGOTIATE; + + if(data->state.negotiate.state == GSS_AUTHSENT) { + /* if we sent GSS authentication in the outgoing request and we get + this back, we're in trouble */ + infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; } - } - } - else -#endif -#ifdef USE_NTLM - /* NTLM support requires the SSL crypto libs */ - if(checkprefix("NTLM", start)) { - *availp |= CURLAUTH_NTLM; - authp->avail |= CURLAUTH_NTLM; - if(authp->picked == CURLAUTH_NTLM || - authp->picked == CURLAUTH_NTLM_WB) { - /* NTLM authentication is picked and activated */ - CURLcode ntlm = - Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); - if(CURLE_OK == ntlm) { + else { + neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start); + if(neg == 0) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; data->state.authproblem = FALSE; -#ifdef NTLM_WB_ENABLED - if(authp->picked == CURLAUTH_NTLM_WB) { - *availp &= ~CURLAUTH_NTLM; - authp->avail &= ~CURLAUTH_NTLM; - *availp |= CURLAUTH_NTLM_WB; - authp->avail |= CURLAUTH_NTLM_WB; - - /* Get the challenge-message which will be passed to - * ntlm_auth for generating the type 3 message later */ - while(*start && ISSPACE(*start)) - start++; - if(checkprefix("NTLM", start)) { - start += strlen("NTLM"); - while(*start && ISSPACE(*start)) - start++; - if(*start) - if((conn->challenge_header = strdup(start)) == NULL) - return CURLE_OUT_OF_MEMORY; - } - } -#endif + /* we received GSS auth info and we dealt with it fine */ + data->state.negotiate.state = GSS_AUTHRECV; } else { - infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; } } } else #endif -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(checkprefix("Digest", start)) { - if((authp->avail & CURLAUTH_DIGEST) != 0) { - infof(data, "Ignoring duplicate digest auth header.\n"); - } - else { - CURLdigest dig; - *availp |= CURLAUTH_DIGEST; - authp->avail |= CURLAUTH_DIGEST; - - /* We call this function on input Digest headers even if Digest - * authentication isn't activated yet, as we need to store the - * incoming data from this header in case we are gonna use Digest. */ - dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); - - if(CURLDIGEST_FINE != dig) { +#ifdef USE_NTLM + /* NTLM support requires the SSL crypto libs */ + if(checkprefix("NTLM", start)) { + *availp |= CURLAUTH_NTLM; + authp->avail |= CURLAUTH_NTLM; + if(authp->picked == CURLAUTH_NTLM || + authp->picked == CURLAUTH_NTLM_WB) { + /* NTLM authentication is picked and activated */ + CURLcode ntlm = + Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); + if(CURLE_OK == ntlm) { + data->state.authproblem = FALSE; +#ifdef NTLM_WB_ENABLED + if(authp->picked == CURLAUTH_NTLM_WB) { + *availp &= ~CURLAUTH_NTLM; + authp->avail &= ~CURLAUTH_NTLM; + *availp |= CURLAUTH_NTLM_WB; + authp->avail |= CURLAUTH_NTLM_WB; + + /* Get the challenge-message which will be passed to + * ntlm_auth for generating the type 3 message later */ + while(*start && ISSPACE(*start)) + start++; + if(checkprefix("NTLM", start)) { + start += strlen("NTLM"); + while(*start && ISSPACE(*start)) + start++; + if(*start) + if((conn->challenge_header = strdup(start)) == NULL) + return CURLE_OUT_OF_MEMORY; + } + } +#endif + } + else { infof(data, "Authentication problem. Ignoring this.\n"); data->state.authproblem = TRUE; } @@ -827,19 +805,51 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, } else #endif - if(checkprefix("Basic", start)) { - *availp |= CURLAUTH_BASIC; - authp->avail |= CURLAUTH_BASIC; - if(authp->picked == CURLAUTH_BASIC) { - /* We asked for Basic authentication but got a 40X back - anyway, which basically means our name+password isn't - valid. */ - authp->avail = CURLAUTH_NONE; - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; +#ifndef CURL_DISABLE_CRYPTO_AUTH + if(checkprefix("Digest", start)) { + if((authp->avail & CURLAUTH_DIGEST) != 0) { + infof(data, "Ignoring duplicate digest auth header.\n"); + } + else { + CURLdigest dig; + *availp |= CURLAUTH_DIGEST; + authp->avail |= CURLAUTH_DIGEST; + + /* We call this function on input Digest headers even if Digest + * authentication isn't activated yet, as we need to store the + * incoming data from this header in case we are gonna use + * Digest. */ + dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); + + if(CURLDIGEST_FINE != dig) { + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } } - } + else +#endif + if(checkprefix("Basic", start)) { + *availp |= CURLAUTH_BASIC; + authp->avail |= CURLAUTH_BASIC; + if(authp->picked == CURLAUTH_BASIC) { + /* We asked for Basic authentication but got a 40X back + anyway, which basically means our name+password isn't + valid. */ + authp->avail = CURLAUTH_NONE; + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; + } + } + /* there may be multiple methods on one line, so keep reading */ + while(*start && *start != ',') /* read up to the next comma */ + start++; + if(*start == ',') /* if we're on a comma, skip it */ + start++; + while(*start && ISSPACE(*start)) + start++; + } return CURLE_OK; } -- cgit v1.2.1 From d7934b8bd49114cbb54f7401742f7fb088e2f796 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 21 Oct 2011 23:36:54 +0200 Subject: curl_multi_fdset: correct fdset with FTP PORT use After a PORT has been issued, and the multi handle would switch to the CURLM_STATE_DO_MORE state (which is unique for FTP), libcurl would return the wrong fdset to wait for when curl_multi_fdset() is called. The code would blindly assume that it was waiting for a connect of the second connection, while that isn't true immediately after the PORT command. Also, the function multi.c:domore_getsock() was highly FTP-centric and therefore ugly to keep in protocol-agnostic code. I solved this problem by introducing a new function pointer in the Curl_handler struct called domore_getsock() which is only called during the DOMORE state for protocols that set that pointer. The new ftp.c:ftp_domore_getsock() function now returns fdset info about the control connection's command/response handling while such a state is in use, and goes over to waiting for a writable second connection first once the commands are done. The original problem could be seen by running test 525 and checking the time stamps in the FTP server log. I can verify that this fix at least fixes this problem. Bug: http://curl.haxx.se/mail/lib-2011-10/0250.html Reported by: Gokhan Sengun --- lib/http.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index e41cb7af3..f85cd6c55 100644 --- a/lib/http.c +++ b/lib/http.c @@ -118,6 +118,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ @@ -141,6 +142,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* doing */ https_getsock, /* proto_getsock */ http_getsock_do, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ -- cgit v1.2.1 From 4851dafcf164bf2de5bd33c3cf2b786422ed05b6 Mon Sep 17 00:00:00 2001 From: Rene Bernhardt Date: Thu, 3 Nov 2011 23:25:17 +0100 Subject: HTTP auth: fix proxy Negotiate bug If a proxy offers several Authentication schemes where NTLM and Negotiate are offered by the proxy and you tell libcurl not to use the Negotiate scheme then the request never returns when the proxy answers with its HTTP 407 reply. It is reproducible by the following steps: - Use a proxy that offers NTLM and Negotiate ( CURLOPT_PROXY and CURLOPT_PROXYPORT ) - Tell libcurl NOT to use Negotiate CURL_EASY_SETOPT(CURLOPT_PROXYAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_NTLM ) - Start the request The call to CURL_EASY_PERFORM never returns. If you switch on debug logging you can see that libcurl issues a new request As soon as it received the 407 reply. Instead it should return and set the response code to 407. Bug: http://curl.haxx.se/mail/lib-2011-10/0323.html --- lib/http.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index f85cd6c55..fe1c7fd88 100644 --- a/lib/http.c +++ b/lib/http.c @@ -741,25 +741,26 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, *availp |= CURLAUTH_GSSNEGOTIATE; authp->avail |= CURLAUTH_GSSNEGOTIATE; - if(data->state.negotiate.state == GSS_AUTHSENT) { - /* if we sent GSS authentication in the outgoing request and we get - this back, we're in trouble */ - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - else { - neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start); - if(neg == 0) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authproblem = FALSE; - /* we received GSS auth info and we dealt with it fine */ - data->state.negotiate.state = GSS_AUTHRECV; + if(authp->picked == CURLAUTH_GSSNEGOTIATE) { + if(data->state.negotiate.state == GSS_AUTHSENT) { + /* if we sent GSS authentication in the outgoing request and we get + this back, we're in trouble */ + infof(data, "Authentication problem. Ignoring this.\n"); + data->state.authproblem = TRUE; } else { - data->state.authproblem = TRUE; + neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); + if(neg == 0) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received GSS auth info and we dealt with it fine */ + data->state.negotiate.state = GSS_AUTHRECV; + } + else + data->state.authproblem = TRUE; } } } -- cgit v1.2.1 From 41b02378342322aa8e264260057502f4d7493239 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 8 Mar 2012 23:31:38 +0100 Subject: CONNECT: made generically not per-protocol Curl_protocol_connect() now does the tunneling through the HTTP proxy if requested instead of letting each protocol specific connection function do it. --- lib/http.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index fe1c7fd88..374de7d21 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1309,27 +1309,10 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) function to make the re-use checks properly be able to check this bit. */ conn->bits.close = FALSE; -#ifndef CURL_DISABLE_PROXY - /* If we are not using a proxy and we want a secure connection, perform SSL - * initialization & connection now. If using a proxy with https, then we - * must tell the proxy to CONNECT to the host we want to talk to. Only - * after the connect has occurred, can we start talking SSL - */ - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - - /* either SSL over proxy, or explicitly asked for */ - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, - conn->remote_port); - if(CURLE_OK != result) - return result; - } - if(conn->bits.tunnel_connecting) { /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; } -#endif /* CURL_DISABLE_PROXY */ if(conn->given->flags & PROTOPT_SSL) { /* perform SSL initialization */ -- cgit v1.2.1 From e650dbde86d47fc9ded3a8328b8d765fce54078b Mon Sep 17 00:00:00 2001 From: Andrei Cipu Date: Sat, 10 Mar 2012 16:48:59 +0100 Subject: Curl_http: strip off [brackets] from ipv6-only host headers Since the host name is passed in to the cookie engine it will not work correctly if the brackets are left in the name. Bug:http://curl.haxx.se/mail/lib-2012-03/0036.html --- lib/http.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 374de7d21..c7a6df015 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1840,9 +1840,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* ignore empty data */ free(cookiehost); else { - char *colon = strchr(cookiehost, ':'); - if(colon) - *colon = 0; /* The host must not include an embedded port number */ + /* If the host begins with '[', we start searching for the port after + the bracket has been closed */ + int startsearch = 0; + if(*cookiehost == '[') { + char *closingbracket = strchr(++cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; + } + else { + char *colon = strchr(cookiehost + startsearch, ':'); + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } Curl_safefree(conn->allocptr.cookiehost); conn->allocptr.cookiehost = cookiehost; } -- cgit v1.2.1 From c83de6d07625b813e3bbc31f9a0827c3a0007355 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 21 Mar 2012 23:22:39 +0100 Subject: CONNECT: fix multi interface regression The refactoring of HTTP CONNECT handling in commit 41b0237834232 that made it protocol independent broke it for the multi interface. This fix now introduce a better state handling and moved some logic to the http_proxy.c source file. Reported by: Yang Tse Bug: http://curl.haxx.se/mail/lib-2012-03/0162.html --- lib/http.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index c7a6df015..a8b3e28fd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1309,10 +1309,17 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) function to make the re-use checks properly be able to check this bit. */ conn->bits.close = FALSE; - if(conn->bits.tunnel_connecting) { + if(data->state.used_interface == Curl_if_multi) { + /* when the multi interface is used, the CONNECT procedure might not have + been completed */ + result = Curl_proxy_connect(conn); + if(result) + return result; + } + + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; - } if(conn->given->flags & PROTOPT_SSL) { /* perform SSL initialization */ -- cgit v1.2.1 From 97b66ebefe2090aea734af57c5e7e182a97f20bb Mon Sep 17 00:00:00 2001 From: Andrei Cipu Date: Thu, 22 Mar 2012 08:52:45 +0100 Subject: cookies: strip the numerical ipv6 host properly The commit e650dbde86d4 that stripped off [brackets] from ipv6-only host headers for the sake of cookie parsing wrongly incremented the host pointer which would cause a bad free() call later on. --- lib/http.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a8b3e28fd..ec76bbe46 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1851,9 +1851,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) the bracket has been closed */ int startsearch = 0; if(*cookiehost == '[') { - char *closingbracket = strchr(++cookiehost, ']'); + char *closingbracket; + closingbracket = strchr(cookiehost+1, ']'); if(closingbracket) *closingbracket = 0; + /* since the 'cookiehost' is an allocated memory area that will be + freed later we cannot simply increment the pointer */ + memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); } else { char *colon = strchr(cookiehost + startsearch, ':'); -- cgit v1.2.1 From ad595c3ba9f26f7713ba80da6624d0a391f98d91 Mon Sep 17 00:00:00 2001 From: Andrei Cipu Date: Wed, 4 Apr 2012 15:35:24 +0300 Subject: IPv6 cookie domain: get rid of the first bracket before the second. Commit 97b66ebe was copying a smaller buffer, thus duplicating the last character. --- lib/http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index ec76bbe46..0ce575ba8 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1852,12 +1852,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) int startsearch = 0; if(*cookiehost == '[') { char *closingbracket; - closingbracket = strchr(cookiehost+1, ']'); - if(closingbracket) - *closingbracket = 0; /* since the 'cookiehost' is an allocated memory area that will be freed later we cannot simply increment the pointer */ memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1); + closingbracket = strchr(cookiehost, ']'); + if(closingbracket) + *closingbracket = 0; } else { char *colon = strchr(cookiehost + startsearch, ':'); -- cgit v1.2.1 From 9421b06397d25426ab013e2b90d4604ed6430926 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 18 Apr 2012 23:04:35 +0200 Subject: Take in account that CURLAUTH_* bitmasks are now 'unsigned long' Data type of internal vars holding CURLAUTH_* bitmasks changed from 'long' to 'unsigned long' for proper handling and operating. --- lib/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0ce575ba8..d4324400f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -284,7 +284,7 @@ static bool pickoneauth(struct auth *pick) { bool picked; /* only deal with authentication we want */ - long avail = pick->avail & pick->want; + unsigned long avail = pick->avail & pick->want; picked = TRUE; /* The order of these checks is highly relevant, as this will be the order @@ -697,7 +697,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, */ struct SessionHandle *data = conn->data; - long *availp; + unsigned long *availp; const char *start; struct auth *authp; -- cgit v1.2.1 From 560cd6227271752536de237e41c374d0a3e11f1d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 20 Apr 2012 20:40:55 +0200 Subject: HTTP: empty chunked POST ended up in two zero size chunks When doing a chunked-encoded POST with -d (CURLOPT_POSTFIELDS) and the size of the POST was zero length, it made libcurl first send a zero chunk and then the terminating one. This could confuse a receiver and it should rather just send the terminating chunk as it does with this fix. Test case 1333 is added to verify. Bug: http://curl.haxx.se/mail/archive-2012-04/0060.html Reported by: Arnaud Compan --- lib/http.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index d4324400f..a13989417 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1088,7 +1088,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, if(conn->data->set.verbose) { /* this data _may_ contain binary stuff */ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); - if((size_t)amount > headlen) { + if(bodylen) { /* there was body data sent beyond the initial header part, pass that on to the debug callback too */ Curl_debug(conn->data, CURLINFO_DATA_OUT, @@ -2480,11 +2480,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) included_body = postsize; } else { - /* Append the POST data chunky-style */ - result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); - if(CURLE_OK == result) - result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); + if(postsize) { + /* Append the POST data chunky-style */ + result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); + if(CURLE_OK == result) + result = Curl_add_buffer(req_buffer, data->set.postfields, + (size_t)postsize); + } if(CURLE_OK == result) result = Curl_add_buffer(req_buffer, "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); -- cgit v1.2.1 From 1f635608bb3c870977babc1a5d707937a7470134 Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Mon, 9 Apr 2012 15:19:54 +0200 Subject: http: Replaced specific SSL libraries list in https_getsock fallback --- lib/http.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index a13989417..2726165bf 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1398,8 +1398,7 @@ static int https_getsock(struct connectdata *conn, return CURLE_OK; } #else -#if defined(USE_NSS) || defined(USE_QSOSSL) || \ - defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL) +#ifdef USE_SSL static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -1409,7 +1408,7 @@ static int https_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -#endif /* USE_AXTLS || USE_POLARSSL || USE_QSOSSL || USE_NSS */ +#endif /* USE_SSL */ #endif /* USE_SSLEAY || USE_GNUTLS */ /* -- cgit v1.2.1 From 6085ca2aeddb38e4d5f24c47bd98111b236cf384 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 14 Jun 2012 13:32:05 +0200 Subject: Fix bad failf() and info() usage Calls to failf() are not supposed to provide trailing newline. Calls to infof() must provide trailing newline. Fixed 30 or so strings. --- lib/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 2726165bf..4298b213a 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1601,7 +1601,7 @@ CURLcode Curl_add_timecondition(struct SessionHandle *data, result = Curl_gmtime(data->set.timevalue, &keeptime); if(result) { - failf(data, "Invalid TIMEVALUE\n"); + failf(data, "Invalid TIMEVALUE"); return result; } tm = &keeptime; -- cgit v1.2.1 From c42ca3e73a223b8ce9d655444755098c41fe0c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20H=C3=A4gele?= Date: Mon, 9 Jul 2012 13:54:13 +0200 Subject: https_getsock: provided for schannel backend as well The function https_getsock was only implemented properly when USE_SSLEAY or USE_GNUTLS is defined, but it is also necessary for USE_SCHANNEL. The problem occurs when Curl_read_plain or Curl_write_plain returns CURLE_AGAIN. In that case CURL_OK is returned to the multi-interface an the used socket is set to state CURL_POLL_REMOVE and the easy-state is set to CURLM_STATE_PROTOCONNECT. This is fine, because later the socket should be set to CURL_POLL_IN or CURL_POLL_OUT via multi_getsock. That's where https_getsock is called and doesn't return any sockets. --- lib/http.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4298b213a..7b0dc38d2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1371,9 +1371,9 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) } #endif -#if defined(USE_SSLEAY) || defined(USE_GNUTLS) -/* This function is for OpenSSL and GnuTLS only. It should be made to query - the generic SSL layer instead. */ +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) +/* This function is for OpenSSL, GnuTLS and schannel only. It should be + made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -1409,7 +1409,7 @@ static int https_getsock(struct connectdata *conn, return GETSOCK_BLANK; } #endif /* USE_SSL */ -#endif /* USE_SSLEAY || USE_GNUTLS */ +#endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */ /* * Curl_http_done() gets called from Curl_done() after a single HTTP request -- cgit v1.2.1 From 85ce195f75e16d59840e3de74bc5b2846630cabd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Jul 2012 23:13:52 +0200 Subject: HEAD: don't force-close after response-headers A HEAD response has no body length and gets the headers like the corresponding GET would so it should not get closed after the response based on the same rules. This mistake caused connections that did HEAD to get closed too often without a valid reason. Bug: http://curl.haxx.se/bug/view.cgi?id=3542731 Reported by: Eelco Dolstra --- lib/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 7b0dc38d2..b421a2c73 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2851,7 +2851,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, if((k->size == -1) && !k->chunk && !conn->bits.close && (conn->httpversion >= 11) && - !(conn->handler->protocol & CURLPROTO_RTSP)) { + !(conn->handler->protocol & CURLPROTO_RTSP) && + data->set.httpreq != HTTPREQ_HEAD) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Content-Encoding chunked have been received, according to RFC2616 section 4.4 point 5, we -- cgit v1.2.1 From d317ca50ae7d8bb250431f86709e53b94f7f6ddf Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 20 Jul 2012 13:33:58 +0200 Subject: http: print reason phrase from HTTP status line on error Bug: https://bugzilla.redhat.com/676596 --- lib/http.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index b421a2c73..06bdf610c 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2726,6 +2726,42 @@ static CURLcode header_append(struct SessionHandle *data, return CURLE_OK; } +static void print_http_error(struct SessionHandle *data) +{ + struct SingleRequest *k = &data->req; + char *beg = k->p; + + /* make sure that data->req.p points to the HTTP status line */ + if(!strncmp(beg, "HTTP", 4)) { + + /* skip to HTTP status code */ + beg = strchr(beg, ' '); + if(beg && *++beg) { + + /* find trailing CR */ + char end_char = '\r'; + char *end = strchr(beg, end_char); + if(!end) { + /* try to find LF (workaround for non-compliant HTTP servers) */ + end_char = '\n'; + end = strchr(beg, end_char); + } + + if(end) { + /* temporarily replace CR or LF by NUL and print the error message */ + *end = '\0'; + failf(data, "The requested URL returned error: %s", beg); + + /* restore the previously replaced CR or LF */ + *end = end_char; + return; + } + } + } + + /* fall-back to printing the HTTP status code only */ + failf(data, "The requested URL returned error: %d", k->httpcode); +} /* * Read any HTTP header lines from the server and pass them to the client app. @@ -3114,8 +3150,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } else { /* serious error, go home! */ - failf (data, "The requested URL returned error: %d", - k->httpcode); + print_http_error(data); return CURLE_HTTP_RETURNED_ERROR; } } -- cgit v1.2.1 From f92779198d07abb18e8a5c4dd3a2e1b7c4c8726a Mon Sep 17 00:00:00 2001 From: Nick Zitzmann Date: Mon, 16 Jul 2012 20:20:57 -0600 Subject: darwinssl: fixed freeze involving the multi interface Previously the curl_multi interface would freeze if darwinssl was enabled and at least one of the handles tried to connect to a Web site using HTTPS. Removed the "wouldblock" state darwinssl was using because I figured out a solution for our "would block but in which direction?" dilemma. --- lib/http.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 06bdf610c..0c12d1896 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1371,9 +1371,10 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) } #endif -#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) -/* This function is for OpenSSL, GnuTLS and schannel only. It should be - made to query the generic SSL layer instead. */ +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) +/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. + It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) -- cgit v1.2.1 From 487538e87a3d5e1ac5874d4522a5636713054132 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Nov 2012 23:08:29 +0100 Subject: http_perhapsrewind: consider NTLM over proxy too The logic previously checked for a started NTLM negotiation only for host and not also with proxy, leading to problems doing POSTs over a proxy NTLM that are larger than 2000 bytes. Now it includes proxy in the check. Bug: http://curl.haxx.se/bug/view.cgi?id=3582321 Reported by: John Suprock --- lib/http.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 0c12d1896..4eee83221 100644 --- a/lib/http.c +++ b/lib/http.c @@ -387,7 +387,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { if(((expectsend - bytessent) < 2000) || - (conn->ntlm.state != NTLMSTATE_NONE)) { + (conn->ntlm.state != NTLMSTATE_NONE) || + (conn->proxyntlm.state != NTLMSTATE_NONE)) { /* The NTLM-negotiation has started *OR* there is just a little (<2K) data left to send, keep on sending. */ @@ -407,7 +408,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) " bytes\n", (curl_off_t)(expectsend - bytessent)); } - /* This is not NTLM or NTLM with many bytes left to send: close + /* This is not NTLM or many bytes left to send: close */ conn->bits.close = TRUE; data->req.size = 0; /* don't download any more than 0 bytes */ -- cgit v1.2.1 From 0683adbf50a99f0917c74cd3c5def77254ba9258 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Sun, 25 Nov 2012 18:34:01 +0100 Subject: Remove stray CRLF in chunk-encoded content-free request bodies .. that are sent when auth-negotiating before a chunked upload or when setting the 'Transfer-Encoding: chunked' header and intentionally sending no content. Adjust test565 and test1333 accordingly. --- lib/http.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 4eee83221..965b37503 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2484,15 +2484,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(postsize) { /* Append the POST data chunky-style */ result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); - if(CURLE_OK == result) + if(CURLE_OK == result) { result = Curl_add_buffer(req_buffer, data->set.postfields, (size_t)postsize); + if(CURLE_OK == result) + result = Curl_add_buffer(req_buffer, "\r\n", 2); + included_body = postsize + 2; + } } if(CURLE_OK == result) result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ - included_body = postsize + 7; + "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ + included_body += 5; } if(result) return result; @@ -2526,8 +2530,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* Chunky upload is selected and we're negotiating auth still, send end-of-data only */ result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ + "\x30\x0d\x0a\x0d\x0a", 5); + /* 0 CR LF CR LF */ if(result) return result; } -- cgit v1.2.1 From d021f2e8a0067fc769652f27afec9024c0d02b3d Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Thu, 6 Dec 2012 12:12:04 +0100 Subject: Introducing a new persistent connection caching system using "bundles". A bundle is a list of all persistent connections to the same host. The connection cache consists of a hash of bundles, with the hostname as the key. The benefits may not be obvious, but they are two: 1) Faster search for connections to reuse, since the hash lookup only finds connections to the host in question. 2) It lays out the groundworks for an upcoming patch, which will introduce multiple HTTP pipelines. This patch also removes the awkward list of "closure handles", which were needed to send QUIT commands to the FTP server when closing a connection. Now we allocate a separate closure handle and use that one to close all connections. This has been tested in a live system for a few weeks, and of course passes the test suite. --- lib/http.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/http.c') diff --git a/lib/http.c b/lib/http.c index 965b37503..0b6d7d4c5 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3170,6 +3170,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, } else if(conn->httpversion >= 11 && !conn->bits.close) { + /* If HTTP version is >= 1.1 and connection is persistent server supports pipelining. */ DEBUGF(infof(data, -- cgit v1.2.1