1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, 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 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifndef CURL_DISABLE_HTTP
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
44 #ifdef HAVE_SYS_PARAM_H
45 #include <sys/param.h>
49 #include <curl/curl.h>
54 #include "curl_base64.h"
57 #include "vtls/vtls.h"
58 #include "http_digest.h"
59 #include "curl_ntlm.h"
60 #include "curl_ntlm_wb.h"
61 #include "http_negotiate.h"
66 #include "curl_memory.h"
68 #include "parsedate.h" /* for the week day and month names */
69 #include "strtoofft.h"
72 #include "content_encoding.h"
73 #include "http_proxy.h"
75 #include "non-ascii.h"
81 #define _MPRINTF_REPLACE /* use our functions only */
82 #include <curl/mprintf.h>
84 /* The last #include file should be: */
88 * Forward declarations.
91 static int http_getsock_do(struct connectdata *conn,
94 static int http_should_fail(struct connectdata *conn);
97 static CURLcode https_connecting(struct connectdata *conn, bool *done);
98 static int https_getsock(struct connectdata *conn,
102 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
106 * HTTP handler interface.
108 const struct Curl_handler Curl_handler_http = {
110 Curl_http_setup_conn, /* setup_connection */
111 Curl_http, /* do_it */
112 Curl_http_done, /* done */
113 ZERO_NULL, /* do_more */
114 Curl_http_connect, /* connect_it */
115 ZERO_NULL, /* connecting */
116 ZERO_NULL, /* doing */
117 ZERO_NULL, /* proto_getsock */
118 http_getsock_do, /* doing_getsock */
119 ZERO_NULL, /* domore_getsock */
120 ZERO_NULL, /* perform_getsock */
121 ZERO_NULL, /* disconnect */
122 ZERO_NULL, /* readwrite */
123 PORT_HTTP, /* defport */
124 CURLPROTO_HTTP, /* protocol */
125 PROTOPT_CREDSPERREQUEST /* flags */
130 * HTTPS handler interface.
132 const struct Curl_handler Curl_handler_https = {
133 "HTTPS", /* scheme */
134 Curl_http_setup_conn, /* setup_connection */
135 Curl_http, /* do_it */
136 Curl_http_done, /* done */
137 ZERO_NULL, /* do_more */
138 Curl_http_connect, /* connect_it */
139 https_connecting, /* connecting */
140 ZERO_NULL, /* doing */
141 https_getsock, /* proto_getsock */
142 http_getsock_do, /* doing_getsock */
143 ZERO_NULL, /* domore_getsock */
144 ZERO_NULL, /* perform_getsock */
145 ZERO_NULL, /* disconnect */
146 ZERO_NULL, /* readwrite */
147 PORT_HTTPS, /* defport */
148 CURLPROTO_HTTPS, /* protocol */
149 PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
154 CURLcode Curl_http_setup_conn(struct connectdata *conn)
156 /* allocate the HTTP-specific struct for the SessionHandle, only to survive
157 during this request */
158 DEBUGASSERT(conn->data->req.protop == NULL);
160 conn->data->req.protop = calloc(1, sizeof(struct HTTP));
161 if(!conn->data->req.protop)
162 return CURLE_OUT_OF_MEMORY;
168 * checkheaders() checks the linked list of custom HTTP headers for a
169 * particular header (prefix).
171 * Returns a pointer to the first matching header or NULL if none matched.
173 char *Curl_checkheaders(const struct connectdata *conn,
174 const char *thisheader)
176 struct curl_slist *head;
177 size_t thislen = strlen(thisheader);
178 struct SessionHandle *data = conn->data;
180 for(head = data->set.headers;head; head=head->next) {
181 if(Curl_raw_nequal(head->data, thisheader, thislen))
188 * checkProxyHeaders() checks the linked list of custom proxy headers
189 * if proxy headers are not available, then it will lookup into http header
192 * It takes a connectdata struct as input instead of the SessionHandle simply
193 * to know if this is a proxy request or not, as it then might check a
194 * different header list.
197 char *Curl_checkProxyheaders(const struct connectdata *conn,
198 const char *thisheader)
200 struct curl_slist *head;
201 size_t thislen = strlen(thisheader);
202 struct SessionHandle *data = conn->data;
204 for(head = (conn->bits.proxy && data->set.sep_headers)?
205 data->set.proxyheaders:data->set.headers;
206 head; head=head->next) {
207 if(Curl_raw_nequal(head->data, thisheader, thislen))
214 * Strip off leading and trailing whitespace from the value in the
215 * given HTTP header line and return a strdupped copy. Returns NULL in
216 * case of allocation failure. Returns an empty string if the header value
217 * consists entirely of whitespace.
219 char *Curl_copy_header_value(const char *header)
228 /* Find the end of the header name */
229 while(*header && (*header != ':'))
233 /* Skip over colon */
236 /* Find the first non-space letter */
238 while(*start && ISSPACE(*start))
241 /* data is in the host encoding so
242 use '\r' and '\n' instead of 0x0d and 0x0a */
243 end = strchr(start, '\r');
245 end = strchr(start, '\n');
247 end = strchr(start, '\0');
251 /* skip all trailing space letters */
252 while((end > start) && ISSPACE(*end))
255 /* get length of the type */
256 len = end - start + 1;
258 value = malloc(len + 1);
262 memcpy(value, start, len);
263 value[len] = 0; /* zero terminate */
269 * http_output_basic() sets up an Authorization: header (or the proxy version)
270 * for HTTP Basic authentication.
274 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
277 char *authorization = NULL;
278 struct SessionHandle *data = conn->data;
285 userp = &conn->allocptr.proxyuserpwd;
286 user = conn->proxyuser;
287 pwd = conn->proxypasswd;
290 userp = &conn->allocptr.userpwd;
295 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
297 error = Curl_base64_encode(data,
298 data->state.buffer, strlen(data->state.buffer),
299 &authorization, &size);
304 return CURLE_REMOTE_ACCESS_DENIED;
306 Curl_safefree(*userp);
307 *userp = aprintf("%sAuthorization: Basic %s\r\n",
312 return CURLE_OUT_OF_MEMORY;
317 /* pickoneauth() selects the most favourable authentication method from the
318 * ones available and the ones we want.
320 * return TRUE if one was picked
322 static bool pickoneauth(struct auth *pick)
325 /* only deal with authentication we want */
326 unsigned long avail = pick->avail & pick->want;
329 /* The order of these checks is highly relevant, as this will be the order
330 of preference in case of the existence of multiple accepted types. */
331 if(avail & CURLAUTH_GSSNEGOTIATE)
332 pick->picked = CURLAUTH_GSSNEGOTIATE;
333 else if(avail & CURLAUTH_DIGEST)
334 pick->picked = CURLAUTH_DIGEST;
335 else if(avail & CURLAUTH_NTLM)
336 pick->picked = CURLAUTH_NTLM;
337 else if(avail & CURLAUTH_NTLM_WB)
338 pick->picked = CURLAUTH_NTLM_WB;
339 else if(avail & CURLAUTH_BASIC)
340 pick->picked = CURLAUTH_BASIC;
342 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
345 pick->avail = CURLAUTH_NONE; /* clear it here */
351 * Curl_http_perhapsrewind()
353 * If we are doing POST or PUT {
354 * If we have more data to send {
355 * If we are doing NTLM {
356 * Keep sending since we must not disconnect
359 * If there is more than just a little data left to send, close
360 * the current connection by force.
363 * If we have sent any data {
364 * If we don't have track of all the data {
365 * call app to tell it to rewind
368 * rewind internally so that the operation can restart fine
373 static CURLcode http_perhapsrewind(struct connectdata *conn)
375 struct SessionHandle *data = conn->data;
376 struct HTTP *http = data->req.protop;
377 curl_off_t bytessent;
378 curl_off_t expectsend = -1; /* default is unknown */
381 /* If this is still NULL, we have not reach very far and we can safely
382 skip this rewinding stuff */
385 switch(data->set.httpreq) {
393 bytessent = http->writebytecount;
395 if(conn->bits.authneg)
396 /* This is a state where we are known to be negotiating and we don't send
400 /* figure out how much data we are expected to send */
401 switch(data->set.httpreq) {
403 if(data->set.postfieldsize != -1)
404 expectsend = data->set.postfieldsize;
405 else if(data->set.postfields)
406 expectsend = (curl_off_t)strlen(data->set.postfields);
409 if(data->state.infilesize != -1)
410 expectsend = data->state.infilesize;
412 case HTTPREQ_POST_FORM:
413 expectsend = http->postsize;
420 conn->bits.rewindaftersend = FALSE; /* default */
422 if((expectsend == -1) || (expectsend > bytessent)) {
423 /* There is still data left to send */
424 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
425 (data->state.authhost.picked == CURLAUTH_NTLM) ||
426 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
427 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
428 if(((expectsend - bytessent) < 2000) ||
429 (conn->ntlm.state != NTLMSTATE_NONE) ||
430 (conn->proxyntlm.state != NTLMSTATE_NONE)) {
431 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
432 data left to send, keep on sending. */
434 /* rewind data when completely done sending! */
435 if(!conn->bits.authneg) {
436 conn->bits.rewindaftersend = TRUE;
437 infof(data, "Rewind stream after send\n");
443 /* this is already marked to get closed */
446 infof(data, "NTLM send, close instead of sending %"
447 CURL_FORMAT_CURL_OFF_T " bytes\n",
448 (curl_off_t)(expectsend - bytessent));
451 /* This is not NTLM or many bytes left to send: close
453 connclose(conn, "Mid-auth HTTP and much data left to send");
454 data->req.size = 0; /* don't download any more than 0 bytes */
456 /* There still is data left to send, but this connection is marked for
457 closure so we can safely do the rewind right now */
461 /* we rewind now at once since if we already sent something */
462 return Curl_readrewind(conn);
468 * Curl_http_auth_act() gets called when all HTTP headers have been received
469 * and it checks what authentication methods that are available and decides
470 * which one (if any) to use. It will set 'newurl' if an auth method was
474 CURLcode Curl_http_auth_act(struct connectdata *conn)
476 struct SessionHandle *data = conn->data;
477 bool pickhost = FALSE;
478 bool pickproxy = FALSE;
479 CURLcode code = CURLE_OK;
481 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
482 /* this is a transient response code, ignore */
485 if(data->state.authproblem)
486 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
488 if(conn->bits.user_passwd &&
489 ((data->req.httpcode == 401) ||
490 (conn->bits.authneg && data->req.httpcode < 300))) {
491 pickhost = pickoneauth(&data->state.authhost);
493 data->state.authproblem = TRUE;
495 if(conn->bits.proxy_user_passwd &&
496 ((data->req.httpcode == 407) ||
497 (conn->bits.authneg && data->req.httpcode < 300))) {
498 pickproxy = pickoneauth(&data->state.authproxy);
500 data->state.authproblem = TRUE;
503 if(pickhost || pickproxy) {
504 /* In case this is GSS auth, the newurl field is already allocated so
505 we must make sure to free it before allocating a new one. As figured
506 out in bug #2284386 */
507 Curl_safefree(data->req.newurl);
508 data->req.newurl = strdup(data->change.url); /* clone URL */
509 if(!data->req.newurl)
510 return CURLE_OUT_OF_MEMORY;
512 if((data->set.httpreq != HTTPREQ_GET) &&
513 (data->set.httpreq != HTTPREQ_HEAD) &&
514 !conn->bits.rewindaftersend) {
515 code = http_perhapsrewind(conn);
521 else if((data->req.httpcode < 300) &&
522 (!data->state.authhost.done) &&
523 conn->bits.authneg) {
524 /* no (known) authentication available,
525 authentication is not "done" yet and
526 no authentication seems to be required and
527 we didn't try HEAD or GET */
528 if((data->set.httpreq != HTTPREQ_GET) &&
529 (data->set.httpreq != HTTPREQ_HEAD)) {
530 data->req.newurl = strdup(data->change.url); /* clone URL */
531 if(!data->req.newurl)
532 return CURLE_OUT_OF_MEMORY;
533 data->state.authhost.done = TRUE;
536 if(http_should_fail(conn)) {
537 failf (data, "The requested URL returned error: %d",
539 code = CURLE_HTTP_RETURNED_ERROR;
547 * Output the correct authentication header depending on the auth type
548 * and whether or not it is to a proxy.
551 output_auth_headers(struct connectdata *conn,
552 struct auth *authstatus,
557 struct SessionHandle *data = conn->data;
558 const char *auth=NULL;
559 CURLcode result = CURLE_OK;
560 #ifdef USE_HTTP_NEGOTIATE
561 struct negotiatedata *negdata = proxy?
562 &data->state.proxyneg:&data->state.negotiate;
565 #ifdef CURL_DISABLE_CRYPTO_AUTH
570 #ifdef USE_HTTP_NEGOTIATE
571 negdata->state = GSS_AUTHNONE;
572 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
573 negdata->context && !GSS_ERROR(negdata->status)) {
574 auth="GSS-Negotiate";
575 result = Curl_output_negotiate(conn, proxy);
578 authstatus->done = TRUE;
579 negdata->state = GSS_AUTHSENT;
584 if(authstatus->picked == CURLAUTH_NTLM) {
586 result = Curl_output_ntlm(conn, proxy);
592 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
593 if(authstatus->picked == CURLAUTH_NTLM_WB) {
595 result = Curl_output_ntlm_wb(conn, proxy);
601 #ifndef CURL_DISABLE_CRYPTO_AUTH
602 if(authstatus->picked == CURLAUTH_DIGEST) {
604 result = Curl_output_digest(conn,
606 (const unsigned char *)request,
607 (const unsigned char *)path);
613 if(authstatus->picked == CURLAUTH_BASIC) {
615 if((proxy && conn->bits.proxy_user_passwd &&
616 !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
617 (!proxy && conn->bits.user_passwd &&
618 !Curl_checkheaders(conn, "Authorization:"))) {
620 result = http_output_basic(conn, proxy);
624 /* NOTE: this function should set 'done' TRUE, as the other auth
625 functions work that way */
626 authstatus->done = TRUE;
630 infof(data, "%s auth using %s with user '%s'\n",
631 proxy?"Proxy":"Server", auth,
632 proxy?(conn->proxyuser?conn->proxyuser:""):
633 (conn->user?conn->user:""));
634 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
637 authstatus->multi = FALSE;
643 * Curl_http_output_auth() setups the authentication headers for the
644 * host/proxy and the correct authentication
645 * method. conn->data->state.authdone is set to TRUE when authentication is
648 * @param conn all information about the current connection
649 * @param request pointer to the request keyword
650 * @param path pointer to the requested path
651 * @param proxytunnel boolean if this is the request setting up a "proxy
657 Curl_http_output_auth(struct connectdata *conn,
660 bool proxytunnel) /* TRUE if this is the request setting
661 up the proxy tunnel */
663 CURLcode result = CURLE_OK;
664 struct SessionHandle *data = conn->data;
665 struct auth *authhost;
666 struct auth *authproxy;
670 authhost = &data->state.authhost;
671 authproxy = &data->state.authproxy;
673 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
674 conn->bits.user_passwd)
675 /* continue please */ ;
677 authhost->done = TRUE;
678 authproxy->done = TRUE;
679 return CURLE_OK; /* no authentication with no user or password */
682 if(authhost->want && !authhost->picked)
683 /* The app has selected one or more methods, but none has been picked
684 so far by a server round-trip. Then we set the picked one to the
685 want one, and if this is one single bit it'll be used instantly. */
686 authhost->picked = authhost->want;
688 if(authproxy->want && !authproxy->picked)
689 /* The app has selected one or more methods, but none has been picked so
690 far by a proxy round-trip. Then we set the picked one to the want one,
691 and if this is one single bit it'll be used instantly. */
692 authproxy->picked = authproxy->want;
694 #ifndef CURL_DISABLE_PROXY
695 /* Send proxy authentication header if needed */
696 if(conn->bits.httpproxy &&
697 (conn->bits.tunnel_proxy == proxytunnel)) {
698 result = output_auth_headers(conn, authproxy, request, path, TRUE);
705 #endif /* CURL_DISABLE_PROXY */
706 /* we have no proxy so let's pretend we're done authenticating
708 authproxy->done = TRUE;
710 /* To prevent the user+password to get sent to other than the original
711 host due to a location-follow, we do some weirdo checks here */
712 if(!data->state.this_is_a_follow ||
714 !data->state.first_host ||
715 data->set.http_disable_hostname_check_before_authentication ||
716 Curl_raw_equal(data->state.first_host, conn->host.name)) {
717 result = output_auth_headers(conn, authhost, request, path, FALSE);
720 authhost->done = TRUE;
727 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
728 * headers. They are dealt with both in the transfer.c main loop and in the
729 * proxy CONNECT loop.
732 CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
733 const char *auth) /* the first non-space */
736 * This resource requires authentication
738 struct SessionHandle *data = conn->data;
740 unsigned long *availp;
744 availp = &data->info.proxyauthavail;
745 authp = &data->state.authproxy;
748 availp = &data->info.httpauthavail;
749 authp = &data->state.authhost;
753 * Here we check if we want the specific single authentication (using ==) and
754 * if we do, we initiate usage of it.
756 * If the provided authentication is wanted as one out of several accepted
757 * types (using &), we OR this authentication type to the authavail
762 * ->picked is first set to the 'want' value (one or more bits) before the
763 * request is sent, and then it is again set _after_ all response 401/407
764 * headers have been received but then only to a single preferred method
770 #ifdef USE_HTTP_NEGOTIATE
771 if(checkprefix("GSS-Negotiate", auth) ||
772 checkprefix("Negotiate", auth)) {
774 *availp |= CURLAUTH_GSSNEGOTIATE;
775 authp->avail |= CURLAUTH_GSSNEGOTIATE;
777 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
778 if(data->state.negotiate.state == GSS_AUTHSENT) {
779 /* if we sent GSS authentication in the outgoing request and we get
780 this back, we're in trouble */
781 infof(data, "Authentication problem. Ignoring this.\n");
782 data->state.authproblem = TRUE;
784 else if(data->state.negotiate.state == GSS_AUTHNONE) {
785 neg = Curl_input_negotiate(conn, proxy, auth);
787 DEBUGASSERT(!data->req.newurl);
788 data->req.newurl = strdup(data->change.url);
789 if(!data->req.newurl)
790 return CURLE_OUT_OF_MEMORY;
791 data->state.authproblem = FALSE;
792 /* we received GSS auth info and we dealt with it fine */
793 data->state.negotiate.state = GSS_AUTHRECV;
796 data->state.authproblem = TRUE;
803 /* NTLM support requires the SSL crypto libs */
804 if(checkprefix("NTLM", auth)) {
805 *availp |= CURLAUTH_NTLM;
806 authp->avail |= CURLAUTH_NTLM;
807 if(authp->picked == CURLAUTH_NTLM ||
808 authp->picked == CURLAUTH_NTLM_WB) {
809 /* NTLM authentication is picked and activated */
811 Curl_input_ntlm(conn, proxy, auth);
812 if(CURLE_OK == ntlm) {
813 data->state.authproblem = FALSE;
814 #ifdef NTLM_WB_ENABLED
815 if(authp->picked == CURLAUTH_NTLM_WB) {
816 *availp &= ~CURLAUTH_NTLM;
817 authp->avail &= ~CURLAUTH_NTLM;
818 *availp |= CURLAUTH_NTLM_WB;
819 authp->avail |= CURLAUTH_NTLM_WB;
821 /* Get the challenge-message which will be passed to
822 * ntlm_auth for generating the type 3 message later */
823 while(*auth && ISSPACE(*auth))
825 if(checkprefix("NTLM", auth)) {
826 auth += strlen("NTLM");
827 while(*auth && ISSPACE(*auth))
830 if((conn->challenge_header = strdup(auth)) == NULL)
831 return CURLE_OUT_OF_MEMORY;
837 infof(data, "Authentication problem. Ignoring this.\n");
838 data->state.authproblem = TRUE;
844 #ifndef CURL_DISABLE_CRYPTO_AUTH
845 if(checkprefix("Digest", auth)) {
846 if((authp->avail & CURLAUTH_DIGEST) != 0) {
847 infof(data, "Ignoring duplicate digest auth header.\n");
851 *availp |= CURLAUTH_DIGEST;
852 authp->avail |= CURLAUTH_DIGEST;
854 /* We call this function on input Digest headers even if Digest
855 * authentication isn't activated yet, as we need to store the
856 * incoming data from this header in case we are gonna use
858 dig = Curl_input_digest(conn, proxy, auth);
860 if(CURLDIGEST_FINE != dig) {
861 infof(data, "Authentication problem. Ignoring this.\n");
862 data->state.authproblem = TRUE;
868 if(checkprefix("Basic", auth)) {
869 *availp |= CURLAUTH_BASIC;
870 authp->avail |= CURLAUTH_BASIC;
871 if(authp->picked == CURLAUTH_BASIC) {
872 /* We asked for Basic authentication but got a 40X back
873 anyway, which basically means our name+password isn't
875 authp->avail = CURLAUTH_NONE;
876 infof(data, "Authentication problem. Ignoring this.\n");
877 data->state.authproblem = TRUE;
881 /* there may be multiple methods on one line, so keep reading */
882 while(*auth && *auth != ',') /* read up to the next comma */
884 if(*auth == ',') /* if we're on a comma, skip it */
886 while(*auth && ISSPACE(*auth))
893 * http_should_fail() determines whether an HTTP response has gotten us
894 * into an error state or not.
896 * @param conn all information about the current connection
898 * @retval 0 communications should continue
900 * @retval 1 communications should not continue
902 static int http_should_fail(struct connectdata *conn)
904 struct SessionHandle *data;
911 httpcode = data->req.httpcode;
914 ** If we haven't been asked to fail on error,
917 if(!data->set.http_fail_on_error)
921 ** Any code < 400 is never terminal.
926 if(data->state.resume_from &&
927 (data->set.httpreq==HTTPREQ_GET) &&
929 /* "Requested Range Not Satisfiable", just proceed and
930 pretend this is no error */
935 ** Any code >= 400 that's not 401 or 407 is always
938 if((httpcode != 401) &&
943 ** All we have left to deal with is 401 and 407
945 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
948 ** Examine the current authentication state to see if this
949 ** is an error. The idea is for this function to get
950 ** called after processing all the headers in a response
951 ** message. So, if we've been to asked to authenticate a
952 ** particular stage, and we've done it, we're OK. But, if
953 ** we're already completely authenticated, it's not OK to
954 ** get another 401 or 407.
956 ** It is possible for authentication to go stale such that
957 ** the client needs to reauthenticate. Once that info is
958 ** available, use it here.
962 ** Either we're not authenticating, or we're supposed to
963 ** be authenticating something else. This is an error.
965 if((httpcode == 401) && !conn->bits.user_passwd)
967 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
970 return data->state.authproblem;
974 * readmoredata() is a "fread() emulation" to provide POST and/or request
975 * data. It is used when a huge POST is to be made and the entire chunk wasn't
976 * sent in the first send(). This function will then be called from the
977 * transfer.c loop when more data is to be sent to the peer.
979 * Returns the amount of bytes it filled the buffer with.
981 static size_t readmoredata(char *buffer,
986 struct connectdata *conn = (struct connectdata *)userp;
987 struct HTTP *http = conn->data->req.protop;
988 size_t fullsize = size * nitems;
990 if(0 == http->postsize)
991 /* nothing to return */
994 /* make sure that a HTTP request is never sent away chunked! */
995 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
997 if(http->postsize <= (curl_off_t)fullsize) {
998 memcpy(buffer, http->postdata, (size_t)http->postsize);
999 fullsize = (size_t)http->postsize;
1001 if(http->backup.postsize) {
1002 /* move backup data into focus and continue on that */
1003 http->postdata = http->backup.postdata;
1004 http->postsize = http->backup.postsize;
1005 conn->fread_func = http->backup.fread_func;
1006 conn->fread_in = http->backup.fread_in;
1008 http->sending++; /* move one step up */
1010 http->backup.postsize=0;
1018 memcpy(buffer, http->postdata, fullsize);
1019 http->postdata += fullsize;
1020 http->postsize -= fullsize;
1025 /* ------------------------------------------------------------------------- */
1026 /* add_buffer functions */
1029 * Curl_add_buffer_init() sets up and returns a fine buffer struct
1031 Curl_send_buffer *Curl_add_buffer_init(void)
1033 return calloc(1, sizeof(Curl_send_buffer));
1037 * Curl_add_buffer_send() sends a header buffer and frees all associated
1038 * memory. Body data may be appended to the header data if desired.
1042 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
1043 struct connectdata *conn,
1045 /* add the number of sent bytes to this
1047 long *bytes_written,
1049 /* how much of the buffer contains body data */
1050 size_t included_body_bytes,
1058 struct HTTP *http = conn->data->req.protop;
1060 curl_socket_t sockfd;
1063 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1065 sockfd = conn->sock[socketindex];
1067 /* The looping below is required since we use non-blocking sockets, but due
1068 to the circumstances we will just loop and try again and again etc */
1071 size = in->size_used;
1073 headersize = size - included_body_bytes; /* the initial part that isn't body
1076 DEBUGASSERT(size > included_body_bytes);
1078 res = Curl_convert_to_network(conn->data, ptr, headersize);
1079 /* Curl_convert_to_network calls failf if unsuccessful */
1081 /* conversion failed, free memory and return to the caller */
1089 if(conn->handler->flags & PROTOPT_SSL) {
1090 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1091 when we speak HTTPS, as if only a fraction of it is sent now, this data
1092 needs to fit into the normal read-callback buffer later on and that
1093 buffer is using this size.
1096 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1098 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1099 library when we attempt to re-send this buffer. Sending the same data
1100 is not enough, we must use the exact same address. For this reason, we
1101 must copy the data to the uploadbuffer first, since that is the buffer
1102 we will be using if this send is retried later.
1104 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1105 ptr = conn->data->state.uploadbuffer;
1110 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1112 if(CURLE_OK == res) {
1114 * Note that we may not send the entire chunk at once, and we have a set
1115 * number of data bytes at the end of the big buffer (out of which we may
1116 * only send away a part).
1118 /* how much of the header that was sent */
1119 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1120 size_t bodylen = amount - headlen;
1122 if(conn->data->set.verbose) {
1123 /* this data _may_ contain binary stuff */
1124 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1126 /* there was body data sent beyond the initial header part, pass that
1127 on to the debug callback too */
1128 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1129 ptr+headlen, bodylen, conn);
1133 /* since we sent a piece of the body here, up the byte counter for it
1135 http->writebytecount += bodylen;
1137 /* 'amount' can never be a very large value here so typecasting it so a
1138 signed 31 bit value should not cause problems even if ssize_t is
1140 *bytes_written += (long)amount;
1143 if((size_t)amount != size) {
1144 /* The whole request could not be sent in one system call. We must
1145 queue it up and send it later when we get the chance. We must not
1146 loop here and wait until it might work again. */
1150 ptr = in->buffer + amount;
1152 /* backup the currently set pointers */
1153 http->backup.fread_func = conn->fread_func;
1154 http->backup.fread_in = conn->fread_in;
1155 http->backup.postdata = http->postdata;
1156 http->backup.postsize = http->postsize;
1158 /* set the new pointers for the request-sending */
1159 conn->fread_func = (curl_read_callback)readmoredata;
1160 conn->fread_in = (void *)conn;
1161 http->postdata = ptr;
1162 http->postsize = (curl_off_t)size;
1164 http->send_buffer = in;
1165 http->sending = HTTPSEND_REQUEST;
1169 http->sending = HTTPSEND_BODY;
1170 /* the full buffer was sent, clean up and return */
1173 if((size_t)amount != size)
1174 /* We have no continue-send mechanism now, fail. This can only happen
1175 when this function is used from the CONNECT sending function. We
1176 currently (stupidly) assume that the whole request is always sent
1177 away in the first single chunk.
1181 return CURLE_SEND_ERROR;
1183 conn->writechannel_inuse = FALSE;
1195 * add_bufferf() add the formatted input to the buffer.
1197 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1202 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1206 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1210 /* If we failed, we cleanup the whole buffer and return error */
1214 return CURLE_OUT_OF_MEMORY;
1218 * add_buffer() appends a memory chunk to the existing buffer
1220 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1225 if(~size < in->size_used) {
1226 /* If resulting used size of send buffer would wrap size_t, cleanup
1227 the whole buffer and return error. Otherwise the required buffer
1228 size will fit into a single allocatable memory chunk */
1229 Curl_safefree(in->buffer);
1231 return CURLE_OUT_OF_MEMORY;
1235 ((in->size_used + size) > (in->size_max - 1))) {
1237 /* If current buffer size isn't enough to hold the result, use a
1238 buffer size that doubles the required size. If this new size
1239 would wrap size_t, then just use the largest possible one */
1241 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1242 (~(size*2) < (in->size_used*2)))
1243 new_size = (size_t)-1;
1245 new_size = (in->size_used+size)*2;
1248 /* we have a buffer, enlarge the existing one */
1249 new_rb = realloc(in->buffer, new_size);
1251 /* create a new buffer */
1252 new_rb = malloc(new_size);
1255 /* If we failed, we cleanup the whole buffer and return error */
1256 Curl_safefree(in->buffer);
1258 return CURLE_OUT_OF_MEMORY;
1261 in->buffer = new_rb;
1262 in->size_max = new_size;
1264 memcpy(&in->buffer[in->size_used], inptr, size);
1266 in->size_used += size;
1271 /* end of the add_buffer functions */
1272 /* ------------------------------------------------------------------------- */
1277 * Curl_compareheader()
1279 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1280 * Pass headers WITH the colon.
1283 Curl_compareheader(const char *headerline, /* line to check */
1284 const char *header, /* header keyword _with_ colon */
1285 const char *content) /* content string to find */
1287 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1288 * by a colon (":") and the field value. Field names are case-insensitive.
1289 * The field value MAY be preceded by any amount of LWS, though a single SP
1292 size_t hlen = strlen(header);
1298 if(!Curl_raw_nequal(headerline, header, hlen))
1299 return FALSE; /* doesn't start with header */
1301 /* pass the header */
1302 start = &headerline[hlen];
1304 /* pass all white spaces */
1305 while(*start && ISSPACE(*start))
1308 /* find the end of the header line */
1309 end = strchr(start, '\r'); /* lines end with CRLF */
1311 /* in case there's a non-standard compliant line here */
1312 end = strchr(start, '\n');
1315 /* hm, there's no line ending here, use the zero byte! */
1316 end = strchr(start, '\0');
1319 len = end-start; /* length of the content part of the input line */
1320 clen = strlen(content); /* length of the word to find */
1322 /* find the content string in the rest of the line */
1323 for(;len>=clen;len--, start++) {
1324 if(Curl_raw_nequal(start, content, clen))
1325 return TRUE; /* match! */
1328 return FALSE; /* no match */
1332 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1333 * the generic Curl_connect().
1335 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1339 /* We default to persistent connections. We set this already in this connect
1340 function to make the re-use checks properly be able to check this bit. */
1341 connkeep(conn, "HTTP default");
1343 /* the CONNECT procedure might not have been completed */
1344 result = Curl_proxy_connect(conn);
1348 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1349 /* nothing else to do except wait right now - we're not done here. */
1352 if(conn->given->flags & PROTOPT_SSL) {
1353 /* perform SSL initialization */
1354 result = https_connecting(conn, done);
1364 /* this returns the socket to wait for in the DO and DOING state for the multi
1365 interface and then we're always _sending_ a request and thus we wait for
1366 the single socket to become writable only */
1367 static int http_getsock_do(struct connectdata *conn,
1368 curl_socket_t *socks,
1372 (void)numsocks; /* unused, we trust it to be at least 1 */
1373 socks[0] = conn->sock[FIRSTSOCKET];
1374 return GETSOCK_WRITESOCK(0);
1378 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1381 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1383 /* perform SSL initialization for this socket */
1384 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1386 connclose(conn, "Failed HTTPS connection");
1392 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
1393 defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
1394 /* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
1395 It should be made to query the generic SSL layer instead. */
1396 static int https_getsock(struct connectdata *conn,
1397 curl_socket_t *socks,
1400 if(conn->handler->flags & PROTOPT_SSL) {
1401 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1404 return GETSOCK_BLANK;
1406 if(connssl->connecting_state == ssl_connect_2_writing) {
1408 socks[0] = conn->sock[FIRSTSOCKET];
1409 return GETSOCK_WRITESOCK(0);
1411 else if(connssl->connecting_state == ssl_connect_2_reading) {
1413 socks[0] = conn->sock[FIRSTSOCKET];
1414 return GETSOCK_READSOCK(0);
1421 static int https_getsock(struct connectdata *conn,
1422 curl_socket_t *socks,
1428 return GETSOCK_BLANK;
1430 #endif /* USE_SSL */
1431 #endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
1434 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1435 * has been performed.
1438 CURLcode Curl_http_done(struct connectdata *conn,
1439 CURLcode status, bool premature)
1441 struct SessionHandle *data = conn->data;
1442 struct HTTP *http =data->req.protop;
1444 Curl_unencode_cleanup(conn);
1446 /* set the proper values (possibly modified on POST) */
1447 conn->fread_func = data->set.fread_func; /* restore */
1448 conn->fread_in = data->set.in; /* restore */
1449 conn->seek_func = data->set.seek_func; /* restore */
1450 conn->seek_client = data->set.seek_client; /* restore */
1455 if(http->send_buffer) {
1456 Curl_send_buffer *buff = http->send_buffer;
1460 http->send_buffer = NULL; /* clear the pointer */
1463 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1464 data->req.bytecount = http->readbytecount + http->writebytecount;
1466 Curl_formclean(&http->sendit); /* Now free that whole lot */
1468 /* a file being uploaded was left opened, close it! */
1469 fclose(http->form.fp);
1470 http->form.fp = NULL;
1473 else if(HTTPREQ_PUT == data->set.httpreq)
1474 data->req.bytecount = http->readbytecount + http->writebytecount;
1476 if(status != CURLE_OK)
1479 if(!premature && /* this check is pointless when DONE is called before the
1480 entire operation is complete */
1481 !conn->bits.retry &&
1482 !data->set.connect_only &&
1483 ((http->readbytecount +
1484 data->req.headerbytecount -
1485 data->req.deductheadercount)) <= 0) {
1486 /* If this connection isn't simply closed to be retried, AND nothing was
1487 read from the HTTP server (that counts), this can't be right so we
1488 return an error here */
1489 failf(data, "Empty reply from server");
1490 return CURLE_GOT_NOTHING;
1498 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1499 * to avoid it include:
1501 * - if the user specifically requested HTTP 1.0
1502 * - if the server we are connected to only supports 1.0
1503 * - if any server previously contacted to handle this request only supports
1506 static bool use_http_1_1plus(const struct SessionHandle *data,
1507 const struct connectdata *conn)
1509 return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
1510 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1511 ((conn->httpversion == 11) ||
1512 ((conn->httpversion != 10) &&
1513 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1516 /* check and possibly add an Expect: header */
1517 static CURLcode expect100(struct SessionHandle *data,
1518 struct connectdata *conn,
1519 Curl_send_buffer *req_buffer)
1521 CURLcode result = CURLE_OK;
1523 data->state.expect100header = FALSE; /* default to false unless it is set
1525 if(conn->httpversion == 20) {
1526 /* We don't use Expect in HTTP2 */
1529 if(use_http_1_1plus(data, conn)) {
1530 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1531 100-continue to the headers which actually speeds up post operations
1532 (as there is one packet coming back from the web server) */
1533 ptr = Curl_checkheaders(conn, "Expect:");
1535 data->state.expect100header =
1536 Curl_compareheader(ptr, "Expect:", "100-continue");
1539 result = Curl_add_bufferf(req_buffer,
1540 "Expect: 100-continue\r\n");
1541 if(result == CURLE_OK)
1542 data->state.expect100header = TRUE;
1549 HEADER_SERVER, /* direct to server */
1550 HEADER_PROXY, /* regular request to proxy */
1551 HEADER_CONNECT /* sending CONNECT to a proxy */
1554 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1556 Curl_send_buffer *req_buffer)
1559 struct curl_slist *h[2];
1560 struct curl_slist *headers;
1561 int numlists=1; /* by default */
1562 struct SessionHandle *data = conn->data;
1565 enum proxy_use proxy;
1568 proxy = HEADER_CONNECT;
1570 proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
1571 HEADER_PROXY:HEADER_SERVER;
1575 h[0] = data->set.headers;
1578 h[0] = data->set.headers;
1579 if(data->set.sep_headers) {
1580 h[1] = data->set.proxyheaders;
1584 case HEADER_CONNECT:
1585 if(data->set.sep_headers)
1586 h[0] = data->set.proxyheaders;
1588 h[0] = data->set.headers;
1592 /* loop through one or two lists */
1593 for(i=0; i < numlists; i++) {
1597 ptr = strchr(headers->data, ':');
1599 /* we require a colon for this to be a true header */
1601 ptr++; /* pass the colon */
1602 while(*ptr && ISSPACE(*ptr))
1606 /* only send this if the contents was non-blank */
1608 if(conn->allocptr.host &&
1609 /* a Host: header was sent already, don't pass on any custom Host:
1610 header as that will produce *two* in the same request! */
1611 checkprefix("Host:", headers->data))
1613 else if(data->set.httpreq == HTTPREQ_POST_FORM &&
1614 /* this header (extended by formdata.c) is sent later */
1615 checkprefix("Content-Type:", headers->data))
1617 else if(conn->bits.authneg &&
1618 /* while doing auth neg, don't allow the custom length since
1619 we will force length zero then */
1620 checkprefix("Content-Length", headers->data))
1622 else if(conn->allocptr.te &&
1623 /* when asking for Transfer-Encoding, don't pass on a custom
1625 checkprefix("Connection", headers->data))
1628 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1636 ptr = strchr(headers->data, ';');
1639 ptr++; /* pass the semicolon */
1640 while(*ptr && ISSPACE(*ptr))
1644 /* this may be used for something else in the future */
1647 if(*(--ptr) == ';') {
1650 /* send no-value custom header if terminated by semicolon */
1652 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1660 headers = headers->next;
1666 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1667 Curl_send_buffer *req_buffer)
1669 const struct tm *tm;
1670 char *buf = data->state.buffer;
1671 CURLcode result = CURLE_OK;
1674 result = Curl_gmtime(data->set.timevalue, &keeptime);
1676 failf(data, "Invalid TIMEVALUE");
1681 /* The If-Modified-Since header family should have their times set in
1682 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1683 * represented in Greenwich Mean Time (GMT), without exception. For the
1684 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1685 * Time)." (see page 20 of RFC2616).
1688 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1689 snprintf(buf, BUFSIZE-1,
1690 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1691 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1693 Curl_month[tm->tm_mon],
1699 switch(data->set.timecondition) {
1700 case CURL_TIMECOND_IFMODSINCE:
1702 result = Curl_add_bufferf(req_buffer,
1703 "If-Modified-Since: %s\r\n", buf);
1705 case CURL_TIMECOND_IFUNMODSINCE:
1706 result = Curl_add_bufferf(req_buffer,
1707 "If-Unmodified-Since: %s\r\n", buf);
1709 case CURL_TIMECOND_LASTMOD:
1710 result = Curl_add_bufferf(req_buffer,
1711 "Last-Modified: %s\r\n", buf);
1719 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1720 * request is to be performed. This creates and sends a properly constructed
1723 CURLcode Curl_http(struct connectdata *conn, bool *done)
1725 struct SessionHandle *data=conn->data;
1726 CURLcode result=CURLE_OK;
1728 const char *ppath = data->state.path;
1729 bool paste_ftp_userpwd = FALSE;
1730 char ftp_typecode[sizeof("/;type=?")] = "";
1731 const char *host = conn->host.name;
1732 const char *te = ""; /* transfer-encoding */
1734 const char *request;
1735 Curl_HttpReq httpreq = data->set.httpreq;
1736 char *addcookies = NULL;
1737 curl_off_t included_body = 0;
1738 const char *httpstring;
1739 Curl_send_buffer *req_buffer;
1740 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1741 int seekerr = CURL_SEEKFUNC_OK;
1743 /* Always consider the DO phase done after this function call, even if there
1744 may be parts of the request that is not yet sent, since we can deal with
1745 the rest of the request in the PERFORM phase. */
1748 if(conn->httpversion < 20) { /* unless the connection is re-used and already
1750 switch (conn->negnpn) {
1752 Curl_http2_init(conn);
1753 Curl_http2_setup(conn);
1754 Curl_http2_switched(conn);
1757 /* continue with HTTP/1.1 when explicitly requested */
1760 /* and as fallback */
1765 /* prepare for a http2 request */
1766 Curl_http2_setup(conn);
1769 http = data->req.protop;
1771 if(!data->state.this_is_a_follow) {
1772 /* this is not a followed location, get the original host name */
1773 if(data->state.first_host)
1774 /* Free to avoid leaking memory on multiple requests*/
1775 free(data->state.first_host);
1777 data->state.first_host = strdup(conn->host.name);
1778 if(!data->state.first_host)
1779 return CURLE_OUT_OF_MEMORY;
1781 http->writebytecount = http->readbytecount = 0;
1783 if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
1785 httpreq = HTTPREQ_PUT;
1788 /* Now set the 'request' pointer to the proper request string */
1789 if(data->set.str[STRING_CUSTOMREQUEST])
1790 request = data->set.str[STRING_CUSTOMREQUEST];
1792 if(data->set.opt_no_body)
1795 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1798 case HTTPREQ_POST_FORM:
1804 default: /* this should never happen */
1815 /* The User-Agent string might have been allocated in url.c already, because
1816 it might have been used in the proxy connect, but if we have got a header
1817 with the user-agent string specified, we erase the previously made string
1819 if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
1820 free(conn->allocptr.uagent);
1821 conn->allocptr.uagent=NULL;
1824 /* setup the authentication headers */
1825 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1829 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1830 (httpreq != HTTPREQ_GET) &&
1831 (httpreq != HTTPREQ_HEAD)) {
1832 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1833 with content-length zero as a "probe". */
1834 conn->bits.authneg = TRUE;
1837 conn->bits.authneg = FALSE;
1839 Curl_safefree(conn->allocptr.ref);
1840 if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
1841 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1842 if(!conn->allocptr.ref)
1843 return CURLE_OUT_OF_MEMORY;
1846 conn->allocptr.ref = NULL;
1848 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
1849 addcookies = data->set.str[STRING_COOKIE];
1851 if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
1852 data->set.str[STRING_ENCODING]) {
1853 Curl_safefree(conn->allocptr.accept_encoding);
1854 conn->allocptr.accept_encoding =
1855 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1856 if(!conn->allocptr.accept_encoding)
1857 return CURLE_OUT_OF_MEMORY;
1861 /* we only consider transfer-encoding magic if libz support is built-in */
1863 if(!Curl_checkheaders(conn, "TE:") &&
1864 data->set.http_transfer_encoding) {
1865 /* When we are to insert a TE: header in the request, we must also insert
1866 TE in a Connection: header, so we need to merge the custom provided
1867 Connection: header and prevent the original to get sent. Note that if
1868 the user has inserted his/hers own TE: header we don't do this magic
1869 but then assume that the user will handle it all! */
1870 char *cptr = Curl_checkheaders(conn, "Connection:");
1871 #define TE_HEADER "TE: gzip\r\n"
1873 Curl_safefree(conn->allocptr.te);
1875 /* Create the (updated) Connection: header */
1876 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1877 strdup("Connection: TE\r\n" TE_HEADER);
1879 if(!conn->allocptr.te)
1880 return CURLE_OUT_OF_MEMORY;
1884 if(conn->httpversion == 20)
1885 /* In HTTP2 forbids Transfer-Encoding: chunked */
1888 ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
1890 /* Some kind of TE is requested, check if 'chunked' is chosen */
1891 data->req.upload_chunky =
1892 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1895 if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
1897 (data->state.infilesize == -1)) {
1898 if(conn->bits.authneg)
1899 /* don't enable chunked during auth neg */
1901 else if(use_http_1_1plus(data, conn)) {
1902 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1903 data->req.upload_chunky = TRUE;
1906 failf(data, "Chunky upload is not supported by HTTP 1.0");
1907 return CURLE_UPLOAD_FAILED;
1911 /* else, no chunky upload */
1912 data->req.upload_chunky = FALSE;
1915 if(data->req.upload_chunky)
1916 te = "Transfer-Encoding: chunked\r\n";
1920 Curl_safefree(conn->allocptr.host);
1922 ptr = Curl_checkheaders(conn, "Host:");
1923 if(ptr && (!data->state.this_is_a_follow ||
1924 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1925 #if !defined(CURL_DISABLE_COOKIES)
1926 /* If we have a given custom Host: header, we extract the host name in
1927 order to possibly use it for cookie reasons later on. We only allow the
1928 custom Host: header if this is NOT a redirect, as setting Host: in the
1929 redirected request is being out on thin ice. Except if the host name
1930 is the same as the first one! */
1931 char *cookiehost = Curl_copy_header_value(ptr);
1933 return CURLE_OUT_OF_MEMORY;
1935 /* ignore empty data */
1938 /* If the host begins with '[', we start searching for the port after
1939 the bracket has been closed */
1940 int startsearch = 0;
1941 if(*cookiehost == '[') {
1942 char *closingbracket;
1943 /* since the 'cookiehost' is an allocated memory area that will be
1944 freed later we cannot simply increment the pointer */
1945 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
1946 closingbracket = strchr(cookiehost, ']');
1948 *closingbracket = 0;
1951 char *colon = strchr(cookiehost + startsearch, ':');
1953 *colon = 0; /* The host must not include an embedded port number */
1955 Curl_safefree(conn->allocptr.cookiehost);
1956 conn->allocptr.cookiehost = cookiehost;
1960 conn->allocptr.host = NULL;
1963 /* When building Host: headers, we must put the host name within
1964 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
1966 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
1967 (conn->remote_port == PORT_HTTPS)) ||
1968 ((conn->given->protocol&CURLPROTO_HTTP) &&
1969 (conn->remote_port == PORT_HTTP)) )
1970 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
1971 the port number in the host string */
1972 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
1973 conn->bits.ipv6_ip?"[":"",
1975 conn->bits.ipv6_ip?"]":"");
1977 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
1978 conn->bits.ipv6_ip?"[":"",
1980 conn->bits.ipv6_ip?"]":"",
1983 if(!conn->allocptr.host)
1984 /* without Host: we can't make a nice request */
1985 return CURLE_OUT_OF_MEMORY;
1988 #ifndef CURL_DISABLE_PROXY
1989 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
1990 /* Using a proxy but does not tunnel through it */
1992 /* The path sent to the proxy is in fact the entire URL. But if the remote
1993 host is a IDN-name, we must make sure that the request we produce only
1994 uses the encoded host name! */
1995 if(conn->host.dispname != conn->host.name) {
1996 char *url = data->change.url;
1997 ptr = strstr(url, conn->host.dispname);
1999 /* This is where the display name starts in the URL, now replace this
2000 part with the encoded name. TODO: This method of replacing the host
2001 name is rather crude as I believe there's a slight risk that the
2002 user has entered a user name or password that contain the host name
2004 size_t currlen = strlen(conn->host.dispname);
2005 size_t newlen = strlen(conn->host.name);
2006 size_t urllen = strlen(url);
2010 newurl = malloc(urllen + newlen - currlen + 1);
2012 /* copy the part before the host name */
2013 memcpy(newurl, url, ptr - url);
2014 /* append the new host name instead of the old */
2015 memcpy(newurl + (ptr - url), conn->host.name, newlen);
2016 /* append the piece after the host name */
2017 memcpy(newurl + newlen + (ptr - url),
2018 ptr + currlen, /* copy the trailing zero byte too */
2019 urllen - (ptr-url) - currlen + 1);
2020 if(data->change.url_alloc) {
2021 Curl_safefree(data->change.url);
2022 data->change.url_alloc = FALSE;
2024 data->change.url = newurl;
2025 data->change.url_alloc = TRUE;
2028 return CURLE_OUT_OF_MEMORY;
2031 ppath = data->change.url;
2032 if(checkprefix("ftp://", ppath)) {
2033 if(data->set.proxy_transfer_mode) {
2034 /* when doing ftp, append ;type=<a|i> if not present */
2035 char *type = strstr(ppath, ";type=");
2036 if(type && type[6] && type[7] == 0) {
2037 switch (Curl_raw_toupper(type[6])) {
2047 char *p = ftp_typecode;
2048 /* avoid sending invalid URLs like ftp://example.com;type=i if the
2049 * user specified ftp://example.com without the slash */
2050 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
2053 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
2054 data->set.prefer_ascii ? 'a' : 'i');
2057 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
2058 paste_ftp_userpwd = TRUE;
2061 #endif /* CURL_DISABLE_PROXY */
2063 if(HTTPREQ_POST_FORM == httpreq) {
2064 /* we must build the whole post sequence first, so that we have a size of
2065 the whole transfer before we start to send it */
2066 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
2067 Curl_checkheaders(conn, "Content-Type:"),
2073 http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
2075 if(( (HTTPREQ_POST == httpreq) ||
2076 (HTTPREQ_POST_FORM == httpreq) ||
2077 (HTTPREQ_PUT == httpreq) ) &&
2078 data->state.resume_from) {
2079 /**********************************************************************
2080 * Resuming upload in HTTP means that we PUT or POST and that we have
2081 * got a resume_from value set. The resume value has already created
2082 * a Range: header that will be passed along. We need to "fast forward"
2083 * the file the given number of bytes and decrease the assume upload
2084 * file size before we continue this venture in the dark lands of HTTP.
2085 *********************************************************************/
2087 if(data->state.resume_from < 0 ) {
2089 * This is meant to get the size of the present remote-file by itself.
2090 * We don't support this now. Bail out!
2092 data->state.resume_from = 0;
2095 if(data->state.resume_from && !data->state.this_is_a_follow) {
2096 /* do we still game? */
2098 /* Now, let's read off the proper amount of bytes from the
2100 if(conn->seek_func) {
2101 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2105 if(seekerr != CURL_SEEKFUNC_OK) {
2106 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2107 failf(data, "Could not seek stream");
2108 return CURLE_READ_ERROR;
2110 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2112 curl_off_t passed=0;
2114 size_t readthisamountnow =
2115 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2116 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2118 size_t actuallyread =
2119 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2122 passed += actuallyread;
2123 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2124 /* this checks for greater-than only to make sure that the
2125 CURL_READFUNC_ABORT return code still aborts */
2126 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2127 " bytes from the input", passed);
2128 return CURLE_READ_ERROR;
2130 } while(passed < data->state.resume_from);
2134 /* now, decrease the size of the read */
2135 if(data->state.infilesize>0) {
2136 data->state.infilesize -= data->state.resume_from;
2138 if(data->state.infilesize <= 0) {
2139 failf(data, "File already completely uploaded");
2140 return CURLE_PARTIAL_FILE;
2143 /* we've passed, proceed as normal */
2146 if(data->state.use_range) {
2148 * A range is selected. We use different headers whether we're downloading
2149 * or uploading and we always let customized headers override our internal
2150 * ones if any such are specified.
2152 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2153 !Curl_checkheaders(conn, "Range:")) {
2154 /* if a line like this was already allocated, free the previous one */
2155 if(conn->allocptr.rangeline)
2156 free(conn->allocptr.rangeline);
2157 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2160 else if((httpreq != HTTPREQ_GET) &&
2161 !Curl_checkheaders(conn, "Content-Range:")) {
2163 /* if a line like this was already allocated, free the previous one */
2164 if(conn->allocptr.rangeline)
2165 free(conn->allocptr.rangeline);
2167 if(data->set.set_resume_from < 0) {
2168 /* Upload resume was asked for, but we don't know the size of the
2169 remote part so we tell the server (and act accordingly) that we
2170 upload the whole file (again) */
2171 conn->allocptr.rangeline =
2172 aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
2173 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2174 data->state.infilesize - 1, data->state.infilesize);
2177 else if(data->state.resume_from) {
2178 /* This is because "resume" was selected */
2179 curl_off_t total_expected_size=
2180 data->state.resume_from + data->state.infilesize;
2181 conn->allocptr.rangeline =
2182 aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
2183 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2184 data->state.range, total_expected_size-1,
2185 total_expected_size);
2188 /* Range was selected and then we just pass the incoming range and
2189 append total size */
2190 conn->allocptr.rangeline =
2191 aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2192 data->state.range, data->state.infilesize);
2194 if(!conn->allocptr.rangeline)
2195 return CURLE_OUT_OF_MEMORY;
2199 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2201 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
2203 /* initialize a dynamic send-buffer */
2204 req_buffer = Curl_add_buffer_init();
2207 return CURLE_OUT_OF_MEMORY;
2209 /* add the main request stuff */
2210 /* GET/HEAD/POST/PUT */
2211 result = Curl_add_bufferf(req_buffer, "%s ", request);
2216 if(paste_ftp_userpwd)
2217 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2218 conn->user, conn->passwd,
2219 ppath + sizeof("ftp://") - 1);
2221 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2226 Curl_add_bufferf(req_buffer,
2227 "%s" /* ftp typecode (;type=x) */
2228 " HTTP/%s\r\n" /* HTTP version */
2229 "%s" /* proxyuserpwd */
2232 "%s" /* user agent */
2236 "%s" /* accept-encoding */
2238 "%s" /* Proxy-Connection */
2239 "%s",/* transfer-encoding */
2243 conn->allocptr.proxyuserpwd?
2244 conn->allocptr.proxyuserpwd:"",
2245 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2246 (data->state.use_range && conn->allocptr.rangeline)?
2247 conn->allocptr.rangeline:"",
2248 (data->set.str[STRING_USERAGENT] &&
2249 *data->set.str[STRING_USERAGENT] &&
2250 conn->allocptr.uagent)?
2251 conn->allocptr.uagent:"",
2252 (conn->allocptr.host?conn->allocptr.host:""),
2253 http->p_accept?http->p_accept:"",
2254 conn->allocptr.te?conn->allocptr.te:"",
2255 (data->set.str[STRING_ENCODING] &&
2256 *data->set.str[STRING_ENCODING] &&
2257 conn->allocptr.accept_encoding)?
2258 conn->allocptr.accept_encoding:"",
2259 (data->change.referer && conn->allocptr.ref)?
2260 conn->allocptr.ref:"" /* Referer: <data> */,
2261 (conn->bits.httpproxy &&
2262 !conn->bits.tunnel_proxy &&
2263 !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
2264 "Proxy-Connection: Keep-Alive\r\n":"",
2269 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2270 * with basic and digest, it will be freed anyway by the next request
2273 Curl_safefree (conn->allocptr.userpwd);
2274 conn->allocptr.userpwd = NULL;
2279 if(!(conn->handler->flags&PROTOPT_SSL) &&
2280 (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
2281 /* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
2283 result = Curl_http2_request_upgrade(req_buffer, conn);
2288 #if !defined(CURL_DISABLE_COOKIES)
2289 if(data->cookies || addcookies) {
2290 struct Cookie *co=NULL; /* no cookies from start */
2294 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2295 co = Curl_cookie_getlist(data->cookies,
2296 conn->allocptr.cookiehost?
2297 conn->allocptr.cookiehost:host,
2299 (conn->handler->protocol&CURLPROTO_HTTPS)?
2301 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2304 struct Cookie *store=co;
2305 /* now loop through all cookies that matched */
2309 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2313 result = Curl_add_bufferf(req_buffer,
2314 "%s%s=%s", count?"; ":"",
2315 co->name, co->value);
2320 co = co->next; /* next cookie please */
2322 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2324 if(addcookies && (CURLE_OK == result)) {
2326 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2327 if(CURLE_OK == result) {
2328 result = Curl_add_bufferf(req_buffer, "%s%s",
2334 if(count && (CURLE_OK == result))
2335 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2342 if(data->set.timecondition) {
2343 result = Curl_add_timecondition(data, req_buffer);
2348 result = Curl_add_custom_headers(conn, FALSE, req_buffer);
2352 http->postdata = NULL; /* nothing to post at this point */
2353 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2355 /* If 'authdone' is FALSE, we must not set the write socket index to the
2356 Curl_transfer() call below, as we're not ready to actually upload any
2361 case HTTPREQ_POST_FORM:
2362 if(!http->sendit || conn->bits.authneg) {
2363 /* nothing to post! */
2364 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2368 result = Curl_add_buffer_send(req_buffer, conn,
2369 &data->info.request_size, 0, FIRSTSOCKET);
2371 failf(data, "Failed sending POST request");
2373 /* setup variables for the upcoming transfer */
2374 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2379 if(Curl_FormInit(&http->form, http->sendit)) {
2380 failf(data, "Internal HTTP POST error!");
2381 return CURLE_HTTP_POST_ERROR;
2384 /* Get the currently set callback function pointer and store that in the
2385 form struct since we might want the actual user-provided callback later
2386 on. The conn->fread_func pointer itself will be changed for the
2387 multipart case to the function that returns a multipart formatted
2389 http->form.fread_func = conn->fread_func;
2391 /* Set the read function to read from the generated form data */
2392 conn->fread_func = (curl_read_callback)Curl_FormReader;
2393 conn->fread_in = &http->form;
2395 http->sending = HTTPSEND_BODY;
2397 if(!data->req.upload_chunky &&
2398 !Curl_checkheaders(conn, "Content-Length:")) {
2399 /* only add Content-Length if not uploading chunked */
2400 result = Curl_add_bufferf(req_buffer,
2401 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2402 "\r\n", http->postsize);
2407 result = expect100(data, conn, req_buffer);
2413 /* Get Content-Type: line from Curl_formpostheader.
2416 size_t linelength=0;
2417 contentType = Curl_formpostheader((void *)&http->form,
2420 failf(data, "Could not get Content-Type header line!");
2421 return CURLE_HTTP_POST_ERROR;
2424 result = Curl_add_buffer(req_buffer, contentType, linelength);
2429 /* make the request end in a true CRLF */
2430 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2434 /* set upload size to the progress meter */
2435 Curl_pgrsSetUploadSize(data, http->postsize);
2437 /* fire away the whole request to the server */
2438 result = Curl_add_buffer_send(req_buffer, conn,
2439 &data->info.request_size, 0, FIRSTSOCKET);
2441 failf(data, "Failed sending POST request");
2443 /* setup variables for the upcoming transfer */
2444 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2445 &http->readbytecount, FIRSTSOCKET,
2446 &http->writebytecount);
2449 Curl_formclean(&http->sendit); /* free that whole lot */
2453 /* convert the form data */
2454 result = Curl_convert_form(data, http->sendit);
2456 Curl_formclean(&http->sendit); /* free that whole lot */
2462 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2464 if(conn->bits.authneg)
2467 postsize = data->state.infilesize;
2469 if((postsize != -1) && !data->req.upload_chunky &&
2470 !Curl_checkheaders(conn, "Content-Length:")) {
2471 /* only add Content-Length if not uploading chunked */
2472 result = Curl_add_bufferf(req_buffer,
2473 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2480 result = expect100(data, conn, req_buffer);
2485 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2489 /* set the upload size to the progress meter */
2490 Curl_pgrsSetUploadSize(data, postsize);
2492 /* this sends the buffer and frees all the buffer resources */
2493 result = Curl_add_buffer_send(req_buffer, conn,
2494 &data->info.request_size, 0, FIRSTSOCKET);
2496 failf(data, "Failed sending PUT request");
2498 /* prepare for transfer */
2499 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2500 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2501 postsize?&http->writebytecount:NULL);
2507 /* this is the simple POST, using x-www-form-urlencoded style */
2509 if(conn->bits.authneg)
2512 /* figure out the size of the postfields */
2513 postsize = (data->set.postfieldsize != -1)?
2514 data->set.postfieldsize:
2515 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2518 /* We only set Content-Length and allow a custom Content-Length if
2519 we don't upload data chunked, as RFC2616 forbids us to set both
2520 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2521 if((postsize != -1) && !data->req.upload_chunky &&
2522 !Curl_checkheaders(conn, "Content-Length:")) {
2523 /* we allow replacing this header if not during auth negotiation,
2524 although it isn't very wise to actually set your own */
2525 result = Curl_add_bufferf(req_buffer,
2526 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2532 if(!Curl_checkheaders(conn, "Content-Type:")) {
2533 result = Curl_add_bufferf(req_buffer,
2534 "Content-Type: application/"
2535 "x-www-form-urlencoded\r\n");
2540 /* For really small posts we don't use Expect: headers at all, and for
2541 the somewhat bigger ones we allow the app to disable it. Just make
2542 sure that the expect100header is always set to the preferred value
2544 ptr = Curl_checkheaders(conn, "Expect:");
2546 data->state.expect100header =
2547 Curl_compareheader(ptr, "Expect:", "100-continue");
2549 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2550 result = expect100(data, conn, req_buffer);
2555 data->state.expect100header = FALSE;
2557 if(data->set.postfields) {
2559 /* In HTTP2, we send request body in DATA frame regardless of
2561 if(conn->httpversion != 20 &&
2562 !data->state.expect100header &&
2563 (postsize < MAX_INITIAL_POST_SIZE)) {
2564 /* if we don't use expect: 100 AND
2565 postsize is less than MAX_INITIAL_POST_SIZE
2567 then append the post data to the HTTP request header. This limit
2568 is no magic limit but only set to prevent really huge POSTs to
2569 get the data duplicated with malloc() and family. */
2571 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2575 if(!data->req.upload_chunky) {
2576 /* We're not sending it 'chunked', append it to the request
2577 already now to reduce the number if send() calls */
2578 result = Curl_add_buffer(req_buffer, data->set.postfields,
2580 included_body = postsize;
2584 /* Append the POST data chunky-style */
2585 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2586 if(CURLE_OK == result) {
2587 result = Curl_add_buffer(req_buffer, data->set.postfields,
2589 if(CURLE_OK == result)
2590 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2591 included_body = postsize + 2;
2594 if(CURLE_OK == result)
2595 result = Curl_add_buffer(req_buffer,
2596 "\x30\x0d\x0a\x0d\x0a", 5);
2602 /* Make sure the progress information is accurate */
2603 Curl_pgrsSetUploadSize(data, postsize);
2606 /* A huge POST coming up, do data separate from the request */
2607 http->postsize = postsize;
2608 http->postdata = data->set.postfields;
2610 http->sending = HTTPSEND_BODY;
2612 conn->fread_func = (curl_read_callback)readmoredata;
2613 conn->fread_in = (void *)conn;
2615 /* set the upload size to the progress meter */
2616 Curl_pgrsSetUploadSize(data, http->postsize);
2618 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2624 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2628 if(data->req.upload_chunky && conn->bits.authneg) {
2629 /* Chunky upload is selected and we're negotiating auth still, send
2631 result = Curl_add_buffer(req_buffer,
2632 "\x30\x0d\x0a\x0d\x0a", 5);
2638 else if(data->set.postfieldsize) {
2639 /* set the upload size to the progress meter */
2640 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2642 /* set the pointer to mark that we will send the post body using the
2643 read callback, but only if we're not in authenticate
2645 if(!conn->bits.authneg) {
2646 http->postdata = (char *)&http->postdata;
2647 http->postsize = postsize;
2651 /* issue the request */
2652 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2653 (size_t)included_body, FIRSTSOCKET);
2656 failf(data, "Failed sending HTTP POST request");
2658 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2659 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2660 http->postdata?&http->writebytecount:NULL);
2664 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2668 /* issue the request */
2669 result = Curl_add_buffer_send(req_buffer, conn,
2670 &data->info.request_size, 0, FIRSTSOCKET);
2673 failf(data, "Failed sending HTTP request");
2675 /* HTTP GET/HEAD download: */
2676 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2677 http->postdata?FIRSTSOCKET:-1,
2678 http->postdata?&http->writebytecount:NULL);
2683 if(http->writebytecount) {
2684 /* if a request-body has been sent off, we make sure this progress is noted
2686 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2687 if(Curl_pgrsUpdate(conn))
2688 result = CURLE_ABORTED_BY_CALLBACK;
2690 if(http->writebytecount >= postsize) {
2691 /* already sent the entire request body, mark the "upload" as
2693 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
2694 " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
2695 http->writebytecount, postsize);
2696 data->req.upload_done = TRUE;
2697 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2698 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2708 * Returns TRUE if member of the list matches prefix of string
2711 checkhttpprefix(struct SessionHandle *data,
2714 struct curl_slist *head = data->set.http200aliases;
2716 #ifdef CURL_DOES_CONVERSIONS
2717 /* convert from the network encoding using a scratch area */
2718 char *scratch = strdup(s);
2719 if(NULL == scratch) {
2720 failf (data, "Failed to allocate memory for conversion!");
2721 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2723 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2724 /* Curl_convert_from_network calls failf if unsuccessful */
2726 return FALSE; /* can't return CURLE_foobar so return FALSE */
2729 #endif /* CURL_DOES_CONVERSIONS */
2732 if(checkprefix(head->data, s)) {
2739 if(!rc && (checkprefix("HTTP/", s)))
2742 #ifdef CURL_DOES_CONVERSIONS
2744 #endif /* CURL_DOES_CONVERSIONS */
2748 #ifndef CURL_DISABLE_RTSP
2750 checkrtspprefix(struct SessionHandle *data,
2754 #ifdef CURL_DOES_CONVERSIONS
2755 /* convert from the network encoding using a scratch area */
2756 char *scratch = strdup(s);
2757 if(NULL == scratch) {
2758 failf (data, "Failed to allocate memory for conversion!");
2759 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2761 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2762 /* Curl_convert_from_network calls failf if unsuccessful */
2764 return FALSE; /* can't return CURLE_foobar so return FALSE */
2768 (void)data; /* unused */
2769 #endif /* CURL_DOES_CONVERSIONS */
2770 if(checkprefix("RTSP/", s))
2775 #endif /* CURL_DISABLE_RTSP */
2778 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2781 #ifndef CURL_DISABLE_RTSP
2782 if(conn->handler->protocol & CURLPROTO_RTSP)
2783 return checkrtspprefix(data, s);
2786 #endif /* CURL_DISABLE_RTSP */
2788 return checkhttpprefix(data, s);
2792 * header_append() copies a chunk of data to the end of the already received
2793 * header. We make sure that the full string fit in the allocated header
2794 * buffer, or else we enlarge it.
2796 static CURLcode header_append(struct SessionHandle *data,
2797 struct SingleRequest *k,
2800 if(k->hbuflen + length >= data->state.headersize) {
2801 /* We enlarge the header buffer as it is too small */
2806 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2807 /* The reason to have a max limit for this is to avoid the risk of a bad
2808 server feeding libcurl with a never-ending header that will cause
2809 reallocs infinitely */
2810 failf (data, "Avoided giant realloc for header (max is %d)!",
2811 CURL_MAX_HTTP_HEADER);
2812 return CURLE_OUT_OF_MEMORY;
2815 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2816 hbufp_index = k->hbufp - data->state.headerbuff;
2817 newbuff = realloc(data->state.headerbuff, newsize);
2819 failf (data, "Failed to alloc memory for big header!");
2820 return CURLE_OUT_OF_MEMORY;
2822 data->state.headersize=newsize;
2823 data->state.headerbuff = newbuff;
2824 k->hbufp = data->state.headerbuff + hbufp_index;
2826 memcpy(k->hbufp, k->str_start, length);
2828 k->hbuflen += length;
2834 static void print_http_error(struct SessionHandle *data)
2836 struct SingleRequest *k = &data->req;
2839 /* make sure that data->req.p points to the HTTP status line */
2840 if(!strncmp(beg, "HTTP", 4)) {
2842 /* skip to HTTP status code */
2843 beg = strchr(beg, ' ');
2846 /* find trailing CR */
2847 char end_char = '\r';
2848 char *end = strchr(beg, end_char);
2850 /* try to find LF (workaround for non-compliant HTTP servers) */
2852 end = strchr(beg, end_char);
2856 /* temporarily replace CR or LF by NUL and print the error message */
2858 failf(data, "The requested URL returned error: %s", beg);
2860 /* restore the previously replaced CR or LF */
2867 /* fall-back to printing the HTTP status code only */
2868 failf(data, "The requested URL returned error: %d", k->httpcode);
2872 * Read any HTTP header lines from the server and pass them to the client app.
2874 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2875 struct connectdata *conn,
2880 struct SingleRequest *k = &data->req;
2882 /* header line within buffer loop */
2888 /* str_start is start of line within buf */
2889 k->str_start = k->str;
2891 /* data is in network encoding so use 0x0a instead of '\n' */
2892 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2895 /* Not a complete header line within buffer, append the data to
2896 the end of the headerbuff. */
2897 result = header_append(data, k, *nread);
2901 if(!k->headerline && (k->hbuflen>5)) {
2902 /* make a first check that this looks like a protocol header */
2903 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2904 /* this is not the beginning of a protocol first header line */
2906 k->badheader = HEADER_ALLBAD;
2911 break; /* read more and try again */
2914 /* decrease the size of the remaining (supposed) header line */
2915 rest_length = (k->end_ptr - k->str)+1;
2916 *nread -= (ssize_t)rest_length;
2918 k->str = k->end_ptr + 1; /* move past new line */
2920 full_length = k->str - k->str_start;
2922 result = header_append(data, k, full_length);
2926 k->end_ptr = k->hbufp;
2927 k->p = data->state.headerbuff;
2930 * We now have a FULL header line that p points to
2933 if(!k->headerline) {
2934 /* the first read header */
2935 if((k->hbuflen>5) &&
2936 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2937 /* this is not the beginning of a protocol first header line */
2940 /* since there's more, this is a partial bad header */
2941 k->badheader = HEADER_PARTHEADER;
2943 /* this was all we read so it's all a bad header */
2944 k->badheader = HEADER_ALLBAD;
2945 *nread = (ssize_t)rest_length;
2951 /* headers are in network encoding so
2952 use 0x0a and 0x0d instead of '\n' and '\r' */
2953 if((0x0a == *k->p) || (0x0d == *k->p)) {
2955 /* Zero-length header line means end of headers! */
2957 #ifdef CURL_DOES_CONVERSIONS
2959 *k->p = '\r'; /* replace with CR in host encoding */
2960 k->p++; /* pass the CR byte */
2963 *k->p = '\n'; /* replace with LF in host encoding */
2964 k->p++; /* pass the LF byte */
2968 k->p++; /* pass the \r byte */
2970 k->p++; /* pass the \n byte */
2971 #endif /* CURL_DOES_CONVERSIONS */
2973 if(100 <= k->httpcode && 199 >= k->httpcode) {
2975 * We have made a HTTP PUT or POST and this is 1.1-lingo
2976 * that tells us that the server is OK with this and ready
2977 * to receive the data.
2978 * However, we'll get more headers now so we must get
2979 * back into the header-parsing state!
2982 k->headerline = 0; /* restart the header line counter */
2984 /* "A user agent MAY ignore unexpected 1xx status responses." */
2985 switch(k->httpcode) {
2987 /* if we did wait for this do enable write now! */
2989 k->exp100 = EXP100_SEND_DATA;
2990 k->keepon |= KEEP_SEND;
2994 /* Switching Protocols */
2995 if(k->upgr101 == UPGR101_REQUESTED) {
2996 infof(data, "Received 101\n");
2997 k->upgr101 = UPGR101_RECEIVED;
2999 /* switch to http2 now */
3000 Curl_http2_switched(conn);
3008 k->header = FALSE; /* no more header to parse! */
3010 if((k->size == -1) && !k->chunk && !conn->bits.close &&
3011 (conn->httpversion == 11) &&
3012 !(conn->handler->protocol & CURLPROTO_RTSP) &&
3013 data->set.httpreq != HTTPREQ_HEAD) {
3014 /* On HTTP 1.1, when connection is not to get closed, but no
3015 Content-Length nor Content-Encoding chunked have been
3016 received, according to RFC2616 section 4.4 point 5, we
3017 assume that the server will close the connection to
3018 signal the end of the document. */
3019 infof(data, "no chunk, no close, no size. Assume close to "
3021 connclose(conn, "HTTP: No end-of-message indicator");
3026 * When all the headers have been parsed, see if we should give
3027 * up and return an error.
3029 if(http_should_fail(conn)) {
3030 failf (data, "The requested URL returned error: %d",
3032 return CURLE_HTTP_RETURNED_ERROR;
3035 /* now, only output this if the header AND body are requested:
3037 writetype = CLIENTWRITE_HEADER;
3038 if(data->set.include_header)
3039 writetype |= CLIENTWRITE_BODY;
3041 headerlen = k->p - data->state.headerbuff;
3043 result = Curl_client_write(conn, writetype,
3044 data->state.headerbuff,
3049 data->info.header_size += (long)headerlen;
3050 data->req.headerbytecount += (long)headerlen;
3052 data->req.deductheadercount =
3053 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
3055 if(!*stop_reading) {
3056 /* Curl_http_auth_act() checks what authentication methods
3057 * that are available and decides which one (if any) to
3058 * use. It will set 'newurl' if an auth method was picked. */
3059 result = Curl_http_auth_act(conn);
3064 if(k->httpcode >= 300) {
3065 if((!conn->bits.authneg) && !conn->bits.close &&
3066 !conn->bits.rewindaftersend) {
3068 * General treatment of errors when about to send data. Including :
3069 * "417 Expectation Failed", while waiting for 100-continue.
3071 * The check for close above is done simply because of something
3072 * else has already deemed the connection to get closed then
3073 * something else should've considered the big picture and we
3076 * rewindaftersend indicates that something has told libcurl to
3077 * continue sending even if it gets discarded
3080 switch(data->set.httpreq) {
3083 case HTTPREQ_POST_FORM:
3084 /* We got an error response. If this happened before the whole
3085 * request body has been sent we stop sending and mark the
3086 * connection for closure after we've read the entire response.
3088 if(!k->upload_done) {
3089 infof(data, "HTTP error before end of send, stop sending\n");
3090 connclose(conn, "Stop sending data before everything sent");
3091 k->upload_done = TRUE;
3092 k->keepon &= ~KEEP_SEND; /* don't send */
3093 if(data->state.expect100header)
3094 k->exp100 = EXP100_FAILED;
3098 default: /* default label present to avoid compiler warnings */
3104 if(conn->bits.rewindaftersend) {
3105 /* We rewind after a complete send, so thus we continue
3107 infof(data, "Keep sending data to get tossed away!\n");
3108 k->keepon |= KEEP_SEND;
3114 * really end-of-headers.
3116 * If we requested a "no body", this is a good time to get
3117 * out and return home.
3119 if(data->set.opt_no_body)
3120 *stop_reading = TRUE;
3122 /* If we know the expected size of this document, we set the
3123 maximum download size to the size of the expected
3124 document or else, we won't know when to stop reading!
3126 Note that we set the download maximum even if we read a
3127 "Connection: close" header, to make sure that
3128 "Content-Length: 0" still prevents us from attempting to
3129 read the (missing) response-body.
3131 /* According to RFC2616 section 4.4, we MUST ignore
3132 Content-Length: headers if we are now receiving data
3133 using chunked Transfer-Encoding.
3136 k->maxdownload = k->size = -1;
3139 /* We do this operation even if no_body is true, since this
3140 data might be retrieved later with curl_easy_getinfo()
3141 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3143 Curl_pgrsSetDownloadSize(data, k->size);
3144 k->maxdownload = k->size;
3147 /* If max download size is *zero* (nothing) we already
3148 have nothing and can safely return ok now! */
3149 if(0 == k->maxdownload)
3150 *stop_reading = TRUE;
3153 /* we make sure that this socket isn't read more now */
3154 k->keepon &= ~KEEP_RECV;
3157 if(data->set.verbose)
3158 Curl_debug(data, CURLINFO_HEADER_IN,
3159 k->str_start, headerlen, conn);
3160 break; /* exit header line loop */
3163 /* We continue reading headers, so reset the line-based
3164 header parsing variables hbufp && hbuflen */
3165 k->hbufp = data->state.headerbuff;
3171 * Checks for special headers coming up.
3174 if(!k->headerline++) {
3175 /* This is the first header, it MUST be the error code line
3176 or else we consider this to be the body right away! */
3177 int httpversion_major;
3178 int rtspversion_major;
3180 #ifdef CURL_DOES_CONVERSIONS
3181 #define HEADER1 scratch
3182 #define SCRATCHSIZE 21
3184 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3185 /* We can't really convert this yet because we
3186 don't know if it's the 1st header line or the body.
3187 So we do a partial conversion into a scratch area,
3188 leaving the data at k->p as-is.
3190 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3191 scratch[SCRATCHSIZE] = 0; /* null terminate */
3192 res = Curl_convert_from_network(data,
3196 /* Curl_convert_from_network calls failf if unsuccessful */
3199 #define HEADER1 k->p /* no conversion needed, just use k->p */
3200 #endif /* CURL_DOES_CONVERSIONS */
3202 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
3203 nc = sscanf(HEADER1,
3209 conn->httpversion += 10 * httpversion_major;
3212 /* this is the real world, not a Nirvana
3213 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3215 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3216 conn->httpversion = 10;
3218 /* If user has set option HTTP200ALIASES,
3219 compare header line against list of aliases
3222 if(checkhttpprefix(data, k->p)) {
3225 conn->httpversion = 10;
3230 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3231 nc = sscanf(HEADER1,
3237 conn->rtspversion += 10 * rtspversion_major;
3238 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3241 /* TODO: do we care about the other cases here? */
3247 data->info.httpcode = k->httpcode;
3249 data->info.httpversion = conn->httpversion;
3250 if(!data->state.httpversion ||
3251 data->state.httpversion > conn->httpversion)
3252 /* store the lowest server version we encounter */
3253 data->state.httpversion = conn->httpversion;
3256 * This code executes as part of processing the header. As a
3257 * result, it's not totally clear how to interpret the
3258 * response code yet as that depends on what other headers may
3259 * be present. 401 and 407 may be errors, but may be OK
3260 * depending on how authentication is working. Other codes
3261 * are definitely errors, so give up here.
3263 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3264 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3265 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3267 if(data->state.resume_from &&
3268 (data->set.httpreq==HTTPREQ_GET) &&
3269 (k->httpcode == 416)) {
3270 /* "Requested Range Not Satisfiable", just proceed and
3271 pretend this is no error */
3274 /* serious error, go home! */
3275 print_http_error(data);
3276 return CURLE_HTTP_RETURNED_ERROR;
3280 if(conn->httpversion == 10) {
3281 /* Default action for HTTP/1.0 must be to close, unless
3282 we get one of those fancy headers that tell us the
3283 server keeps it open for us! */
3284 infof(data, "HTTP 1.0, assume close after body\n");
3285 connclose(conn, "HTTP/1.0 close after body");
3287 else if(conn->httpversion >= 11 &&
3288 !conn->bits.close) {
3289 struct connectbundle *cb_ptr;
3291 /* If HTTP version is >= 1.1 and connection is persistent
3292 server supports pipelining. */
3294 "HTTP 1.1 or later with persistent connection, "
3295 "pipelining supported\n"));
3296 /* Activate pipelining if needed */
3297 cb_ptr = conn->bundle;
3299 if(!Curl_pipeline_site_blacklisted(data, conn))
3300 cb_ptr->server_supports_pipelining = TRUE;
3304 switch(k->httpcode) {
3306 /* (quote from RFC2616, section 10.2.5): The server has
3307 * fulfilled the request but does not need to return an
3308 * entity-body ... The 204 response MUST NOT include a
3309 * message-body, and thus is always terminated by the first
3310 * empty line after the header fields. */
3313 /* (quote from RFC2616, section 10.3.5): The 304 response
3314 * MUST NOT contain a message-body, and thus is always
3315 * terminated by the first empty line after the header
3317 if(data->set.timecondition)
3318 data->info.timecond = TRUE;
3321 k->ignorecl = TRUE; /* ignore Content-Length headers */
3329 k->header = FALSE; /* this is not a header line */
3334 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3335 /* Curl_convert_from_network calls failf if unsuccessful */
3339 /* Check for Content-Length: header lines to get size */
3340 if(!k->ignorecl && !data->set.ignorecl &&
3341 checkprefix("Content-Length:", k->p)) {
3342 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3343 if(data->set.max_filesize &&
3344 contentlength > data->set.max_filesize) {
3345 failf(data, "Maximum file size exceeded");
3346 return CURLE_FILESIZE_EXCEEDED;
3348 if(contentlength >= 0) {
3349 k->size = contentlength;
3350 k->maxdownload = k->size;
3351 /* we set the progress download size already at this point
3352 just to make it easier for apps/callbacks to extract this
3353 info as soon as possible */
3354 Curl_pgrsSetDownloadSize(data, k->size);
3357 /* Negative Content-Length is really odd, and we know it
3358 happens for example when older Apache servers send large
3360 connclose(conn, "negative content-length");
3361 infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
3362 ", closing after transfer\n", contentlength);
3365 /* check for Content-Type: header lines to get the MIME-type */
3366 else if(checkprefix("Content-Type:", k->p)) {
3367 char *contenttype = Curl_copy_header_value(k->p);
3369 return CURLE_OUT_OF_MEMORY;
3371 /* ignore empty data */
3374 Curl_safefree(data->info.contenttype);
3375 data->info.contenttype = contenttype;
3378 else if(checkprefix("Server:", k->p)) {
3379 char *server_name = Curl_copy_header_value(k->p);
3381 /* Turn off pipelining if the server version is blacklisted */
3382 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3383 if(Curl_pipeline_server_blacklisted(data, server_name))
3384 conn->bundle->server_supports_pipelining = FALSE;
3386 Curl_safefree(server_name);
3388 else if((conn->httpversion == 10) &&
3389 conn->bits.httpproxy &&
3390 Curl_compareheader(k->p,
3391 "Proxy-Connection:", "keep-alive")) {
3393 * When a HTTP/1.0 reply comes when using a proxy, the
3394 * 'Proxy-Connection: keep-alive' line tells us the
3395 * connection will be kept alive for our pleasure.
3396 * Default action for 1.0 is to close.
3398 connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
3399 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3401 else if((conn->httpversion == 11) &&
3402 conn->bits.httpproxy &&
3403 Curl_compareheader(k->p,
3404 "Proxy-Connection:", "close")) {
3406 * We get a HTTP/1.1 response from a proxy and it says it'll
3407 * close down after this transfer.
3409 connclose(conn, "Proxy-Connection: asked to close after done");
3410 infof(data, "HTTP/1.1 proxy connection set close!\n");
3412 else if((conn->httpversion == 10) &&
3413 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3415 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3416 * tells us the connection will be kept alive for our
3417 * pleasure. Default action for 1.0 is to close.
3419 * [RFC2068, section 19.7.1] */
3420 connkeep(conn, "Connection keep-alive");
3421 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3423 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3425 * [RFC 2616, section 8.1.2.1]
3426 * "Connection: close" is HTTP/1.1 language and means that
3427 * the connection will close when this request has been
3430 connclose(conn, "Connection: close used");
3432 else if(checkprefix("Transfer-Encoding:", k->p)) {
3433 /* One or more encodings. We check for chunked and/or a compression
3436 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3437 * means that the server will send a series of "chunks". Each
3438 * chunk starts with line with info (including size of the
3439 * coming block) (terminated with CRLF), then a block of data
3440 * with the previously mentioned size. There can be any amount
3441 * of chunks, and a chunk-data set to zero signals the
3446 /* Find the first non-space letter */
3450 /* skip whitespaces and commas */
3451 while(*start && (ISSPACE(*start) || (*start == ',')))
3454 if(checkprefix("chunked", start)) {
3455 k->chunk = TRUE; /* chunks coming our way */
3457 /* init our chunky engine */
3458 Curl_httpchunk_init(conn);
3463 if(k->auto_decoding)
3464 /* TODO: we only support the first mentioned compression for now */
3467 if(checkprefix("identity", start)) {
3468 k->auto_decoding = IDENTITY;
3471 else if(checkprefix("deflate", start)) {
3472 k->auto_decoding = DEFLATE;
3475 else if(checkprefix("gzip", start)) {
3476 k->auto_decoding = GZIP;
3479 else if(checkprefix("x-gzip", start)) {
3480 k->auto_decoding = GZIP;
3483 else if(checkprefix("compress", start)) {
3484 k->auto_decoding = COMPRESS;
3487 else if(checkprefix("x-compress", start)) {
3488 k->auto_decoding = COMPRESS;
3498 else if(checkprefix("Content-Encoding:", k->p) &&
3499 (data->set.str[STRING_ENCODING] ||
3500 conn->httpversion == 20)) {
3502 * Process Content-Encoding. Look for the values: identity,
3503 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3504 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3505 * 2616). zlib cannot handle compress. However, errors are
3506 * handled further down when the response body is processed
3510 /* Find the first non-space letter */
3512 while(*start && ISSPACE(*start))
3515 /* Record the content-encoding for later use */
3516 if(checkprefix("identity", start))
3517 k->auto_decoding = IDENTITY;
3518 else if(checkprefix("deflate", start))
3519 k->auto_decoding = DEFLATE;
3520 else if(checkprefix("gzip", start)
3521 || checkprefix("x-gzip", start))
3522 k->auto_decoding = GZIP;
3523 else if(checkprefix("compress", start)
3524 || checkprefix("x-compress", start))
3525 k->auto_decoding = COMPRESS;
3527 else if(checkprefix("Content-Range:", k->p)) {
3528 /* Content-Range: bytes [num]-
3529 Content-Range: bytes: [num]-
3530 Content-Range: [num]-
3532 The second format was added since Sun's webserver
3533 JavaWebServer/1.1.1 obviously sends the header this way!
3534 The third added since some servers use that!
3537 char *ptr = k->p + 14;
3539 /* Move forward until first digit */
3540 while(*ptr && !ISDIGIT(*ptr))
3543 k->offset = curlx_strtoofft(ptr, NULL, 10);
3545 if(data->state.resume_from == k->offset)
3546 /* we asked for a resume and we got it */
3547 k->content_range = TRUE;
3549 #if !defined(CURL_DISABLE_COOKIES)
3550 else if(data->cookies &&
3551 checkprefix("Set-Cookie:", k->p)) {
3552 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3553 CURL_LOCK_ACCESS_SINGLE);
3554 Curl_cookie_add(data,
3555 data->cookies, TRUE, k->p+11,
3556 /* If there is a custom-set Host: name, use it
3557 here, or else use real peer host name. */
3558 conn->allocptr.cookiehost?
3559 conn->allocptr.cookiehost:conn->host.name,
3561 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3564 else if(checkprefix("Last-Modified:", k->p) &&
3565 (data->set.timecondition || data->set.get_filetime) ) {
3566 time_t secs=time(NULL);
3567 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3569 if(data->set.get_filetime)
3570 data->info.filetime = (long)k->timeofdoc;
3572 else if((checkprefix("WWW-Authenticate:", k->p) &&
3573 (401 == k->httpcode)) ||
3574 (checkprefix("Proxy-authenticate:", k->p) &&
3575 (407 == k->httpcode))) {
3577 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3578 char *auth = Curl_copy_header_value(k->p);
3580 return CURLE_OUT_OF_MEMORY;
3582 result = Curl_http_input_auth(conn, proxy, auth);
3584 Curl_safefree(auth);
3589 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3590 checkprefix("Location:", k->p) &&
3591 !data->req.location) {
3592 /* this is the URL that the server advises us to use instead */
3593 char *location = Curl_copy_header_value(k->p);
3595 return CURLE_OUT_OF_MEMORY;
3597 /* ignore empty data */
3600 data->req.location = location;
3602 if(data->set.http_follow_location) {
3603 DEBUGASSERT(!data->req.newurl);
3604 data->req.newurl = strdup(data->req.location); /* clone */
3605 if(!data->req.newurl)
3606 return CURLE_OUT_OF_MEMORY;
3608 /* some cases of POST and PUT etc needs to rewind the data
3609 stream at this point */
3610 result = http_perhapsrewind(conn);
3616 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3617 result = Curl_rtsp_parseheader(conn, k->p);
3623 * End of header-checks. Write them to the client.
3626 writetype = CLIENTWRITE_HEADER;
3627 if(data->set.include_header)
3628 writetype |= CLIENTWRITE_BODY;
3630 if(data->set.verbose)
3631 Curl_debug(data, CURLINFO_HEADER_IN,
3632 k->p, (size_t)k->hbuflen, conn);
3634 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3638 data->info.header_size += (long)k->hbuflen;
3639 data->req.headerbytecount += (long)k->hbuflen;
3641 /* reset hbufp pointer && hbuflen */
3642 k->hbufp = data->state.headerbuff;
3645 while(!*stop_reading && *k->str); /* header line within buffer */
3647 /* We might have reached the end of the header part here, but
3648 there might be a non-header part left in the end of the read
3654 #endif /* CURL_DISABLE_HTTP */