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"
80 #define _MPRINTF_REPLACE /* use our functions only */
81 #include <curl/mprintf.h>
83 /* The last #include file should be: */
87 * Forward declarations.
90 static int http_getsock_do(struct connectdata *conn,
93 static int http_should_fail(struct connectdata *conn);
96 static CURLcode https_connecting(struct connectdata *conn, bool *done);
97 static int https_getsock(struct connectdata *conn,
101 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
105 * HTTP handler interface.
107 const struct Curl_handler Curl_handler_http = {
109 Curl_http_setup_conn, /* setup_connection */
110 Curl_http, /* do_it */
111 Curl_http_done, /* done */
112 ZERO_NULL, /* do_more */
113 Curl_http_connect, /* connect_it */
114 ZERO_NULL, /* connecting */
115 ZERO_NULL, /* doing */
116 ZERO_NULL, /* proto_getsock */
117 http_getsock_do, /* doing_getsock */
118 ZERO_NULL, /* domore_getsock */
119 ZERO_NULL, /* perform_getsock */
120 ZERO_NULL, /* disconnect */
121 ZERO_NULL, /* readwrite */
122 PORT_HTTP, /* defport */
123 CURLPROTO_HTTP, /* protocol */
124 PROTOPT_NONE /* flags */
129 * HTTPS handler interface.
131 const struct Curl_handler Curl_handler_https = {
132 "HTTPS", /* scheme */
133 Curl_http_setup_conn, /* setup_connection */
134 Curl_http, /* do_it */
135 Curl_http_done, /* done */
136 ZERO_NULL, /* do_more */
137 Curl_http_connect, /* connect_it */
138 https_connecting, /* connecting */
139 ZERO_NULL, /* doing */
140 https_getsock, /* proto_getsock */
141 http_getsock_do, /* doing_getsock */
142 ZERO_NULL, /* domore_getsock */
143 ZERO_NULL, /* perform_getsock */
144 ZERO_NULL, /* disconnect */
145 ZERO_NULL, /* readwrite */
146 PORT_HTTPS, /* defport */
147 CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */
148 PROTOPT_SSL /* flags */
153 CURLcode Curl_http_setup_conn(struct connectdata *conn)
155 /* allocate the HTTP-specific struct for the SessionHandle, only to survive
156 during this request */
157 DEBUGASSERT(conn->data->req.protop == NULL);
159 conn->data->req.protop = calloc(1, sizeof(struct HTTP));
160 if(!conn->data->req.protop)
161 return CURLE_OUT_OF_MEMORY;
167 * checkheaders() checks the linked list of custom HTTP headers for a
168 * particular header (prefix).
170 * Returns a pointer to the first matching header or NULL if none matched.
172 char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
174 struct curl_slist *head;
175 size_t thislen = strlen(thisheader);
177 for(head = data->set.headers; head; head=head->next) {
178 if(Curl_raw_nequal(head->data, thisheader, thislen))
185 * Strip off leading and trailing whitespace from the value in the
186 * given HTTP header line and return a strdupped copy. Returns NULL in
187 * case of allocation failure. Returns an empty string if the header value
188 * consists entirely of whitespace.
190 char *Curl_copy_header_value(const char *header)
199 /* Find the end of the header name */
200 while(*header && (*header != ':'))
204 /* Skip over colon */
207 /* Find the first non-space letter */
209 while(*start && ISSPACE(*start))
212 /* data is in the host encoding so
213 use '\r' and '\n' instead of 0x0d and 0x0a */
214 end = strchr(start, '\r');
216 end = strchr(start, '\n');
218 end = strchr(start, '\0');
222 /* skip all trailing space letters */
223 while((end > start) && ISSPACE(*end))
226 /* get length of the type */
227 len = end - start + 1;
229 value = malloc(len + 1);
233 memcpy(value, start, len);
234 value[len] = 0; /* zero terminate */
240 * http_output_basic() sets up an Authorization: header (or the proxy version)
241 * for HTTP Basic authentication.
245 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
248 char *authorization = NULL;
249 struct SessionHandle *data = conn->data;
256 userp = &conn->allocptr.proxyuserpwd;
257 user = conn->proxyuser;
258 pwd = conn->proxypasswd;
261 userp = &conn->allocptr.userpwd;
266 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
268 error = Curl_base64_encode(data,
269 data->state.buffer, strlen(data->state.buffer),
270 &authorization, &size);
275 return CURLE_REMOTE_ACCESS_DENIED;
277 Curl_safefree(*userp);
278 *userp = aprintf("%sAuthorization: Basic %s\r\n",
283 return CURLE_OUT_OF_MEMORY;
288 /* pickoneauth() selects the most favourable authentication method from the
289 * ones available and the ones we want.
291 * return TRUE if one was picked
293 static bool pickoneauth(struct auth *pick)
296 /* only deal with authentication we want */
297 unsigned long avail = pick->avail & pick->want;
300 /* The order of these checks is highly relevant, as this will be the order
301 of preference in case of the existence of multiple accepted types. */
302 if(avail & CURLAUTH_GSSNEGOTIATE)
303 pick->picked = CURLAUTH_GSSNEGOTIATE;
304 else if(avail & CURLAUTH_DIGEST)
305 pick->picked = CURLAUTH_DIGEST;
306 else if(avail & CURLAUTH_NTLM)
307 pick->picked = CURLAUTH_NTLM;
308 else if(avail & CURLAUTH_NTLM_WB)
309 pick->picked = CURLAUTH_NTLM_WB;
310 else if(avail & CURLAUTH_BASIC)
311 pick->picked = CURLAUTH_BASIC;
313 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
316 pick->avail = CURLAUTH_NONE; /* clear it here */
322 * Curl_http_perhapsrewind()
324 * If we are doing POST or PUT {
325 * If we have more data to send {
326 * If we are doing NTLM {
327 * Keep sending since we must not disconnect
330 * If there is more than just a little data left to send, close
331 * the current connection by force.
334 * If we have sent any data {
335 * If we don't have track of all the data {
336 * call app to tell it to rewind
339 * rewind internally so that the operation can restart fine
344 static CURLcode http_perhapsrewind(struct connectdata *conn)
346 struct SessionHandle *data = conn->data;
347 struct HTTP *http = data->req.protop;
348 curl_off_t bytessent;
349 curl_off_t expectsend = -1; /* default is unknown */
352 /* If this is still NULL, we have not reach very far and we can safely
353 skip this rewinding stuff */
356 switch(data->set.httpreq) {
364 bytessent = http->writebytecount;
366 if(conn->bits.authneg)
367 /* This is a state where we are known to be negotiating and we don't send
371 /* figure out how much data we are expected to send */
372 switch(data->set.httpreq) {
374 if(data->set.postfieldsize != -1)
375 expectsend = data->set.postfieldsize;
376 else if(data->set.postfields)
377 expectsend = (curl_off_t)strlen(data->set.postfields);
380 if(data->set.infilesize != -1)
381 expectsend = data->set.infilesize;
383 case HTTPREQ_POST_FORM:
384 expectsend = http->postsize;
391 conn->bits.rewindaftersend = FALSE; /* default */
393 if((expectsend == -1) || (expectsend > bytessent)) {
394 /* There is still data left to send */
395 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
396 (data->state.authhost.picked == CURLAUTH_NTLM) ||
397 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
398 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
399 if(((expectsend - bytessent) < 2000) ||
400 (conn->ntlm.state != NTLMSTATE_NONE) ||
401 (conn->proxyntlm.state != NTLMSTATE_NONE)) {
402 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
403 data left to send, keep on sending. */
405 /* rewind data when completely done sending! */
406 if(!conn->bits.authneg) {
407 conn->bits.rewindaftersend = TRUE;
408 infof(data, "Rewind stream after send\n");
414 /* this is already marked to get closed */
417 infof(data, "NTLM send, close instead of sending %"
418 CURL_FORMAT_CURL_OFF_T " bytes\n",
419 (curl_off_t)(expectsend - bytessent));
422 /* This is not NTLM or many bytes left to send: close
424 conn->bits.close = TRUE;
425 data->req.size = 0; /* don't download any more than 0 bytes */
427 /* There still is data left to send, but this connection is marked for
428 closure so we can safely do the rewind right now */
432 /* we rewind now at once since if we already sent something */
433 return Curl_readrewind(conn);
439 * Curl_http_auth_act() gets called when all HTTP headers have been received
440 * and it checks what authentication methods that are available and decides
441 * which one (if any) to use. It will set 'newurl' if an auth method was
445 CURLcode Curl_http_auth_act(struct connectdata *conn)
447 struct SessionHandle *data = conn->data;
448 bool pickhost = FALSE;
449 bool pickproxy = FALSE;
450 CURLcode code = CURLE_OK;
452 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
453 /* this is a transient response code, ignore */
456 if(data->state.authproblem)
457 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
459 if(conn->bits.user_passwd &&
460 ((data->req.httpcode == 401) ||
461 (conn->bits.authneg && data->req.httpcode < 300))) {
462 pickhost = pickoneauth(&data->state.authhost);
464 data->state.authproblem = TRUE;
466 if(conn->bits.proxy_user_passwd &&
467 ((data->req.httpcode == 407) ||
468 (conn->bits.authneg && data->req.httpcode < 300))) {
469 pickproxy = pickoneauth(&data->state.authproxy);
471 data->state.authproblem = TRUE;
474 if(pickhost || pickproxy) {
475 /* In case this is GSS auth, the newurl field is already allocated so
476 we must make sure to free it before allocating a new one. As figured
477 out in bug #2284386 */
478 Curl_safefree(data->req.newurl);
479 data->req.newurl = strdup(data->change.url); /* clone URL */
480 if(!data->req.newurl)
481 return CURLE_OUT_OF_MEMORY;
483 if((data->set.httpreq != HTTPREQ_GET) &&
484 (data->set.httpreq != HTTPREQ_HEAD) &&
485 !conn->bits.rewindaftersend) {
486 code = http_perhapsrewind(conn);
492 else if((data->req.httpcode < 300) &&
493 (!data->state.authhost.done) &&
494 conn->bits.authneg) {
495 /* no (known) authentication available,
496 authentication is not "done" yet and
497 no authentication seems to be required and
498 we didn't try HEAD or GET */
499 if((data->set.httpreq != HTTPREQ_GET) &&
500 (data->set.httpreq != HTTPREQ_HEAD)) {
501 data->req.newurl = strdup(data->change.url); /* clone URL */
502 if(!data->req.newurl)
503 return CURLE_OUT_OF_MEMORY;
504 data->state.authhost.done = TRUE;
507 if(http_should_fail(conn)) {
508 failf (data, "The requested URL returned error: %d",
510 code = CURLE_HTTP_RETURNED_ERROR;
518 * Output the correct authentication header depending on the auth type
519 * and whether or not it is to a proxy.
522 output_auth_headers(struct connectdata *conn,
523 struct auth *authstatus,
528 struct SessionHandle *data = conn->data;
529 const char *auth=NULL;
530 CURLcode result = CURLE_OK;
531 #ifdef USE_HTTP_NEGOTIATE
532 struct negotiatedata *negdata = proxy?
533 &data->state.proxyneg:&data->state.negotiate;
536 #ifdef CURL_DISABLE_CRYPTO_AUTH
541 #ifdef USE_HTTP_NEGOTIATE
542 negdata->state = GSS_AUTHNONE;
543 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
544 negdata->context && !GSS_ERROR(negdata->status)) {
545 auth="GSS-Negotiate";
546 result = Curl_output_negotiate(conn, proxy);
549 authstatus->done = TRUE;
550 negdata->state = GSS_AUTHSENT;
555 if(authstatus->picked == CURLAUTH_NTLM) {
557 result = Curl_output_ntlm(conn, proxy);
563 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
564 if(authstatus->picked == CURLAUTH_NTLM_WB) {
566 result = Curl_output_ntlm_wb(conn, proxy);
572 #ifndef CURL_DISABLE_CRYPTO_AUTH
573 if(authstatus->picked == CURLAUTH_DIGEST) {
575 result = Curl_output_digest(conn,
577 (const unsigned char *)request,
578 (const unsigned char *)path);
584 if(authstatus->picked == CURLAUTH_BASIC) {
586 if((proxy && conn->bits.proxy_user_passwd &&
587 !Curl_checkheaders(data, "Proxy-authorization:")) ||
588 (!proxy && conn->bits.user_passwd &&
589 !Curl_checkheaders(data, "Authorization:"))) {
591 result = http_output_basic(conn, proxy);
595 /* NOTE: this function should set 'done' TRUE, as the other auth
596 functions work that way */
597 authstatus->done = TRUE;
601 infof(data, "%s auth using %s with user '%s'\n",
602 proxy?"Proxy":"Server", auth,
603 proxy?(conn->proxyuser?conn->proxyuser:""):
604 (conn->user?conn->user:""));
605 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
608 authstatus->multi = FALSE;
614 * Curl_http_output_auth() setups the authentication headers for the
615 * host/proxy and the correct authentication
616 * method. conn->data->state.authdone is set to TRUE when authentication is
619 * @param conn all information about the current connection
620 * @param request pointer to the request keyword
621 * @param path pointer to the requested path
622 * @param proxytunnel boolean if this is the request setting up a "proxy
628 Curl_http_output_auth(struct connectdata *conn,
631 bool proxytunnel) /* TRUE if this is the request setting
632 up the proxy tunnel */
634 CURLcode result = CURLE_OK;
635 struct SessionHandle *data = conn->data;
636 struct auth *authhost;
637 struct auth *authproxy;
641 authhost = &data->state.authhost;
642 authproxy = &data->state.authproxy;
644 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
645 conn->bits.user_passwd)
646 /* continue please */ ;
648 authhost->done = TRUE;
649 authproxy->done = TRUE;
650 return CURLE_OK; /* no authentication with no user or password */
653 if(authhost->want && !authhost->picked)
654 /* The app has selected one or more methods, but none has been picked
655 so far by a server round-trip. Then we set the picked one to the
656 want one, and if this is one single bit it'll be used instantly. */
657 authhost->picked = authhost->want;
659 if(authproxy->want && !authproxy->picked)
660 /* The app has selected one or more methods, but none has been picked so
661 far by a proxy round-trip. Then we set the picked one to the want one,
662 and if this is one single bit it'll be used instantly. */
663 authproxy->picked = authproxy->want;
665 #ifndef CURL_DISABLE_PROXY
666 /* Send proxy authentication header if needed */
667 if(conn->bits.httpproxy &&
668 (conn->bits.tunnel_proxy == proxytunnel)) {
669 result = output_auth_headers(conn, authproxy, request, path, TRUE);
676 #endif /* CURL_DISABLE_PROXY */
677 /* we have no proxy so let's pretend we're done authenticating
679 authproxy->done = TRUE;
681 /* To prevent the user+password to get sent to other than the original
682 host due to a location-follow, we do some weirdo checks here */
683 if(!data->state.this_is_a_follow ||
685 !data->state.first_host ||
686 data->set.http_disable_hostname_check_before_authentication ||
687 Curl_raw_equal(data->state.first_host, conn->host.name)) {
688 result = output_auth_headers(conn, authhost, request, path, FALSE);
691 authhost->done = TRUE;
698 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
699 * headers. They are dealt with both in the transfer.c main loop and in the
700 * proxy CONNECT loop.
703 CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
704 const char *auth) /* the first non-space */
707 * This resource requires authentication
709 struct SessionHandle *data = conn->data;
711 unsigned long *availp;
715 availp = &data->info.proxyauthavail;
716 authp = &data->state.authproxy;
719 availp = &data->info.httpauthavail;
720 authp = &data->state.authhost;
724 * Here we check if we want the specific single authentication (using ==) and
725 * if we do, we initiate usage of it.
727 * If the provided authentication is wanted as one out of several accepted
728 * types (using &), we OR this authentication type to the authavail
733 * ->picked is first set to the 'want' value (one or more bits) before the
734 * request is sent, and then it is again set _after_ all response 401/407
735 * headers have been received but then only to a single preferred method
741 #ifdef USE_HTTP_NEGOTIATE
742 if(checkprefix("GSS-Negotiate", auth) ||
743 checkprefix("Negotiate", auth)) {
745 *availp |= CURLAUTH_GSSNEGOTIATE;
746 authp->avail |= CURLAUTH_GSSNEGOTIATE;
748 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
749 if(data->state.negotiate.state == GSS_AUTHSENT) {
750 /* if we sent GSS authentication in the outgoing request and we get
751 this back, we're in trouble */
752 infof(data, "Authentication problem. Ignoring this.\n");
753 data->state.authproblem = TRUE;
756 neg = Curl_input_negotiate(conn, proxy, auth);
758 DEBUGASSERT(!data->req.newurl);
759 data->req.newurl = strdup(data->change.url);
760 if(!data->req.newurl)
761 return CURLE_OUT_OF_MEMORY;
762 data->state.authproblem = FALSE;
763 /* we received GSS auth info and we dealt with it fine */
764 data->state.negotiate.state = GSS_AUTHRECV;
767 data->state.authproblem = TRUE;
774 /* NTLM support requires the SSL crypto libs */
775 if(checkprefix("NTLM", auth)) {
776 *availp |= CURLAUTH_NTLM;
777 authp->avail |= CURLAUTH_NTLM;
778 if(authp->picked == CURLAUTH_NTLM ||
779 authp->picked == CURLAUTH_NTLM_WB) {
780 /* NTLM authentication is picked and activated */
782 Curl_input_ntlm(conn, proxy, auth);
783 if(CURLE_OK == ntlm) {
784 data->state.authproblem = FALSE;
785 #ifdef NTLM_WB_ENABLED
786 if(authp->picked == CURLAUTH_NTLM_WB) {
787 *availp &= ~CURLAUTH_NTLM;
788 authp->avail &= ~CURLAUTH_NTLM;
789 *availp |= CURLAUTH_NTLM_WB;
790 authp->avail |= CURLAUTH_NTLM_WB;
792 /* Get the challenge-message which will be passed to
793 * ntlm_auth for generating the type 3 message later */
794 while(*auth && ISSPACE(*auth))
796 if(checkprefix("NTLM", auth)) {
797 auth += strlen("NTLM");
798 while(*auth && ISSPACE(*auth))
801 if((conn->challenge_header = strdup(auth)) == NULL)
802 return CURLE_OUT_OF_MEMORY;
808 infof(data, "Authentication problem. Ignoring this.\n");
809 data->state.authproblem = TRUE;
815 #ifndef CURL_DISABLE_CRYPTO_AUTH
816 if(checkprefix("Digest", auth)) {
817 if((authp->avail & CURLAUTH_DIGEST) != 0) {
818 infof(data, "Ignoring duplicate digest auth header.\n");
822 *availp |= CURLAUTH_DIGEST;
823 authp->avail |= CURLAUTH_DIGEST;
825 /* We call this function on input Digest headers even if Digest
826 * authentication isn't activated yet, as we need to store the
827 * incoming data from this header in case we are gonna use
829 dig = Curl_input_digest(conn, proxy, auth);
831 if(CURLDIGEST_FINE != dig) {
832 infof(data, "Authentication problem. Ignoring this.\n");
833 data->state.authproblem = TRUE;
839 if(checkprefix("Basic", auth)) {
840 *availp |= CURLAUTH_BASIC;
841 authp->avail |= CURLAUTH_BASIC;
842 if(authp->picked == CURLAUTH_BASIC) {
843 /* We asked for Basic authentication but got a 40X back
844 anyway, which basically means our name+password isn't
846 authp->avail = CURLAUTH_NONE;
847 infof(data, "Authentication problem. Ignoring this.\n");
848 data->state.authproblem = TRUE;
852 /* there may be multiple methods on one line, so keep reading */
853 while(*auth && *auth != ',') /* read up to the next comma */
855 if(*auth == ',') /* if we're on a comma, skip it */
857 while(*auth && ISSPACE(*auth))
864 * http_should_fail() determines whether an HTTP response has gotten us
865 * into an error state or not.
867 * @param conn all information about the current connection
869 * @retval 0 communications should continue
871 * @retval 1 communications should not continue
873 static int http_should_fail(struct connectdata *conn)
875 struct SessionHandle *data;
882 httpcode = data->req.httpcode;
885 ** If we haven't been asked to fail on error,
888 if(!data->set.http_fail_on_error)
892 ** Any code < 400 is never terminal.
897 if(data->state.resume_from &&
898 (data->set.httpreq==HTTPREQ_GET) &&
900 /* "Requested Range Not Satisfiable", just proceed and
901 pretend this is no error */
906 ** Any code >= 400 that's not 401 or 407 is always
909 if((httpcode != 401) &&
914 ** All we have left to deal with is 401 and 407
916 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
919 ** Examine the current authentication state to see if this
920 ** is an error. The idea is for this function to get
921 ** called after processing all the headers in a response
922 ** message. So, if we've been to asked to authenticate a
923 ** particular stage, and we've done it, we're OK. But, if
924 ** we're already completely authenticated, it's not OK to
925 ** get another 401 or 407.
927 ** It is possible for authentication to go stale such that
928 ** the client needs to reauthenticate. Once that info is
929 ** available, use it here.
933 ** Either we're not authenticating, or we're supposed to
934 ** be authenticating something else. This is an error.
936 if((httpcode == 401) && !conn->bits.user_passwd)
938 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
941 return data->state.authproblem;
945 * readmoredata() is a "fread() emulation" to provide POST and/or request
946 * data. It is used when a huge POST is to be made and the entire chunk wasn't
947 * sent in the first send(). This function will then be called from the
948 * transfer.c loop when more data is to be sent to the peer.
950 * Returns the amount of bytes it filled the buffer with.
952 static size_t readmoredata(char *buffer,
957 struct connectdata *conn = (struct connectdata *)userp;
958 struct HTTP *http = conn->data->req.protop;
959 size_t fullsize = size * nitems;
961 if(0 == http->postsize)
962 /* nothing to return */
965 /* make sure that a HTTP request is never sent away chunked! */
966 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
968 if(http->postsize <= (curl_off_t)fullsize) {
969 memcpy(buffer, http->postdata, (size_t)http->postsize);
970 fullsize = (size_t)http->postsize;
972 if(http->backup.postsize) {
973 /* move backup data into focus and continue on that */
974 http->postdata = http->backup.postdata;
975 http->postsize = http->backup.postsize;
976 conn->fread_func = http->backup.fread_func;
977 conn->fread_in = http->backup.fread_in;
979 http->sending++; /* move one step up */
981 http->backup.postsize=0;
989 memcpy(buffer, http->postdata, fullsize);
990 http->postdata += fullsize;
991 http->postsize -= fullsize;
996 /* ------------------------------------------------------------------------- */
997 /* add_buffer functions */
1000 * Curl_add_buffer_init() sets up and returns a fine buffer struct
1002 Curl_send_buffer *Curl_add_buffer_init(void)
1004 return calloc(1, sizeof(Curl_send_buffer));
1008 * Curl_add_buffer_send() sends a header buffer and frees all associated
1009 * memory. Body data may be appended to the header data if desired.
1013 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
1014 struct connectdata *conn,
1016 /* add the number of sent bytes to this
1018 long *bytes_written,
1020 /* how much of the buffer contains body data */
1021 size_t included_body_bytes,
1029 struct HTTP *http = conn->data->req.protop;
1031 curl_socket_t sockfd;
1034 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1036 sockfd = conn->sock[socketindex];
1038 /* The looping below is required since we use non-blocking sockets, but due
1039 to the circumstances we will just loop and try again and again etc */
1042 size = in->size_used;
1044 headersize = size - included_body_bytes; /* the initial part that isn't body
1047 DEBUGASSERT(size > included_body_bytes);
1049 res = Curl_convert_to_network(conn->data, ptr, headersize);
1050 /* Curl_convert_to_network calls failf if unsuccessful */
1052 /* conversion failed, free memory and return to the caller */
1060 if(conn->handler->flags & PROTOPT_SSL) {
1061 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1062 when we speak HTTPS, as if only a fraction of it is sent now, this data
1063 needs to fit into the normal read-callback buffer later on and that
1064 buffer is using this size.
1067 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1069 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1070 library when we attempt to re-send this buffer. Sending the same data
1071 is not enough, we must use the exact same address. For this reason, we
1072 must copy the data to the uploadbuffer first, since that is the buffer
1073 we will be using if this send is retried later.
1075 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1076 ptr = conn->data->state.uploadbuffer;
1081 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1083 if(CURLE_OK == res) {
1085 * Note that we may not send the entire chunk at once, and we have a set
1086 * number of data bytes at the end of the big buffer (out of which we may
1087 * only send away a part).
1089 /* how much of the header that was sent */
1090 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1091 size_t bodylen = amount - headlen;
1093 if(conn->data->set.verbose) {
1094 /* this data _may_ contain binary stuff */
1095 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1097 /* there was body data sent beyond the initial header part, pass that
1098 on to the debug callback too */
1099 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1100 ptr+headlen, bodylen, conn);
1104 /* since we sent a piece of the body here, up the byte counter for it
1106 http->writebytecount += bodylen;
1108 /* 'amount' can never be a very large value here so typecasting it so a
1109 signed 31 bit value should not cause problems even if ssize_t is
1111 *bytes_written += (long)amount;
1114 if((size_t)amount != size) {
1115 /* The whole request could not be sent in one system call. We must
1116 queue it up and send it later when we get the chance. We must not
1117 loop here and wait until it might work again. */
1121 ptr = in->buffer + amount;
1123 /* backup the currently set pointers */
1124 http->backup.fread_func = conn->fread_func;
1125 http->backup.fread_in = conn->fread_in;
1126 http->backup.postdata = http->postdata;
1127 http->backup.postsize = http->postsize;
1129 /* set the new pointers for the request-sending */
1130 conn->fread_func = (curl_read_callback)readmoredata;
1131 conn->fread_in = (void *)conn;
1132 http->postdata = ptr;
1133 http->postsize = (curl_off_t)size;
1135 http->send_buffer = in;
1136 http->sending = HTTPSEND_REQUEST;
1140 http->sending = HTTPSEND_BODY;
1141 /* the full buffer was sent, clean up and return */
1144 if((size_t)amount != size)
1145 /* We have no continue-send mechanism now, fail. This can only happen
1146 when this function is used from the CONNECT sending function. We
1147 currently (stupidly) assume that the whole request is always sent
1148 away in the first single chunk.
1152 return CURLE_SEND_ERROR;
1154 conn->writechannel_inuse = FALSE;
1166 * add_bufferf() add the formatted input to the buffer.
1168 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1173 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1177 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1181 /* If we failed, we cleanup the whole buffer and return error */
1185 return CURLE_OUT_OF_MEMORY;
1189 * add_buffer() appends a memory chunk to the existing buffer
1191 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1196 if(~size < in->size_used) {
1197 /* If resulting used size of send buffer would wrap size_t, cleanup
1198 the whole buffer and return error. Otherwise the required buffer
1199 size will fit into a single allocatable memory chunk */
1200 Curl_safefree(in->buffer);
1202 return CURLE_OUT_OF_MEMORY;
1206 ((in->size_used + size) > (in->size_max - 1))) {
1208 /* If current buffer size isn't enough to hold the result, use a
1209 buffer size that doubles the required size. If this new size
1210 would wrap size_t, then just use the largest possible one */
1212 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1213 (~(size*2) < (in->size_used*2)))
1214 new_size = (size_t)-1;
1216 new_size = (in->size_used+size)*2;
1219 /* we have a buffer, enlarge the existing one */
1220 new_rb = realloc(in->buffer, new_size);
1222 /* create a new buffer */
1223 new_rb = malloc(new_size);
1226 /* If we failed, we cleanup the whole buffer and return error */
1227 Curl_safefree(in->buffer);
1229 return CURLE_OUT_OF_MEMORY;
1232 in->buffer = new_rb;
1233 in->size_max = new_size;
1235 memcpy(&in->buffer[in->size_used], inptr, size);
1237 in->size_used += size;
1242 /* end of the add_buffer functions */
1243 /* ------------------------------------------------------------------------- */
1248 * Curl_compareheader()
1250 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1251 * Pass headers WITH the colon.
1254 Curl_compareheader(const char *headerline, /* line to check */
1255 const char *header, /* header keyword _with_ colon */
1256 const char *content) /* content string to find */
1258 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1259 * by a colon (":") and the field value. Field names are case-insensitive.
1260 * The field value MAY be preceded by any amount of LWS, though a single SP
1263 size_t hlen = strlen(header);
1269 if(!Curl_raw_nequal(headerline, header, hlen))
1270 return FALSE; /* doesn't start with header */
1272 /* pass the header */
1273 start = &headerline[hlen];
1275 /* pass all white spaces */
1276 while(*start && ISSPACE(*start))
1279 /* find the end of the header line */
1280 end = strchr(start, '\r'); /* lines end with CRLF */
1282 /* in case there's a non-standard compliant line here */
1283 end = strchr(start, '\n');
1286 /* hm, there's no line ending here, use the zero byte! */
1287 end = strchr(start, '\0');
1290 len = end-start; /* length of the content part of the input line */
1291 clen = strlen(content); /* length of the word to find */
1293 /* find the content string in the rest of the line */
1294 for(;len>=clen;len--, start++) {
1295 if(Curl_raw_nequal(start, content, clen))
1296 return TRUE; /* match! */
1299 return FALSE; /* no match */
1303 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1304 * the generic Curl_connect().
1306 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1310 /* We default to persistent connections. We set this already in this connect
1311 function to make the re-use checks properly be able to check this bit. */
1312 conn->bits.close = FALSE;
1314 /* the CONNECT procedure might not have been completed */
1315 result = Curl_proxy_connect(conn);
1319 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1320 /* nothing else to do except wait right now - we're not done here. */
1323 if(conn->given->flags & PROTOPT_SSL) {
1324 /* perform SSL initialization */
1325 result = https_connecting(conn, done);
1335 /* this returns the socket to wait for in the DO and DOING state for the multi
1336 interface and then we're always _sending_ a request and thus we wait for
1337 the single socket to become writable only */
1338 static int http_getsock_do(struct connectdata *conn,
1339 curl_socket_t *socks,
1343 (void)numsocks; /* unused, we trust it to be at least 1 */
1344 socks[0] = conn->sock[FIRSTSOCKET];
1345 return GETSOCK_WRITESOCK(0);
1349 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1352 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1354 /* perform SSL initialization for this socket */
1355 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1357 conn->bits.close = TRUE; /* a failed connection is marked for closure
1358 to prevent (bad) re-use or similar */
1363 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
1364 defined(USE_DARWINSSL)
1365 /* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only.
1366 It should be made to query the generic SSL layer instead. */
1367 static int https_getsock(struct connectdata *conn,
1368 curl_socket_t *socks,
1371 if(conn->handler->flags & PROTOPT_SSL) {
1372 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1375 return GETSOCK_BLANK;
1377 if(connssl->connecting_state == ssl_connect_2_writing) {
1379 socks[0] = conn->sock[FIRSTSOCKET];
1380 return GETSOCK_WRITESOCK(0);
1382 else if(connssl->connecting_state == ssl_connect_2_reading) {
1384 socks[0] = conn->sock[FIRSTSOCKET];
1385 return GETSOCK_READSOCK(0);
1392 static int https_getsock(struct connectdata *conn,
1393 curl_socket_t *socks,
1399 return GETSOCK_BLANK;
1401 #endif /* USE_SSL */
1402 #endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
1405 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1406 * has been performed.
1409 CURLcode Curl_http_done(struct connectdata *conn,
1410 CURLcode status, bool premature)
1412 struct SessionHandle *data = conn->data;
1413 struct HTTP *http =data->req.protop;
1415 Curl_unencode_cleanup(conn);
1417 /* set the proper values (possibly modified on POST) */
1418 conn->fread_func = data->set.fread_func; /* restore */
1419 conn->fread_in = data->set.in; /* restore */
1420 conn->seek_func = data->set.seek_func; /* restore */
1421 conn->seek_client = data->set.seek_client; /* restore */
1426 if(http->send_buffer) {
1427 Curl_send_buffer *buff = http->send_buffer;
1431 http->send_buffer = NULL; /* clear the pointer */
1434 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1435 data->req.bytecount = http->readbytecount + http->writebytecount;
1437 Curl_formclean(&http->sendit); /* Now free that whole lot */
1439 /* a file being uploaded was left opened, close it! */
1440 fclose(http->form.fp);
1441 http->form.fp = NULL;
1444 else if(HTTPREQ_PUT == data->set.httpreq)
1445 data->req.bytecount = http->readbytecount + http->writebytecount;
1447 if(status != CURLE_OK)
1450 if(!premature && /* this check is pointless when DONE is called before the
1451 entire operation is complete */
1452 !conn->bits.retry &&
1453 !data->set.connect_only &&
1454 ((http->readbytecount +
1455 data->req.headerbytecount -
1456 data->req.deductheadercount)) <= 0) {
1457 /* If this connection isn't simply closed to be retried, AND nothing was
1458 read from the HTTP server (that counts), this can't be right so we
1459 return an error here */
1460 failf(data, "Empty reply from server");
1461 return CURLE_GOT_NOTHING;
1469 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1470 * to avoid it include:
1472 * - if the user specifically requested HTTP 1.0
1473 * - if the server we are connected to only supports 1.0
1474 * - if any server previously contacted to handle this request only supports
1477 static bool use_http_1_1plus(const struct SessionHandle *data,
1478 const struct connectdata *conn)
1480 return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
1481 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1482 ((conn->httpversion == 11) ||
1483 ((conn->httpversion != 10) &&
1484 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1487 /* check and possibly add an Expect: header */
1488 static CURLcode expect100(struct SessionHandle *data,
1489 struct connectdata *conn,
1490 Curl_send_buffer *req_buffer)
1492 CURLcode result = CURLE_OK;
1494 data->state.expect100header = FALSE; /* default to false unless it is set
1496 if(conn->httpversion == 20) {
1497 /* We don't use Expect in HTTP2 */
1500 if(use_http_1_1plus(data, conn)) {
1501 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1502 100-continue to the headers which actually speeds up post operations
1503 (as there is one packet coming back from the web server) */
1504 ptr = Curl_checkheaders(data, "Expect:");
1506 data->state.expect100header =
1507 Curl_compareheader(ptr, "Expect:", "100-continue");
1510 result = Curl_add_bufferf(req_buffer,
1511 "Expect: 100-continue\r\n");
1512 if(result == CURLE_OK)
1513 data->state.expect100header = TRUE;
1519 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1520 Curl_send_buffer *req_buffer)
1523 struct curl_slist *headers=conn->data->set.headers;
1526 ptr = strchr(headers->data, ':');
1528 /* we require a colon for this to be a true header */
1530 ptr++; /* pass the colon */
1531 while(*ptr && ISSPACE(*ptr))
1535 /* only send this if the contents was non-blank */
1537 if(conn->allocptr.host &&
1538 /* a Host: header was sent already, don't pass on any custom Host:
1539 header as that will produce *two* in the same request! */
1540 checkprefix("Host:", headers->data))
1542 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
1543 /* this header (extended by formdata.c) is sent later */
1544 checkprefix("Content-Type:", headers->data))
1546 else if(conn->bits.authneg &&
1547 /* while doing auth neg, don't allow the custom length since
1548 we will force length zero then */
1549 checkprefix("Content-Length", headers->data))
1551 else if(conn->allocptr.te &&
1552 /* when asking for Transfer-Encoding, don't pass on a custom
1554 checkprefix("Connection", headers->data))
1557 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1565 ptr = strchr(headers->data, ';');
1568 ptr++; /* pass the semicolon */
1569 while(*ptr && ISSPACE(*ptr))
1573 /* this may be used for something else in the future */
1576 if(*(--ptr) == ';') {
1579 /* send no-value custom header if terminated by semicolon */
1581 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1589 headers = headers->next;
1594 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1595 Curl_send_buffer *req_buffer)
1597 const struct tm *tm;
1598 char *buf = data->state.buffer;
1599 CURLcode result = CURLE_OK;
1602 result = Curl_gmtime(data->set.timevalue, &keeptime);
1604 failf(data, "Invalid TIMEVALUE");
1609 /* The If-Modified-Since header family should have their times set in
1610 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1611 * represented in Greenwich Mean Time (GMT), without exception. For the
1612 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1613 * Time)." (see page 20 of RFC2616).
1616 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1617 snprintf(buf, BUFSIZE-1,
1618 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1619 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1621 Curl_month[tm->tm_mon],
1627 switch(data->set.timecondition) {
1628 case CURL_TIMECOND_IFMODSINCE:
1630 result = Curl_add_bufferf(req_buffer,
1631 "If-Modified-Since: %s\r\n", buf);
1633 case CURL_TIMECOND_IFUNMODSINCE:
1634 result = Curl_add_bufferf(req_buffer,
1635 "If-Unmodified-Since: %s\r\n", buf);
1637 case CURL_TIMECOND_LASTMOD:
1638 result = Curl_add_bufferf(req_buffer,
1639 "Last-Modified: %s\r\n", buf);
1647 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1648 * request is to be performed. This creates and sends a properly constructed
1651 CURLcode Curl_http(struct connectdata *conn, bool *done)
1653 struct SessionHandle *data=conn->data;
1654 CURLcode result=CURLE_OK;
1656 const char *ppath = data->state.path;
1657 bool paste_ftp_userpwd = FALSE;
1658 char ftp_typecode[sizeof("/;type=?")] = "";
1659 const char *host = conn->host.name;
1660 const char *te = ""; /* transfer-encoding */
1662 const char *request;
1663 Curl_HttpReq httpreq = data->set.httpreq;
1664 char *addcookies = NULL;
1665 curl_off_t included_body = 0;
1666 const char *httpstring;
1667 Curl_send_buffer *req_buffer;
1668 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1669 int seekerr = CURL_SEEKFUNC_OK;
1671 /* Always consider the DO phase done after this function call, even if there
1672 may be parts of the request that is not yet sent, since we can deal with
1673 the rest of the request in the PERFORM phase. */
1676 switch (conn->negnpn) {
1677 case NPN_HTTP2_DRAFT09:
1678 infof(data, "http, we have to use HTTP-draft-09/2\n");
1679 Curl_http2_init(conn);
1680 Curl_http2_switched(conn);
1683 /* continue with HTTP/1.1 when explicitly requested */
1686 /* and as fallback */
1690 http = data->req.protop;
1692 if(!data->state.this_is_a_follow) {
1693 /* this is not a followed location, get the original host name */
1694 if(data->state.first_host)
1695 /* Free to avoid leaking memory on multiple requests*/
1696 free(data->state.first_host);
1698 data->state.first_host = strdup(conn->host.name);
1699 if(!data->state.first_host)
1700 return CURLE_OUT_OF_MEMORY;
1702 http->writebytecount = http->readbytecount = 0;
1704 if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
1706 httpreq = HTTPREQ_PUT;
1709 /* Now set the 'request' pointer to the proper request string */
1710 if(data->set.str[STRING_CUSTOMREQUEST])
1711 request = data->set.str[STRING_CUSTOMREQUEST];
1713 if(data->set.opt_no_body)
1716 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1719 case HTTPREQ_POST_FORM:
1725 default: /* this should never happen */
1736 /* The User-Agent string might have been allocated in url.c already, because
1737 it might have been used in the proxy connect, but if we have got a header
1738 with the user-agent string specified, we erase the previously made string
1740 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
1741 free(conn->allocptr.uagent);
1742 conn->allocptr.uagent=NULL;
1745 /* setup the authentication headers */
1746 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1750 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1751 (httpreq != HTTPREQ_GET) &&
1752 (httpreq != HTTPREQ_HEAD)) {
1753 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1754 with content-length zero as a "probe". */
1755 conn->bits.authneg = TRUE;
1758 conn->bits.authneg = FALSE;
1760 Curl_safefree(conn->allocptr.ref);
1761 if(data->change.referer && !Curl_checkheaders(data, "Referer:")) {
1762 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1763 if(!conn->allocptr.ref)
1764 return CURLE_OUT_OF_MEMORY;
1767 conn->allocptr.ref = NULL;
1769 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
1770 addcookies = data->set.str[STRING_COOKIE];
1772 if(!Curl_checkheaders(data, "Accept-Encoding:") &&
1773 data->set.str[STRING_ENCODING]) {
1774 Curl_safefree(conn->allocptr.accept_encoding);
1775 conn->allocptr.accept_encoding =
1776 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1777 if(!conn->allocptr.accept_encoding)
1778 return CURLE_OUT_OF_MEMORY;
1782 /* we only consider transfer-encoding magic if libz support is built-in */
1784 if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) {
1785 /* When we are to insert a TE: header in the request, we must also insert
1786 TE in a Connection: header, so we need to merge the custom provided
1787 Connection: header and prevent the original to get sent. Note that if
1788 the user has inserted his/hers own TE: header we don't do this magic
1789 but then assume that the user will handle it all! */
1790 char *cptr = Curl_checkheaders(data, "Connection:");
1791 #define TE_HEADER "TE: gzip\r\n"
1793 Curl_safefree(conn->allocptr.te);
1795 /* Create the (updated) Connection: header */
1796 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1797 strdup("Connection: TE\r\n" TE_HEADER);
1799 if(!conn->allocptr.te)
1800 return CURLE_OUT_OF_MEMORY;
1804 if(conn->httpversion == 20)
1805 /* In HTTP2 forbids Transfer-Encoding: chunked */
1808 ptr = Curl_checkheaders(data, "Transfer-Encoding:");
1810 /* Some kind of TE is requested, check if 'chunked' is chosen */
1811 data->req.upload_chunky =
1812 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1815 if((conn->handler->protocol&CURLPROTO_HTTP) &&
1817 (data->set.infilesize == -1)) {
1818 if(conn->bits.authneg)
1819 /* don't enable chunked during auth neg */
1821 else if(use_http_1_1plus(data, conn)) {
1822 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1823 data->req.upload_chunky = TRUE;
1826 failf(data, "Chunky upload is not supported by HTTP 1.0");
1827 return CURLE_UPLOAD_FAILED;
1831 /* else, no chunky upload */
1832 data->req.upload_chunky = FALSE;
1835 if(data->req.upload_chunky)
1836 te = "Transfer-Encoding: chunked\r\n";
1840 Curl_safefree(conn->allocptr.host);
1842 ptr = Curl_checkheaders(data, "Host:");
1843 if(ptr && (!data->state.this_is_a_follow ||
1844 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1845 #if !defined(CURL_DISABLE_COOKIES)
1846 /* If we have a given custom Host: header, we extract the host name in
1847 order to possibly use it for cookie reasons later on. We only allow the
1848 custom Host: header if this is NOT a redirect, as setting Host: in the
1849 redirected request is being out on thin ice. Except if the host name
1850 is the same as the first one! */
1851 char *cookiehost = Curl_copy_header_value(ptr);
1853 return CURLE_OUT_OF_MEMORY;
1855 /* ignore empty data */
1858 /* If the host begins with '[', we start searching for the port after
1859 the bracket has been closed */
1860 int startsearch = 0;
1861 if(*cookiehost == '[') {
1862 char *closingbracket;
1863 /* since the 'cookiehost' is an allocated memory area that will be
1864 freed later we cannot simply increment the pointer */
1865 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
1866 closingbracket = strchr(cookiehost, ']');
1868 *closingbracket = 0;
1871 char *colon = strchr(cookiehost + startsearch, ':');
1873 *colon = 0; /* The host must not include an embedded port number */
1875 Curl_safefree(conn->allocptr.cookiehost);
1876 conn->allocptr.cookiehost = cookiehost;
1880 conn->allocptr.host = NULL;
1883 /* When building Host: headers, we must put the host name within
1884 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
1886 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
1887 (conn->remote_port == PORT_HTTPS)) ||
1888 ((conn->given->protocol&CURLPROTO_HTTP) &&
1889 (conn->remote_port == PORT_HTTP)) )
1890 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
1891 the port number in the host string */
1892 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
1893 conn->bits.ipv6_ip?"[":"",
1895 conn->bits.ipv6_ip?"]":"");
1897 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
1898 conn->bits.ipv6_ip?"[":"",
1900 conn->bits.ipv6_ip?"]":"",
1903 if(!conn->allocptr.host)
1904 /* without Host: we can't make a nice request */
1905 return CURLE_OUT_OF_MEMORY;
1908 #ifndef CURL_DISABLE_PROXY
1909 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
1910 /* Using a proxy but does not tunnel through it */
1912 /* The path sent to the proxy is in fact the entire URL. But if the remote
1913 host is a IDN-name, we must make sure that the request we produce only
1914 uses the encoded host name! */
1915 if(conn->host.dispname != conn->host.name) {
1916 char *url = data->change.url;
1917 ptr = strstr(url, conn->host.dispname);
1919 /* This is where the display name starts in the URL, now replace this
1920 part with the encoded name. TODO: This method of replacing the host
1921 name is rather crude as I believe there's a slight risk that the
1922 user has entered a user name or password that contain the host name
1924 size_t currlen = strlen(conn->host.dispname);
1925 size_t newlen = strlen(conn->host.name);
1926 size_t urllen = strlen(url);
1930 newurl = malloc(urllen + newlen - currlen + 1);
1932 /* copy the part before the host name */
1933 memcpy(newurl, url, ptr - url);
1934 /* append the new host name instead of the old */
1935 memcpy(newurl + (ptr - url), conn->host.name, newlen);
1936 /* append the piece after the host name */
1937 memcpy(newurl + newlen + (ptr - url),
1938 ptr + currlen, /* copy the trailing zero byte too */
1939 urllen - (ptr-url) - currlen + 1);
1940 if(data->change.url_alloc) {
1941 Curl_safefree(data->change.url);
1942 data->change.url_alloc = FALSE;
1944 data->change.url = newurl;
1945 data->change.url_alloc = TRUE;
1948 return CURLE_OUT_OF_MEMORY;
1951 ppath = data->change.url;
1952 if(checkprefix("ftp://", ppath)) {
1953 if(data->set.proxy_transfer_mode) {
1954 /* when doing ftp, append ;type=<a|i> if not present */
1955 char *type = strstr(ppath, ";type=");
1956 if(type && type[6] && type[7] == 0) {
1957 switch (Curl_raw_toupper(type[6])) {
1967 char *p = ftp_typecode;
1968 /* avoid sending invalid URLs like ftp://example.com;type=i if the
1969 * user specified ftp://example.com without the slash */
1970 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
1973 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
1974 data->set.prefer_ascii ? 'a' : 'i');
1977 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
1978 paste_ftp_userpwd = TRUE;
1981 #endif /* CURL_DISABLE_PROXY */
1983 if(HTTPREQ_POST_FORM == httpreq) {
1984 /* we must build the whole post sequence first, so that we have a size of
1985 the whole transfer before we start to send it */
1986 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
1987 Curl_checkheaders(data, "Content-Type:"),
1993 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
1995 if(( (HTTPREQ_POST == httpreq) ||
1996 (HTTPREQ_POST_FORM == httpreq) ||
1997 (HTTPREQ_PUT == httpreq) ) &&
1998 data->state.resume_from) {
1999 /**********************************************************************
2000 * Resuming upload in HTTP means that we PUT or POST and that we have
2001 * got a resume_from value set. The resume value has already created
2002 * a Range: header that will be passed along. We need to "fast forward"
2003 * the file the given number of bytes and decrease the assume upload
2004 * file size before we continue this venture in the dark lands of HTTP.
2005 *********************************************************************/
2007 if(data->state.resume_from < 0 ) {
2009 * This is meant to get the size of the present remote-file by itself.
2010 * We don't support this now. Bail out!
2012 data->state.resume_from = 0;
2015 if(data->state.resume_from && !data->state.this_is_a_follow) {
2016 /* do we still game? */
2018 /* Now, let's read off the proper amount of bytes from the
2020 if(conn->seek_func) {
2021 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2025 if(seekerr != CURL_SEEKFUNC_OK) {
2026 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2027 failf(data, "Could not seek stream");
2028 return CURLE_READ_ERROR;
2030 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2032 curl_off_t passed=0;
2034 size_t readthisamountnow =
2035 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2036 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2038 size_t actuallyread =
2039 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2042 passed += actuallyread;
2043 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2044 /* this checks for greater-than only to make sure that the
2045 CURL_READFUNC_ABORT return code still aborts */
2046 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2047 " bytes from the input", passed);
2048 return CURLE_READ_ERROR;
2050 } while(passed < data->state.resume_from);
2054 /* now, decrease the size of the read */
2055 if(data->set.infilesize>0) {
2056 data->set.infilesize -= data->state.resume_from;
2058 if(data->set.infilesize <= 0) {
2059 failf(data, "File already completely uploaded");
2060 return CURLE_PARTIAL_FILE;
2063 /* we've passed, proceed as normal */
2066 if(data->state.use_range) {
2068 * A range is selected. We use different headers whether we're downloading
2069 * or uploading and we always let customized headers override our internal
2070 * ones if any such are specified.
2072 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2073 !Curl_checkheaders(data, "Range:")) {
2074 /* if a line like this was already allocated, free the previous one */
2075 if(conn->allocptr.rangeline)
2076 free(conn->allocptr.rangeline);
2077 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2080 else if((httpreq != HTTPREQ_GET) &&
2081 !Curl_checkheaders(data, "Content-Range:")) {
2083 /* if a line like this was already allocated, free the previous one */
2084 if(conn->allocptr.rangeline)
2085 free(conn->allocptr.rangeline);
2087 if(data->set.set_resume_from < 0) {
2088 /* Upload resume was asked for, but we don't know the size of the
2089 remote part so we tell the server (and act accordingly) that we
2090 upload the whole file (again) */
2091 conn->allocptr.rangeline =
2092 aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
2093 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2094 data->set.infilesize - 1, data->set.infilesize);
2097 else if(data->state.resume_from) {
2098 /* This is because "resume" was selected */
2099 curl_off_t total_expected_size=
2100 data->state.resume_from + data->set.infilesize;
2101 conn->allocptr.rangeline =
2102 aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
2103 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2104 data->state.range, total_expected_size-1,
2105 total_expected_size);
2108 /* Range was selected and then we just pass the incoming range and
2109 append total size */
2110 conn->allocptr.rangeline =
2111 aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2112 data->state.range, data->set.infilesize);
2114 if(!conn->allocptr.rangeline)
2115 return CURLE_OUT_OF_MEMORY;
2119 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2121 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
2123 /* initialize a dynamic send-buffer */
2124 req_buffer = Curl_add_buffer_init();
2127 return CURLE_OUT_OF_MEMORY;
2129 /* add the main request stuff */
2130 /* GET/HEAD/POST/PUT */
2131 result = Curl_add_bufferf(req_buffer, "%s ", request);
2136 if(paste_ftp_userpwd)
2137 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2138 conn->user, conn->passwd,
2139 ppath + sizeof("ftp://") - 1);
2141 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2146 Curl_add_bufferf(req_buffer,
2147 "%s" /* ftp typecode (;type=x) */
2148 " HTTP/%s\r\n" /* HTTP version */
2149 "%s" /* proxyuserpwd */
2152 "%s" /* user agent */
2156 "%s" /* accept-encoding */
2158 "%s" /* Proxy-Connection */
2159 "%s",/* transfer-encoding */
2163 conn->allocptr.proxyuserpwd?
2164 conn->allocptr.proxyuserpwd:"",
2165 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2166 (data->state.use_range && conn->allocptr.rangeline)?
2167 conn->allocptr.rangeline:"",
2168 (data->set.str[STRING_USERAGENT] &&
2169 *data->set.str[STRING_USERAGENT] &&
2170 conn->allocptr.uagent)?
2171 conn->allocptr.uagent:"",
2172 (conn->allocptr.host?conn->allocptr.host:""),
2173 http->p_accept?http->p_accept:"",
2174 conn->allocptr.te?conn->allocptr.te:"",
2175 (data->set.str[STRING_ENCODING] &&
2176 *data->set.str[STRING_ENCODING] &&
2177 conn->allocptr.accept_encoding)?
2178 conn->allocptr.accept_encoding:"",
2179 (data->change.referer && conn->allocptr.ref)?
2180 conn->allocptr.ref:"" /* Referer: <data> */,
2181 (conn->bits.httpproxy &&
2182 !conn->bits.tunnel_proxy &&
2183 !Curl_checkheaders(data, "Proxy-Connection:"))?
2184 "Proxy-Connection: Keep-Alive\r\n":"",
2189 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2190 * with basic and digest, it will be freed anyway by the next request
2193 Curl_safefree (conn->allocptr.userpwd);
2194 conn->allocptr.userpwd = NULL;
2199 if(!(conn->handler->flags&PROTOPT_SSL) &&
2200 (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
2201 /* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
2203 result = Curl_http2_request_upgrade(req_buffer, conn);
2208 #if !defined(CURL_DISABLE_COOKIES)
2209 if(data->cookies || addcookies) {
2210 struct Cookie *co=NULL; /* no cookies from start */
2214 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2215 co = Curl_cookie_getlist(data->cookies,
2216 conn->allocptr.cookiehost?
2217 conn->allocptr.cookiehost:host,
2219 (conn->handler->protocol&CURLPROTO_HTTPS)?
2221 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2224 struct Cookie *store=co;
2225 /* now loop through all cookies that matched */
2229 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2233 result = Curl_add_bufferf(req_buffer,
2234 "%s%s=%s", count?"; ":"",
2235 co->name, co->value);
2240 co = co->next; /* next cookie please */
2242 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2244 if(addcookies && (CURLE_OK == result)) {
2246 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2247 if(CURLE_OK == result) {
2248 result = Curl_add_bufferf(req_buffer, "%s%s",
2254 if(count && (CURLE_OK == result))
2255 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2262 if(data->set.timecondition) {
2263 result = Curl_add_timecondition(data, req_buffer);
2268 result = Curl_add_custom_headers(conn, req_buffer);
2272 http->postdata = NULL; /* nothing to post at this point */
2273 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2275 /* If 'authdone' is FALSE, we must not set the write socket index to the
2276 Curl_transfer() call below, as we're not ready to actually upload any
2281 case HTTPREQ_POST_FORM:
2282 if(!http->sendit || conn->bits.authneg) {
2283 /* nothing to post! */
2284 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2288 result = Curl_add_buffer_send(req_buffer, conn,
2289 &data->info.request_size, 0, FIRSTSOCKET);
2291 failf(data, "Failed sending POST request");
2293 /* setup variables for the upcoming transfer */
2294 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2299 if(Curl_FormInit(&http->form, http->sendit)) {
2300 failf(data, "Internal HTTP POST error!");
2301 return CURLE_HTTP_POST_ERROR;
2304 /* Get the currently set callback function pointer and store that in the
2305 form struct since we might want the actual user-provided callback later
2306 on. The conn->fread_func pointer itself will be changed for the
2307 multipart case to the function that returns a multipart formatted
2309 http->form.fread_func = conn->fread_func;
2311 /* Set the read function to read from the generated form data */
2312 conn->fread_func = (curl_read_callback)Curl_FormReader;
2313 conn->fread_in = &http->form;
2315 http->sending = HTTPSEND_BODY;
2317 if(!data->req.upload_chunky &&
2318 !Curl_checkheaders(data, "Content-Length:")) {
2319 /* only add Content-Length if not uploading chunked */
2320 result = Curl_add_bufferf(req_buffer,
2321 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2322 "\r\n", http->postsize);
2327 result = expect100(data, conn, req_buffer);
2333 /* Get Content-Type: line from Curl_formpostheader.
2336 size_t linelength=0;
2337 contentType = Curl_formpostheader((void *)&http->form,
2340 failf(data, "Could not get Content-Type header line!");
2341 return CURLE_HTTP_POST_ERROR;
2344 result = Curl_add_buffer(req_buffer, contentType, linelength);
2349 /* make the request end in a true CRLF */
2350 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2354 /* set upload size to the progress meter */
2355 Curl_pgrsSetUploadSize(data, http->postsize);
2357 /* fire away the whole request to the server */
2358 result = Curl_add_buffer_send(req_buffer, conn,
2359 &data->info.request_size, 0, FIRSTSOCKET);
2361 failf(data, "Failed sending POST request");
2363 /* setup variables for the upcoming transfer */
2364 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2365 &http->readbytecount, FIRSTSOCKET,
2366 &http->writebytecount);
2369 Curl_formclean(&http->sendit); /* free that whole lot */
2373 /* convert the form data */
2374 result = Curl_convert_form(data, http->sendit);
2376 Curl_formclean(&http->sendit); /* free that whole lot */
2382 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2384 if(conn->bits.authneg)
2387 postsize = data->set.infilesize;
2389 if((postsize != -1) && !data->req.upload_chunky &&
2390 !Curl_checkheaders(data, "Content-Length:")) {
2391 /* only add Content-Length if not uploading chunked */
2392 result = Curl_add_bufferf(req_buffer,
2393 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2399 result = expect100(data, conn, req_buffer);
2403 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2407 /* set the upload size to the progress meter */
2408 Curl_pgrsSetUploadSize(data, postsize);
2410 /* this sends the buffer and frees all the buffer resources */
2411 result = Curl_add_buffer_send(req_buffer, conn,
2412 &data->info.request_size, 0, FIRSTSOCKET);
2414 failf(data, "Failed sending PUT request");
2416 /* prepare for transfer */
2417 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2418 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2419 postsize?&http->writebytecount:NULL);
2425 /* this is the simple POST, using x-www-form-urlencoded style */
2427 if(conn->bits.authneg)
2430 /* figure out the size of the postfields */
2431 postsize = (data->set.postfieldsize != -1)?
2432 data->set.postfieldsize:
2433 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2436 /* We only set Content-Length and allow a custom Content-Length if
2437 we don't upload data chunked, as RFC2616 forbids us to set both
2438 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2439 if((postsize != -1) && !data->req.upload_chunky &&
2440 !Curl_checkheaders(data, "Content-Length:")) {
2441 /* we allow replacing this header if not during auth negotiation,
2442 although it isn't very wise to actually set your own */
2443 result = Curl_add_bufferf(req_buffer,
2444 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2450 if(!Curl_checkheaders(data, "Content-Type:")) {
2451 result = Curl_add_bufferf(req_buffer,
2452 "Content-Type: application/"
2453 "x-www-form-urlencoded\r\n");
2458 /* For really small posts we don't use Expect: headers at all, and for
2459 the somewhat bigger ones we allow the app to disable it. Just make
2460 sure that the expect100header is always set to the preferred value
2462 ptr = Curl_checkheaders(data, "Expect:");
2464 data->state.expect100header =
2465 Curl_compareheader(ptr, "Expect:", "100-continue");
2467 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2468 result = expect100(data, conn, req_buffer);
2473 data->state.expect100header = FALSE;
2475 if(data->set.postfields) {
2477 /* In HTTP2, we send request body in DATA frame regardless of
2479 if(conn->httpversion != 20 &&
2480 !data->state.expect100header &&
2481 (postsize < MAX_INITIAL_POST_SIZE)) {
2482 /* if we don't use expect: 100 AND
2483 postsize is less than MAX_INITIAL_POST_SIZE
2485 then append the post data to the HTTP request header. This limit
2486 is no magic limit but only set to prevent really huge POSTs to
2487 get the data duplicated with malloc() and family. */
2489 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2493 if(!data->req.upload_chunky) {
2494 /* We're not sending it 'chunked', append it to the request
2495 already now to reduce the number if send() calls */
2496 result = Curl_add_buffer(req_buffer, data->set.postfields,
2498 included_body = postsize;
2502 /* Append the POST data chunky-style */
2503 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2504 if(CURLE_OK == result) {
2505 result = Curl_add_buffer(req_buffer, data->set.postfields,
2507 if(CURLE_OK == result)
2508 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2509 included_body = postsize + 2;
2512 if(CURLE_OK == result)
2513 result = Curl_add_buffer(req_buffer,
2514 "\x30\x0d\x0a\x0d\x0a", 5);
2520 /* Make sure the progress information is accurate */
2521 Curl_pgrsSetUploadSize(data, postsize);
2524 /* A huge POST coming up, do data separate from the request */
2525 http->postsize = postsize;
2526 http->postdata = data->set.postfields;
2528 http->sending = HTTPSEND_BODY;
2530 conn->fread_func = (curl_read_callback)readmoredata;
2531 conn->fread_in = (void *)conn;
2533 /* set the upload size to the progress meter */
2534 Curl_pgrsSetUploadSize(data, http->postsize);
2536 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2542 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2546 if(data->req.upload_chunky && conn->bits.authneg) {
2547 /* Chunky upload is selected and we're negotiating auth still, send
2549 result = Curl_add_buffer(req_buffer,
2550 "\x30\x0d\x0a\x0d\x0a", 5);
2556 else if(data->set.postfieldsize) {
2557 /* set the upload size to the progress meter */
2558 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2560 /* set the pointer to mark that we will send the post body using the
2561 read callback, but only if we're not in authenticate
2563 if(!conn->bits.authneg) {
2564 http->postdata = (char *)&http->postdata;
2565 http->postsize = postsize;
2569 /* issue the request */
2570 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2571 (size_t)included_body, FIRSTSOCKET);
2574 failf(data, "Failed sending HTTP POST request");
2576 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2577 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2578 http->postdata?&http->writebytecount:NULL);
2582 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2586 /* issue the request */
2587 result = Curl_add_buffer_send(req_buffer, conn,
2588 &data->info.request_size, 0, FIRSTSOCKET);
2591 failf(data, "Failed sending HTTP request");
2593 /* HTTP GET/HEAD download: */
2594 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2595 http->postdata?FIRSTSOCKET:-1,
2596 http->postdata?&http->writebytecount:NULL);
2601 if(http->writebytecount) {
2602 /* if a request-body has been sent off, we make sure this progress is noted
2604 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2605 if(Curl_pgrsUpdate(conn))
2606 result = CURLE_ABORTED_BY_CALLBACK;
2608 if(http->writebytecount >= postsize) {
2609 /* already sent the entire request body, mark the "upload" as
2611 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
2612 " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
2613 http->writebytecount, postsize);
2614 data->req.upload_done = TRUE;
2615 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2616 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2626 * Returns TRUE if member of the list matches prefix of string
2629 checkhttpprefix(struct SessionHandle *data,
2632 struct curl_slist *head = data->set.http200aliases;
2634 #ifdef CURL_DOES_CONVERSIONS
2635 /* convert from the network encoding using a scratch area */
2636 char *scratch = strdup(s);
2637 if(NULL == scratch) {
2638 failf (data, "Failed to allocate memory for conversion!");
2639 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2641 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2642 /* Curl_convert_from_network calls failf if unsuccessful */
2644 return FALSE; /* can't return CURLE_foobar so return FALSE */
2647 #endif /* CURL_DOES_CONVERSIONS */
2650 if(checkprefix(head->data, s)) {
2657 if(!rc && (checkprefix("HTTP/", s)))
2660 #ifdef CURL_DOES_CONVERSIONS
2662 #endif /* CURL_DOES_CONVERSIONS */
2666 #ifndef CURL_DISABLE_RTSP
2668 checkrtspprefix(struct SessionHandle *data,
2672 #ifdef CURL_DOES_CONVERSIONS
2673 /* convert from the network encoding using a scratch area */
2674 char *scratch = strdup(s);
2675 if(NULL == scratch) {
2676 failf (data, "Failed to allocate memory for conversion!");
2677 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2679 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2680 /* Curl_convert_from_network calls failf if unsuccessful */
2682 return FALSE; /* can't return CURLE_foobar so return FALSE */
2686 (void)data; /* unused */
2687 #endif /* CURL_DOES_CONVERSIONS */
2688 if(checkprefix("RTSP/", s))
2693 #endif /* CURL_DISABLE_RTSP */
2696 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2699 #ifndef CURL_DISABLE_RTSP
2700 if(conn->handler->protocol & CURLPROTO_RTSP)
2701 return checkrtspprefix(data, s);
2704 #endif /* CURL_DISABLE_RTSP */
2706 return checkhttpprefix(data, s);
2710 * header_append() copies a chunk of data to the end of the already received
2711 * header. We make sure that the full string fit in the allocated header
2712 * buffer, or else we enlarge it.
2714 static CURLcode header_append(struct SessionHandle *data,
2715 struct SingleRequest *k,
2718 if(k->hbuflen + length >= data->state.headersize) {
2719 /* We enlarge the header buffer as it is too small */
2724 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2725 /* The reason to have a max limit for this is to avoid the risk of a bad
2726 server feeding libcurl with a never-ending header that will cause
2727 reallocs infinitely */
2728 failf (data, "Avoided giant realloc for header (max is %d)!",
2729 CURL_MAX_HTTP_HEADER);
2730 return CURLE_OUT_OF_MEMORY;
2733 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2734 hbufp_index = k->hbufp - data->state.headerbuff;
2735 newbuff = realloc(data->state.headerbuff, newsize);
2737 failf (data, "Failed to alloc memory for big header!");
2738 return CURLE_OUT_OF_MEMORY;
2740 data->state.headersize=newsize;
2741 data->state.headerbuff = newbuff;
2742 k->hbufp = data->state.headerbuff + hbufp_index;
2744 memcpy(k->hbufp, k->str_start, length);
2746 k->hbuflen += length;
2752 static void print_http_error(struct SessionHandle *data)
2754 struct SingleRequest *k = &data->req;
2757 /* make sure that data->req.p points to the HTTP status line */
2758 if(!strncmp(beg, "HTTP", 4)) {
2760 /* skip to HTTP status code */
2761 beg = strchr(beg, ' ');
2764 /* find trailing CR */
2765 char end_char = '\r';
2766 char *end = strchr(beg, end_char);
2768 /* try to find LF (workaround for non-compliant HTTP servers) */
2770 end = strchr(beg, end_char);
2774 /* temporarily replace CR or LF by NUL and print the error message */
2776 failf(data, "The requested URL returned error: %s", beg);
2778 /* restore the previously replaced CR or LF */
2785 /* fall-back to printing the HTTP status code only */
2786 failf(data, "The requested URL returned error: %d", k->httpcode);
2790 * Read any HTTP header lines from the server and pass them to the client app.
2792 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2793 struct connectdata *conn,
2798 struct SingleRequest *k = &data->req;
2800 /* header line within buffer loop */
2806 /* str_start is start of line within buf */
2807 k->str_start = k->str;
2809 /* data is in network encoding so use 0x0a instead of '\n' */
2810 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2813 /* Not a complete header line within buffer, append the data to
2814 the end of the headerbuff. */
2815 result = header_append(data, k, *nread);
2819 if(!k->headerline && (k->hbuflen>5)) {
2820 /* make a first check that this looks like a protocol header */
2821 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2822 /* this is not the beginning of a protocol first header line */
2824 k->badheader = HEADER_ALLBAD;
2829 break; /* read more and try again */
2832 /* decrease the size of the remaining (supposed) header line */
2833 rest_length = (k->end_ptr - k->str)+1;
2834 *nread -= (ssize_t)rest_length;
2836 k->str = k->end_ptr + 1; /* move past new line */
2838 full_length = k->str - k->str_start;
2840 result = header_append(data, k, full_length);
2844 k->end_ptr = k->hbufp;
2845 k->p = data->state.headerbuff;
2848 * We now have a FULL header line that p points to
2851 if(!k->headerline) {
2852 /* the first read header */
2853 if((k->hbuflen>5) &&
2854 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2855 /* this is not the beginning of a protocol first header line */
2858 /* since there's more, this is a partial bad header */
2859 k->badheader = HEADER_PARTHEADER;
2861 /* this was all we read so it's all a bad header */
2862 k->badheader = HEADER_ALLBAD;
2863 *nread = (ssize_t)rest_length;
2869 /* headers are in network encoding so
2870 use 0x0a and 0x0d instead of '\n' and '\r' */
2871 if((0x0a == *k->p) || (0x0d == *k->p)) {
2873 /* Zero-length header line means end of headers! */
2875 #ifdef CURL_DOES_CONVERSIONS
2877 *k->p = '\r'; /* replace with CR in host encoding */
2878 k->p++; /* pass the CR byte */
2881 *k->p = '\n'; /* replace with LF in host encoding */
2882 k->p++; /* pass the LF byte */
2886 k->p++; /* pass the \r byte */
2888 k->p++; /* pass the \n byte */
2889 #endif /* CURL_DOES_CONVERSIONS */
2891 if(100 <= k->httpcode && 199 >= k->httpcode) {
2893 * We have made a HTTP PUT or POST and this is 1.1-lingo
2894 * that tells us that the server is OK with this and ready
2895 * to receive the data.
2896 * However, we'll get more headers now so we must get
2897 * back into the header-parsing state!
2900 k->headerline = 0; /* restart the header line counter */
2902 /* "A user agent MAY ignore unexpected 1xx status responses." */
2903 switch(k->httpcode) {
2905 /* if we did wait for this do enable write now! */
2907 k->exp100 = EXP100_SEND_DATA;
2908 k->keepon |= KEEP_SEND;
2912 /* Switching Protocols */
2913 if(k->upgr101 == UPGR101_REQUESTED) {
2914 infof(data, "Received 101\n");
2915 k->upgr101 = UPGR101_RECEIVED;
2917 /* switch to http2 now */
2918 Curl_http2_switched(conn);
2926 k->header = FALSE; /* no more header to parse! */
2928 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2929 (conn->httpversion >= 11) &&
2930 !(conn->handler->protocol & CURLPROTO_RTSP) &&
2931 data->set.httpreq != HTTPREQ_HEAD) {
2932 /* On HTTP 1.1, when connection is not to get closed, but no
2933 Content-Length nor Content-Encoding chunked have been
2934 received, according to RFC2616 section 4.4 point 5, we
2935 assume that the server will close the connection to
2936 signal the end of the document. */
2937 infof(data, "no chunk, no close, no size. Assume close to "
2939 conn->bits.close = TRUE;
2944 * When all the headers have been parsed, see if we should give
2945 * up and return an error.
2947 if(http_should_fail(conn)) {
2948 failf (data, "The requested URL returned error: %d",
2950 return CURLE_HTTP_RETURNED_ERROR;
2953 /* now, only output this if the header AND body are requested:
2955 writetype = CLIENTWRITE_HEADER;
2956 if(data->set.include_header)
2957 writetype |= CLIENTWRITE_BODY;
2959 headerlen = k->p - data->state.headerbuff;
2961 result = Curl_client_write(conn, writetype,
2962 data->state.headerbuff,
2967 data->info.header_size += (long)headerlen;
2968 data->req.headerbytecount += (long)headerlen;
2970 data->req.deductheadercount =
2971 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2973 if(!*stop_reading) {
2974 /* Curl_http_auth_act() checks what authentication methods
2975 * that are available and decides which one (if any) to
2976 * use. It will set 'newurl' if an auth method was picked. */
2977 result = Curl_http_auth_act(conn);
2982 if(k->httpcode >= 300) {
2983 if((!conn->bits.authneg) && !conn->bits.close &&
2984 !conn->bits.rewindaftersend) {
2986 * General treatment of errors when about to send data. Including :
2987 * "417 Expectation Failed", while waiting for 100-continue.
2989 * The check for close above is done simply because of something
2990 * else has already deemed the connection to get closed then
2991 * something else should've considered the big picture and we
2994 * rewindaftersend indicates that something has told libcurl to
2995 * continue sending even if it gets discarded
2998 switch(data->set.httpreq) {
3001 case HTTPREQ_POST_FORM:
3002 /* We got an error response. If this happened before the whole
3003 * request body has been sent we stop sending and mark the
3004 * connection for closure after we've read the entire response.
3006 if(!k->upload_done) {
3007 infof(data, "HTTP error before end of send, stop sending\n");
3008 conn->bits.close = TRUE; /* close after this */
3009 k->upload_done = TRUE;
3010 k->keepon &= ~KEEP_SEND; /* don't send */
3011 if(data->state.expect100header)
3012 k->exp100 = EXP100_FAILED;
3016 default: /* default label present to avoid compiler warnings */
3022 if(conn->bits.rewindaftersend) {
3023 /* We rewind after a complete send, so thus we continue
3025 infof(data, "Keep sending data to get tossed away!\n");
3026 k->keepon |= KEEP_SEND;
3032 * really end-of-headers.
3034 * If we requested a "no body", this is a good time to get
3035 * out and return home.
3037 if(data->set.opt_no_body)
3038 *stop_reading = TRUE;
3040 /* If we know the expected size of this document, we set the
3041 maximum download size to the size of the expected
3042 document or else, we won't know when to stop reading!
3044 Note that we set the download maximum even if we read a
3045 "Connection: close" header, to make sure that
3046 "Content-Length: 0" still prevents us from attempting to
3047 read the (missing) response-body.
3049 /* According to RFC2616 section 4.4, we MUST ignore
3050 Content-Length: headers if we are now receiving data
3051 using chunked Transfer-Encoding.
3054 k->maxdownload = k->size = -1;
3057 /* We do this operation even if no_body is true, since this
3058 data might be retrieved later with curl_easy_getinfo()
3059 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3061 Curl_pgrsSetDownloadSize(data, k->size);
3062 k->maxdownload = k->size;
3065 /* If max download size is *zero* (nothing) we already
3066 have nothing and can safely return ok now! */
3067 if(0 == k->maxdownload)
3068 *stop_reading = TRUE;
3071 /* we make sure that this socket isn't read more now */
3072 k->keepon &= ~KEEP_RECV;
3075 if(data->set.verbose)
3076 Curl_debug(data, CURLINFO_HEADER_IN,
3077 k->str_start, headerlen, conn);
3078 break; /* exit header line loop */
3081 /* We continue reading headers, so reset the line-based
3082 header parsing variables hbufp && hbuflen */
3083 k->hbufp = data->state.headerbuff;
3089 * Checks for special headers coming up.
3092 if(!k->headerline++) {
3093 /* This is the first header, it MUST be the error code line
3094 or else we consider this to be the body right away! */
3095 int httpversion_major;
3096 int rtspversion_major;
3098 #ifdef CURL_DOES_CONVERSIONS
3099 #define HEADER1 scratch
3100 #define SCRATCHSIZE 21
3102 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3103 /* We can't really convert this yet because we
3104 don't know if it's the 1st header line or the body.
3105 So we do a partial conversion into a scratch area,
3106 leaving the data at k->p as-is.
3108 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3109 scratch[SCRATCHSIZE] = 0; /* null terminate */
3110 res = Curl_convert_from_network(data,
3114 /* Curl_convert_from_network calls failf if unsuccessful */
3117 #define HEADER1 k->p /* no conversion needed, just use k->p */
3118 #endif /* CURL_DOES_CONVERSIONS */
3120 if(conn->handler->protocol & CURLPROTO_HTTP) {
3121 nc = sscanf(HEADER1,
3127 conn->httpversion += 10 * httpversion_major;
3130 /* this is the real world, not a Nirvana
3131 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3133 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3134 conn->httpversion = 10;
3136 /* If user has set option HTTP200ALIASES,
3137 compare header line against list of aliases
3140 if(checkhttpprefix(data, k->p)) {
3143 conn->httpversion = 10;
3148 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3149 nc = sscanf(HEADER1,
3155 conn->rtspversion += 10 * rtspversion_major;
3156 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3159 /* TODO: do we care about the other cases here? */
3165 data->info.httpcode = k->httpcode;
3167 data->info.httpversion = conn->httpversion;
3168 if(!data->state.httpversion ||
3169 data->state.httpversion > conn->httpversion)
3170 /* store the lowest server version we encounter */
3171 data->state.httpversion = conn->httpversion;
3174 * This code executes as part of processing the header. As a
3175 * result, it's not totally clear how to interpret the
3176 * response code yet as that depends on what other headers may
3177 * be present. 401 and 407 may be errors, but may be OK
3178 * depending on how authentication is working. Other codes
3179 * are definitely errors, so give up here.
3181 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3182 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3183 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3185 if(data->state.resume_from &&
3186 (data->set.httpreq==HTTPREQ_GET) &&
3187 (k->httpcode == 416)) {
3188 /* "Requested Range Not Satisfiable", just proceed and
3189 pretend this is no error */
3192 /* serious error, go home! */
3193 print_http_error(data);
3194 return CURLE_HTTP_RETURNED_ERROR;
3198 if(conn->httpversion == 10) {
3199 /* Default action for HTTP/1.0 must be to close, unless
3200 we get one of those fancy headers that tell us the
3201 server keeps it open for us! */
3202 infof(data, "HTTP 1.0, assume close after body\n");
3203 conn->bits.close = TRUE;
3205 else if(conn->httpversion >= 11 &&
3206 !conn->bits.close) {
3207 struct connectbundle *cb_ptr;
3209 /* If HTTP version is >= 1.1 and connection is persistent
3210 server supports pipelining. */
3212 "HTTP 1.1 or later with persistent connection, "
3213 "pipelining supported\n"));
3214 /* Activate pipelining if needed */
3215 cb_ptr = conn->bundle;
3217 if(!Curl_pipeline_site_blacklisted(data, conn))
3218 cb_ptr->server_supports_pipelining = TRUE;
3222 switch(k->httpcode) {
3224 /* (quote from RFC2616, section 10.2.5): The server has
3225 * fulfilled the request but does not need to return an
3226 * entity-body ... The 204 response MUST NOT include a
3227 * message-body, and thus is always terminated by the first
3228 * empty line after the header fields. */
3231 /* (quote from RFC2616, section 10.3.5): The 304 response
3232 * MUST NOT contain a message-body, and thus is always
3233 * terminated by the first empty line after the header
3235 if(data->set.timecondition)
3236 data->info.timecond = TRUE;
3239 k->ignorecl = TRUE; /* ignore Content-Length headers */
3247 k->header = FALSE; /* this is not a header line */
3252 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3253 /* Curl_convert_from_network calls failf if unsuccessful */
3257 /* Check for Content-Length: header lines to get size */
3258 if(!k->ignorecl && !data->set.ignorecl &&
3259 checkprefix("Content-Length:", k->p)) {
3260 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3261 if(data->set.max_filesize &&
3262 contentlength > data->set.max_filesize) {
3263 failf(data, "Maximum file size exceeded");
3264 return CURLE_FILESIZE_EXCEEDED;
3266 if(contentlength >= 0) {
3267 k->size = contentlength;
3268 k->maxdownload = k->size;
3269 /* we set the progress download size already at this point
3270 just to make it easier for apps/callbacks to extract this
3271 info as soon as possible */
3272 Curl_pgrsSetDownloadSize(data, k->size);
3275 /* Negative Content-Length is really odd, and we know it
3276 happens for example when older Apache servers send large
3278 conn->bits.close = TRUE;
3279 infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
3280 ", closing after transfer\n", contentlength);
3283 /* check for Content-Type: header lines to get the MIME-type */
3284 else if(checkprefix("Content-Type:", k->p)) {
3285 char *contenttype = Curl_copy_header_value(k->p);
3287 return CURLE_OUT_OF_MEMORY;
3289 /* ignore empty data */
3292 Curl_safefree(data->info.contenttype);
3293 data->info.contenttype = contenttype;
3296 else if(checkprefix("Server:", k->p)) {
3297 char *server_name = Curl_copy_header_value(k->p);
3299 /* Turn off pipelining if the server version is blacklisted */
3300 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3301 if(Curl_pipeline_server_blacklisted(data, server_name))
3302 conn->bundle->server_supports_pipelining = FALSE;
3304 Curl_safefree(server_name);
3306 else if((conn->httpversion == 10) &&
3307 conn->bits.httpproxy &&
3308 Curl_compareheader(k->p,
3309 "Proxy-Connection:", "keep-alive")) {
3311 * When a HTTP/1.0 reply comes when using a proxy, the
3312 * 'Proxy-Connection: keep-alive' line tells us the
3313 * connection will be kept alive for our pleasure.
3314 * Default action for 1.0 is to close.
3316 conn->bits.close = FALSE; /* don't close when done */
3317 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3319 else if((conn->httpversion == 11) &&
3320 conn->bits.httpproxy &&
3321 Curl_compareheader(k->p,
3322 "Proxy-Connection:", "close")) {
3324 * We get a HTTP/1.1 response from a proxy and it says it'll
3325 * close down after this transfer.
3327 conn->bits.close = TRUE; /* close when done */
3328 infof(data, "HTTP/1.1 proxy connection set close!\n");
3330 else if((conn->httpversion == 10) &&
3331 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3333 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3334 * tells us the connection will be kept alive for our
3335 * pleasure. Default action for 1.0 is to close.
3337 * [RFC2068, section 19.7.1] */
3338 conn->bits.close = FALSE; /* don't close when done */
3339 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3341 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3343 * [RFC 2616, section 8.1.2.1]
3344 * "Connection: close" is HTTP/1.1 language and means that
3345 * the connection will close when this request has been
3348 conn->bits.close = TRUE; /* close when done */
3350 else if(checkprefix("Transfer-Encoding:", k->p)) {
3351 /* One or more encodings. We check for chunked and/or a compression
3354 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3355 * means that the server will send a series of "chunks". Each
3356 * chunk starts with line with info (including size of the
3357 * coming block) (terminated with CRLF), then a block of data
3358 * with the previously mentioned size. There can be any amount
3359 * of chunks, and a chunk-data set to zero signals the
3364 /* Find the first non-space letter */
3368 /* skip whitespaces and commas */
3369 while(*start && (ISSPACE(*start) || (*start == ',')))
3372 if(checkprefix("chunked", start)) {
3373 k->chunk = TRUE; /* chunks coming our way */
3375 /* init our chunky engine */
3376 Curl_httpchunk_init(conn);
3381 if(k->auto_decoding)
3382 /* TODO: we only support the first mentioned compression for now */
3385 if(checkprefix("identity", start)) {
3386 k->auto_decoding = IDENTITY;
3389 else if(checkprefix("deflate", start)) {
3390 k->auto_decoding = DEFLATE;
3393 else if(checkprefix("gzip", start)) {
3394 k->auto_decoding = GZIP;
3397 else if(checkprefix("x-gzip", start)) {
3398 k->auto_decoding = GZIP;
3401 else if(checkprefix("compress", start)) {
3402 k->auto_decoding = COMPRESS;
3405 else if(checkprefix("x-compress", start)) {
3406 k->auto_decoding = COMPRESS;
3416 else if(checkprefix("Content-Encoding:", k->p) &&
3417 (data->set.str[STRING_ENCODING] ||
3418 conn->httpversion == 20)) {
3420 * Process Content-Encoding. Look for the values: identity,
3421 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3422 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3423 * 2616). zlib cannot handle compress. However, errors are
3424 * handled further down when the response body is processed
3428 /* Find the first non-space letter */
3430 while(*start && ISSPACE(*start))
3433 /* Record the content-encoding for later use */
3434 if(checkprefix("identity", start))
3435 k->auto_decoding = IDENTITY;
3436 else if(checkprefix("deflate", start))
3437 k->auto_decoding = DEFLATE;
3438 else if(checkprefix("gzip", start)
3439 || checkprefix("x-gzip", start))
3440 k->auto_decoding = GZIP;
3441 else if(checkprefix("compress", start)
3442 || checkprefix("x-compress", start))
3443 k->auto_decoding = COMPRESS;
3445 else if(checkprefix("Content-Range:", k->p)) {
3446 /* Content-Range: bytes [num]-
3447 Content-Range: bytes: [num]-
3448 Content-Range: [num]-
3450 The second format was added since Sun's webserver
3451 JavaWebServer/1.1.1 obviously sends the header this way!
3452 The third added since some servers use that!
3455 char *ptr = k->p + 14;
3457 /* Move forward until first digit */
3458 while(*ptr && !ISDIGIT(*ptr))
3461 k->offset = curlx_strtoofft(ptr, NULL, 10);
3463 if(data->state.resume_from == k->offset)
3464 /* we asked for a resume and we got it */
3465 k->content_range = TRUE;
3467 #if !defined(CURL_DISABLE_COOKIES)
3468 else if(data->cookies &&
3469 checkprefix("Set-Cookie:", k->p)) {
3470 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3471 CURL_LOCK_ACCESS_SINGLE);
3472 Curl_cookie_add(data,
3473 data->cookies, TRUE, k->p+11,
3474 /* If there is a custom-set Host: name, use it
3475 here, or else use real peer host name. */
3476 conn->allocptr.cookiehost?
3477 conn->allocptr.cookiehost:conn->host.name,
3479 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3482 else if(checkprefix("Last-Modified:", k->p) &&
3483 (data->set.timecondition || data->set.get_filetime) ) {
3484 time_t secs=time(NULL);
3485 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3487 if(data->set.get_filetime)
3488 data->info.filetime = (long)k->timeofdoc;
3490 else if((checkprefix("WWW-Authenticate:", k->p) &&
3491 (401 == k->httpcode)) ||
3492 (checkprefix("Proxy-authenticate:", k->p) &&
3493 (407 == k->httpcode))) {
3495 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3496 char *auth = Curl_copy_header_value(k->p);
3498 return CURLE_OUT_OF_MEMORY;
3500 result = Curl_http_input_auth(conn, proxy, auth);
3502 Curl_safefree(auth);
3507 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3508 checkprefix("Location:", k->p) &&
3509 !data->req.location) {
3510 /* this is the URL that the server advises us to use instead */
3511 char *location = Curl_copy_header_value(k->p);
3513 return CURLE_OUT_OF_MEMORY;
3515 /* ignore empty data */
3518 data->req.location = location;
3520 if(data->set.http_follow_location) {
3521 DEBUGASSERT(!data->req.newurl);
3522 data->req.newurl = strdup(data->req.location); /* clone */
3523 if(!data->req.newurl)
3524 return CURLE_OUT_OF_MEMORY;
3526 /* some cases of POST and PUT etc needs to rewind the data
3527 stream at this point */
3528 result = http_perhapsrewind(conn);
3534 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3535 result = Curl_rtsp_parseheader(conn, k->p);
3541 * End of header-checks. Write them to the client.
3544 writetype = CLIENTWRITE_HEADER;
3545 if(data->set.include_header)
3546 writetype |= CLIENTWRITE_BODY;
3548 if(data->set.verbose)
3549 Curl_debug(data, CURLINFO_HEADER_IN,
3550 k->p, (size_t)k->hbuflen, conn);
3552 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3556 data->info.header_size += (long)k->hbuflen;
3557 data->req.headerbytecount += (long)k->hbuflen;
3559 /* reset hbufp pointer && hbuflen */
3560 k->hbufp = data->state.headerbuff;
3563 while(!*stop_reading && *k->str); /* header line within buffer */
3565 /* We might have reached the end of the header part here, but
3566 there might be a non-header part left in the end of the read
3572 #endif /* CURL_DISABLE_HTTP */