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 result = 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_NEGOTIATE)
332 pick->picked = CURLAUTH_NEGOTIATE;
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 */
350 /* whether to complete request (for authentication) in current connection */
351 static bool complete_request(struct connectdata *conn,
352 curl_off_t remaining_bytes)
354 #if defined(USE_NTLM) || defined(USE_SPNEGO)
355 struct SessionHandle *data = conn->data;
356 bool have_ntlm_or_negotiate = FALSE;
357 bool auth_started = FALSE;
359 /* don't reset connection when we're in NTLM or Negotiate authentication;
360 * those authenticate the connection - creating a new connection breaks the
364 #if defined(USE_NTLM)
365 /* proxy NTLM authentication */
366 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
367 (data->state.authproxy.picked == CURLAUTH_NTLM_WB)) {
368 have_ntlm_or_negotiate = TRUE;
369 auth_started = auth_started
370 || (conn->proxyntlm.state != NTLMSTATE_NONE);
373 /* normal NTLM authentication */
374 if((data->state.authhost.picked == CURLAUTH_NTLM) ||
375 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
376 have_ntlm_or_negotiate = TRUE;
377 auth_started = auth_started
378 || (conn->ntlm.state != NTLMSTATE_NONE);
382 #if defined(USE_SPNEGO)
383 /* proxy Negotiate authentication */
384 if(data->state.authproxy.picked == CURLAUTH_NEGOTIATE) {
385 have_ntlm_or_negotiate = TRUE;
386 auth_started = auth_started
387 || (data->state.proxyneg.state != GSS_AUTHNONE);
390 /* normal Negotiate authentication */
391 if(data->state.authhost.picked == CURLAUTH_NEGOTIATE) {
392 have_ntlm_or_negotiate = TRUE;
393 auth_started = auth_started
394 || (data->state.negotiate.state != GSS_AUTHNONE);
398 if(have_ntlm_or_negotiate) {
399 if(remaining_bytes < 2000 || auth_started) {
400 /* NTLM/Negotiation has started *OR* there is just a little (<2K)
401 * data left to send, keep on sending.
404 /* rewind data when completely done sending! */
405 if(!conn->bits.authneg) {
406 conn->bits.rewindaftersend = TRUE;
407 infof(data, "Rewind stream after send\n");
413 infof(data, "NTLM/Negotiate send, close instead of sending %"
414 CURL_FORMAT_CURL_OFF_T " bytes\n",
418 /* unused parameters: */
420 (void)remaining_bytes;
427 * Curl_http_perhapsrewind()
429 * If we are doing POST or PUT {
430 * If we have more data to send {
431 * If we are doing NTLM {
432 * Keep sending since we must not disconnect
435 * If there is more than just a little data left to send, close
436 * the current connection by force.
439 * If we have sent any data {
440 * If we don't have track of all the data {
441 * call app to tell it to rewind
444 * rewind internally so that the operation can restart fine
449 static CURLcode http_perhapsrewind(struct connectdata *conn)
451 struct SessionHandle *data = conn->data;
452 struct HTTP *http = data->req.protop;
453 curl_off_t bytessent;
454 curl_off_t expectsend = -1; /* default is unknown */
457 /* If this is still NULL, we have not reach very far and we can safely
458 skip this rewinding stuff */
461 switch(data->set.httpreq) {
469 bytessent = http->writebytecount;
471 if(conn->bits.authneg) {
472 /* This is a state where we are known to be negotiating and we don't send
476 else if(!conn->bits.protoconnstart) {
477 /* HTTP CONNECT in progress: there is no body */
481 /* figure out how much data we are expected to send */
482 switch(data->set.httpreq) {
484 if(data->set.postfieldsize != -1)
485 expectsend = data->set.postfieldsize;
486 else if(data->set.postfields)
487 expectsend = (curl_off_t)strlen(data->set.postfields);
490 if(data->state.infilesize != -1)
491 expectsend = data->state.infilesize;
493 case HTTPREQ_POST_FORM:
494 expectsend = http->postsize;
501 conn->bits.rewindaftersend = FALSE; /* default */
503 if((expectsend == -1) || (expectsend > bytessent)) {
505 /* this is already marked to get closed */
508 if(complete_request(conn, (curl_off_t)(expectsend - bytessent)))
511 /* This is not NTLM or many bytes left to send: close */
512 connclose(conn, "Mid-auth HTTP and much data left to send");
513 data->req.size = 0; /* don't download any more than 0 bytes */
515 /* There still is data left to send, but this connection is marked for
516 closure so we can safely do the rewind right now */
520 /* we rewind now at once since we already sent something */
521 return Curl_readrewind(conn);
527 * Curl_http_auth_act() gets called when all HTTP headers have been received
528 * and it checks what authentication methods that are available and decides
529 * which one (if any) to use. It will set 'newurl' if an auth method was
533 CURLcode Curl_http_auth_act(struct connectdata *conn)
535 struct SessionHandle *data = conn->data;
536 bool pickhost = FALSE;
537 bool pickproxy = FALSE;
538 CURLcode result = CURLE_OK;
540 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
541 /* this is a transient response code, ignore */
544 if(data->state.authproblem)
545 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
547 if(conn->bits.user_passwd &&
548 ((data->req.httpcode == 401) ||
549 (conn->bits.authneg && data->req.httpcode < 300))) {
550 pickhost = pickoneauth(&data->state.authhost);
552 data->state.authproblem = TRUE;
554 if(conn->bits.proxy_user_passwd &&
555 ((data->req.httpcode == 407) ||
556 (conn->bits.authneg && data->req.httpcode < 300))) {
557 pickproxy = pickoneauth(&data->state.authproxy);
559 data->state.authproblem = TRUE;
562 if(pickhost || pickproxy) {
563 /* In case this is GSS auth, the newurl field is already allocated so
564 we must make sure to free it before allocating a new one. As figured
565 out in bug #2284386 */
566 Curl_safefree(data->req.newurl);
567 data->req.newurl = strdup(data->change.url); /* clone URL */
568 if(!data->req.newurl)
569 return CURLE_OUT_OF_MEMORY;
571 if((data->set.httpreq != HTTPREQ_GET) &&
572 (data->set.httpreq != HTTPREQ_HEAD) &&
573 !conn->bits.rewindaftersend) {
574 result = http_perhapsrewind(conn);
580 else if((data->req.httpcode < 300) &&
581 (!data->state.authhost.done) &&
582 conn->bits.authneg) {
583 /* no (known) authentication available,
584 authentication is not "done" yet and
585 no authentication seems to be required and
586 we didn't try HEAD or GET */
587 if((data->set.httpreq != HTTPREQ_GET) &&
588 (data->set.httpreq != HTTPREQ_HEAD)) {
589 data->req.newurl = strdup(data->change.url); /* clone URL */
590 if(!data->req.newurl)
591 return CURLE_OUT_OF_MEMORY;
592 data->state.authhost.done = TRUE;
595 if(http_should_fail(conn)) {
596 failf (data, "The requested URL returned error: %d",
598 result = CURLE_HTTP_RETURNED_ERROR;
606 * Output the correct authentication header depending on the auth type
607 * and whether or not it is to a proxy.
610 output_auth_headers(struct connectdata *conn,
611 struct auth *authstatus,
616 const char *auth = NULL;
617 CURLcode result = CURLE_OK;
618 #if defined(USE_SPNEGO) || !defined(CURL_DISABLE_VERBOSE_STRINGS)
619 struct SessionHandle *data = conn->data;
622 struct negotiatedata *negdata = proxy?
623 &data->state.proxyneg:&data->state.negotiate;
626 #ifdef CURL_DISABLE_CRYPTO_AUTH
632 negdata->state = GSS_AUTHNONE;
633 if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
634 negdata->context && !GSS_ERROR(negdata->status)) {
636 result = Curl_output_negotiate(conn, proxy);
639 authstatus->done = TRUE;
640 negdata->state = GSS_AUTHSENT;
645 if(authstatus->picked == CURLAUTH_NTLM) {
647 result = Curl_output_ntlm(conn, proxy);
653 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
654 if(authstatus->picked == CURLAUTH_NTLM_WB) {
656 result = Curl_output_ntlm_wb(conn, proxy);
662 #ifndef CURL_DISABLE_CRYPTO_AUTH
663 if(authstatus->picked == CURLAUTH_DIGEST) {
665 result = Curl_output_digest(conn,
667 (const unsigned char *)request,
668 (const unsigned char *)path);
674 if(authstatus->picked == CURLAUTH_BASIC) {
676 if((proxy && conn->bits.proxy_user_passwd &&
677 !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
678 (!proxy && conn->bits.user_passwd &&
679 !Curl_checkheaders(conn, "Authorization:"))) {
681 result = http_output_basic(conn, proxy);
685 /* NOTE: this function should set 'done' TRUE, as the other auth
686 functions work that way */
687 authstatus->done = TRUE;
691 infof(data, "%s auth using %s with user '%s'\n",
692 proxy?"Proxy":"Server", auth,
693 proxy?(conn->proxyuser?conn->proxyuser:""):
694 (conn->user?conn->user:""));
695 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
698 authstatus->multi = FALSE;
704 * Curl_http_output_auth() setups the authentication headers for the
705 * host/proxy and the correct authentication
706 * method. conn->data->state.authdone is set to TRUE when authentication is
709 * @param conn all information about the current connection
710 * @param request pointer to the request keyword
711 * @param path pointer to the requested path
712 * @param proxytunnel boolean if this is the request setting up a "proxy
718 Curl_http_output_auth(struct connectdata *conn,
721 bool proxytunnel) /* TRUE if this is the request setting
722 up the proxy tunnel */
724 CURLcode result = CURLE_OK;
725 struct SessionHandle *data = conn->data;
726 struct auth *authhost;
727 struct auth *authproxy;
731 authhost = &data->state.authhost;
732 authproxy = &data->state.authproxy;
734 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
735 conn->bits.user_passwd)
736 /* continue please */ ;
738 authhost->done = TRUE;
739 authproxy->done = TRUE;
740 return CURLE_OK; /* no authentication with no user or password */
743 if(authhost->want && !authhost->picked)
744 /* The app has selected one or more methods, but none has been picked
745 so far by a server round-trip. Then we set the picked one to the
746 want one, and if this is one single bit it'll be used instantly. */
747 authhost->picked = authhost->want;
749 if(authproxy->want && !authproxy->picked)
750 /* The app has selected one or more methods, but none has been picked so
751 far by a proxy round-trip. Then we set the picked one to the want one,
752 and if this is one single bit it'll be used instantly. */
753 authproxy->picked = authproxy->want;
755 #ifndef CURL_DISABLE_PROXY
756 /* Send proxy authentication header if needed */
757 if(conn->bits.httpproxy &&
758 (conn->bits.tunnel_proxy == proxytunnel)) {
759 result = output_auth_headers(conn, authproxy, request, path, TRUE);
766 #endif /* CURL_DISABLE_PROXY */
767 /* we have no proxy so let's pretend we're done authenticating
769 authproxy->done = TRUE;
771 /* To prevent the user+password to get sent to other than the original
772 host due to a location-follow, we do some weirdo checks here */
773 if(!data->state.this_is_a_follow ||
775 !data->state.first_host ||
776 data->set.http_disable_hostname_check_before_authentication ||
777 Curl_raw_equal(data->state.first_host, conn->host.name)) {
778 result = output_auth_headers(conn, authhost, request, path, FALSE);
781 authhost->done = TRUE;
788 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
789 * headers. They are dealt with both in the transfer.c main loop and in the
790 * proxy CONNECT loop.
793 CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
794 const char *auth) /* the first non-space */
797 * This resource requires authentication
799 struct SessionHandle *data = conn->data;
802 struct negotiatedata *negdata = proxy?
803 &data->state.proxyneg:&data->state.negotiate;
805 unsigned long *availp;
809 availp = &data->info.proxyauthavail;
810 authp = &data->state.authproxy;
813 availp = &data->info.httpauthavail;
814 authp = &data->state.authhost;
818 * Here we check if we want the specific single authentication (using ==) and
819 * if we do, we initiate usage of it.
821 * If the provided authentication is wanted as one out of several accepted
822 * types (using &), we OR this authentication type to the authavail
827 * ->picked is first set to the 'want' value (one or more bits) before the
828 * request is sent, and then it is again set _after_ all response 401/407
829 * headers have been received but then only to a single preferred method
836 if(checkprefix("Negotiate", auth)) {
838 *availp |= CURLAUTH_NEGOTIATE;
839 authp->avail |= CURLAUTH_NEGOTIATE;
841 if(authp->picked == CURLAUTH_NEGOTIATE) {
842 if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
843 neg = Curl_input_negotiate(conn, proxy, auth);
845 DEBUGASSERT(!data->req.newurl);
846 data->req.newurl = strdup(data->change.url);
847 if(!data->req.newurl)
848 return CURLE_OUT_OF_MEMORY;
849 data->state.authproblem = FALSE;
850 /* we received a GSS auth token and we dealt with it fine */
851 negdata->state = GSS_AUTHRECV;
854 data->state.authproblem = TRUE;
861 /* NTLM support requires the SSL crypto libs */
862 if(checkprefix("NTLM", auth)) {
863 *availp |= CURLAUTH_NTLM;
864 authp->avail |= CURLAUTH_NTLM;
865 if(authp->picked == CURLAUTH_NTLM ||
866 authp->picked == CURLAUTH_NTLM_WB) {
867 /* NTLM authentication is picked and activated */
868 CURLcode result = Curl_input_ntlm(conn, proxy, auth);
870 data->state.authproblem = FALSE;
871 #ifdef NTLM_WB_ENABLED
872 if(authp->picked == CURLAUTH_NTLM_WB) {
873 *availp &= ~CURLAUTH_NTLM;
874 authp->avail &= ~CURLAUTH_NTLM;
875 *availp |= CURLAUTH_NTLM_WB;
876 authp->avail |= CURLAUTH_NTLM_WB;
878 /* Get the challenge-message which will be passed to
879 * ntlm_auth for generating the type 3 message later */
880 while(*auth && ISSPACE(*auth))
882 if(checkprefix("NTLM", auth)) {
883 auth += strlen("NTLM");
884 while(*auth && ISSPACE(*auth))
887 if((conn->challenge_header = strdup(auth)) == NULL)
888 return CURLE_OUT_OF_MEMORY;
894 infof(data, "Authentication problem. Ignoring this.\n");
895 data->state.authproblem = TRUE;
901 #ifndef CURL_DISABLE_CRYPTO_AUTH
902 if(checkprefix("Digest", auth)) {
903 if((authp->avail & CURLAUTH_DIGEST) != 0) {
904 infof(data, "Ignoring duplicate digest auth header.\n");
908 *availp |= CURLAUTH_DIGEST;
909 authp->avail |= CURLAUTH_DIGEST;
911 /* We call this function on input Digest headers even if Digest
912 * authentication isn't activated yet, as we need to store the
913 * incoming data from this header in case we are gonna use
915 result = Curl_input_digest(conn, proxy, auth);
917 infof(data, "Authentication problem. Ignoring this.\n");
918 data->state.authproblem = TRUE;
924 if(checkprefix("Basic", auth)) {
925 *availp |= CURLAUTH_BASIC;
926 authp->avail |= CURLAUTH_BASIC;
927 if(authp->picked == CURLAUTH_BASIC) {
928 /* We asked for Basic authentication but got a 40X back
929 anyway, which basically means our name+password isn't
931 authp->avail = CURLAUTH_NONE;
932 infof(data, "Authentication problem. Ignoring this.\n");
933 data->state.authproblem = TRUE;
937 /* there may be multiple methods on one line, so keep reading */
938 while(*auth && *auth != ',') /* read up to the next comma */
940 if(*auth == ',') /* if we're on a comma, skip it */
942 while(*auth && ISSPACE(*auth))
949 * http_should_fail() determines whether an HTTP response has gotten us
950 * into an error state or not.
952 * @param conn all information about the current connection
954 * @retval 0 communications should continue
956 * @retval 1 communications should not continue
958 static int http_should_fail(struct connectdata *conn)
960 struct SessionHandle *data;
967 httpcode = data->req.httpcode;
970 ** If we haven't been asked to fail on error,
973 if(!data->set.http_fail_on_error)
977 ** Any code < 400 is never terminal.
983 ** Any code >= 400 that's not 401 or 407 is always
986 if((httpcode != 401) &&
991 ** All we have left to deal with is 401 and 407
993 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
996 ** Examine the current authentication state to see if this
997 ** is an error. The idea is for this function to get
998 ** called after processing all the headers in a response
999 ** message. So, if we've been to asked to authenticate a
1000 ** particular stage, and we've done it, we're OK. But, if
1001 ** we're already completely authenticated, it's not OK to
1002 ** get another 401 or 407.
1004 ** It is possible for authentication to go stale such that
1005 ** the client needs to reauthenticate. Once that info is
1006 ** available, use it here.
1010 ** Either we're not authenticating, or we're supposed to
1011 ** be authenticating something else. This is an error.
1013 if((httpcode == 401) && !conn->bits.user_passwd)
1015 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
1018 return data->state.authproblem;
1022 * readmoredata() is a "fread() emulation" to provide POST and/or request
1023 * data. It is used when a huge POST is to be made and the entire chunk wasn't
1024 * sent in the first send(). This function will then be called from the
1025 * transfer.c loop when more data is to be sent to the peer.
1027 * Returns the amount of bytes it filled the buffer with.
1029 static size_t readmoredata(char *buffer,
1034 struct connectdata *conn = (struct connectdata *)userp;
1035 struct HTTP *http = conn->data->req.protop;
1036 size_t fullsize = size * nitems;
1038 if(0 == http->postsize)
1039 /* nothing to return */
1042 /* make sure that a HTTP request is never sent away chunked! */
1043 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
1045 if(http->postsize <= (curl_off_t)fullsize) {
1046 memcpy(buffer, http->postdata, (size_t)http->postsize);
1047 fullsize = (size_t)http->postsize;
1049 if(http->backup.postsize) {
1050 /* move backup data into focus and continue on that */
1051 http->postdata = http->backup.postdata;
1052 http->postsize = http->backup.postsize;
1053 conn->fread_func = http->backup.fread_func;
1054 conn->fread_in = http->backup.fread_in;
1056 http->sending++; /* move one step up */
1058 http->backup.postsize=0;
1066 memcpy(buffer, http->postdata, fullsize);
1067 http->postdata += fullsize;
1068 http->postsize -= fullsize;
1073 /* ------------------------------------------------------------------------- */
1074 /* add_buffer functions */
1077 * Curl_add_buffer_init() sets up and returns a fine buffer struct
1079 Curl_send_buffer *Curl_add_buffer_init(void)
1081 return calloc(1, sizeof(Curl_send_buffer));
1085 * Curl_add_buffer_send() sends a header buffer and frees all associated
1086 * memory. Body data may be appended to the header data if desired.
1090 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
1091 struct connectdata *conn,
1093 /* add the number of sent bytes to this
1095 long *bytes_written,
1097 /* how much of the buffer contains body data */
1098 size_t included_body_bytes,
1106 struct HTTP *http = conn->data->req.protop;
1108 curl_socket_t sockfd;
1111 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1113 sockfd = conn->sock[socketindex];
1115 /* The looping below is required since we use non-blocking sockets, but due
1116 to the circumstances we will just loop and try again and again etc */
1119 size = in->size_used;
1121 headersize = size - included_body_bytes; /* the initial part that isn't body
1124 DEBUGASSERT(size > included_body_bytes);
1126 result = Curl_convert_to_network(conn->data, ptr, headersize);
1127 /* Curl_convert_to_network calls failf if unsuccessful */
1129 /* conversion failed, free memory and return to the caller */
1137 if(conn->handler->flags & PROTOPT_SSL) {
1138 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1139 when we speak HTTPS, as if only a fraction of it is sent now, this data
1140 needs to fit into the normal read-callback buffer later on and that
1141 buffer is using this size.
1144 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1146 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1147 library when we attempt to re-send this buffer. Sending the same data
1148 is not enough, we must use the exact same address. For this reason, we
1149 must copy the data to the uploadbuffer first, since that is the buffer
1150 we will be using if this send is retried later.
1152 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1153 ptr = conn->data->state.uploadbuffer;
1158 result = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1162 * Note that we may not send the entire chunk at once, and we have a set
1163 * number of data bytes at the end of the big buffer (out of which we may
1164 * only send away a part).
1166 /* how much of the header that was sent */
1167 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1168 size_t bodylen = amount - headlen;
1170 if(conn->data->set.verbose) {
1171 /* this data _may_ contain binary stuff */
1172 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1174 /* there was body data sent beyond the initial header part, pass that
1175 on to the debug callback too */
1176 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1177 ptr+headlen, bodylen, conn);
1181 /* since we sent a piece of the body here, up the byte counter for it
1183 http->writebytecount += bodylen;
1185 /* 'amount' can never be a very large value here so typecasting it so a
1186 signed 31 bit value should not cause problems even if ssize_t is
1188 *bytes_written += (long)amount;
1191 if((size_t)amount != size) {
1192 /* The whole request could not be sent in one system call. We must
1193 queue it up and send it later when we get the chance. We must not
1194 loop here and wait until it might work again. */
1198 ptr = in->buffer + amount;
1200 /* backup the currently set pointers */
1201 http->backup.fread_func = conn->fread_func;
1202 http->backup.fread_in = conn->fread_in;
1203 http->backup.postdata = http->postdata;
1204 http->backup.postsize = http->postsize;
1206 /* set the new pointers for the request-sending */
1207 conn->fread_func = (curl_read_callback)readmoredata;
1208 conn->fread_in = (void *)conn;
1209 http->postdata = ptr;
1210 http->postsize = (curl_off_t)size;
1212 http->send_buffer = in;
1213 http->sending = HTTPSEND_REQUEST;
1217 http->sending = HTTPSEND_BODY;
1218 /* the full buffer was sent, clean up and return */
1221 if((size_t)amount != size)
1222 /* We have no continue-send mechanism now, fail. This can only happen
1223 when this function is used from the CONNECT sending function. We
1224 currently (stupidly) assume that the whole request is always sent
1225 away in the first single chunk.
1229 return CURLE_SEND_ERROR;
1231 conn->writechannel_inuse = FALSE;
1243 * add_bufferf() add the formatted input to the buffer.
1245 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1250 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1254 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1258 /* If we failed, we cleanup the whole buffer and return error */
1262 return CURLE_OUT_OF_MEMORY;
1266 * add_buffer() appends a memory chunk to the existing buffer
1268 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1273 if(~size < in->size_used) {
1274 /* If resulting used size of send buffer would wrap size_t, cleanup
1275 the whole buffer and return error. Otherwise the required buffer
1276 size will fit into a single allocatable memory chunk */
1277 Curl_safefree(in->buffer);
1279 return CURLE_OUT_OF_MEMORY;
1283 ((in->size_used + size) > (in->size_max - 1))) {
1285 /* If current buffer size isn't enough to hold the result, use a
1286 buffer size that doubles the required size. If this new size
1287 would wrap size_t, then just use the largest possible one */
1289 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1290 (~(size*2) < (in->size_used*2)))
1291 new_size = (size_t)-1;
1293 new_size = (in->size_used+size)*2;
1296 /* we have a buffer, enlarge the existing one */
1297 new_rb = realloc(in->buffer, new_size);
1299 /* create a new buffer */
1300 new_rb = malloc(new_size);
1303 /* If we failed, we cleanup the whole buffer and return error */
1304 Curl_safefree(in->buffer);
1306 return CURLE_OUT_OF_MEMORY;
1309 in->buffer = new_rb;
1310 in->size_max = new_size;
1312 memcpy(&in->buffer[in->size_used], inptr, size);
1314 in->size_used += size;
1319 /* end of the add_buffer functions */
1320 /* ------------------------------------------------------------------------- */
1325 * Curl_compareheader()
1327 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1328 * Pass headers WITH the colon.
1331 Curl_compareheader(const char *headerline, /* line to check */
1332 const char *header, /* header keyword _with_ colon */
1333 const char *content) /* content string to find */
1335 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1336 * by a colon (":") and the field value. Field names are case-insensitive.
1337 * The field value MAY be preceded by any amount of LWS, though a single SP
1340 size_t hlen = strlen(header);
1346 if(!Curl_raw_nequal(headerline, header, hlen))
1347 return FALSE; /* doesn't start with header */
1349 /* pass the header */
1350 start = &headerline[hlen];
1352 /* pass all white spaces */
1353 while(*start && ISSPACE(*start))
1356 /* find the end of the header line */
1357 end = strchr(start, '\r'); /* lines end with CRLF */
1359 /* in case there's a non-standard compliant line here */
1360 end = strchr(start, '\n');
1363 /* hm, there's no line ending here, use the zero byte! */
1364 end = strchr(start, '\0');
1367 len = end-start; /* length of the content part of the input line */
1368 clen = strlen(content); /* length of the word to find */
1370 /* find the content string in the rest of the line */
1371 for(;len>=clen;len--, start++) {
1372 if(Curl_raw_nequal(start, content, clen))
1373 return TRUE; /* match! */
1376 return FALSE; /* no match */
1380 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1381 * the generic Curl_connect().
1383 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1387 /* We default to persistent connections. We set this already in this connect
1388 function to make the re-use checks properly be able to check this bit. */
1389 connkeep(conn, "HTTP default");
1391 /* the CONNECT procedure might not have been completed */
1392 result = Curl_proxy_connect(conn);
1396 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1397 /* nothing else to do except wait right now - we're not done here. */
1400 if(conn->given->flags & PROTOPT_SSL) {
1401 /* perform SSL initialization */
1402 result = https_connecting(conn, done);
1412 /* this returns the socket to wait for in the DO and DOING state for the multi
1413 interface and then we're always _sending_ a request and thus we wait for
1414 the single socket to become writable only */
1415 static int http_getsock_do(struct connectdata *conn,
1416 curl_socket_t *socks,
1420 (void)numsocks; /* unused, we trust it to be at least 1 */
1421 socks[0] = conn->sock[FIRSTSOCKET];
1422 return GETSOCK_WRITESOCK(0);
1426 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1429 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1431 /* perform SSL initialization for this socket */
1432 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1434 connclose(conn, "Failed HTTPS connection");
1440 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
1441 defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
1442 /* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
1443 It should be made to query the generic SSL layer instead. */
1444 static int https_getsock(struct connectdata *conn,
1445 curl_socket_t *socks,
1448 if(conn->handler->flags & PROTOPT_SSL) {
1449 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1452 return GETSOCK_BLANK;
1454 if(connssl->connecting_state == ssl_connect_2_writing) {
1456 socks[0] = conn->sock[FIRSTSOCKET];
1457 return GETSOCK_WRITESOCK(0);
1459 else if(connssl->connecting_state == ssl_connect_2_reading) {
1461 socks[0] = conn->sock[FIRSTSOCKET];
1462 return GETSOCK_READSOCK(0);
1469 static int https_getsock(struct connectdata *conn,
1470 curl_socket_t *socks,
1476 return GETSOCK_BLANK;
1478 #endif /* USE_SSL */
1479 #endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
1482 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1483 * has been performed.
1486 CURLcode Curl_http_done(struct connectdata *conn,
1487 CURLcode status, bool premature)
1489 struct SessionHandle *data = conn->data;
1490 struct HTTP *http =data->req.protop;
1492 Curl_unencode_cleanup(conn);
1495 if(data->state.proxyneg.state == GSS_AUTHSENT ||
1496 data->state.negotiate.state == GSS_AUTHSENT) {
1497 /* add forbid re-use if http-code != 401 as a WA
1498 * only needed for 401 that failed handling
1499 * otherwie state will be RECV with current code */
1500 if((data->req.httpcode != 401) && (data->req.httpcode != 407))
1501 connclose(conn, "Negotiate transfer completed");
1502 Curl_cleanup_negotiate(data);
1506 /* set the proper values (possibly modified on POST) */
1507 conn->fread_func = data->set.fread_func; /* restore */
1508 conn->fread_in = data->set.in; /* restore */
1509 conn->seek_func = data->set.seek_func; /* restore */
1510 conn->seek_client = data->set.seek_client; /* restore */
1515 if(http->send_buffer) {
1516 Curl_send_buffer *buff = http->send_buffer;
1520 http->send_buffer = NULL; /* clear the pointer */
1523 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1524 data->req.bytecount = http->readbytecount + http->writebytecount;
1526 Curl_formclean(&http->sendit); /* Now free that whole lot */
1528 /* a file being uploaded was left opened, close it! */
1529 fclose(http->form.fp);
1530 http->form.fp = NULL;
1533 else if(HTTPREQ_PUT == data->set.httpreq)
1534 data->req.bytecount = http->readbytecount + http->writebytecount;
1539 if(!premature && /* this check is pointless when DONE is called before the
1540 entire operation is complete */
1541 !conn->bits.retry &&
1542 !data->set.connect_only &&
1543 ((http->readbytecount +
1544 data->req.headerbytecount -
1545 data->req.deductheadercount)) <= 0) {
1546 /* If this connection isn't simply closed to be retried, AND nothing was
1547 read from the HTTP server (that counts), this can't be right so we
1548 return an error here */
1549 failf(data, "Empty reply from server");
1550 return CURLE_GOT_NOTHING;
1558 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1559 * to avoid it include:
1561 * - if the user specifically requested HTTP 1.0
1562 * - if the server we are connected to only supports 1.0
1563 * - if any server previously contacted to handle this request only supports
1566 static bool use_http_1_1plus(const struct SessionHandle *data,
1567 const struct connectdata *conn)
1569 return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
1570 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1571 ((conn->httpversion == 11) ||
1572 ((conn->httpversion != 10) &&
1573 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1576 /* check and possibly add an Expect: header */
1577 static CURLcode expect100(struct SessionHandle *data,
1578 struct connectdata *conn,
1579 Curl_send_buffer *req_buffer)
1581 CURLcode result = CURLE_OK;
1583 data->state.expect100header = FALSE; /* default to false unless it is set
1585 if(use_http_1_1plus(data, conn)) {
1586 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1587 100-continue to the headers which actually speeds up post operations
1588 (as there is one packet coming back from the web server) */
1589 ptr = Curl_checkheaders(conn, "Expect:");
1591 data->state.expect100header =
1592 Curl_compareheader(ptr, "Expect:", "100-continue");
1595 result = Curl_add_bufferf(req_buffer,
1596 "Expect: 100-continue\r\n");
1598 data->state.expect100header = TRUE;
1605 HEADER_SERVER, /* direct to server */
1606 HEADER_PROXY, /* regular request to proxy */
1607 HEADER_CONNECT /* sending CONNECT to a proxy */
1610 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1612 Curl_send_buffer *req_buffer)
1615 struct curl_slist *h[2];
1616 struct curl_slist *headers;
1617 int numlists=1; /* by default */
1618 struct SessionHandle *data = conn->data;
1621 enum proxy_use proxy;
1624 proxy = HEADER_CONNECT;
1626 proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
1627 HEADER_PROXY:HEADER_SERVER;
1631 h[0] = data->set.headers;
1634 h[0] = data->set.headers;
1635 if(data->set.sep_headers) {
1636 h[1] = data->set.proxyheaders;
1640 case HEADER_CONNECT:
1641 if(data->set.sep_headers)
1642 h[0] = data->set.proxyheaders;
1644 h[0] = data->set.headers;
1648 /* loop through one or two lists */
1649 for(i=0; i < numlists; i++) {
1653 ptr = strchr(headers->data, ':');
1655 /* we require a colon for this to be a true header */
1657 ptr++; /* pass the colon */
1658 while(*ptr && ISSPACE(*ptr))
1662 /* only send this if the contents was non-blank */
1664 if(conn->allocptr.host &&
1665 /* a Host: header was sent already, don't pass on any custom Host:
1666 header as that will produce *two* in the same request! */
1667 checkprefix("Host:", headers->data))
1669 else if(data->set.httpreq == HTTPREQ_POST_FORM &&
1670 /* this header (extended by formdata.c) is sent later */
1671 checkprefix("Content-Type:", headers->data))
1673 else if(conn->bits.authneg &&
1674 /* while doing auth neg, don't allow the custom length since
1675 we will force length zero then */
1676 checkprefix("Content-Length", headers->data))
1678 else if(conn->allocptr.te &&
1679 /* when asking for Transfer-Encoding, don't pass on a custom
1681 checkprefix("Connection", headers->data))
1684 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1692 ptr = strchr(headers->data, ';');
1695 ptr++; /* pass the semicolon */
1696 while(*ptr && ISSPACE(*ptr))
1700 /* this may be used for something else in the future */
1703 if(*(--ptr) == ';') {
1706 /* send no-value custom header if terminated by semicolon */
1708 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1716 headers = headers->next;
1722 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1723 Curl_send_buffer *req_buffer)
1725 const struct tm *tm;
1726 char *buf = data->state.buffer;
1728 CURLcode result = Curl_gmtime(data->set.timevalue, &keeptime);
1730 failf(data, "Invalid TIMEVALUE");
1735 /* The If-Modified-Since header family should have their times set in
1736 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1737 * represented in Greenwich Mean Time (GMT), without exception. For the
1738 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1739 * Time)." (see page 20 of RFC2616).
1742 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1743 snprintf(buf, BUFSIZE-1,
1744 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1745 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1747 Curl_month[tm->tm_mon],
1753 switch(data->set.timecondition) {
1754 case CURL_TIMECOND_IFMODSINCE:
1756 result = Curl_add_bufferf(req_buffer,
1757 "If-Modified-Since: %s\r\n", buf);
1759 case CURL_TIMECOND_IFUNMODSINCE:
1760 result = Curl_add_bufferf(req_buffer,
1761 "If-Unmodified-Since: %s\r\n", buf);
1763 case CURL_TIMECOND_LASTMOD:
1764 result = Curl_add_bufferf(req_buffer,
1765 "Last-Modified: %s\r\n", buf);
1773 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1774 * request is to be performed. This creates and sends a properly constructed
1777 CURLcode Curl_http(struct connectdata *conn, bool *done)
1779 struct SessionHandle *data = conn->data;
1780 CURLcode result = CURLE_OK;
1782 const char *ppath = data->state.path;
1783 bool paste_ftp_userpwd = FALSE;
1784 char ftp_typecode[sizeof("/;type=?")] = "";
1785 const char *host = conn->host.name;
1786 const char *te = ""; /* transfer-encoding */
1788 const char *request;
1789 Curl_HttpReq httpreq = data->set.httpreq;
1790 #if !defined(CURL_DISABLE_COOKIES)
1791 char *addcookies = NULL;
1793 curl_off_t included_body = 0;
1794 const char *httpstring;
1795 Curl_send_buffer *req_buffer;
1796 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1797 int seekerr = CURL_SEEKFUNC_OK;
1799 /* Always consider the DO phase done after this function call, even if there
1800 may be parts of the request that is not yet sent, since we can deal with
1801 the rest of the request in the PERFORM phase. */
1804 if(conn->httpversion < 20) { /* unless the connection is re-used and already
1806 switch(conn->negnpn) {
1808 result = Curl_http2_init(conn);
1812 result = Curl_http2_setup(conn);
1816 result = Curl_http2_switched(conn, NULL, 0);
1821 /* continue with HTTP/1.1 when explicitly requested */
1824 /* and as fallback */
1829 /* prepare for a http2 request */
1830 result = Curl_http2_setup(conn);
1835 http = data->req.protop;
1837 if(!data->state.this_is_a_follow) {
1838 /* this is not a followed location, get the original host name */
1839 if(data->state.first_host)
1840 /* Free to avoid leaking memory on multiple requests*/
1841 free(data->state.first_host);
1843 data->state.first_host = strdup(conn->host.name);
1844 if(!data->state.first_host)
1845 return CURLE_OUT_OF_MEMORY;
1847 http->writebytecount = http->readbytecount = 0;
1849 if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
1851 httpreq = HTTPREQ_PUT;
1854 /* Now set the 'request' pointer to the proper request string */
1855 if(data->set.str[STRING_CUSTOMREQUEST])
1856 request = data->set.str[STRING_CUSTOMREQUEST];
1858 if(data->set.opt_no_body)
1861 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1864 case HTTPREQ_POST_FORM:
1870 default: /* this should never happen */
1881 /* The User-Agent string might have been allocated in url.c already, because
1882 it might have been used in the proxy connect, but if we have got a header
1883 with the user-agent string specified, we erase the previously made string
1885 if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
1886 free(conn->allocptr.uagent);
1887 conn->allocptr.uagent=NULL;
1890 /* setup the authentication headers */
1891 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1895 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1896 (httpreq != HTTPREQ_GET) &&
1897 (httpreq != HTTPREQ_HEAD)) {
1898 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1899 with content-length zero as a "probe". */
1900 conn->bits.authneg = TRUE;
1903 conn->bits.authneg = FALSE;
1905 Curl_safefree(conn->allocptr.ref);
1906 if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
1907 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1908 if(!conn->allocptr.ref)
1909 return CURLE_OUT_OF_MEMORY;
1912 conn->allocptr.ref = NULL;
1914 #if !defined(CURL_DISABLE_COOKIES)
1915 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
1916 addcookies = data->set.str[STRING_COOKIE];
1919 if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
1920 data->set.str[STRING_ENCODING]) {
1921 Curl_safefree(conn->allocptr.accept_encoding);
1922 conn->allocptr.accept_encoding =
1923 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1924 if(!conn->allocptr.accept_encoding)
1925 return CURLE_OUT_OF_MEMORY;
1929 /* we only consider transfer-encoding magic if libz support is built-in */
1931 if(!Curl_checkheaders(conn, "TE:") &&
1932 data->set.http_transfer_encoding) {
1933 /* When we are to insert a TE: header in the request, we must also insert
1934 TE in a Connection: header, so we need to merge the custom provided
1935 Connection: header and prevent the original to get sent. Note that if
1936 the user has inserted his/hers own TE: header we don't do this magic
1937 but then assume that the user will handle it all! */
1938 char *cptr = Curl_checkheaders(conn, "Connection:");
1939 #define TE_HEADER "TE: gzip\r\n"
1941 Curl_safefree(conn->allocptr.te);
1943 /* Create the (updated) Connection: header */
1944 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1945 strdup("Connection: TE\r\n" TE_HEADER);
1947 if(!conn->allocptr.te)
1948 return CURLE_OUT_OF_MEMORY;
1952 if(conn->httpversion == 20)
1953 /* In HTTP2 forbids Transfer-Encoding: chunked */
1956 ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
1958 /* Some kind of TE is requested, check if 'chunked' is chosen */
1959 data->req.upload_chunky =
1960 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1963 if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
1965 (data->state.infilesize == -1)) {
1966 if(conn->bits.authneg)
1967 /* don't enable chunked during auth neg */
1969 else if(use_http_1_1plus(data, conn)) {
1970 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1971 data->req.upload_chunky = TRUE;
1974 failf(data, "Chunky upload is not supported by HTTP 1.0");
1975 return CURLE_UPLOAD_FAILED;
1979 /* else, no chunky upload */
1980 data->req.upload_chunky = FALSE;
1983 if(data->req.upload_chunky)
1984 te = "Transfer-Encoding: chunked\r\n";
1988 Curl_safefree(conn->allocptr.host);
1990 ptr = Curl_checkheaders(conn, "Host:");
1991 if(ptr && (!data->state.this_is_a_follow ||
1992 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1993 #if !defined(CURL_DISABLE_COOKIES)
1994 /* If we have a given custom Host: header, we extract the host name in
1995 order to possibly use it for cookie reasons later on. We only allow the
1996 custom Host: header if this is NOT a redirect, as setting Host: in the
1997 redirected request is being out on thin ice. Except if the host name
1998 is the same as the first one! */
1999 char *cookiehost = Curl_copy_header_value(ptr);
2001 return CURLE_OUT_OF_MEMORY;
2003 /* ignore empty data */
2006 /* If the host begins with '[', we start searching for the port after
2007 the bracket has been closed */
2008 int startsearch = 0;
2009 if(*cookiehost == '[') {
2010 char *closingbracket;
2011 /* since the 'cookiehost' is an allocated memory area that will be
2012 freed later we cannot simply increment the pointer */
2013 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
2014 closingbracket = strchr(cookiehost, ']');
2016 *closingbracket = 0;
2019 char *colon = strchr(cookiehost + startsearch, ':');
2021 *colon = 0; /* The host must not include an embedded port number */
2023 Curl_safefree(conn->allocptr.cookiehost);
2024 conn->allocptr.cookiehost = cookiehost;
2028 conn->allocptr.host = NULL;
2031 /* When building Host: headers, we must put the host name within
2032 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
2034 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
2035 (conn->remote_port == PORT_HTTPS)) ||
2036 ((conn->given->protocol&CURLPROTO_HTTP) &&
2037 (conn->remote_port == PORT_HTTP)) )
2038 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
2039 the port number in the host string */
2040 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2041 conn->bits.ipv6_ip?"[":"",
2043 conn->bits.ipv6_ip?"]":"");
2045 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
2046 conn->bits.ipv6_ip?"[":"",
2048 conn->bits.ipv6_ip?"]":"",
2051 if(!conn->allocptr.host)
2052 /* without Host: we can't make a nice request */
2053 return CURLE_OUT_OF_MEMORY;
2056 #ifndef CURL_DISABLE_PROXY
2057 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2058 /* Using a proxy but does not tunnel through it */
2060 /* The path sent to the proxy is in fact the entire URL. But if the remote
2061 host is a IDN-name, we must make sure that the request we produce only
2062 uses the encoded host name! */
2063 if(conn->host.dispname != conn->host.name) {
2064 char *url = data->change.url;
2065 ptr = strstr(url, conn->host.dispname);
2067 /* This is where the display name starts in the URL, now replace this
2068 part with the encoded name. TODO: This method of replacing the host
2069 name is rather crude as I believe there's a slight risk that the
2070 user has entered a user name or password that contain the host name
2072 size_t currlen = strlen(conn->host.dispname);
2073 size_t newlen = strlen(conn->host.name);
2074 size_t urllen = strlen(url);
2078 newurl = malloc(urllen + newlen - currlen + 1);
2080 /* copy the part before the host name */
2081 memcpy(newurl, url, ptr - url);
2082 /* append the new host name instead of the old */
2083 memcpy(newurl + (ptr - url), conn->host.name, newlen);
2084 /* append the piece after the host name */
2085 memcpy(newurl + newlen + (ptr - url),
2086 ptr + currlen, /* copy the trailing zero byte too */
2087 urllen - (ptr-url) - currlen + 1);
2088 if(data->change.url_alloc) {
2089 Curl_safefree(data->change.url);
2090 data->change.url_alloc = FALSE;
2092 data->change.url = newurl;
2093 data->change.url_alloc = TRUE;
2096 return CURLE_OUT_OF_MEMORY;
2099 ppath = data->change.url;
2100 if(checkprefix("ftp://", ppath)) {
2101 if(data->set.proxy_transfer_mode) {
2102 /* when doing ftp, append ;type=<a|i> if not present */
2103 char *type = strstr(ppath, ";type=");
2104 if(type && type[6] && type[7] == 0) {
2105 switch (Curl_raw_toupper(type[6])) {
2115 char *p = ftp_typecode;
2116 /* avoid sending invalid URLs like ftp://example.com;type=i if the
2117 * user specified ftp://example.com without the slash */
2118 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
2121 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
2122 data->set.prefer_ascii ? 'a' : 'i');
2125 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
2126 paste_ftp_userpwd = TRUE;
2129 #endif /* CURL_DISABLE_PROXY */
2131 if(HTTPREQ_POST_FORM == httpreq) {
2132 /* we must build the whole post sequence first, so that we have a size of
2133 the whole transfer before we start to send it */
2134 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
2135 Curl_checkheaders(conn, "Content-Type:"),
2141 http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
2143 if(( (HTTPREQ_POST == httpreq) ||
2144 (HTTPREQ_POST_FORM == httpreq) ||
2145 (HTTPREQ_PUT == httpreq) ) &&
2146 data->state.resume_from) {
2147 /**********************************************************************
2148 * Resuming upload in HTTP means that we PUT or POST and that we have
2149 * got a resume_from value set. The resume value has already created
2150 * a Range: header that will be passed along. We need to "fast forward"
2151 * the file the given number of bytes and decrease the assume upload
2152 * file size before we continue this venture in the dark lands of HTTP.
2153 *********************************************************************/
2155 if(data->state.resume_from < 0 ) {
2157 * This is meant to get the size of the present remote-file by itself.
2158 * We don't support this now. Bail out!
2160 data->state.resume_from = 0;
2163 if(data->state.resume_from && !data->state.this_is_a_follow) {
2164 /* do we still game? */
2166 /* Now, let's read off the proper amount of bytes from the
2168 if(conn->seek_func) {
2169 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2173 if(seekerr != CURL_SEEKFUNC_OK) {
2174 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2175 failf(data, "Could not seek stream");
2176 return CURLE_READ_ERROR;
2178 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2180 curl_off_t passed=0;
2182 size_t readthisamountnow =
2183 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2184 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2186 size_t actuallyread =
2187 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2190 passed += actuallyread;
2191 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2192 /* this checks for greater-than only to make sure that the
2193 CURL_READFUNC_ABORT return code still aborts */
2194 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2195 " bytes from the input", passed);
2196 return CURLE_READ_ERROR;
2198 } while(passed < data->state.resume_from);
2202 /* now, decrease the size of the read */
2203 if(data->state.infilesize>0) {
2204 data->state.infilesize -= data->state.resume_from;
2206 if(data->state.infilesize <= 0) {
2207 failf(data, "File already completely uploaded");
2208 return CURLE_PARTIAL_FILE;
2211 /* we've passed, proceed as normal */
2214 if(data->state.use_range) {
2216 * A range is selected. We use different headers whether we're downloading
2217 * or uploading and we always let customized headers override our internal
2218 * ones if any such are specified.
2220 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2221 !Curl_checkheaders(conn, "Range:")) {
2222 /* if a line like this was already allocated, free the previous one */
2223 if(conn->allocptr.rangeline)
2224 free(conn->allocptr.rangeline);
2225 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2228 else if((httpreq != HTTPREQ_GET) &&
2229 !Curl_checkheaders(conn, "Content-Range:")) {
2231 /* if a line like this was already allocated, free the previous one */
2232 if(conn->allocptr.rangeline)
2233 free(conn->allocptr.rangeline);
2235 if(data->set.set_resume_from < 0) {
2236 /* Upload resume was asked for, but we don't know the size of the
2237 remote part so we tell the server (and act accordingly) that we
2238 upload the whole file (again) */
2239 conn->allocptr.rangeline =
2240 aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
2241 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2242 data->state.infilesize - 1, data->state.infilesize);
2245 else if(data->state.resume_from) {
2246 /* This is because "resume" was selected */
2247 curl_off_t total_expected_size=
2248 data->state.resume_from + data->state.infilesize;
2249 conn->allocptr.rangeline =
2250 aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
2251 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2252 data->state.range, total_expected_size-1,
2253 total_expected_size);
2256 /* Range was selected and then we just pass the incoming range and
2257 append total size */
2258 conn->allocptr.rangeline =
2259 aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2260 data->state.range, data->state.infilesize);
2262 if(!conn->allocptr.rangeline)
2263 return CURLE_OUT_OF_MEMORY;
2267 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2269 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
2271 /* initialize a dynamic send-buffer */
2272 req_buffer = Curl_add_buffer_init();
2275 return CURLE_OUT_OF_MEMORY;
2277 /* add the main request stuff */
2278 /* GET/HEAD/POST/PUT */
2279 result = Curl_add_bufferf(req_buffer, "%s ", request);
2284 if(paste_ftp_userpwd)
2285 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2286 conn->user, conn->passwd,
2287 ppath + sizeof("ftp://") - 1);
2289 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2294 Curl_add_bufferf(req_buffer,
2295 "%s" /* ftp typecode (;type=x) */
2296 " HTTP/%s\r\n" /* HTTP version */
2297 "%s" /* proxyuserpwd */
2300 "%s" /* user agent */
2304 "%s" /* accept-encoding */
2306 "%s" /* Proxy-Connection */
2307 "%s",/* transfer-encoding */
2311 conn->allocptr.proxyuserpwd?
2312 conn->allocptr.proxyuserpwd:"",
2313 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2314 (data->state.use_range && conn->allocptr.rangeline)?
2315 conn->allocptr.rangeline:"",
2316 (data->set.str[STRING_USERAGENT] &&
2317 *data->set.str[STRING_USERAGENT] &&
2318 conn->allocptr.uagent)?
2319 conn->allocptr.uagent:"",
2320 (conn->allocptr.host?conn->allocptr.host:""),
2321 http->p_accept?http->p_accept:"",
2322 conn->allocptr.te?conn->allocptr.te:"",
2323 (data->set.str[STRING_ENCODING] &&
2324 *data->set.str[STRING_ENCODING] &&
2325 conn->allocptr.accept_encoding)?
2326 conn->allocptr.accept_encoding:"",
2327 (data->change.referer && conn->allocptr.ref)?
2328 conn->allocptr.ref:"" /* Referer: <data> */,
2329 (conn->bits.httpproxy &&
2330 !conn->bits.tunnel_proxy &&
2331 !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
2332 "Proxy-Connection: Keep-Alive\r\n":"",
2337 * Free userpwd for Negotiate/NTLM. Cannot reuse as it is associated with
2338 * the connection and shouldn't be repeated over it either.
2340 switch (data->state.authhost.picked) {
2341 case CURLAUTH_NEGOTIATE:
2343 case CURLAUTH_NTLM_WB:
2344 Curl_safefree(conn->allocptr.userpwd);
2349 * Same for proxyuserpwd
2351 switch (data->state.authproxy.picked) {
2352 case CURLAUTH_NEGOTIATE:
2354 case CURLAUTH_NTLM_WB:
2355 Curl_safefree(conn->allocptr.proxyuserpwd);
2362 if(!(conn->handler->flags&PROTOPT_SSL) &&
2363 conn->httpversion != 20 &&
2364 (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
2365 /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
2367 result = Curl_http2_request_upgrade(req_buffer, conn);
2372 #if !defined(CURL_DISABLE_COOKIES)
2373 if(data->cookies || addcookies) {
2374 struct Cookie *co=NULL; /* no cookies from start */
2378 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2379 co = Curl_cookie_getlist(data->cookies,
2380 conn->allocptr.cookiehost?
2381 conn->allocptr.cookiehost:host,
2383 (conn->handler->protocol&CURLPROTO_HTTPS)?
2385 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2388 struct Cookie *store=co;
2389 /* now loop through all cookies that matched */
2393 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2397 result = Curl_add_bufferf(req_buffer,
2398 "%s%s=%s", count?"; ":"",
2399 co->name, co->value);
2404 co = co->next; /* next cookie please */
2406 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2408 if(addcookies && !result) {
2410 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2412 result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"",
2417 if(count && !result)
2418 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2425 if(data->set.timecondition) {
2426 result = Curl_add_timecondition(data, req_buffer);
2431 result = Curl_add_custom_headers(conn, FALSE, req_buffer);
2435 http->postdata = NULL; /* nothing to post at this point */
2436 Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
2438 /* If 'authdone' is FALSE, we must not set the write socket index to the
2439 Curl_transfer() call below, as we're not ready to actually upload any
2444 case HTTPREQ_POST_FORM:
2445 if(!http->sendit || conn->bits.authneg) {
2446 /* nothing to post! */
2447 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2451 result = Curl_add_buffer_send(req_buffer, conn,
2452 &data->info.request_size, 0, FIRSTSOCKET);
2454 failf(data, "Failed sending POST request");
2456 /* setup variables for the upcoming transfer */
2457 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2462 if(Curl_FormInit(&http->form, http->sendit)) {
2463 failf(data, "Internal HTTP POST error!");
2464 return CURLE_HTTP_POST_ERROR;
2467 /* Get the currently set callback function pointer and store that in the
2468 form struct since we might want the actual user-provided callback later
2469 on. The conn->fread_func pointer itself will be changed for the
2470 multipart case to the function that returns a multipart formatted
2472 http->form.fread_func = conn->fread_func;
2474 /* Set the read function to read from the generated form data */
2475 conn->fread_func = (curl_read_callback)Curl_FormReader;
2476 conn->fread_in = &http->form;
2478 http->sending = HTTPSEND_BODY;
2480 if(!data->req.upload_chunky &&
2481 !Curl_checkheaders(conn, "Content-Length:")) {
2482 /* only add Content-Length if not uploading chunked */
2483 result = Curl_add_bufferf(req_buffer,
2484 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2485 "\r\n", http->postsize);
2490 result = expect100(data, conn, req_buffer);
2496 /* Get Content-Type: line from Curl_formpostheader.
2499 size_t linelength=0;
2500 contentType = Curl_formpostheader((void *)&http->form,
2503 failf(data, "Could not get Content-Type header line!");
2504 return CURLE_HTTP_POST_ERROR;
2507 result = Curl_add_buffer(req_buffer, contentType, linelength);
2512 /* make the request end in a true CRLF */
2513 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2517 /* set upload size to the progress meter */
2518 Curl_pgrsSetUploadSize(data, http->postsize);
2520 /* fire away the whole request to the server */
2521 result = Curl_add_buffer_send(req_buffer, conn,
2522 &data->info.request_size, 0, FIRSTSOCKET);
2524 failf(data, "Failed sending POST request");
2526 /* setup variables for the upcoming transfer */
2527 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2528 &http->readbytecount, FIRSTSOCKET,
2529 &http->writebytecount);
2532 Curl_formclean(&http->sendit); /* free that whole lot */
2536 /* convert the form data */
2537 result = Curl_convert_form(data, http->sendit);
2539 Curl_formclean(&http->sendit); /* free that whole lot */
2545 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2547 if(conn->bits.authneg)
2550 postsize = data->state.infilesize;
2552 if((postsize != -1) && !data->req.upload_chunky &&
2553 !Curl_checkheaders(conn, "Content-Length:")) {
2554 /* only add Content-Length if not uploading chunked */
2555 result = Curl_add_bufferf(req_buffer,
2556 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2563 result = expect100(data, conn, req_buffer);
2568 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2572 /* set the upload size to the progress meter */
2573 Curl_pgrsSetUploadSize(data, postsize);
2575 /* this sends the buffer and frees all the buffer resources */
2576 result = Curl_add_buffer_send(req_buffer, conn,
2577 &data->info.request_size, 0, FIRSTSOCKET);
2579 failf(data, "Failed sending PUT request");
2581 /* prepare for transfer */
2582 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2583 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2584 postsize?&http->writebytecount:NULL);
2590 /* this is the simple POST, using x-www-form-urlencoded style */
2592 if(conn->bits.authneg)
2595 /* figure out the size of the postfields */
2596 postsize = (data->set.postfieldsize != -1)?
2597 data->set.postfieldsize:
2598 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2601 /* We only set Content-Length and allow a custom Content-Length if
2602 we don't upload data chunked, as RFC2616 forbids us to set both
2603 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2604 if((postsize != -1) && !data->req.upload_chunky &&
2605 !Curl_checkheaders(conn, "Content-Length:")) {
2606 /* we allow replacing this header if not during auth negotiation,
2607 although it isn't very wise to actually set your own */
2608 result = Curl_add_bufferf(req_buffer,
2609 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2615 if(!Curl_checkheaders(conn, "Content-Type:")) {
2616 result = Curl_add_bufferf(req_buffer,
2617 "Content-Type: application/"
2618 "x-www-form-urlencoded\r\n");
2623 /* For really small posts we don't use Expect: headers at all, and for
2624 the somewhat bigger ones we allow the app to disable it. Just make
2625 sure that the expect100header is always set to the preferred value
2627 ptr = Curl_checkheaders(conn, "Expect:");
2629 data->state.expect100header =
2630 Curl_compareheader(ptr, "Expect:", "100-continue");
2632 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2633 result = expect100(data, conn, req_buffer);
2638 data->state.expect100header = FALSE;
2640 if(data->set.postfields) {
2642 /* In HTTP2, we send request body in DATA frame regardless of
2644 if(conn->httpversion != 20 &&
2645 !data->state.expect100header &&
2646 (postsize < MAX_INITIAL_POST_SIZE)) {
2647 /* if we don't use expect: 100 AND
2648 postsize is less than MAX_INITIAL_POST_SIZE
2650 then append the post data to the HTTP request header. This limit
2651 is no magic limit but only set to prevent really huge POSTs to
2652 get the data duplicated with malloc() and family. */
2654 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2658 if(!data->req.upload_chunky) {
2659 /* We're not sending it 'chunked', append it to the request
2660 already now to reduce the number if send() calls */
2661 result = Curl_add_buffer(req_buffer, data->set.postfields,
2663 included_body = postsize;
2667 /* Append the POST data chunky-style */
2668 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2670 result = Curl_add_buffer(req_buffer, data->set.postfields,
2673 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2674 included_body = postsize + 2;
2678 result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
2684 /* Make sure the progress information is accurate */
2685 Curl_pgrsSetUploadSize(data, postsize);
2688 /* A huge POST coming up, do data separate from the request */
2689 http->postsize = postsize;
2690 http->postdata = data->set.postfields;
2692 http->sending = HTTPSEND_BODY;
2694 conn->fread_func = (curl_read_callback)readmoredata;
2695 conn->fread_in = (void *)conn;
2697 /* set the upload size to the progress meter */
2698 Curl_pgrsSetUploadSize(data, http->postsize);
2700 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2706 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2710 if(data->req.upload_chunky && conn->bits.authneg) {
2711 /* Chunky upload is selected and we're negotiating auth still, send
2713 result = Curl_add_buffer(req_buffer,
2714 "\x30\x0d\x0a\x0d\x0a", 5);
2720 else if(data->set.postfieldsize) {
2721 /* set the upload size to the progress meter */
2722 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2724 /* set the pointer to mark that we will send the post body using the
2725 read callback, but only if we're not in authenticate
2727 if(!conn->bits.authneg) {
2728 http->postdata = (char *)&http->postdata;
2729 http->postsize = postsize;
2733 /* issue the request */
2734 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2735 (size_t)included_body, FIRSTSOCKET);
2738 failf(data, "Failed sending HTTP POST request");
2740 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2741 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2742 http->postdata?&http->writebytecount:NULL);
2746 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2750 /* issue the request */
2751 result = Curl_add_buffer_send(req_buffer, conn,
2752 &data->info.request_size, 0, FIRSTSOCKET);
2755 failf(data, "Failed sending HTTP request");
2757 /* HTTP GET/HEAD download: */
2758 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2759 http->postdata?FIRSTSOCKET:-1,
2760 http->postdata?&http->writebytecount:NULL);
2765 if(http->writebytecount) {
2766 /* if a request-body has been sent off, we make sure this progress is noted
2768 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2769 if(Curl_pgrsUpdate(conn))
2770 result = CURLE_ABORTED_BY_CALLBACK;
2772 if(http->writebytecount >= postsize) {
2773 /* already sent the entire request body, mark the "upload" as
2775 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
2776 " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
2777 http->writebytecount, postsize);
2778 data->req.upload_done = TRUE;
2779 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2780 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2790 * Returns TRUE if member of the list matches prefix of string
2793 checkhttpprefix(struct SessionHandle *data,
2796 struct curl_slist *head = data->set.http200aliases;
2798 #ifdef CURL_DOES_CONVERSIONS
2799 /* convert from the network encoding using a scratch area */
2800 char *scratch = strdup(s);
2801 if(NULL == scratch) {
2802 failf (data, "Failed to allocate memory for conversion!");
2803 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2805 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2806 /* Curl_convert_from_network calls failf if unsuccessful */
2808 return FALSE; /* can't return CURLE_foobar so return FALSE */
2811 #endif /* CURL_DOES_CONVERSIONS */
2814 if(checkprefix(head->data, s)) {
2821 if(!rc && (checkprefix("HTTP/", s)))
2824 #ifdef CURL_DOES_CONVERSIONS
2826 #endif /* CURL_DOES_CONVERSIONS */
2830 #ifndef CURL_DISABLE_RTSP
2832 checkrtspprefix(struct SessionHandle *data,
2836 #ifdef CURL_DOES_CONVERSIONS
2837 /* convert from the network encoding using a scratch area */
2838 char *scratch = strdup(s);
2839 if(NULL == scratch) {
2840 failf (data, "Failed to allocate memory for conversion!");
2841 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2843 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2844 /* Curl_convert_from_network calls failf if unsuccessful */
2846 return FALSE; /* can't return CURLE_foobar so return FALSE */
2850 (void)data; /* unused */
2851 #endif /* CURL_DOES_CONVERSIONS */
2852 if(checkprefix("RTSP/", s))
2857 #endif /* CURL_DISABLE_RTSP */
2860 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2863 #ifndef CURL_DISABLE_RTSP
2864 if(conn->handler->protocol & CURLPROTO_RTSP)
2865 return checkrtspprefix(data, s);
2868 #endif /* CURL_DISABLE_RTSP */
2870 return checkhttpprefix(data, s);
2874 * header_append() copies a chunk of data to the end of the already received
2875 * header. We make sure that the full string fit in the allocated header
2876 * buffer, or else we enlarge it.
2878 static CURLcode header_append(struct SessionHandle *data,
2879 struct SingleRequest *k,
2882 if(k->hbuflen + length >= data->state.headersize) {
2883 /* We enlarge the header buffer as it is too small */
2888 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2889 /* The reason to have a max limit for this is to avoid the risk of a bad
2890 server feeding libcurl with a never-ending header that will cause
2891 reallocs infinitely */
2892 failf (data, "Avoided giant realloc for header (max is %d)!",
2893 CURL_MAX_HTTP_HEADER);
2894 return CURLE_OUT_OF_MEMORY;
2897 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2898 hbufp_index = k->hbufp - data->state.headerbuff;
2899 newbuff = realloc(data->state.headerbuff, newsize);
2901 failf (data, "Failed to alloc memory for big header!");
2902 return CURLE_OUT_OF_MEMORY;
2904 data->state.headersize=newsize;
2905 data->state.headerbuff = newbuff;
2906 k->hbufp = data->state.headerbuff + hbufp_index;
2908 memcpy(k->hbufp, k->str_start, length);
2910 k->hbuflen += length;
2916 static void print_http_error(struct SessionHandle *data)
2918 struct SingleRequest *k = &data->req;
2921 /* make sure that data->req.p points to the HTTP status line */
2922 if(!strncmp(beg, "HTTP", 4)) {
2924 /* skip to HTTP status code */
2925 beg = strchr(beg, ' ');
2928 /* find trailing CR */
2929 char end_char = '\r';
2930 char *end = strchr(beg, end_char);
2932 /* try to find LF (workaround for non-compliant HTTP servers) */
2934 end = strchr(beg, end_char);
2938 /* temporarily replace CR or LF by NUL and print the error message */
2940 failf(data, "The requested URL returned error: %s", beg);
2942 /* restore the previously replaced CR or LF */
2949 /* fall-back to printing the HTTP status code only */
2950 failf(data, "The requested URL returned error: %d", k->httpcode);
2954 * Read any HTTP header lines from the server and pass them to the client app.
2956 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2957 struct connectdata *conn,
2962 struct SingleRequest *k = &data->req;
2964 /* header line within buffer loop */
2970 /* str_start is start of line within buf */
2971 k->str_start = k->str;
2973 /* data is in network encoding so use 0x0a instead of '\n' */
2974 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2977 /* Not a complete header line within buffer, append the data to
2978 the end of the headerbuff. */
2979 result = header_append(data, k, *nread);
2983 if(!k->headerline && (k->hbuflen>5)) {
2984 /* make a first check that this looks like a protocol header */
2985 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2986 /* this is not the beginning of a protocol first header line */
2988 k->badheader = HEADER_ALLBAD;
2993 break; /* read more and try again */
2996 /* decrease the size of the remaining (supposed) header line */
2997 rest_length = (k->end_ptr - k->str)+1;
2998 *nread -= (ssize_t)rest_length;
3000 k->str = k->end_ptr + 1; /* move past new line */
3002 full_length = k->str - k->str_start;
3004 result = header_append(data, k, full_length);
3008 k->end_ptr = k->hbufp;
3009 k->p = data->state.headerbuff;
3012 * We now have a FULL header line that p points to
3015 if(!k->headerline) {
3016 /* the first read header */
3017 if((k->hbuflen>5) &&
3018 !checkprotoprefix(data, conn, data->state.headerbuff)) {
3019 /* this is not the beginning of a protocol first header line */
3022 /* since there's more, this is a partial bad header */
3023 k->badheader = HEADER_PARTHEADER;
3025 /* this was all we read so it's all a bad header */
3026 k->badheader = HEADER_ALLBAD;
3027 *nread = (ssize_t)rest_length;
3033 /* headers are in network encoding so
3034 use 0x0a and 0x0d instead of '\n' and '\r' */
3035 if((0x0a == *k->p) || (0x0d == *k->p)) {
3037 /* Zero-length header line means end of headers! */
3039 #ifdef CURL_DOES_CONVERSIONS
3041 *k->p = '\r'; /* replace with CR in host encoding */
3042 k->p++; /* pass the CR byte */
3045 *k->p = '\n'; /* replace with LF in host encoding */
3046 k->p++; /* pass the LF byte */
3050 k->p++; /* pass the \r byte */
3052 k->p++; /* pass the \n byte */
3053 #endif /* CURL_DOES_CONVERSIONS */
3055 if(100 <= k->httpcode && 199 >= k->httpcode) {
3057 * We have made a HTTP PUT or POST and this is 1.1-lingo
3058 * that tells us that the server is OK with this and ready
3059 * to receive the data.
3060 * However, we'll get more headers now so we must get
3061 * back into the header-parsing state!
3064 k->headerline = 0; /* restart the header line counter */
3066 /* "A user agent MAY ignore unexpected 1xx status responses." */
3067 switch(k->httpcode) {
3069 /* if we did wait for this do enable write now! */
3071 k->exp100 = EXP100_SEND_DATA;
3072 k->keepon |= KEEP_SEND;
3076 /* Switching Protocols */
3077 if(k->upgr101 == UPGR101_REQUESTED) {
3078 infof(data, "Received 101\n");
3079 k->upgr101 = UPGR101_RECEIVED;
3081 /* switch to http2 now. The bytes after response headers
3082 are also processed here, otherwise they are lost. */
3083 result = Curl_http2_switched(conn, k->str, *nread);
3094 k->header = FALSE; /* no more header to parse! */
3096 if((k->size == -1) && !k->chunk && !conn->bits.close &&
3097 (conn->httpversion == 11) &&
3098 !(conn->handler->protocol & CURLPROTO_RTSP) &&
3099 data->set.httpreq != HTTPREQ_HEAD) {
3100 /* On HTTP 1.1, when connection is not to get closed, but no
3101 Content-Length nor Content-Encoding chunked have been
3102 received, according to RFC2616 section 4.4 point 5, we
3103 assume that the server will close the connection to
3104 signal the end of the document. */
3105 infof(data, "no chunk, no close, no size. Assume close to "
3107 connclose(conn, "HTTP: No end-of-message indicator");
3112 * When all the headers have been parsed, see if we should give
3113 * up and return an error.
3115 if(http_should_fail(conn)) {
3116 failf (data, "The requested URL returned error: %d",
3118 return CURLE_HTTP_RETURNED_ERROR;
3121 /* now, only output this if the header AND body are requested:
3123 writetype = CLIENTWRITE_HEADER;
3124 if(data->set.include_header)
3125 writetype |= CLIENTWRITE_BODY;
3127 headerlen = k->p - data->state.headerbuff;
3129 result = Curl_client_write(conn, writetype,
3130 data->state.headerbuff,
3135 data->info.header_size += (long)headerlen;
3136 data->req.headerbytecount += (long)headerlen;
3138 data->req.deductheadercount =
3139 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
3141 if(!*stop_reading) {
3142 /* Curl_http_auth_act() checks what authentication methods
3143 * that are available and decides which one (if any) to
3144 * use. It will set 'newurl' if an auth method was picked. */
3145 result = Curl_http_auth_act(conn);
3150 if(k->httpcode >= 300) {
3151 if((!conn->bits.authneg) && !conn->bits.close &&
3152 !conn->bits.rewindaftersend) {
3154 * General treatment of errors when about to send data. Including :
3155 * "417 Expectation Failed", while waiting for 100-continue.
3157 * The check for close above is done simply because of something
3158 * else has already deemed the connection to get closed then
3159 * something else should've considered the big picture and we
3162 * rewindaftersend indicates that something has told libcurl to
3163 * continue sending even if it gets discarded
3166 switch(data->set.httpreq) {
3169 case HTTPREQ_POST_FORM:
3170 /* We got an error response. If this happened before the whole
3171 * request body has been sent we stop sending and mark the
3172 * connection for closure after we've read the entire response.
3174 if(!k->upload_done) {
3175 infof(data, "HTTP error before end of send, stop sending\n");
3176 connclose(conn, "Stop sending data before everything sent");
3177 k->upload_done = TRUE;
3178 k->keepon &= ~KEEP_SEND; /* don't send */
3179 if(data->state.expect100header)
3180 k->exp100 = EXP100_FAILED;
3184 default: /* default label present to avoid compiler warnings */
3190 if(conn->bits.rewindaftersend) {
3191 /* We rewind after a complete send, so thus we continue
3193 infof(data, "Keep sending data to get tossed away!\n");
3194 k->keepon |= KEEP_SEND;
3200 * really end-of-headers.
3202 * If we requested a "no body", this is a good time to get
3203 * out and return home.
3205 if(data->set.opt_no_body)
3206 *stop_reading = TRUE;
3208 /* If we know the expected size of this document, we set the
3209 maximum download size to the size of the expected
3210 document or else, we won't know when to stop reading!
3212 Note that we set the download maximum even if we read a
3213 "Connection: close" header, to make sure that
3214 "Content-Length: 0" still prevents us from attempting to
3215 read the (missing) response-body.
3217 /* According to RFC2616 section 4.4, we MUST ignore
3218 Content-Length: headers if we are now receiving data
3219 using chunked Transfer-Encoding.
3222 k->maxdownload = k->size = -1;
3225 /* We do this operation even if no_body is true, since this
3226 data might be retrieved later with curl_easy_getinfo()
3227 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3229 Curl_pgrsSetDownloadSize(data, k->size);
3230 k->maxdownload = k->size;
3233 /* If max download size is *zero* (nothing) we already
3234 have nothing and can safely return ok now! */
3235 if(0 == k->maxdownload)
3236 *stop_reading = TRUE;
3239 /* we make sure that this socket isn't read more now */
3240 k->keepon &= ~KEEP_RECV;
3243 if(data->set.verbose)
3244 Curl_debug(data, CURLINFO_HEADER_IN,
3245 k->str_start, headerlen, conn);
3246 break; /* exit header line loop */
3249 /* We continue reading headers, so reset the line-based
3250 header parsing variables hbufp && hbuflen */
3251 k->hbufp = data->state.headerbuff;
3257 * Checks for special headers coming up.
3260 if(!k->headerline++) {
3261 /* This is the first header, it MUST be the error code line
3262 or else we consider this to be the body right away! */
3263 int httpversion_major;
3264 int rtspversion_major;
3266 #ifdef CURL_DOES_CONVERSIONS
3267 #define HEADER1 scratch
3268 #define SCRATCHSIZE 21
3270 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3271 /* We can't really convert this yet because we
3272 don't know if it's the 1st header line or the body.
3273 So we do a partial conversion into a scratch area,
3274 leaving the data at k->p as-is.
3276 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3277 scratch[SCRATCHSIZE] = 0; /* null terminate */
3278 res = Curl_convert_from_network(data,
3282 /* Curl_convert_from_network calls failf if unsuccessful */
3285 #define HEADER1 k->p /* no conversion needed, just use k->p */
3286 #endif /* CURL_DOES_CONVERSIONS */
3288 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
3290 * https://tools.ietf.org/html/rfc7230#section-3.1.2
3292 * The reponse code is always a three-digit number in HTTP as the spec
3293 * says. We try to allow any number here, but we cannot make
3294 * guarantees on future behaviors since it isn't within the protocol.
3296 nc = sscanf(HEADER1,
3302 conn->httpversion += 10 * httpversion_major;
3304 if(k->upgr101 == UPGR101_RECEIVED) {
3305 /* supposedly upgraded to http2 now */
3306 if(conn->httpversion != 20)
3307 infof(data, "Lying server, not serving HTTP/2\n");
3311 /* this is the real world, not a Nirvana
3312 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3314 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3315 conn->httpversion = 10;
3317 /* If user has set option HTTP200ALIASES,
3318 compare header line against list of aliases
3321 if(checkhttpprefix(data, k->p)) {
3324 conn->httpversion = 10;
3329 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3330 nc = sscanf(HEADER1,
3336 conn->rtspversion += 10 * rtspversion_major;
3337 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3340 /* TODO: do we care about the other cases here? */
3346 data->info.httpcode = k->httpcode;
3348 data->info.httpversion = conn->httpversion;
3349 if(!data->state.httpversion ||
3350 data->state.httpversion > conn->httpversion)
3351 /* store the lowest server version we encounter */
3352 data->state.httpversion = conn->httpversion;
3355 * This code executes as part of processing the header. As a
3356 * result, it's not totally clear how to interpret the
3357 * response code yet as that depends on what other headers may
3358 * be present. 401 and 407 may be errors, but may be OK
3359 * depending on how authentication is working. Other codes
3360 * are definitely errors, so give up here.
3362 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3363 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3364 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3366 if(data->state.resume_from &&
3367 (data->set.httpreq==HTTPREQ_GET) &&
3368 (k->httpcode == 416)) {
3369 /* "Requested Range Not Satisfiable", just proceed and
3370 pretend this is no error */
3373 /* serious error, go home! */
3374 print_http_error(data);
3375 return CURLE_HTTP_RETURNED_ERROR;
3379 if(conn->httpversion == 10) {
3380 /* Default action for HTTP/1.0 must be to close, unless
3381 we get one of those fancy headers that tell us the
3382 server keeps it open for us! */
3383 infof(data, "HTTP 1.0, assume close after body\n");
3384 connclose(conn, "HTTP/1.0 close after body");
3386 else if(conn->httpversion == 20 ||
3387 (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
3388 /* Don't enable pipelining for HTTP/2 or upgraded connection. For
3389 HTTP/2, we do not support multiplexing. In general, requests
3390 cannot be pipelined in upgraded connection, since it is now
3391 different protocol. */
3393 "HTTP 2 or upgraded connection do not support "
3394 "pipelining for now\n"));
3396 else if(conn->httpversion >= 11 &&
3397 !conn->bits.close) {
3398 struct connectbundle *cb_ptr;
3400 /* If HTTP version is >= 1.1 and connection is persistent
3401 server supports pipelining. */
3403 "HTTP 1.1 or later with persistent connection, "
3404 "pipelining supported\n"));
3405 /* Activate pipelining if needed */
3406 cb_ptr = conn->bundle;
3408 if(!Curl_pipeline_site_blacklisted(data, conn))
3409 cb_ptr->server_supports_pipelining = TRUE;
3413 switch(k->httpcode) {
3415 /* (quote from RFC2616, section 10.2.5): The server has
3416 * fulfilled the request but does not need to return an
3417 * entity-body ... The 204 response MUST NOT include a
3418 * message-body, and thus is always terminated by the first
3419 * empty line after the header fields. */
3422 /* (quote from RFC2616, section 10.3.5): The 304 response
3423 * MUST NOT contain a message-body, and thus is always
3424 * terminated by the first empty line after the header
3426 if(data->set.timecondition)
3427 data->info.timecond = TRUE;
3430 k->ignorecl = TRUE; /* ignore Content-Length headers */
3438 k->header = FALSE; /* this is not a header line */
3443 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3444 /* Curl_convert_from_network calls failf if unsuccessful */
3448 /* Check for Content-Length: header lines to get size */
3449 if(!k->ignorecl && !data->set.ignorecl &&
3450 checkprefix("Content-Length:", k->p)) {
3451 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3452 if(data->set.max_filesize &&
3453 contentlength > data->set.max_filesize) {
3454 failf(data, "Maximum file size exceeded");
3455 return CURLE_FILESIZE_EXCEEDED;
3457 if(contentlength >= 0) {
3458 k->size = contentlength;
3459 k->maxdownload = k->size;
3460 /* we set the progress download size already at this point
3461 just to make it easier for apps/callbacks to extract this
3462 info as soon as possible */
3463 Curl_pgrsSetDownloadSize(data, k->size);
3466 /* Negative Content-Length is really odd, and we know it
3467 happens for example when older Apache servers send large
3469 connclose(conn, "negative content-length");
3470 infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
3471 ", closing after transfer\n", contentlength);
3474 /* check for Content-Type: header lines to get the MIME-type */
3475 else if(checkprefix("Content-Type:", k->p)) {
3476 char *contenttype = Curl_copy_header_value(k->p);
3478 return CURLE_OUT_OF_MEMORY;
3480 /* ignore empty data */
3483 Curl_safefree(data->info.contenttype);
3484 data->info.contenttype = contenttype;
3487 else if(checkprefix("Server:", k->p)) {
3488 char *server_name = Curl_copy_header_value(k->p);
3490 /* Turn off pipelining if the server version is blacklisted */
3491 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3492 if(Curl_pipeline_server_blacklisted(data, server_name))
3493 conn->bundle->server_supports_pipelining = FALSE;
3495 Curl_safefree(server_name);
3497 else if((conn->httpversion == 10) &&
3498 conn->bits.httpproxy &&
3499 Curl_compareheader(k->p,
3500 "Proxy-Connection:", "keep-alive")) {
3502 * When a HTTP/1.0 reply comes when using a proxy, the
3503 * 'Proxy-Connection: keep-alive' line tells us the
3504 * connection will be kept alive for our pleasure.
3505 * Default action for 1.0 is to close.
3507 connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
3508 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3510 else if((conn->httpversion == 11) &&
3511 conn->bits.httpproxy &&
3512 Curl_compareheader(k->p,
3513 "Proxy-Connection:", "close")) {
3515 * We get a HTTP/1.1 response from a proxy and it says it'll
3516 * close down after this transfer.
3518 connclose(conn, "Proxy-Connection: asked to close after done");
3519 infof(data, "HTTP/1.1 proxy connection set close!\n");
3521 else if((conn->httpversion == 10) &&
3522 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3524 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3525 * tells us the connection will be kept alive for our
3526 * pleasure. Default action for 1.0 is to close.
3528 * [RFC2068, section 19.7.1] */
3529 connkeep(conn, "Connection keep-alive");
3530 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3532 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3534 * [RFC 2616, section 8.1.2.1]
3535 * "Connection: close" is HTTP/1.1 language and means that
3536 * the connection will close when this request has been
3539 connclose(conn, "Connection: close used");
3541 else if(checkprefix("Transfer-Encoding:", k->p)) {
3542 /* One or more encodings. We check for chunked and/or a compression
3545 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3546 * means that the server will send a series of "chunks". Each
3547 * chunk starts with line with info (including size of the
3548 * coming block) (terminated with CRLF), then a block of data
3549 * with the previously mentioned size. There can be any amount
3550 * of chunks, and a chunk-data set to zero signals the
3555 /* Find the first non-space letter */
3559 /* skip whitespaces and commas */
3560 while(*start && (ISSPACE(*start) || (*start == ',')))
3563 if(checkprefix("chunked", start)) {
3564 k->chunk = TRUE; /* chunks coming our way */
3566 /* init our chunky engine */
3567 Curl_httpchunk_init(conn);
3572 if(k->auto_decoding)
3573 /* TODO: we only support the first mentioned compression for now */
3576 if(checkprefix("identity", start)) {
3577 k->auto_decoding = IDENTITY;
3580 else if(checkprefix("deflate", start)) {
3581 k->auto_decoding = DEFLATE;
3584 else if(checkprefix("gzip", start)) {
3585 k->auto_decoding = GZIP;
3588 else if(checkprefix("x-gzip", start)) {
3589 k->auto_decoding = GZIP;
3592 else if(checkprefix("compress", start)) {
3593 k->auto_decoding = COMPRESS;
3596 else if(checkprefix("x-compress", start)) {
3597 k->auto_decoding = COMPRESS;
3607 else if(checkprefix("Content-Encoding:", k->p) &&
3608 (data->set.str[STRING_ENCODING] ||
3609 conn->httpversion == 20)) {
3611 * Process Content-Encoding. Look for the values: identity,
3612 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3613 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3614 * 2616). zlib cannot handle compress. However, errors are
3615 * handled further down when the response body is processed
3619 /* Find the first non-space letter */
3621 while(*start && ISSPACE(*start))
3624 /* Record the content-encoding for later use */
3625 if(checkprefix("identity", start))
3626 k->auto_decoding = IDENTITY;
3627 else if(checkprefix("deflate", start))
3628 k->auto_decoding = DEFLATE;
3629 else if(checkprefix("gzip", start)
3630 || checkprefix("x-gzip", start))
3631 k->auto_decoding = GZIP;
3632 else if(checkprefix("compress", start)
3633 || checkprefix("x-compress", start))
3634 k->auto_decoding = COMPRESS;
3636 else if(checkprefix("Content-Range:", k->p)) {
3637 /* Content-Range: bytes [num]-
3638 Content-Range: bytes: [num]-
3639 Content-Range: [num]-
3640 Content-Range: [asterisk]/[total]
3642 The second format was added since Sun's webserver
3643 JavaWebServer/1.1.1 obviously sends the header this way!
3644 The third added since some servers use that!
3645 The forth means the requested range was unsatisfied.
3648 char *ptr = k->p + 14;
3650 /* Move forward until first digit or asterisk */
3651 while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
3654 /* if it truly stopped on a digit */
3656 k->offset = curlx_strtoofft(ptr, NULL, 10);
3658 if(data->state.resume_from == k->offset)
3659 /* we asked for a resume and we got it */
3660 k->content_range = TRUE;
3663 data->state.resume_from = 0; /* get everything */
3665 #if !defined(CURL_DISABLE_COOKIES)
3666 else if(data->cookies &&
3667 checkprefix("Set-Cookie:", k->p)) {
3668 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3669 CURL_LOCK_ACCESS_SINGLE);
3670 Curl_cookie_add(data,
3671 data->cookies, TRUE, k->p+11,
3672 /* If there is a custom-set Host: name, use it
3673 here, or else use real peer host name. */
3674 conn->allocptr.cookiehost?
3675 conn->allocptr.cookiehost:conn->host.name,
3677 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3680 else if(checkprefix("Last-Modified:", k->p) &&
3681 (data->set.timecondition || data->set.get_filetime) ) {
3682 time_t secs=time(NULL);
3683 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3685 if(data->set.get_filetime)
3686 data->info.filetime = (long)k->timeofdoc;
3688 else if((checkprefix("WWW-Authenticate:", k->p) &&
3689 (401 == k->httpcode)) ||
3690 (checkprefix("Proxy-authenticate:", k->p) &&
3691 (407 == k->httpcode))) {
3693 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3694 char *auth = Curl_copy_header_value(k->p);
3696 return CURLE_OUT_OF_MEMORY;
3698 result = Curl_http_input_auth(conn, proxy, auth);
3700 Curl_safefree(auth);
3705 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3706 checkprefix("Location:", k->p) &&
3707 !data->req.location) {
3708 /* this is the URL that the server advises us to use instead */
3709 char *location = Curl_copy_header_value(k->p);
3711 return CURLE_OUT_OF_MEMORY;
3713 /* ignore empty data */
3716 data->req.location = location;
3718 if(data->set.http_follow_location) {
3719 DEBUGASSERT(!data->req.newurl);
3720 data->req.newurl = strdup(data->req.location); /* clone */
3721 if(!data->req.newurl)
3722 return CURLE_OUT_OF_MEMORY;
3724 /* some cases of POST and PUT etc needs to rewind the data
3725 stream at this point */
3726 result = http_perhapsrewind(conn);
3732 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3733 result = Curl_rtsp_parseheader(conn, k->p);
3739 * End of header-checks. Write them to the client.
3742 writetype = CLIENTWRITE_HEADER;
3743 if(data->set.include_header)
3744 writetype |= CLIENTWRITE_BODY;
3746 if(data->set.verbose)
3747 Curl_debug(data, CURLINFO_HEADER_IN,
3748 k->p, (size_t)k->hbuflen, conn);
3750 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3754 data->info.header_size += (long)k->hbuflen;
3755 data->req.headerbytecount += (long)k->hbuflen;
3757 /* reset hbufp pointer && hbuflen */
3758 k->hbufp = data->state.headerbuff;
3761 while(!*stop_reading && *k->str); /* header line within buffer */
3763 /* We might have reached the end of the header part here, but
3764 there might be a non-header part left in the end of the read
3770 #endif /* CURL_DISABLE_HTTP */