1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
25 #ifndef CURL_DISABLE_HTTP
26 /* -- WIN32 approved -- */
37 #ifdef HAVE_SYS_SOCKET_H
38 #include <sys/socket.h>
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
43 #ifdef HAVE_SYS_TIME_H
48 #ifdef TIME_WITH_SYS_TIME
59 #ifdef HAVE_ARPA_INET_H
60 #include <arpa/inet.h>
65 #ifdef HAVE_SYS_IOCTL_H
66 #include <sys/ioctl.h>
69 #ifdef HAVE_SYS_PARAM_H
70 #include <sys/param.h>
76 #include <curl/curl.h>
79 #include "easyif.h" /* for Curl_convert_... prototypes */
82 #include "curl_base64.h"
86 #include "http_digest.h"
87 #include "http_ntlm.h"
88 #include "http_negotiate.h"
93 #include "curl_memory.h"
95 #include "parsedate.h" /* for the week day and month names */
96 #include "strtoofft.h"
99 #include "content_encoding.h"
101 #include "warnless.h"
103 #define _MPRINTF_REPLACE /* use our functions only */
104 #include <curl/mprintf.h>
106 /* The last #include file should be: */
107 #include "memdebug.h"
109 /* Default proxy timeout in milliseconds */
110 #define PROXY_TIMEOUT (3600*1000)
113 * Forward declarations.
116 static int http_getsock_do(struct connectdata *conn,
117 curl_socket_t *socks,
120 static CURLcode https_connecting(struct connectdata *conn, bool *done);
121 static int https_getsock(struct connectdata *conn,
122 curl_socket_t *socks,
125 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
129 * HTTP handler interface.
131 const struct Curl_handler Curl_handler_http = {
133 ZERO_NULL, /* setup_connection */
134 Curl_http, /* do_it */
135 Curl_http_done, /* done */
136 ZERO_NULL, /* do_more */
137 Curl_http_connect, /* connect_it */
138 ZERO_NULL, /* connecting */
139 ZERO_NULL, /* doing */
140 ZERO_NULL, /* proto_getsock */
141 http_getsock_do, /* doing_getsock */
142 ZERO_NULL, /* perform_getsock */
143 ZERO_NULL, /* disconnect */
144 PORT_HTTP, /* defport */
145 PROT_HTTP, /* protocol */
150 * HTTPS handler interface.
152 const struct Curl_handler Curl_handler_https = {
153 "HTTPS", /* scheme */
154 ZERO_NULL, /* setup_connection */
155 Curl_http, /* do_it */
156 Curl_http_done, /* done */
157 ZERO_NULL, /* do_more */
158 Curl_http_connect, /* connect_it */
159 https_connecting, /* connecting */
160 ZERO_NULL, /* doing */
161 https_getsock, /* proto_getsock */
162 http_getsock_do, /* doing_getsock */
163 ZERO_NULL, /* perform_getsock */
164 ZERO_NULL, /* disconnect */
165 PORT_HTTPS, /* defport */
166 PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */
172 * checkheaders() checks the linked list of custom HTTP headers for a
173 * particular header (prefix).
175 * Returns a pointer to the first matching header or NULL if none matched.
177 char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
179 struct curl_slist *head;
180 size_t thislen = strlen(thisheader);
182 for(head = data->set.headers; head; head=head->next) {
183 if(Curl_raw_nequal(head->data, thisheader, thislen))
190 * Strip off leading and trailing whitespace from the value in the
191 * given HTTP header line and return a strdupped copy. Returns NULL in
192 * case of allocation failure. Returns an empty string if the header value
193 * consists entirely of whitespace.
195 char *Curl_copy_header_value(const char *h)
204 /* Find the end of the header name */
205 while (*h && (*h != ':'))
209 /* Skip over colon */
212 /* Find the first non-space letter */
214 while(*start && ISSPACE(*start))
217 /* data is in the host encoding so
218 use '\r' and '\n' instead of 0x0d and 0x0a */
219 end = strchr(start, '\r');
221 end = strchr(start, '\n');
223 end = strchr(start, '\0');
227 /* skip all trailing space letters */
228 while((end > start) && ISSPACE(*end))
231 /* get length of the type */
234 value = malloc(len + 1);
238 memcpy(value, start, len);
239 value[len] = 0; /* zero terminate */
245 * http_output_basic() sets up an Authorization: header (or the proxy version)
246 * for HTTP Basic authentication.
250 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
253 struct SessionHandle *data=conn->data;
259 userp = &conn->allocptr.proxyuserpwd;
260 user = conn->proxyuser;
261 pwd = conn->proxypasswd;
264 userp = &conn->allocptr.userpwd;
269 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
270 if(Curl_base64_encode(data, data->state.buffer,
271 strlen(data->state.buffer),
272 &authorization) > 0) {
275 *userp = aprintf( "%sAuthorization: Basic %s\r\n",
280 return CURLE_OUT_OF_MEMORY;
283 return CURLE_OUT_OF_MEMORY;
287 /* pickoneauth() selects the most favourable authentication method from the
288 * ones available and the ones we want.
290 * return TRUE if one was picked
292 static bool pickoneauth(struct auth *pick)
295 /* only deal with authentication we want */
296 long avail = pick->avail & pick->want;
299 /* The order of these checks is highly relevant, as this will be the order
300 of preference in case of the existence of multiple accepted types. */
301 if(avail & CURLAUTH_GSSNEGOTIATE)
302 pick->picked = CURLAUTH_GSSNEGOTIATE;
303 else if(avail & CURLAUTH_DIGEST)
304 pick->picked = CURLAUTH_DIGEST;
305 else if(avail & CURLAUTH_NTLM)
306 pick->picked = CURLAUTH_NTLM;
307 else if(avail & CURLAUTH_BASIC)
308 pick->picked = CURLAUTH_BASIC;
310 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
313 pick->avail = CURLAUTH_NONE; /* clear it here */
319 * Curl_http_perhapsrewind()
321 * If we are doing POST or PUT {
322 * If we have more data to send {
323 * If we are doing NTLM {
324 * Keep sending since we must not disconnect
327 * If there is more than just a little data left to send, close
328 * the current connection by force.
331 * If we have sent any data {
332 * If we don't have track of all the data {
333 * call app to tell it to rewind
336 * rewind internally so that the operation can restart fine
341 CURLcode Curl_http_perhapsrewind(struct connectdata *conn)
343 struct SessionHandle *data = conn->data;
344 struct HTTP *http = data->state.proto.http;
345 curl_off_t bytessent;
346 curl_off_t expectsend = -1; /* default is unknown */
348 if(!http || !(conn->protocol & PROT_HTTP))
349 /* If this is still NULL, we have not reach very far and we can
350 safely skip this rewinding stuff, or this is attempted to get used
351 when HTTP isn't activated */
354 switch(data->set.httpreq) {
362 bytessent = http->writebytecount;
364 if(conn->bits.authneg)
365 /* This is a state where we are known to be negotiating and we don't send
369 /* figure out how much data we are expected to send */
370 switch(data->set.httpreq) {
372 if(data->set.postfieldsize != -1)
373 expectsend = data->set.postfieldsize;
374 else if(data->set.postfields)
375 expectsend = (curl_off_t)strlen(data->set.postfields);
378 if(data->set.infilesize != -1)
379 expectsend = data->set.infilesize;
381 case HTTPREQ_POST_FORM:
382 expectsend = http->postsize;
389 conn->bits.rewindaftersend = FALSE; /* default */
391 if((expectsend == -1) || (expectsend > bytessent)) {
392 /* There is still data left to send */
393 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
394 (data->state.authhost.picked == CURLAUTH_NTLM)) {
395 if(((expectsend - bytessent) < 2000) ||
396 (conn->ntlm.state != NTLMSTATE_NONE)) {
397 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
398 data left to send, keep on sending. */
400 /* rewind data when completely done sending! */
401 if(!conn->bits.authneg)
402 conn->bits.rewindaftersend = TRUE;
407 /* this is already marked to get closed */
410 infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T
411 " bytes\n", (curl_off_t)(expectsend - bytessent));
414 /* This is not NTLM or NTLM with many bytes left to send: close
416 conn->bits.close = TRUE;
417 data->req.size = 0; /* don't download any more than 0 bytes */
419 /* There still is data left to send, but this connection is marked for
420 closure so we can safely do the rewind right now */
424 /* we rewind now at once since if we already sent something */
425 return Curl_readrewind(conn);
431 * Curl_http_auth_act() gets called when all HTTP headers have been received
432 * and it checks what authentication methods that are available and decides
433 * which one (if any) to use. It will set 'newurl' if an auth method was
437 CURLcode Curl_http_auth_act(struct connectdata *conn)
439 struct SessionHandle *data = conn->data;
440 bool pickhost = FALSE;
441 bool pickproxy = FALSE;
442 CURLcode code = CURLE_OK;
444 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
445 /* this is a transient response code, ignore */
448 if(data->state.authproblem)
449 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
451 if(conn->bits.user_passwd &&
452 ((data->req.httpcode == 401) ||
453 (conn->bits.authneg && data->req.httpcode < 300))) {
454 pickhost = pickoneauth(&data->state.authhost);
456 data->state.authproblem = TRUE;
458 if(conn->bits.proxy_user_passwd &&
459 ((data->req.httpcode == 407) ||
460 (conn->bits.authneg && data->req.httpcode < 300))) {
461 pickproxy = pickoneauth(&data->state.authproxy);
463 data->state.authproblem = TRUE;
466 if(pickhost || pickproxy) {
467 /* In case this is GSS auth, the newurl field is already allocated so
468 we must make sure to free it before allocating a new one. As figured
469 out in bug #2284386 */
470 Curl_safefree(data->req.newurl);
471 data->req.newurl = strdup(data->change.url); /* clone URL */
472 if(!data->req.newurl)
473 return CURLE_OUT_OF_MEMORY;
475 if((data->set.httpreq != HTTPREQ_GET) &&
476 (data->set.httpreq != HTTPREQ_HEAD) &&
477 !conn->bits.rewindaftersend) {
478 code = Curl_http_perhapsrewind(conn);
484 else if((data->req.httpcode < 300) &&
485 (!data->state.authhost.done) &&
486 conn->bits.authneg) {
487 /* no (known) authentication available,
488 authentication is not "done" yet and
489 no authentication seems to be required and
490 we didn't try HEAD or GET */
491 if((data->set.httpreq != HTTPREQ_GET) &&
492 (data->set.httpreq != HTTPREQ_HEAD)) {
493 data->req.newurl = strdup(data->change.url); /* clone URL */
494 if(!data->req.newurl)
495 return CURLE_OUT_OF_MEMORY;
496 data->state.authhost.done = TRUE;
499 if(Curl_http_should_fail(conn)) {
500 failf (data, "The requested URL returned error: %d",
502 code = CURLE_HTTP_RETURNED_ERROR;
510 * Output the correct authentication header depending on the auth type
511 * and whether or not it is to a proxy.
514 output_auth_headers(struct connectdata *conn,
515 struct auth *authstatus,
520 struct SessionHandle *data = conn->data;
521 const char *auth=NULL;
522 CURLcode result = CURLE_OK;
524 struct negotiatedata *negdata = proxy?
525 &data->state.proxyneg:&data->state.negotiate;
528 #ifdef CURL_DISABLE_CRYPTO_AUTH
534 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
535 negdata->context && !GSS_ERROR(negdata->status)) {
536 auth="GSS-Negotiate";
537 result = Curl_output_negotiate(conn, proxy);
540 authstatus->done = TRUE;
541 negdata->state = GSS_AUTHSENT;
546 if(authstatus->picked == CURLAUTH_NTLM) {
548 result = Curl_output_ntlm(conn, proxy);
554 #ifndef CURL_DISABLE_CRYPTO_AUTH
555 if(authstatus->picked == CURLAUTH_DIGEST) {
557 result = Curl_output_digest(conn,
559 (const unsigned char *)request,
560 (const unsigned char *)path);
566 if(authstatus->picked == CURLAUTH_BASIC) {
568 if((proxy && conn->bits.proxy_user_passwd &&
569 !Curl_checkheaders(data, "Proxy-authorization:")) ||
570 (!proxy && conn->bits.user_passwd &&
571 !Curl_checkheaders(data, "Authorization:"))) {
573 result = http_output_basic(conn, proxy);
577 /* NOTE: this function should set 'done' TRUE, as the other auth
578 functions work that way */
579 authstatus->done = TRUE;
583 infof(data, "%s auth using %s with user '%s'\n",
584 proxy?"Proxy":"Server", auth,
585 proxy?(conn->proxyuser?conn->proxyuser:""):
586 (conn->user?conn->user:""));
587 authstatus->multi = (bool)(!authstatus->done);
590 authstatus->multi = FALSE;
596 * Curl_http_output_auth() setups the authentication headers for the
597 * host/proxy and the correct authentication
598 * method. conn->data->state.authdone is set to TRUE when authentication is
601 * @param conn all information about the current connection
602 * @param request pointer to the request keyword
603 * @param path pointer to the requested path
604 * @param proxytunnel boolean if this is the request setting up a "proxy
610 http_output_auth(struct connectdata *conn,
613 bool proxytunnel) /* TRUE if this is the request setting
614 up the proxy tunnel */
616 CURLcode result = CURLE_OK;
617 struct SessionHandle *data = conn->data;
618 struct auth *authhost;
619 struct auth *authproxy;
623 authhost = &data->state.authhost;
624 authproxy = &data->state.authproxy;
626 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
627 conn->bits.user_passwd)
628 /* continue please */ ;
630 authhost->done = TRUE;
631 authproxy->done = TRUE;
632 return CURLE_OK; /* no authentication with no user or password */
635 if(authhost->want && !authhost->picked)
636 /* The app has selected one or more methods, but none has been picked
637 so far by a server round-trip. Then we set the picked one to the
638 want one, and if this is one single bit it'll be used instantly. */
639 authhost->picked = authhost->want;
641 if(authproxy->want && !authproxy->picked)
642 /* The app has selected one or more methods, but none has been picked so
643 far by a proxy round-trip. Then we set the picked one to the want one,
644 and if this is one single bit it'll be used instantly. */
645 authproxy->picked = authproxy->want;
647 #ifndef CURL_DISABLE_PROXY
648 /* Send proxy authentication header if needed */
649 if(conn->bits.httpproxy &&
650 (conn->bits.tunnel_proxy == proxytunnel)) {
651 result = output_auth_headers(conn, authproxy, request, path, TRUE);
658 #endif /* CURL_DISABLE_PROXY */
659 /* we have no proxy so let's pretend we're done authenticating
661 authproxy->done = TRUE;
663 /* To prevent the user+password to get sent to other than the original
664 host due to a location-follow, we do some weirdo checks here */
665 if(!data->state.this_is_a_follow ||
667 !data->state.first_host ||
668 data->set.http_disable_hostname_check_before_authentication ||
669 Curl_raw_equal(data->state.first_host, conn->host.name)) {
670 result = output_auth_headers(conn, authhost, request, path, FALSE);
673 authhost->done = TRUE;
680 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
681 * headers. They are dealt with both in the transfer.c main loop and in the
682 * proxy CONNECT loop.
685 CURLcode Curl_http_input_auth(struct connectdata *conn,
687 const char *header) /* the first non-space */
690 * This resource requires authentication
692 struct SessionHandle *data = conn->data;
698 if(httpcode == 407) {
699 start = header+strlen("Proxy-authenticate:");
700 availp = &data->info.proxyauthavail;
701 authp = &data->state.authproxy;
704 start = header+strlen("WWW-Authenticate:");
705 availp = &data->info.httpauthavail;
706 authp = &data->state.authhost;
709 /* pass all white spaces */
710 while(*start && ISSPACE(*start))
714 * Here we check if we want the specific single authentication (using ==) and
715 * if we do, we initiate usage of it.
717 * If the provided authentication is wanted as one out of several accepted
718 * types (using &), we OR this authentication type to the authavail
723 * ->picked is first set to the 'want' value (one or more bits) before the
724 * request is sent, and then it is again set _after_ all response 401/407
725 * headers have been received but then only to a single preferred method
731 if(checkprefix("GSS-Negotiate", start) ||
732 checkprefix("Negotiate", start)) {
734 *availp |= CURLAUTH_GSSNEGOTIATE;
735 authp->avail |= CURLAUTH_GSSNEGOTIATE;
737 if(data->state.negotiate.state == GSS_AUTHSENT) {
738 /* if we sent GSS authentication in the outgoing request and we get this
739 back, we're in trouble */
740 infof(data, "Authentication problem. Ignoring this.\n");
741 data->state.authproblem = TRUE;
744 neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
746 DEBUGASSERT(!data->req.newurl);
747 data->req.newurl = strdup(data->change.url);
748 if(!data->req.newurl)
749 return CURLE_OUT_OF_MEMORY;
750 data->state.authproblem = FALSE;
751 /* we received GSS auth info and we dealt with it fine */
752 data->state.negotiate.state = GSS_AUTHRECV;
755 data->state.authproblem = TRUE;
762 /* NTLM support requires the SSL crypto libs */
763 if(checkprefix("NTLM", start)) {
764 *availp |= CURLAUTH_NTLM;
765 authp->avail |= CURLAUTH_NTLM;
766 if(authp->picked == CURLAUTH_NTLM) {
767 /* NTLM authentication is picked and activated */
769 Curl_input_ntlm(conn, (bool)(httpcode == 407), start);
771 if(CURLNTLM_BAD != ntlm)
772 data->state.authproblem = FALSE;
774 infof(data, "Authentication problem. Ignoring this.\n");
775 data->state.authproblem = TRUE;
781 #ifndef CURL_DISABLE_CRYPTO_AUTH
782 if(checkprefix("Digest", start)) {
783 if((authp->avail & CURLAUTH_DIGEST) != 0) {
784 infof(data, "Ignoring duplicate digest auth header.\n");
788 *availp |= CURLAUTH_DIGEST;
789 authp->avail |= CURLAUTH_DIGEST;
791 /* We call this function on input Digest headers even if Digest
792 * authentication isn't activated yet, as we need to store the
793 * incoming data from this header in case we are gonna use Digest. */
794 dig = Curl_input_digest(conn, (bool)(httpcode == 407), start);
796 if(CURLDIGEST_FINE != dig) {
797 infof(data, "Authentication problem. Ignoring this.\n");
798 data->state.authproblem = TRUE;
804 if(checkprefix("Basic", start)) {
805 *availp |= CURLAUTH_BASIC;
806 authp->avail |= CURLAUTH_BASIC;
807 if(authp->picked == CURLAUTH_BASIC) {
808 /* We asked for Basic authentication but got a 40X back
809 anyway, which basically means our name+password isn't
811 authp->avail = CURLAUTH_NONE;
812 infof(data, "Authentication problem. Ignoring this.\n");
813 data->state.authproblem = TRUE;
821 * Curl_http_should_fail() determines whether an HTTP response has gotten us
822 * into an error state or not.
824 * @param conn all information about the current connection
826 * @retval 0 communications should continue
828 * @retval 1 communications should not continue
830 int Curl_http_should_fail(struct connectdata *conn)
832 struct SessionHandle *data;
839 httpcode = data->req.httpcode;
842 ** If we haven't been asked to fail on error,
845 if(!data->set.http_fail_on_error)
849 ** Any code < 400 is never terminal.
854 if(data->state.resume_from &&
855 (data->set.httpreq==HTTPREQ_GET) &&
857 /* "Requested Range Not Satisfiable", just proceed and
858 pretend this is no error */
863 ** Any code >= 400 that's not 401 or 407 is always
866 if((httpcode != 401) &&
871 ** All we have left to deal with is 401 and 407
873 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
876 ** Examine the current authentication state to see if this
877 ** is an error. The idea is for this function to get
878 ** called after processing all the headers in a response
879 ** message. So, if we've been to asked to authenticate a
880 ** particular stage, and we've done it, we're OK. But, if
881 ** we're already completely authenticated, it's not OK to
882 ** get another 401 or 407.
884 ** It is possible for authentication to go stale such that
885 ** the client needs to reauthenticate. Once that info is
886 ** available, use it here.
888 #if 0 /* set to 1 when debugging this functionality */
889 infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage);
890 infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant);
891 infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
892 infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
893 infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
894 infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ?
895 data->req.newurl : "(null)");
896 infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
900 ** Either we're not authenticating, or we're supposed to
901 ** be authenticating something else. This is an error.
903 if((httpcode == 401) && !conn->bits.user_passwd)
905 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
908 return data->state.authproblem;
912 * readmoredata() is a "fread() emulation" to provide POST and/or request
913 * data. It is used when a huge POST is to be made and the entire chunk wasn't
914 * sent in the first send(). This function will then be called from the
915 * transfer.c loop when more data is to be sent to the peer.
917 * Returns the amount of bytes it filled the buffer with.
919 static size_t readmoredata(char *buffer,
924 struct connectdata *conn = (struct connectdata *)userp;
925 struct HTTP *http = conn->data->state.proto.http;
926 size_t fullsize = size * nitems;
928 if(0 == http->postsize)
929 /* nothing to return */
932 /* make sure that a HTTP request is never sent away chunked! */
933 conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST);
935 if(http->postsize <= (curl_off_t)fullsize) {
936 memcpy(buffer, http->postdata, (size_t)http->postsize);
937 fullsize = (size_t)http->postsize;
939 if(http->backup.postsize) {
940 /* move backup data into focus and continue on that */
941 http->postdata = http->backup.postdata;
942 http->postsize = http->backup.postsize;
943 conn->fread_func = http->backup.fread_func;
944 conn->fread_in = http->backup.fread_in;
946 http->sending++; /* move one step up */
948 http->backup.postsize=0;
956 memcpy(buffer, http->postdata, fullsize);
957 http->postdata += fullsize;
958 http->postsize -= fullsize;
963 /* ------------------------------------------------------------------------- */
964 /* add_buffer functions */
967 * Curl_add_buffer_init() sets up and returns a fine buffer struct
969 Curl_send_buffer *Curl_add_buffer_init(void)
971 return calloc(1, sizeof(Curl_send_buffer));
975 * Curl_add_buffer_send() sends a header buffer and frees all associated
976 * memory. Body data may be appended to the header data if desired.
980 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
981 struct connectdata *conn,
983 /* add the number of sent bytes to this
987 /* how much of the buffer contains body data */
988 size_t included_body_bytes,
996 struct HTTP *http = conn->data->state.proto.http;
998 curl_socket_t sockfd;
1001 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1003 sockfd = conn->sock[socketindex];
1005 /* The looping below is required since we use non-blocking sockets, but due
1006 to the circumstances we will just loop and try again and again etc */
1009 size = in->size_used;
1011 headersize = size - included_body_bytes; /* the initial part that isn't body
1014 DEBUGASSERT(size > included_body_bytes);
1016 #ifdef CURL_DOES_CONVERSIONS
1017 res = Curl_convert_to_network(conn->data, ptr, headersize);
1018 /* Curl_convert_to_network calls failf if unsuccessful */
1019 if(res != CURLE_OK) {
1020 /* conversion failed, free memory and return to the caller */
1026 #endif /* CURL_DOES_CONVERSIONS */
1028 if(conn->protocol & PROT_HTTPS) {
1029 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1030 when we speak HTTPS, as if only a fraction of it is sent now, this data
1031 needs to fit into the normal read-callback buffer later on and that
1032 buffer is using this size.
1035 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1037 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1038 library when we attempt to re-send this buffer. Sending the same data
1039 is not enough, we must use the exact same address. For this reason, we
1040 must copy the data to the uploadbuffer first, since that is the buffer
1041 we will be using if this send is retried later.
1043 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1044 ptr = conn->data->state.uploadbuffer;
1049 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1051 if(CURLE_OK == res) {
1053 * Note that we may not send the entire chunk at once, and we have a set
1054 * number of data bytes at the end of the big buffer (out of which we may
1055 * only send away a part).
1057 /* how much of the header that was sent */
1058 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1059 size_t bodylen = amount - headlen;
1061 if(conn->data->set.verbose) {
1062 /* this data _may_ contain binary stuff */
1063 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1064 if((size_t)amount > headlen) {
1065 /* there was body data sent beyond the initial header part, pass that
1066 on to the debug callback too */
1067 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1068 ptr+headlen, bodylen, conn);
1072 /* since we sent a piece of the body here, up the byte counter for it
1074 http->writebytecount += bodylen;
1076 /* 'amount' can never be a very large value here so typecasting it so a
1077 signed 31 bit value should not cause problems even if ssize_t is
1079 *bytes_written += (long)amount;
1082 if((size_t)amount != size) {
1083 /* The whole request could not be sent in one system call. We must
1084 queue it up and send it later when we get the chance. We must not
1085 loop here and wait until it might work again. */
1089 ptr = in->buffer + amount;
1091 /* backup the currently set pointers */
1092 http->backup.fread_func = conn->fread_func;
1093 http->backup.fread_in = conn->fread_in;
1094 http->backup.postdata = http->postdata;
1095 http->backup.postsize = http->postsize;
1097 /* set the new pointers for the request-sending */
1098 conn->fread_func = (curl_read_callback)readmoredata;
1099 conn->fread_in = (void *)conn;
1100 http->postdata = ptr;
1101 http->postsize = (curl_off_t)size;
1103 http->send_buffer = in;
1104 http->sending = HTTPSEND_REQUEST;
1108 http->sending = HTTPSEND_BODY;
1109 /* the full buffer was sent, clean up and return */
1112 if((size_t)amount != size)
1113 /* We have no continue-send mechanism now, fail. This can only happen
1114 when this function is used from the CONNECT sending function. We
1115 currently (stupidly) assume that the whole request is always sent
1116 away in the first single chunk.
1120 return CURLE_SEND_ERROR;
1122 conn->writechannel_inuse = FALSE;
1134 * add_bufferf() add the formatted input to the buffer.
1136 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1141 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1145 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1149 /* If we failed, we cleanup the whole buffer and return error */
1153 return CURLE_OUT_OF_MEMORY;
1157 * add_buffer() appends a memory chunk to the existing buffer
1159 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1164 if(~size < in->size_used) {
1165 /* If resulting used size of send buffer would wrap size_t, cleanup
1166 the whole buffer and return error. Otherwise the required buffer
1167 size will fit into a single allocatable memory chunk */
1168 Curl_safefree(in->buffer);
1170 return CURLE_OUT_OF_MEMORY;
1174 ((in->size_used + size) > (in->size_max - 1))) {
1176 /* If current buffer size isn't enough to hold the result, use a
1177 buffer size that doubles the required size. If this new size
1178 would wrap size_t, then just use the largest possible one */
1180 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1181 (~(size*2) < (in->size_used*2)))
1182 new_size = (size_t)-1;
1184 new_size = (in->size_used+size)*2;
1187 /* we have a buffer, enlarge the existing one */
1188 new_rb = realloc(in->buffer, new_size);
1190 /* create a new buffer */
1191 new_rb = malloc(new_size);
1194 /* If we failed, we cleanup the whole buffer and return error */
1195 Curl_safefree(in->buffer);
1197 return CURLE_OUT_OF_MEMORY;
1200 in->buffer = new_rb;
1201 in->size_max = new_size;
1203 memcpy(&in->buffer[in->size_used], inptr, size);
1205 in->size_used += size;
1210 /* end of the add_buffer functions */
1211 /* ------------------------------------------------------------------------- */
1216 * Curl_compareheader()
1218 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1219 * Pass headers WITH the colon.
1222 Curl_compareheader(const char *headerline, /* line to check */
1223 const char *header, /* header keyword _with_ colon */
1224 const char *content) /* content string to find */
1226 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1227 * by a colon (":") and the field value. Field names are case-insensitive.
1228 * The field value MAY be preceded by any amount of LWS, though a single SP
1231 size_t hlen = strlen(header);
1237 if(!Curl_raw_nequal(headerline, header, hlen))
1238 return FALSE; /* doesn't start with header */
1240 /* pass the header */
1241 start = &headerline[hlen];
1243 /* pass all white spaces */
1244 while(*start && ISSPACE(*start))
1247 /* find the end of the header line */
1248 end = strchr(start, '\r'); /* lines end with CRLF */
1250 /* in case there's a non-standard compliant line here */
1251 end = strchr(start, '\n');
1254 /* hm, there's no line ending here, use the zero byte! */
1255 end = strchr(start, '\0');
1258 len = end-start; /* length of the content part of the input line */
1259 clen = strlen(content); /* length of the word to find */
1261 /* find the content string in the rest of the line */
1262 for(;len>=clen;len--, start++) {
1263 if(Curl_raw_nequal(start, content, clen))
1264 return TRUE; /* match! */
1267 return FALSE; /* no match */
1270 #ifndef CURL_DISABLE_PROXY
1272 * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
1273 * function will issue the necessary commands to get a seamless tunnel through
1274 * this proxy. After that, the socket can be used just as a normal socket.
1276 * This badly needs to be rewritten. CONNECT should be sent and dealt with
1277 * like any ordinary HTTP request, and not specially crafted like this. This
1278 * function only remains here like this for now since the rewrite is a bit too
1279 * much work to do at the moment.
1281 * This function is BLOCKING which is nasty for all multi interface using apps.
1284 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
1286 const char *hostname,
1287 unsigned short remote_port)
1290 struct SessionHandle *data=conn->data;
1291 struct SingleRequest *k = &data->req;
1294 data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
1295 curl_socket_t tunnelsocket = conn->sock[sockindex];
1297 bool closeConnection = FALSE;
1298 bool chunked_encoding = FALSE;
1302 #define SELECT_ERROR 1
1303 #define SELECT_TIMEOUT 2
1304 int error = SELECT_OK;
1306 conn->bits.proxy_connect_closed = FALSE;
1309 if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
1311 Curl_send_buffer *req_buffer;
1313 infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
1314 hostname, remote_port);
1316 if(data->req.newurl) {
1317 /* This only happens if we've looped here due to authentication
1318 reasons, and we don't really use the newly cloned URL here
1319 then. Just free() it. */
1320 free(data->req.newurl);
1321 data->req.newurl = NULL;
1324 /* initialize a dynamic send-buffer */
1325 req_buffer = Curl_add_buffer_init();
1328 return CURLE_OUT_OF_MEMORY;
1330 host_port = aprintf("%s:%hu", hostname, remote_port);
1333 return CURLE_OUT_OF_MEMORY;
1336 /* Setup the proxy-authorization header, if any */
1337 result = http_output_auth(conn, "CONNECT", host_port, TRUE);
1339 if(CURLE_OK == result) {
1340 char *host=(char *)"";
1341 const char *proxyconn="";
1342 const char *useragent="";
1343 const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
1346 if(!Curl_checkheaders(data, "Host:")) {
1347 host = aprintf("Host: %s\r\n", host_port);
1351 return CURLE_OUT_OF_MEMORY;
1354 if(!Curl_checkheaders(data, "Proxy-Connection:"))
1355 proxyconn = "Proxy-Connection: Keep-Alive\r\n";
1357 if(!Curl_checkheaders(data, "User-Agent:") &&
1358 data->set.str[STRING_USERAGENT])
1359 useragent = conn->allocptr.uagent;
1361 /* Send the connect request to the proxy */
1364 Curl_add_bufferf(req_buffer,
1365 "CONNECT %s:%hu HTTP/%s\r\n"
1367 "%s" /* Proxy-Authorization */
1368 "%s" /* User-Agent */
1369 "%s", /* Proxy-Connection */
1370 hostname, remote_port, http,
1372 conn->allocptr.proxyuserpwd?
1373 conn->allocptr.proxyuserpwd:"",
1380 if(CURLE_OK == result)
1381 result = Curl_add_custom_headers(conn, req_buffer);
1383 if(CURLE_OK == result)
1384 /* CRLF terminate the request */
1385 result = Curl_add_bufferf(req_buffer, "\r\n");
1387 if(CURLE_OK == result) {
1388 /* Now send off the request */
1389 result = Curl_add_buffer_send(req_buffer, conn,
1390 &data->info.request_size, 0, sockindex);
1394 failf(data, "Failed sending CONNECT to proxy");
1397 Curl_safefree(req_buffer);
1401 conn->bits.tunnel_connecting = TRUE;
1402 } /* END CONNECT PHASE */
1404 /* now we've issued the CONNECT and we're waiting to hear back -
1405 we try not to block here in multi-mode because that might be a LONG
1406 wait if the proxy cannot connect-through to the remote host. */
1408 /* if timeout is requested, find out how much remaining time we have */
1409 check = timeout - /* timeout time */
1410 Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
1412 failf(data, "Proxy CONNECT aborted due to timeout");
1413 return CURLE_RECV_ERROR;
1416 /* if we're in multi-mode and we would block, return instead for a retry */
1417 if(Curl_if_multi == data->state.used_interface) {
1418 if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
1419 /* return so we'll be called again polling-style */
1423 "Multi mode finished polling for response from "
1428 DEBUGF(infof(data, "Easy mode waiting response from proxy CONNECT."));
1431 /* at this point, either:
1432 1) we're in easy-mode and so it's okay to block waiting for a CONNECT
1434 2) we're in multi-mode and we didn't block - it's either an error or we
1435 now have some data waiting.
1436 In any case, the tunnel_connecting phase is over. */
1437 conn->bits.tunnel_connecting = FALSE;
1439 { /* BEGIN NEGOTIATION PHASE */
1440 size_t nread; /* total size read */
1441 int perline; /* count bytes per line */
1447 ptr=data->state.buffer;
1454 while((nread<BUFSIZE) && (keepon && !error)) {
1456 /* if timeout is requested, find out how much remaining time we have */
1457 check = timeout - /* timeout time */
1458 Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
1460 failf(data, "Proxy CONNECT aborted due to timeout");
1461 error = SELECT_TIMEOUT; /* already too little time */
1465 /* loop every second at least, less if the timeout is near */
1466 switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
1467 check<1000L?(int)check:1000)) {
1468 case -1: /* select() error, stop reading */
1469 error = SELECT_ERROR;
1470 failf(data, "Proxy CONNECT aborted due to select/poll error");
1472 case 0: /* timeout */
1475 DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
1476 result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
1477 if(result==CURLE_AGAIN)
1478 continue; /* go loop yourself */
1481 else if(gotbytes <= 0) {
1483 if(data->set.proxyauth && data->state.authproxy.avail) {
1484 /* proxy auth was requested and there was proxy auth available,
1485 then deem this as "mere" proxy disconnect */
1486 conn->bits.proxy_connect_closed = TRUE;
1489 error = SELECT_ERROR;
1490 failf(data, "Proxy CONNECT aborted");
1495 * We got a whole chunk of data, which can be anything from one
1496 * byte to a set of lines and possibly just a piece of the last
1504 /* This means we are currently ignoring a response-body */
1506 nread = 0; /* make next read start over in the read buffer */
1507 ptr=data->state.buffer;
1509 /* A Content-Length based body: simply count down the counter
1510 and make sure to break out of the loop when we're done! */
1518 /* chunked-encoded body, so we need to do the chunked dance
1519 properly to know when the end of the body is reached */
1521 ssize_t tookcareof=0;
1523 /* now parse the chunked piece of data so that we can
1524 properly tell when the stream ends */
1525 r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
1526 if(r == CHUNKE_STOP) {
1527 /* we're done reading chunks! */
1528 infof(data, "chunk reading DONE\n");
1532 infof(data, "Read %zd bytes of chunk, continue\n",
1537 for(i = 0; i < gotbytes; ptr++, i++) {
1538 perline++; /* amount of bytes in this line so far */
1543 #ifdef CURL_DOES_CONVERSIONS
1544 /* convert from the network encoding */
1545 result = Curl_convert_from_network(data, line_start,
1547 /* Curl_convert_from_network calls failf if unsuccessful */
1550 #endif /* CURL_DOES_CONVERSIONS */
1552 /* output debug if that is requested */
1553 if(data->set.verbose)
1554 Curl_debug(data, CURLINFO_HEADER_IN,
1555 line_start, (size_t)perline, conn);
1557 /* send the header to the callback */
1558 writetype = CLIENTWRITE_HEADER;
1559 if(data->set.include_header)
1560 writetype |= CLIENTWRITE_BODY;
1562 result = Curl_client_write(conn, writetype, line_start,
1567 /* Newlines are CRLF, so the CR is ignored as the line isn't
1568 really terminated until the LF comes. Treat a following CR
1569 as end-of-headers as well.*/
1571 if(('\r' == line_start[0]) ||
1572 ('\n' == line_start[0])) {
1573 /* end of response-headers from the proxy */
1574 nread = 0; /* make next read start over in the read
1576 ptr=data->state.buffer;
1577 if((407 == k->httpcode) && !data->state.authproblem) {
1578 /* If we get a 407 response code with content length
1579 when we have no auth problem, we must ignore the
1580 whole response-body */
1585 infof(data, "Ignore %" FORMAT_OFF_T
1586 " bytes of response-body\n", cl);
1587 /* remove the remaining chunk of what we already
1589 cl -= (gotbytes - i);
1592 /* if the whole thing was already read, we are done!
1596 else if(chunked_encoding) {
1598 /* We set ignorebody true here since the chunked
1599 decoder function will acknowledge that. Pay
1600 attention so that this is cleared again when this
1601 function returns! */
1602 k->ignorebody = TRUE;
1603 infof(data, "%zd bytes of chunk left\n", gotbytes-i);
1605 if(line_start[1] == '\n') {
1606 /* this can only be a LF if the letter at index 0
1612 /* now parse the chunked piece of data so that we can
1613 properly tell when the stream ends */
1614 r = Curl_httpchunk_read(conn, line_start+1,
1615 gotbytes -i, &gotbytes);
1616 if(r == CHUNKE_STOP) {
1617 /* we're done reading chunks! */
1618 infof(data, "chunk reading DONE\n");
1622 infof(data, "Read %zd bytes of chunk, continue\n",
1626 /* without content-length or chunked encoding, we
1627 can't keep the connection alive since the close is
1628 the end signal so we bail out at once instead */
1634 break; /* breaks out of for-loop, not switch() */
1637 /* keep a backup of the position we are about to blank */
1638 letter = line_start[perline];
1639 line_start[perline]=0; /* zero terminate the buffer */
1640 if((checkprefix("WWW-Authenticate:", line_start) &&
1641 (401 == k->httpcode)) ||
1642 (checkprefix("Proxy-authenticate:", line_start) &&
1643 (407 == k->httpcode))) {
1644 result = Curl_http_input_auth(conn, k->httpcode,
1649 else if(checkprefix("Content-Length:", line_start)) {
1650 cl = curlx_strtoofft(line_start +
1651 strlen("Content-Length:"), NULL, 10);
1653 else if(Curl_compareheader(line_start,
1654 "Connection:", "close"))
1655 closeConnection = TRUE;
1656 else if(Curl_compareheader(line_start,
1657 "Transfer-Encoding:",
1659 infof(data, "CONNECT responded chunked\n");
1660 chunked_encoding = TRUE;
1661 /* init our chunky engine */
1662 Curl_httpchunk_init(conn);
1664 else if(Curl_compareheader(line_start,
1665 "Proxy-Connection:", "close"))
1666 closeConnection = TRUE;
1667 else if(2 == sscanf(line_start, "HTTP/1.%d %d",
1670 /* store the HTTP code from the proxy */
1671 data->info.httpproxycode = k->httpcode;
1673 /* put back the letter we blanked out before */
1674 line_start[perline]= letter;
1676 perline=0; /* line starts over here */
1677 line_start = ptr+1; /* this skips the zero byte we wrote */
1683 if(Curl_pgrsUpdate(conn))
1684 return CURLE_ABORTED_BY_CALLBACK;
1685 } /* while there's buffer left and loop is requested */
1688 return CURLE_RECV_ERROR;
1690 if(data->info.httpproxycode != 200) {
1691 /* Deal with the possibly already received authenticate
1692 headers. 'newurl' is set to a new URL if we must loop. */
1693 result = Curl_http_auth_act(conn);
1697 if(conn->bits.close)
1698 /* the connection has been marked for closure, most likely in the
1699 Curl_http_auth_act() function and thus we can kill it at once
1702 closeConnection = TRUE;
1705 if(closeConnection && data->req.newurl) {
1706 /* Connection closed by server. Don't use it anymore */
1707 sclose(conn->sock[sockindex]);
1708 conn->sock[sockindex] = CURL_SOCKET_BAD;
1711 } /* END NEGOTIATION PHASE */
1712 } while(data->req.newurl);
1714 if(200 != data->req.httpcode) {
1715 failf(data, "Received HTTP code %d from proxy after CONNECT",
1716 data->req.httpcode);
1718 if(closeConnection && data->req.newurl)
1719 conn->bits.proxy_connect_closed = TRUE;
1721 return CURLE_RECV_ERROR;
1724 /* If a proxy-authorization header was used for the proxy, then we should
1725 make sure that it isn't accidentally used for the document request
1726 after we've connected. So let's free and clear it here. */
1727 Curl_safefree(conn->allocptr.proxyuserpwd);
1728 conn->allocptr.proxyuserpwd = NULL;
1730 data->state.authproxy.done = TRUE;
1732 infof (data, "Proxy replied OK to CONNECT request\n");
1733 data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
1736 #endif /* CURL_DISABLE_PROXY */
1739 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1740 * the generic Curl_connect().
1742 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1744 struct SessionHandle *data;
1749 /* We default to persistent connections. We set this already in this connect
1750 function to make the re-use checks properly be able to check this bit. */
1751 conn->bits.close = FALSE;
1753 #ifndef CURL_DISABLE_PROXY
1754 /* If we are not using a proxy and we want a secure connection, perform SSL
1755 * initialization & connection now. If using a proxy with https, then we
1756 * must tell the proxy to CONNECT to the host we want to talk to. Only
1757 * after the connect has occurred, can we start talking SSL
1759 if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
1761 /* either SSL over proxy, or explicitly asked for */
1762 result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
1765 if(CURLE_OK != result)
1769 if(conn->bits.tunnel_connecting) {
1770 /* nothing else to do except wait right now - we're not done here. */
1773 #endif /* CURL_DISABLE_PROXY */
1775 if(conn->protocol & PROT_HTTPS) {
1776 /* perform SSL initialization */
1777 if(data->state.used_interface == Curl_if_multi) {
1778 result = https_connecting(conn, done);
1784 result = Curl_ssl_connect(conn, FIRSTSOCKET);
1797 /* this returns the socket to wait for in the DO and DOING state for the multi
1798 interface and then we're always _sending_ a request and thus we wait for
1799 the single socket to become writable only */
1800 static int http_getsock_do(struct connectdata *conn,
1801 curl_socket_t *socks,
1805 (void)numsocks; /* unused, we trust it to be at least 1 */
1806 socks[0] = conn->sock[FIRSTSOCKET];
1807 return GETSOCK_WRITESOCK(0);
1811 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1814 DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS));
1816 /* perform SSL initialization for this socket */
1817 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1819 conn->bits.close = TRUE; /* a failed connection is marked for closure
1820 to prevent (bad) re-use or similar */
1825 #if defined(USE_SSLEAY) || defined(USE_GNUTLS)
1826 /* This function is for OpenSSL and GnuTLS only. It should be made to query
1827 the generic SSL layer instead. */
1828 static int https_getsock(struct connectdata *conn,
1829 curl_socket_t *socks,
1832 if(conn->protocol & PROT_HTTPS) {
1833 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1836 return GETSOCK_BLANK;
1838 if(connssl->connecting_state == ssl_connect_2_writing) {
1840 socks[0] = conn->sock[FIRSTSOCKET];
1841 return GETSOCK_WRITESOCK(0);
1843 else if(connssl->connecting_state == ssl_connect_2_reading) {
1845 socks[0] = conn->sock[FIRSTSOCKET];
1846 return GETSOCK_READSOCK(0);
1853 static int https_getsock(struct connectdata *conn,
1854 curl_socket_t *socks,
1860 return GETSOCK_BLANK;
1864 static int https_getsock(struct connectdata *conn,
1865 curl_socket_t *socks,
1871 return GETSOCK_BLANK;
1875 static int https_getsock(struct connectdata *conn,
1876 curl_socket_t *socks,
1882 return GETSOCK_BLANK;
1890 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1891 * has been performed.
1894 CURLcode Curl_http_done(struct connectdata *conn,
1895 CURLcode status, bool premature)
1897 struct SessionHandle *data = conn->data;
1898 struct HTTP *http =data->state.proto.http;
1899 (void)premature; /* not used */
1901 Curl_unencode_cleanup(conn);
1903 /* set the proper values (possibly modified on POST) */
1904 conn->fread_func = data->set.fread_func; /* restore */
1905 conn->fread_in = data->set.in; /* restore */
1906 conn->seek_func = data->set.seek_func; /* restore */
1907 conn->seek_client = data->set.seek_client; /* restore */
1912 if(http->send_buffer) {
1913 Curl_send_buffer *buff = http->send_buffer;
1917 http->send_buffer = NULL; /* clear the pointer */
1920 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1921 data->req.bytecount = http->readbytecount + http->writebytecount;
1923 Curl_formclean(&http->sendit); /* Now free that whole lot */
1925 /* a file being uploaded was left opened, close it! */
1926 fclose(http->form.fp);
1927 http->form.fp = NULL;
1930 else if(HTTPREQ_PUT == data->set.httpreq)
1931 data->req.bytecount = http->readbytecount + http->writebytecount;
1933 if(status != CURLE_OK)
1936 if(!premature && /* this check is pointless when DONE is called before the
1937 entire operation is complete */
1938 !conn->bits.retry &&
1939 ((http->readbytecount +
1940 data->req.headerbytecount -
1941 data->req.deductheadercount)) <= 0) {
1942 /* If this connection isn't simply closed to be retried, AND nothing was
1943 read from the HTTP server (that counts), this can't be right so we
1944 return an error here */
1945 failf(data, "Empty reply from server");
1946 return CURLE_GOT_NOTHING;
1953 /* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it
1954 are if the user specifically requested HTTP 1.0, if the server we are
1955 connected to only supports 1.0, or if any server previously contacted to
1956 handle this request only supports 1.0. */
1957 static bool use_http_1_1(const struct SessionHandle *data,
1958 const struct connectdata *conn)
1960 return (bool)((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
1961 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1962 ((conn->httpversion == 11) ||
1963 ((conn->httpversion != 10) &&
1964 (data->state.httpversion != 10)))));
1967 /* check and possibly add an Expect: header */
1968 static CURLcode expect100(struct SessionHandle *data,
1969 struct connectdata *conn,
1970 Curl_send_buffer *req_buffer)
1972 CURLcode result = CURLE_OK;
1974 data->state.expect100header = FALSE; /* default to false unless it is set
1976 if(use_http_1_1(data, conn)) {
1977 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1978 100-continue to the headers which actually speeds up post operations
1979 (as there is one packet coming back from the web server) */
1980 ptr = Curl_checkheaders(data, "Expect:");
1982 data->state.expect100header =
1983 Curl_compareheader(ptr, "Expect:", "100-continue");
1986 result = Curl_add_bufferf(req_buffer,
1987 "Expect: 100-continue\r\n");
1988 if(result == CURLE_OK)
1989 data->state.expect100header = TRUE;
1995 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1996 Curl_send_buffer *req_buffer)
1999 struct curl_slist *headers=conn->data->set.headers;
2002 ptr = strchr(headers->data, ':');
2004 /* we require a colon for this to be a true header */
2006 ptr++; /* pass the colon */
2007 while(*ptr && ISSPACE(*ptr))
2011 /* only send this if the contents was non-blank */
2013 if(conn->allocptr.host &&
2014 /* a Host: header was sent already, don't pass on any custom Host:
2015 header as that will produce *two* in the same request! */
2016 checkprefix("Host:", headers->data))
2018 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
2019 /* this header (extended by formdata.c) is sent later */
2020 checkprefix("Content-Type:", headers->data))
2022 else if(conn->bits.authneg &&
2023 /* while doing auth neg, don't allow the custom length since
2024 we will force length zero then */
2025 checkprefix("Content-Length", headers->data))
2028 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
2035 headers = headers->next;
2040 CURLcode Curl_add_timecondition(struct SessionHandle *data,
2041 Curl_send_buffer *req_buffer)
2044 char *buf = data->state.buffer;
2045 CURLcode result = CURLE_OK;
2047 /* The If-Modified-Since header family should have their times set in
2048 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
2049 * represented in Greenwich Mean Time (GMT), without exception. For the
2050 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
2051 * Time)." (see page 20 of RFC2616).
2054 #ifdef HAVE_GMTIME_R
2055 /* thread-safe version */
2057 tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
2059 tm = gmtime(&data->set.timevalue);
2062 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
2063 snprintf(buf, BUFSIZE-1,
2064 "%s, %02d %s %4d %02d:%02d:%02d GMT",
2065 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
2067 Curl_month[tm->tm_mon],
2073 switch(data->set.timecondition) {
2074 case CURL_TIMECOND_IFMODSINCE:
2076 result = Curl_add_bufferf(req_buffer,
2077 "If-Modified-Since: %s\r\n", buf);
2079 case CURL_TIMECOND_IFUNMODSINCE:
2080 result = Curl_add_bufferf(req_buffer,
2081 "If-Unmodified-Since: %s\r\n", buf);
2083 case CURL_TIMECOND_LASTMOD:
2084 result = Curl_add_bufferf(req_buffer,
2085 "Last-Modified: %s\r\n", buf);
2093 * Curl_http() gets called from the generic Curl_do() function when a HTTP
2094 * request is to be performed. This creates and sends a properly constructed
2097 CURLcode Curl_http(struct connectdata *conn, bool *done)
2099 struct SessionHandle *data=conn->data;
2100 CURLcode result=CURLE_OK;
2102 const char *ppath = data->state.path;
2103 bool paste_ftp_userpwd = FALSE;
2104 char ftp_typecode[sizeof("/;type=?")] = "";
2105 const char *host = conn->host.name;
2106 const char *te = ""; /* transfer-encoding */
2108 const char *request;
2109 Curl_HttpReq httpreq = data->set.httpreq;
2110 char *addcookies = NULL;
2111 curl_off_t included_body = 0;
2112 const char *httpstring;
2113 Curl_send_buffer *req_buffer;
2114 curl_off_t postsize; /* off_t type to be able to hold a large file size */
2115 int seekerr = CURL_SEEKFUNC_OK;
2117 /* Always consider the DO phase done after this function call, even if there
2118 may be parts of the request that is not yet sent, since we can deal with
2119 the rest of the request in the PERFORM phase. */
2122 /* If there already is a protocol-specific struct allocated for this
2123 sessionhandle, deal with it */
2124 Curl_reset_reqproto(conn);
2126 if(!data->state.proto.http) {
2127 /* Only allocate this struct if we don't already have it! */
2129 http = calloc(1, sizeof(struct HTTP));
2131 return CURLE_OUT_OF_MEMORY;
2132 data->state.proto.http = http;
2135 http = data->state.proto.http;
2137 if(!data->state.this_is_a_follow) {
2138 /* this is not a followed location, get the original host name */
2139 if(data->state.first_host)
2140 /* Free to avoid leaking memory on multiple requests*/
2141 free(data->state.first_host);
2143 data->state.first_host = strdup(conn->host.name);
2144 if(!data->state.first_host)
2145 return CURLE_OUT_OF_MEMORY;
2148 if( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
2150 httpreq = HTTPREQ_PUT;
2153 /* Now set the 'request' pointer to the proper request string */
2154 if(data->set.str[STRING_CUSTOMREQUEST])
2155 request = data->set.str[STRING_CUSTOMREQUEST];
2157 if(data->set.opt_no_body)
2160 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
2163 case HTTPREQ_POST_FORM:
2169 default: /* this should never happen */
2180 /* The User-Agent string might have been allocated in url.c already, because
2181 it might have been used in the proxy connect, but if we have got a header
2182 with the user-agent string specified, we erase the previously made string
2184 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
2185 free(conn->allocptr.uagent);
2186 conn->allocptr.uagent=NULL;
2189 /* setup the authentication headers */
2190 result = http_output_auth(conn, request, ppath, FALSE);
2194 if((data->state.authhost.multi || data->state.authproxy.multi) &&
2195 (httpreq != HTTPREQ_GET) &&
2196 (httpreq != HTTPREQ_HEAD)) {
2197 /* Auth is required and we are not authenticated yet. Make a PUT or POST
2198 with content-length zero as a "probe". */
2199 conn->bits.authneg = TRUE;
2202 conn->bits.authneg = FALSE;
2204 Curl_safefree(conn->allocptr.ref);
2205 if(data->change.referer && !Curl_checkheaders(data, "Referer:"))
2206 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
2208 conn->allocptr.ref = NULL;
2210 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
2211 addcookies = data->set.str[STRING_COOKIE];
2213 if(!Curl_checkheaders(data, "Accept-Encoding:") &&
2214 data->set.str[STRING_ENCODING]) {
2215 Curl_safefree(conn->allocptr.accept_encoding);
2216 conn->allocptr.accept_encoding =
2217 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
2218 if(!conn->allocptr.accept_encoding)
2219 return CURLE_OUT_OF_MEMORY;
2222 ptr = Curl_checkheaders(data, "Transfer-Encoding:");
2224 /* Some kind of TE is requested, check if 'chunked' is chosen */
2225 data->req.upload_chunky =
2226 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
2229 if((conn->protocol&PROT_HTTP) &&
2231 (data->set.infilesize == -1)) {
2232 if(conn->bits.authneg)
2233 /* don't enable chunked during auth neg */
2235 else if(use_http_1_1(data, conn)) {
2236 /* HTTP, upload, unknown file size and not HTTP 1.0 */
2237 data->req.upload_chunky = TRUE;
2240 failf(data, "Chunky upload is not supported by HTTP 1.0");
2241 return CURLE_UPLOAD_FAILED;
2245 /* else, no chunky upload */
2246 data->req.upload_chunky = FALSE;
2249 if(data->req.upload_chunky)
2250 te = "Transfer-Encoding: chunked\r\n";
2253 Curl_safefree(conn->allocptr.host);
2255 ptr = Curl_checkheaders(data, "Host:");
2256 if(ptr && (!data->state.this_is_a_follow ||
2257 Curl_raw_equal(data->state.first_host, conn->host.name))) {
2258 #if !defined(CURL_DISABLE_COOKIES)
2259 /* If we have a given custom Host: header, we extract the host name in
2260 order to possibly use it for cookie reasons later on. We only allow the
2261 custom Host: header if this is NOT a redirect, as setting Host: in the
2262 redirected request is being out on thin ice. Except if the host name
2263 is the same as the first one! */
2264 char *cookiehost = Curl_copy_header_value(ptr);
2266 return CURLE_OUT_OF_MEMORY;
2268 /* ignore empty data */
2271 char *colon = strchr(cookiehost, ':');
2273 *colon = 0; /* The host must not include an embedded port number */
2274 Curl_safefree(conn->allocptr.cookiehost);
2275 conn->allocptr.cookiehost = cookiehost;
2279 conn->allocptr.host = NULL;
2282 /* When building Host: headers, we must put the host name within
2283 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
2285 if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
2286 (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
2287 /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
2288 the port number in the host string */
2289 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2290 conn->bits.ipv6_ip?"[":"",
2292 conn->bits.ipv6_ip?"]":"");
2294 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
2295 conn->bits.ipv6_ip?"[":"",
2297 conn->bits.ipv6_ip?"]":"",
2300 if(!conn->allocptr.host)
2301 /* without Host: we can't make a nice request */
2302 return CURLE_OUT_OF_MEMORY;
2305 #ifndef CURL_DISABLE_PROXY
2306 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2307 /* Using a proxy but does not tunnel through it */
2309 /* The path sent to the proxy is in fact the entire URL. But if the remote
2310 host is a IDN-name, we must make sure that the request we produce only
2311 uses the encoded host name! */
2312 if(conn->host.dispname != conn->host.name) {
2313 char *url = data->change.url;
2314 ptr = strstr(url, conn->host.dispname);
2316 /* This is where the display name starts in the URL, now replace this
2317 part with the encoded name. TODO: This method of replacing the host
2318 name is rather crude as I believe there's a slight risk that the
2319 user has entered a user name or password that contain the host name
2321 size_t currlen = strlen(conn->host.dispname);
2322 size_t newlen = strlen(conn->host.name);
2323 size_t urllen = strlen(url);
2327 newurl = malloc(urllen + newlen - currlen + 1);
2329 /* copy the part before the host name */
2330 memcpy(newurl, url, ptr - url);
2331 /* append the new host name instead of the old */
2332 memcpy(newurl + (ptr - url), conn->host.name, newlen);
2333 /* append the piece after the host name */
2334 memcpy(newurl + newlen + (ptr - url),
2335 ptr + currlen, /* copy the trailing zero byte too */
2336 urllen - (ptr-url) - currlen + 1);
2337 if(data->change.url_alloc)
2338 free(data->change.url);
2339 data->change.url = newurl;
2340 data->change.url_alloc = TRUE;
2343 return CURLE_OUT_OF_MEMORY;
2346 ppath = data->change.url;
2347 if(checkprefix("ftp://", ppath)) {
2348 if (data->set.proxy_transfer_mode) {
2349 /* when doing ftp, append ;type=<a|i> if not present */
2350 char *type = strstr(ppath, ";type=");
2351 if(type && type[6] && type[7] == 0) {
2352 switch (Curl_raw_toupper(type[6])) {
2362 char *p = ftp_typecode;
2363 /* avoid sending invalid URLs like ftp://example.com;type=i if the
2364 * user specified ftp://example.com without the slash */
2365 if (!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
2368 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
2369 data->set.prefer_ascii ? 'a' : 'i');
2372 if (conn->bits.user_passwd && !conn->bits.userpwd_in_url)
2373 paste_ftp_userpwd = TRUE;
2376 #endif /* CURL_DISABLE_PROXY */
2378 if(HTTPREQ_POST_FORM == httpreq) {
2379 /* we must build the whole post sequence first, so that we have a size of
2380 the whole transfer before we start to send it */
2381 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
2382 Curl_checkheaders(data, "Content-Type:"),
2388 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
2390 if(( (HTTPREQ_POST == httpreq) ||
2391 (HTTPREQ_POST_FORM == httpreq) ||
2392 (HTTPREQ_PUT == httpreq) ) &&
2393 data->state.resume_from) {
2394 /**********************************************************************
2395 * Resuming upload in HTTP means that we PUT or POST and that we have
2396 * got a resume_from value set. The resume value has already created
2397 * a Range: header that will be passed along. We need to "fast forward"
2398 * the file the given number of bytes and decrease the assume upload
2399 * file size before we continue this venture in the dark lands of HTTP.
2400 *********************************************************************/
2402 if(data->state.resume_from < 0 ) {
2404 * This is meant to get the size of the present remote-file by itself.
2405 * We don't support this now. Bail out!
2407 data->state.resume_from = 0;
2410 if(data->state.resume_from && !data->state.this_is_a_follow) {
2411 /* do we still game? */
2413 /* Now, let's read off the proper amount of bytes from the
2415 if(conn->seek_func) {
2416 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2420 if(seekerr != CURL_SEEKFUNC_OK) {
2421 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2422 failf(data, "Could not seek stream");
2423 return CURLE_READ_ERROR;
2425 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2427 curl_off_t passed=0;
2429 size_t readthisamountnow =
2430 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2431 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2433 size_t actuallyread =
2434 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2437 passed += actuallyread;
2438 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2439 /* this checks for greater-than only to make sure that the
2440 CURL_READFUNC_ABORT return code still aborts */
2441 failf(data, "Could only read %" FORMAT_OFF_T
2442 " bytes from the input",
2444 return CURLE_READ_ERROR;
2446 } while(passed < data->state.resume_from);
2450 /* now, decrease the size of the read */
2451 if(data->set.infilesize>0) {
2452 data->set.infilesize -= data->state.resume_from;
2454 if(data->set.infilesize <= 0) {
2455 failf(data, "File already completely uploaded");
2456 return CURLE_PARTIAL_FILE;
2459 /* we've passed, proceed as normal */
2462 if(data->state.use_range) {
2464 * A range is selected. We use different headers whether we're downloading
2465 * or uploading and we always let customized headers override our internal
2466 * ones if any such are specified.
2468 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2469 !Curl_checkheaders(data, "Range:")) {
2470 /* if a line like this was already allocated, free the previous one */
2471 if(conn->allocptr.rangeline)
2472 free(conn->allocptr.rangeline);
2473 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2476 else if((httpreq != HTTPREQ_GET) &&
2477 !Curl_checkheaders(data, "Content-Range:")) {
2479 /* if a line like this was already allocated, free the previous one */
2480 if(conn->allocptr.rangeline)
2481 free(conn->allocptr.rangeline);
2483 if(data->set.set_resume_from < 0) {
2484 /* Upload resume was asked for, but we don't know the size of the
2485 remote part so we tell the server (and act accordingly) that we
2486 upload the whole file (again) */
2487 conn->allocptr.rangeline =
2488 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T
2489 "/%" FORMAT_OFF_T "\r\n",
2490 data->set.infilesize - 1, data->set.infilesize);
2493 else if(data->state.resume_from) {
2494 /* This is because "resume" was selected */
2495 curl_off_t total_expected_size=
2496 data->state.resume_from + data->set.infilesize;
2497 conn->allocptr.rangeline =
2498 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2499 "/%" FORMAT_OFF_T "\r\n",
2500 data->state.range, total_expected_size-1,
2501 total_expected_size);
2504 /* Range was selected and then we just pass the incoming range and
2505 append total size */
2506 conn->allocptr.rangeline =
2507 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2508 data->state.range, data->set.infilesize);
2510 if(!conn->allocptr.rangeline)
2511 return CURLE_OUT_OF_MEMORY;
2515 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2517 httpstring= use_http_1_1(data, conn)?"1.1":"1.0";
2519 /* initialize a dynamic send-buffer */
2520 req_buffer = Curl_add_buffer_init();
2523 return CURLE_OUT_OF_MEMORY;
2525 /* add the main request stuff */
2526 /* GET/HEAD/POST/PUT */
2527 result = Curl_add_bufferf(req_buffer, "%s ", request);
2532 if (paste_ftp_userpwd)
2533 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2534 conn->user, conn->passwd,
2535 ppath + sizeof("ftp://") - 1);
2537 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2541 result = Curl_add_bufferf(req_buffer,
2542 "%s" /* ftp typecode (;type=x) */
2543 " HTTP/%s\r\n" /* HTTP version */
2544 "%s" /* proxyuserpwd */
2547 "%s" /* user agent */
2550 "%s" /* accept-encoding */
2552 "%s" /* Proxy-Connection */
2553 "%s",/* transfer-encoding */
2557 conn->allocptr.proxyuserpwd?
2558 conn->allocptr.proxyuserpwd:"",
2559 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2560 (data->state.use_range && conn->allocptr.rangeline)?
2561 conn->allocptr.rangeline:"",
2562 (data->set.str[STRING_USERAGENT] &&
2563 *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
2564 conn->allocptr.uagent:"",
2565 (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
2566 http->p_accept?http->p_accept:"",
2567 (data->set.str[STRING_ENCODING] &&
2568 *data->set.str[STRING_ENCODING] &&
2569 conn->allocptr.accept_encoding)?
2570 conn->allocptr.accept_encoding:"",
2571 (data->change.referer && conn->allocptr.ref)?
2572 conn->allocptr.ref:"" /* Referer: <data> */,
2573 (conn->bits.httpproxy &&
2574 !conn->bits.tunnel_proxy &&
2575 !Curl_checkheaders(data, "Proxy-Connection:"))?
2576 "Proxy-Connection: Keep-Alive\r\n":"",
2581 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2582 * with basic and digest, it will be freed anyway by the next request
2585 Curl_safefree (conn->allocptr.userpwd);
2586 conn->allocptr.userpwd = NULL;
2591 #if !defined(CURL_DISABLE_COOKIES)
2592 if(data->cookies || addcookies) {
2593 struct Cookie *co=NULL; /* no cookies from start */
2597 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2598 co = Curl_cookie_getlist(data->cookies,
2599 conn->allocptr.cookiehost?
2600 conn->allocptr.cookiehost:host,
2602 (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
2603 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2606 struct Cookie *store=co;
2607 /* now loop through all cookies that matched */
2611 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2615 result = Curl_add_bufferf(req_buffer,
2616 "%s%s=%s", count?"; ":"",
2617 co->name, co->value);
2622 co = co->next; /* next cookie please */
2624 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2626 if(addcookies && (CURLE_OK == result)) {
2628 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2629 if(CURLE_OK == result) {
2630 result = Curl_add_bufferf(req_buffer, "%s%s",
2636 if(count && (CURLE_OK == result))
2637 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2644 if(data->set.timecondition) {
2645 result = Curl_add_timecondition(data, req_buffer);
2650 result = Curl_add_custom_headers(conn, req_buffer);
2654 http->postdata = NULL; /* nothing to post at this point */
2655 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2657 /* If 'authdone' is FALSE, we must not set the write socket index to the
2658 Curl_transfer() call below, as we're not ready to actually upload any
2663 case HTTPREQ_POST_FORM:
2664 if(!http->sendit || conn->bits.authneg) {
2665 /* nothing to post! */
2666 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2670 result = Curl_add_buffer_send(req_buffer, conn,
2671 &data->info.request_size, 0, FIRSTSOCKET);
2673 failf(data, "Failed sending POST request");
2675 /* setup variables for the upcoming transfer */
2676 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2681 if(Curl_FormInit(&http->form, http->sendit)) {
2682 failf(data, "Internal HTTP POST error!");
2683 return CURLE_HTTP_POST_ERROR;
2686 /* Get the currently set callback function pointer and store that in the
2687 form struct since we might want the actual user-provided callback later
2688 on. The conn->fread_func pointer itself will be changed for the
2689 multipart case to the function that returns a multipart formatted
2691 http->form.fread_func = conn->fread_func;
2693 /* Set the read function to read from the generated form data */
2694 conn->fread_func = (curl_read_callback)Curl_FormReader;
2695 conn->fread_in = &http->form;
2697 http->sending = HTTPSEND_BODY;
2699 if(!data->req.upload_chunky) {
2700 /* only add Content-Length if not uploading chunked */
2701 result = Curl_add_bufferf(req_buffer,
2702 "Content-Length: %" FORMAT_OFF_T "\r\n",
2708 result = expect100(data, conn, req_buffer);
2714 /* Get Content-Type: line from Curl_formpostheader.
2717 size_t linelength=0;
2718 contentType = Curl_formpostheader((void *)&http->form,
2721 failf(data, "Could not get Content-Type header line!");
2722 return CURLE_HTTP_POST_ERROR;
2725 result = Curl_add_buffer(req_buffer, contentType, linelength);
2730 /* make the request end in a true CRLF */
2731 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2735 /* set upload size to the progress meter */
2736 Curl_pgrsSetUploadSize(data, http->postsize);
2738 /* fire away the whole request to the server */
2739 result = Curl_add_buffer_send(req_buffer, conn,
2740 &data->info.request_size, 0, FIRSTSOCKET);
2742 failf(data, "Failed sending POST request");
2744 /* setup variables for the upcoming transfer */
2745 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2746 &http->readbytecount, FIRSTSOCKET,
2747 &http->writebytecount);
2750 Curl_formclean(&http->sendit); /* free that whole lot */
2753 #ifdef CURL_DOES_CONVERSIONS
2754 /* time to convert the form data... */
2755 result = Curl_formconvert(data, http->sendit);
2757 Curl_formclean(&http->sendit); /* free that whole lot */
2760 #endif /* CURL_DOES_CONVERSIONS */
2763 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2765 if(conn->bits.authneg)
2768 postsize = data->set.infilesize;
2770 if((postsize != -1) && !data->req.upload_chunky) {
2771 /* only add Content-Length if not uploading chunked */
2772 result = Curl_add_bufferf(req_buffer,
2773 "Content-Length: %" FORMAT_OFF_T "\r\n",
2779 result = expect100(data, conn, req_buffer);
2783 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2787 /* set the upload size to the progress meter */
2788 Curl_pgrsSetUploadSize(data, postsize);
2790 /* this sends the buffer and frees all the buffer resources */
2791 result = Curl_add_buffer_send(req_buffer, conn,
2792 &data->info.request_size, 0, FIRSTSOCKET);
2794 failf(data, "Failed sending PUT request");
2796 /* prepare for transfer */
2797 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2798 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2799 postsize?&http->writebytecount:NULL);
2805 /* this is the simple POST, using x-www-form-urlencoded style */
2807 if(conn->bits.authneg)
2810 /* figure out the size of the postfields */
2811 postsize = (data->set.postfieldsize != -1)?
2812 data->set.postfieldsize:
2813 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2815 if(!data->req.upload_chunky) {
2816 /* We only set Content-Length and allow a custom Content-Length if
2817 we don't upload data chunked, as RFC2616 forbids us to set both
2818 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2820 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
2821 /* we allow replacing this header if not during auth negotiation,
2822 although it isn't very wise to actually set your own */
2823 result = Curl_add_bufferf(req_buffer,
2824 "Content-Length: %" FORMAT_OFF_T"\r\n",
2831 if(!Curl_checkheaders(data, "Content-Type:")) {
2832 result = Curl_add_bufferf(req_buffer,
2833 "Content-Type: application/"
2834 "x-www-form-urlencoded\r\n");
2839 /* For really small posts we don't use Expect: headers at all, and for
2840 the somewhat bigger ones we allow the app to disable it. Just make
2841 sure that the expect100header is always set to the preferred value
2843 ptr = Curl_checkheaders(data, "Expect:");
2845 data->state.expect100header =
2846 Curl_compareheader(ptr, "Expect:", "100-continue");
2848 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2849 result = expect100(data, conn, req_buffer);
2854 data->state.expect100header = FALSE;
2856 if(data->set.postfields) {
2858 if(!data->state.expect100header &&
2859 (postsize < MAX_INITIAL_POST_SIZE)) {
2860 /* if we don't use expect: 100 AND
2861 postsize is less than MAX_INITIAL_POST_SIZE
2863 then append the post data to the HTTP request header. This limit
2864 is no magic limit but only set to prevent really huge POSTs to
2865 get the data duplicated with malloc() and family. */
2867 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2871 if(!data->req.upload_chunky) {
2872 /* We're not sending it 'chunked', append it to the request
2873 already now to reduce the number if send() calls */
2874 result = Curl_add_buffer(req_buffer, data->set.postfields,
2876 included_body = postsize;
2879 /* Append the POST data chunky-style */
2880 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2881 if(CURLE_OK == result)
2882 result = Curl_add_buffer(req_buffer, data->set.postfields,
2884 if(CURLE_OK == result)
2885 result = Curl_add_buffer(req_buffer,
2886 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2887 /* CR LF 0 CR LF CR LF */
2888 included_body = postsize + 7;
2892 /* Make sure the progress information is accurate */
2893 Curl_pgrsSetUploadSize(data, postsize);
2896 /* A huge POST coming up, do data separate from the request */
2897 http->postsize = postsize;
2898 http->postdata = data->set.postfields;
2900 http->sending = HTTPSEND_BODY;
2902 conn->fread_func = (curl_read_callback)readmoredata;
2903 conn->fread_in = (void *)conn;
2905 /* set the upload size to the progress meter */
2906 Curl_pgrsSetUploadSize(data, http->postsize);
2908 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2914 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2918 if(data->req.upload_chunky && conn->bits.authneg) {
2919 /* Chunky upload is selected and we're negotiating auth still, send
2921 result = Curl_add_buffer(req_buffer,
2922 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2923 /* CR LF 0 CR LF CR LF */
2928 else if(data->set.postfieldsize) {
2929 /* set the upload size to the progress meter */
2930 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2932 /* set the pointer to mark that we will send the post body using the
2933 read callback, but only if we're not in authenticate
2935 if(!conn->bits.authneg) {
2936 http->postdata = (char *)&http->postdata;
2937 http->postsize = postsize;
2941 /* issue the request */
2942 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2943 (size_t)included_body, FIRSTSOCKET);
2946 failf(data, "Failed sending HTTP POST request");
2948 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2949 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2950 http->postdata?&http->writebytecount:NULL);
2954 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2958 /* issue the request */
2959 result = Curl_add_buffer_send(req_buffer, conn,
2960 &data->info.request_size, 0, FIRSTSOCKET);
2963 failf(data, "Failed sending HTTP request");
2965 /* HTTP GET/HEAD download: */
2966 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2967 http->postdata?FIRSTSOCKET:-1,
2968 http->postdata?&http->writebytecount:NULL);
2973 if(http->writebytecount) {
2974 /* if a request-body has been sent off, we make sure this progress is noted
2976 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2977 if(Curl_pgrsUpdate(conn))
2978 result = CURLE_ABORTED_BY_CALLBACK;
2987 * Returns TRUE if member of the list matches prefix of string
2990 checkhttpprefix(struct SessionHandle *data,
2993 struct curl_slist *head = data->set.http200aliases;
2995 #ifdef CURL_DOES_CONVERSIONS
2996 /* convert from the network encoding using a scratch area */
2997 char *scratch = strdup(s);
2998 if(NULL == scratch) {
2999 failf (data, "Failed to allocate memory for conversion!");
3000 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3002 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
3003 /* Curl_convert_from_network calls failf if unsuccessful */
3005 return FALSE; /* can't return CURLE_foobar so return FALSE */
3008 #endif /* CURL_DOES_CONVERSIONS */
3011 if(checkprefix(head->data, s)) {
3018 if((rc != TRUE) && (checkprefix("HTTP/", s))) {
3022 #ifdef CURL_DOES_CONVERSIONS
3024 #endif /* CURL_DOES_CONVERSIONS */
3028 #ifndef CURL_DISABLE_RTSP
3030 checkrtspprefix(struct SessionHandle *data,
3034 #ifdef CURL_DOES_CONVERSIONS
3035 /* convert from the network encoding using a scratch area */
3036 char *scratch = strdup(s);
3037 if(NULL == scratch) {
3038 failf (data, "Failed to allocate memory for conversion!");
3039 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3041 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
3042 /* Curl_convert_from_network calls failf if unsuccessful */
3044 return FALSE; /* can't return CURLE_foobar so return FALSE */
3048 (void)data; /* unused */
3049 #endif /* CURL_DOES_CONVERSIONS */
3050 if(checkprefix("RTSP/", s))
3055 #endif /* CURL_DISABLE_RTSP */
3058 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
3061 #ifndef CURL_DISABLE_RTSP
3062 if(conn->protocol & PROT_RTSP)
3063 return checkrtspprefix(data, s);
3066 #endif /* CURL_DISABLE_RTSP */
3068 return checkhttpprefix(data, s);
3072 * header_append() copies a chunk of data to the end of the already received
3073 * header. We make sure that the full string fit in the allocated header
3074 * buffer, or else we enlarge it.
3076 static CURLcode header_append(struct SessionHandle *data,
3077 struct SingleRequest *k,
3080 if(k->hbuflen + length >= data->state.headersize) {
3081 /* We enlarge the header buffer as it is too small */
3086 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
3087 /* The reason to have a max limit for this is to avoid the risk of a bad
3088 server feeding libcurl with a never-ending header that will cause
3089 reallocs infinitely */
3090 failf (data, "Avoided giant realloc for header (max is %d)!",
3091 CURL_MAX_HTTP_HEADER);
3092 return CURLE_OUT_OF_MEMORY;
3095 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
3096 hbufp_index = k->hbufp - data->state.headerbuff;
3097 newbuff = realloc(data->state.headerbuff, newsize);
3099 failf (data, "Failed to alloc memory for big header!");
3100 return CURLE_OUT_OF_MEMORY;
3102 data->state.headersize=newsize;
3103 data->state.headerbuff = newbuff;
3104 k->hbufp = data->state.headerbuff + hbufp_index;
3106 memcpy(k->hbufp, k->str_start, length);
3108 k->hbuflen += length;
3116 * Read any HTTP header lines from the server and pass them to the client app.
3118 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
3119 struct connectdata *conn,
3124 struct SingleRequest *k = &data->req;
3126 /* header line within buffer loop */
3132 /* str_start is start of line within buf */
3133 k->str_start = k->str;
3135 /* data is in network encoding so use 0x0a instead of '\n' */
3136 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
3139 /* Not a complete header line within buffer, append the data to
3140 the end of the headerbuff. */
3141 result = header_append(data, k, *nread);
3145 if(!k->headerline && (k->hbuflen>5)) {
3146 /* make a first check that this looks like a protocol header */
3147 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
3148 /* this is not the beginning of a protocol first header line */
3150 k->badheader = HEADER_ALLBAD;
3155 break; /* read more and try again */
3158 /* decrease the size of the remaining (supposed) header line */
3159 rest_length = (k->end_ptr - k->str)+1;
3160 *nread -= (ssize_t)rest_length;
3162 k->str = k->end_ptr + 1; /* move past new line */
3164 full_length = k->str - k->str_start;
3166 result = header_append(data, k, full_length);
3170 k->end_ptr = k->hbufp;
3171 k->p = data->state.headerbuff;
3174 * We now have a FULL header line that p points to
3177 if(!k->headerline) {
3178 /* the first read header */
3179 if((k->hbuflen>5) &&
3180 !checkprotoprefix(data, conn, data->state.headerbuff)) {
3181 /* this is not the beginning of a protocol first header line */
3184 /* since there's more, this is a partial bad header */
3185 k->badheader = HEADER_PARTHEADER;
3187 /* this was all we read so it's all a bad header */
3188 k->badheader = HEADER_ALLBAD;
3189 *nread = (ssize_t)rest_length;
3195 /* headers are in network encoding so
3196 use 0x0a and 0x0d instead of '\n' and '\r' */
3197 if((0x0a == *k->p) || (0x0d == *k->p)) {
3199 /* Zero-length header line means end of headers! */
3201 #ifdef CURL_DOES_CONVERSIONS
3203 *k->p = '\r'; /* replace with CR in host encoding */
3204 k->p++; /* pass the CR byte */
3207 *k->p = '\n'; /* replace with LF in host encoding */
3208 k->p++; /* pass the LF byte */
3212 k->p++; /* pass the \r byte */
3214 k->p++; /* pass the \n byte */
3215 #endif /* CURL_DOES_CONVERSIONS */
3217 if(100 <= k->httpcode && 199 >= k->httpcode) {
3219 * We have made a HTTP PUT or POST and this is 1.1-lingo
3220 * that tells us that the server is OK with this and ready
3221 * to receive the data.
3222 * However, we'll get more headers now so we must get
3223 * back into the header-parsing state!
3226 k->headerline = 0; /* restart the header line counter */
3228 /* if we did wait for this do enable write now! */
3230 k->exp100 = EXP100_SEND_DATA;
3231 k->keepon |= KEEP_SEND;
3235 k->header = FALSE; /* no more header to parse! */
3237 if((k->size == -1) && !k->chunk && !conn->bits.close &&
3238 (conn->httpversion >= 11) && !(conn->protocol & PROT_RTSP)) {
3239 /* On HTTP 1.1, when connection is not to get closed, but no
3240 Content-Length nor Content-Encoding chunked have been
3241 received, according to RFC2616 section 4.4 point 5, we
3242 assume that the server will close the connection to
3243 signal the end of the document. */
3244 infof(data, "no chunk, no close, no size. Assume close to "
3246 conn->bits.close = TRUE;
3250 if(417 == k->httpcode) {
3252 * we got: "417 Expectation Failed" this means:
3253 * we have made a HTTP call and our Expect Header
3254 * seems to cause a problem => abort the write operations
3255 * (or prevent them from starting).
3257 k->exp100 = EXP100_FAILED;
3258 k->keepon &= ~KEEP_SEND;
3262 * When all the headers have been parsed, see if we should give
3263 * up and return an error.
3265 if(Curl_http_should_fail(conn)) {
3266 failf (data, "The requested URL returned error: %d",
3268 return CURLE_HTTP_RETURNED_ERROR;
3271 /* now, only output this if the header AND body are requested:
3273 writetype = CLIENTWRITE_HEADER;
3274 if(data->set.include_header)
3275 writetype |= CLIENTWRITE_BODY;
3277 headerlen = k->p - data->state.headerbuff;
3279 result = Curl_client_write(conn, writetype,
3280 data->state.headerbuff,
3285 data->info.header_size += (long)headerlen;
3286 data->req.headerbytecount += (long)headerlen;
3288 data->req.deductheadercount =
3289 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
3291 if(!*stop_reading) {
3292 /* Curl_http_auth_act() checks what authentication methods
3293 * that are available and decides which one (if any) to
3294 * use. It will set 'newurl' if an auth method was picked. */
3295 result = Curl_http_auth_act(conn);
3300 if(conn->bits.rewindaftersend) {
3301 /* We rewind after a complete send, so thus we continue
3303 infof(data, "Keep sending data to get tossed away!\n");
3304 k->keepon |= KEEP_SEND;
3310 * really end-of-headers.
3312 * If we requested a "no body", this is a good time to get
3313 * out and return home.
3315 if(data->set.opt_no_body)
3316 *stop_reading = TRUE;
3318 /* If we know the expected size of this document, we set the
3319 maximum download size to the size of the expected
3320 document or else, we won't know when to stop reading!
3322 Note that we set the download maximum even if we read a
3323 "Connection: close" header, to make sure that
3324 "Content-Length: 0" still prevents us from attempting to
3325 read the (missing) response-body.
3327 /* According to RFC2616 section 4.4, we MUST ignore
3328 Content-Length: headers if we are now receiving data
3329 using chunked Transfer-Encoding.
3332 k->maxdownload = k->size = -1;
3335 /* We do this operation even if no_body is true, since this
3336 data might be retrieved later with curl_easy_getinfo()
3337 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3339 Curl_pgrsSetDownloadSize(data, k->size);
3340 k->maxdownload = k->size;
3343 /* If max download size is *zero* (nothing) we already
3344 have nothing and can safely return ok now! */
3345 if(0 == k->maxdownload)
3346 *stop_reading = TRUE;
3349 /* we make sure that this socket isn't read more now */
3350 k->keepon &= ~KEEP_RECV;
3353 if(data->set.verbose)
3354 Curl_debug(data, CURLINFO_HEADER_IN,
3355 k->str_start, headerlen, conn);
3356 break; /* exit header line loop */
3359 /* We continue reading headers, so reset the line-based
3360 header parsing variables hbufp && hbuflen */
3361 k->hbufp = data->state.headerbuff;
3367 * Checks for special headers coming up.
3370 if(!k->headerline++) {
3371 /* This is the first header, it MUST be the error code line
3372 or else we consider this to be the body right away! */
3373 int httpversion_major;
3374 int rtspversion_major;
3376 #ifdef CURL_DOES_CONVERSIONS
3377 #define HEADER1 scratch
3378 #define SCRATCHSIZE 21
3380 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3381 /* We can't really convert this yet because we
3382 don't know if it's the 1st header line or the body.
3383 So we do a partial conversion into a scratch area,
3384 leaving the data at k->p as-is.
3386 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3387 scratch[SCRATCHSIZE] = 0; /* null terminate */
3388 res = Curl_convert_from_network(data,
3391 if(CURLE_OK != res) {
3392 /* Curl_convert_from_network calls failf if unsuccessful */
3396 #define HEADER1 k->p /* no conversion needed, just use k->p */
3397 #endif /* CURL_DOES_CONVERSIONS */
3399 if(conn->protocol & PROT_HTTP) {
3400 nc = sscanf(HEADER1,
3406 conn->httpversion += 10 * httpversion_major;
3409 /* this is the real world, not a Nirvana
3410 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3412 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3413 conn->httpversion = 10;
3415 /* If user has set option HTTP200ALIASES,
3416 compare header line against list of aliases
3419 if(checkhttpprefix(data, k->p)) {
3422 conn->httpversion = 10;
3427 else if(conn->protocol & PROT_RTSP) {
3428 nc = sscanf(HEADER1,
3434 conn->rtspversion += 10 * rtspversion_major;
3435 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3438 /* TODO: do we care about the other cases here? */
3444 data->info.httpcode = k->httpcode;
3446 data->info.httpversion = conn->httpversion;
3447 if (!data->state.httpversion ||
3448 data->state.httpversion > conn->httpversion)
3449 /* store the lowest server version we encounter */
3450 data->state.httpversion = conn->httpversion;
3453 * This code executes as part of processing the header. As a
3454 * result, it's not totally clear how to interpret the
3455 * response code yet as that depends on what other headers may
3456 * be present. 401 and 407 may be errors, but may be OK
3457 * depending on how authentication is working. Other codes
3458 * are definitely errors, so give up here.
3460 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3461 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3462 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3464 if(data->state.resume_from &&
3465 (data->set.httpreq==HTTPREQ_GET) &&
3466 (k->httpcode == 416)) {
3467 /* "Requested Range Not Satisfiable", just proceed and
3468 pretend this is no error */
3471 /* serious error, go home! */
3472 failf (data, "The requested URL returned error: %d",
3474 return CURLE_HTTP_RETURNED_ERROR;
3478 if(conn->httpversion == 10) {
3479 /* Default action for HTTP/1.0 must be to close, unless
3480 we get one of those fancy headers that tell us the
3481 server keeps it open for us! */
3482 infof(data, "HTTP 1.0, assume close after body\n");
3483 conn->bits.close = TRUE;
3485 else if(conn->httpversion >= 11 &&
3486 !conn->bits.close) {
3487 /* If HTTP version is >= 1.1 and connection is persistent
3488 server supports pipelining. */
3490 "HTTP 1.1 or later with persistent connection, "
3491 "pipelining supported\n"));
3492 conn->server_supports_pipelining = TRUE;
3495 switch(k->httpcode) {
3497 /* (quote from RFC2616, section 10.2.5): The server has
3498 * fulfilled the request but does not need to return an
3499 * entity-body ... The 204 response MUST NOT include a
3500 * message-body, and thus is always terminated by the first
3501 * empty line after the header fields. */
3504 /* (quote from RFC2616, section 10.3.5): The 304 response
3505 * MUST NOT contain a message-body, and thus is always
3506 * terminated by the first empty line after the header
3508 if(data->set.timecondition)
3509 data->info.timecond = TRUE;
3512 k->ignorecl = TRUE; /* ignore Content-Length headers */
3520 k->header = FALSE; /* this is not a header line */
3525 #ifdef CURL_DOES_CONVERSIONS
3526 /* convert from the network encoding */
3527 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3528 if(CURLE_OK != result) {
3531 /* Curl_convert_from_network calls failf if unsuccessful */
3532 #endif /* CURL_DOES_CONVERSIONS */
3534 /* Check for Content-Length: header lines to get size */
3535 if(!k->ignorecl && !data->set.ignorecl &&
3536 checkprefix("Content-Length:", k->p)) {
3537 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3538 if(data->set.max_filesize &&
3539 contentlength > data->set.max_filesize) {
3540 failf(data, "Maximum file size exceeded");
3541 return CURLE_FILESIZE_EXCEEDED;
3543 if(contentlength >= 0) {
3544 k->size = contentlength;
3545 k->maxdownload = k->size;
3546 /* we set the progress download size already at this point
3547 just to make it easier for apps/callbacks to extract this
3548 info as soon as possible */
3549 Curl_pgrsSetDownloadSize(data, k->size);
3552 /* Negative Content-Length is really odd, and we know it
3553 happens for example when older Apache servers send large
3555 conn->bits.close = TRUE;
3556 infof(data, "Negative content-length: %" FORMAT_OFF_T
3557 ", closing after transfer\n", contentlength);
3560 /* check for Content-Type: header lines to get the MIME-type */
3561 else if(checkprefix("Content-Type:", k->p)) {
3562 char *contenttype = Curl_copy_header_value(k->p);
3564 return CURLE_OUT_OF_MEMORY;
3566 /* ignore empty data */
3569 Curl_safefree(data->info.contenttype);
3570 data->info.contenttype = contenttype;
3573 else if((conn->httpversion == 10) &&
3574 conn->bits.httpproxy &&
3575 Curl_compareheader(k->p,
3576 "Proxy-Connection:", "keep-alive")) {
3578 * When a HTTP/1.0 reply comes when using a proxy, the
3579 * 'Proxy-Connection: keep-alive' line tells us the
3580 * connection will be kept alive for our pleasure.
3581 * Default action for 1.0 is to close.
3583 conn->bits.close = FALSE; /* don't close when done */
3584 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3586 else if((conn->httpversion == 11) &&
3587 conn->bits.httpproxy &&
3588 Curl_compareheader(k->p,
3589 "Proxy-Connection:", "close")) {
3591 * We get a HTTP/1.1 response from a proxy and it says it'll
3592 * close down after this transfer.
3594 conn->bits.close = TRUE; /* close when done */
3595 infof(data, "HTTP/1.1 proxy connection set close!\n");
3597 else if((conn->httpversion == 10) &&
3598 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3600 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3601 * tells us the connection will be kept alive for our
3602 * pleasure. Default action for 1.0 is to close.
3604 * [RFC2068, section 19.7.1] */
3605 conn->bits.close = FALSE; /* don't close when done */
3606 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3608 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3610 * [RFC 2616, section 8.1.2.1]
3611 * "Connection: close" is HTTP/1.1 language and means that
3612 * the connection will close when this request has been
3615 conn->bits.close = TRUE; /* close when done */
3617 else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") &&
3618 !(conn->protocol & PROT_RTSP)) {
3620 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3621 * means that the server will send a series of "chunks". Each
3622 * chunk starts with line with info (including size of the
3623 * coming block) (terminated with CRLF), then a block of data
3624 * with the previously mentioned size. There can be any amount
3625 * of chunks, and a chunk-data set to zero signals the
3627 k->chunk = TRUE; /* chunks coming our way */
3629 /* init our chunky engine */
3630 Curl_httpchunk_init(conn);
3632 else if(checkprefix("Content-Encoding:", k->p) &&
3633 data->set.str[STRING_ENCODING]) {
3635 * Process Content-Encoding. Look for the values: identity,
3636 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3637 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3638 * 2616). zlib cannot handle compress. However, errors are
3639 * handled further down when the response body is processed
3643 /* Find the first non-space letter */
3645 while(*start && ISSPACE(*start))
3648 /* Record the content-encoding for later use */
3649 if(checkprefix("identity", start))
3650 k->content_encoding = IDENTITY;
3651 else if(checkprefix("deflate", start))
3652 k->content_encoding = DEFLATE;
3653 else if(checkprefix("gzip", start)
3654 || checkprefix("x-gzip", start))
3655 k->content_encoding = GZIP;
3656 else if(checkprefix("compress", start)
3657 || checkprefix("x-compress", start))
3658 k->content_encoding = COMPRESS;
3660 else if(checkprefix("Content-Range:", k->p)) {
3661 /* Content-Range: bytes [num]-
3662 Content-Range: bytes: [num]-
3663 Content-Range: [num]-
3665 The second format was added since Sun's webserver
3666 JavaWebServer/1.1.1 obviously sends the header this way!
3667 The third added since some servers use that!
3670 char *ptr = k->p + 14;
3672 /* Move forward until first digit */
3673 while(*ptr && !ISDIGIT(*ptr))
3676 k->offset = curlx_strtoofft(ptr, NULL, 10);
3678 if(data->state.resume_from == k->offset)
3679 /* we asked for a resume and we got it */
3680 k->content_range = TRUE;
3682 #if !defined(CURL_DISABLE_COOKIES)
3683 else if(data->cookies &&
3684 checkprefix("Set-Cookie:", k->p)) {
3685 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3686 CURL_LOCK_ACCESS_SINGLE);
3687 Curl_cookie_add(data,
3688 data->cookies, TRUE, k->p+11,
3689 /* If there is a custom-set Host: name, use it
3690 here, or else use real peer host name. */
3691 conn->allocptr.cookiehost?
3692 conn->allocptr.cookiehost:conn->host.name,
3694 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3697 else if(checkprefix("Last-Modified:", k->p) &&
3698 (data->set.timecondition || data->set.get_filetime) ) {
3699 time_t secs=time(NULL);
3700 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3702 if(data->set.get_filetime)
3703 data->info.filetime = (long)k->timeofdoc;
3705 else if((checkprefix("WWW-Authenticate:", k->p) &&
3706 (401 == k->httpcode)) ||
3707 (checkprefix("Proxy-authenticate:", k->p) &&
3708 (407 == k->httpcode))) {
3709 result = Curl_http_input_auth(conn, k->httpcode, k->p);
3713 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3714 checkprefix("Location:", k->p)) {
3715 /* this is the URL that the server advises us to use instead */
3716 char *location = Curl_copy_header_value(k->p);
3718 return CURLE_OUT_OF_MEMORY;
3720 /* ignore empty data */
3723 DEBUGASSERT(!data->req.location);
3724 data->req.location = location;
3726 if(data->set.http_follow_location) {
3727 DEBUGASSERT(!data->req.newurl);
3728 data->req.newurl = strdup(data->req.location); /* clone */
3729 if(!data->req.newurl)
3730 return CURLE_OUT_OF_MEMORY;
3732 /* some cases of POST and PUT etc needs to rewind the data
3733 stream at this point */
3734 result = Curl_http_perhapsrewind(conn);
3740 #ifndef CURL_DISABLE_RTSP
3741 else if(conn->protocol & PROT_RTSP) {
3742 result = Curl_rtsp_parseheader(conn, k->p);
3748 * End of header-checks. Write them to the client.
3751 writetype = CLIENTWRITE_HEADER;
3752 if(data->set.include_header)
3753 writetype |= CLIENTWRITE_BODY;
3755 if(data->set.verbose)
3756 Curl_debug(data, CURLINFO_HEADER_IN,
3757 k->p, (size_t)k->hbuflen, conn);
3759 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3763 data->info.header_size += (long)k->hbuflen;
3764 data->req.headerbytecount += (long)k->hbuflen;
3766 /* reset hbufp pointer && hbuflen */
3767 k->hbufp = data->state.headerbuff;
3770 while(!*stop_reading && *k->str); /* header line within buffer */
3772 /* We might have reached the end of the header part here, but
3773 there might be a non-header part left in the end of the read
3779 #endif /* CURL_DISABLE_HTTP */