1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, 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"
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 static char *copy_header_value(const char *h)
199 /* Find the end of the header name */
200 while(*h && (*h != ':'))
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 */
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 %" FORMAT_OFF_T
418 " bytes\n", (curl_off_t)(expectsend - bytessent));
421 /* This is not NTLM or many bytes left to send: close
423 conn->bits.close = TRUE;
424 data->req.size = 0; /* don't download any more than 0 bytes */
426 /* There still is data left to send, but this connection is marked for
427 closure so we can safely do the rewind right now */
431 /* we rewind now at once since if we already sent something */
432 return Curl_readrewind(conn);
438 * Curl_http_auth_act() gets called when all HTTP headers have been received
439 * and it checks what authentication methods that are available and decides
440 * which one (if any) to use. It will set 'newurl' if an auth method was
444 CURLcode Curl_http_auth_act(struct connectdata *conn)
446 struct SessionHandle *data = conn->data;
447 bool pickhost = FALSE;
448 bool pickproxy = FALSE;
449 CURLcode code = CURLE_OK;
451 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
452 /* this is a transient response code, ignore */
455 if(data->state.authproblem)
456 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
458 if(conn->bits.user_passwd &&
459 ((data->req.httpcode == 401) ||
460 (conn->bits.authneg && data->req.httpcode < 300))) {
461 pickhost = pickoneauth(&data->state.authhost);
463 data->state.authproblem = TRUE;
465 if(conn->bits.proxy_user_passwd &&
466 ((data->req.httpcode == 407) ||
467 (conn->bits.authneg && data->req.httpcode < 300))) {
468 pickproxy = pickoneauth(&data->state.authproxy);
470 data->state.authproblem = TRUE;
473 if(pickhost || pickproxy) {
474 /* In case this is GSS auth, the newurl field is already allocated so
475 we must make sure to free it before allocating a new one. As figured
476 out in bug #2284386 */
477 Curl_safefree(data->req.newurl);
478 data->req.newurl = strdup(data->change.url); /* clone URL */
479 if(!data->req.newurl)
480 return CURLE_OUT_OF_MEMORY;
482 if((data->set.httpreq != HTTPREQ_GET) &&
483 (data->set.httpreq != HTTPREQ_HEAD) &&
484 !conn->bits.rewindaftersend) {
485 code = http_perhapsrewind(conn);
491 else if((data->req.httpcode < 300) &&
492 (!data->state.authhost.done) &&
493 conn->bits.authneg) {
494 /* no (known) authentication available,
495 authentication is not "done" yet and
496 no authentication seems to be required and
497 we didn't try HEAD or GET */
498 if((data->set.httpreq != HTTPREQ_GET) &&
499 (data->set.httpreq != HTTPREQ_HEAD)) {
500 data->req.newurl = strdup(data->change.url); /* clone URL */
501 if(!data->req.newurl)
502 return CURLE_OUT_OF_MEMORY;
503 data->state.authhost.done = TRUE;
506 if(http_should_fail(conn)) {
507 failf (data, "The requested URL returned error: %d",
509 code = CURLE_HTTP_RETURNED_ERROR;
517 * Output the correct authentication header depending on the auth type
518 * and whether or not it is to a proxy.
521 output_auth_headers(struct connectdata *conn,
522 struct auth *authstatus,
527 struct SessionHandle *data = conn->data;
528 const char *auth=NULL;
529 CURLcode result = CURLE_OK;
530 #ifdef USE_HTTP_NEGOTIATE
531 struct negotiatedata *negdata = proxy?
532 &data->state.proxyneg:&data->state.negotiate;
535 #ifdef CURL_DISABLE_CRYPTO_AUTH
540 #ifdef USE_HTTP_NEGOTIATE
541 negdata->state = GSS_AUTHNONE;
542 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
543 negdata->context && !GSS_ERROR(negdata->status)) {
544 auth="GSS-Negotiate";
545 result = Curl_output_negotiate(conn, proxy);
548 authstatus->done = TRUE;
549 negdata->state = GSS_AUTHSENT;
554 if(authstatus->picked == CURLAUTH_NTLM) {
556 result = Curl_output_ntlm(conn, proxy);
562 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
563 if(authstatus->picked == CURLAUTH_NTLM_WB) {
565 result = Curl_output_ntlm_wb(conn, proxy);
571 #ifndef CURL_DISABLE_CRYPTO_AUTH
572 if(authstatus->picked == CURLAUTH_DIGEST) {
574 result = Curl_output_digest(conn,
576 (const unsigned char *)request,
577 (const unsigned char *)path);
583 if(authstatus->picked == CURLAUTH_BASIC) {
585 if((proxy && conn->bits.proxy_user_passwd &&
586 !Curl_checkheaders(data, "Proxy-authorization:")) ||
587 (!proxy && conn->bits.user_passwd &&
588 !Curl_checkheaders(data, "Authorization:"))) {
590 result = http_output_basic(conn, proxy);
594 /* NOTE: this function should set 'done' TRUE, as the other auth
595 functions work that way */
596 authstatus->done = TRUE;
600 infof(data, "%s auth using %s with user '%s'\n",
601 proxy?"Proxy":"Server", auth,
602 proxy?(conn->proxyuser?conn->proxyuser:""):
603 (conn->user?conn->user:""));
604 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
607 authstatus->multi = FALSE;
613 * Curl_http_output_auth() setups the authentication headers for the
614 * host/proxy and the correct authentication
615 * method. conn->data->state.authdone is set to TRUE when authentication is
618 * @param conn all information about the current connection
619 * @param request pointer to the request keyword
620 * @param path pointer to the requested path
621 * @param proxytunnel boolean if this is the request setting up a "proxy
627 Curl_http_output_auth(struct connectdata *conn,
630 bool proxytunnel) /* TRUE if this is the request setting
631 up the proxy tunnel */
633 CURLcode result = CURLE_OK;
634 struct SessionHandle *data = conn->data;
635 struct auth *authhost;
636 struct auth *authproxy;
640 authhost = &data->state.authhost;
641 authproxy = &data->state.authproxy;
643 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
644 conn->bits.user_passwd)
645 /* continue please */ ;
647 authhost->done = TRUE;
648 authproxy->done = TRUE;
649 return CURLE_OK; /* no authentication with no user or password */
652 if(authhost->want && !authhost->picked)
653 /* The app has selected one or more methods, but none has been picked
654 so far by a server round-trip. Then we set the picked one to the
655 want one, and if this is one single bit it'll be used instantly. */
656 authhost->picked = authhost->want;
658 if(authproxy->want && !authproxy->picked)
659 /* The app has selected one or more methods, but none has been picked so
660 far by a proxy round-trip. Then we set the picked one to the want one,
661 and if this is one single bit it'll be used instantly. */
662 authproxy->picked = authproxy->want;
664 #ifndef CURL_DISABLE_PROXY
665 /* Send proxy authentication header if needed */
666 if(conn->bits.httpproxy &&
667 (conn->bits.tunnel_proxy == proxytunnel)) {
668 result = output_auth_headers(conn, authproxy, request, path, TRUE);
675 #endif /* CURL_DISABLE_PROXY */
676 /* we have no proxy so let's pretend we're done authenticating
678 authproxy->done = TRUE;
680 /* To prevent the user+password to get sent to other than the original
681 host due to a location-follow, we do some weirdo checks here */
682 if(!data->state.this_is_a_follow ||
684 !data->state.first_host ||
685 data->set.http_disable_hostname_check_before_authentication ||
686 Curl_raw_equal(data->state.first_host, conn->host.name)) {
687 result = output_auth_headers(conn, authhost, request, path, FALSE);
690 authhost->done = TRUE;
697 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
698 * headers. They are dealt with both in the transfer.c main loop and in the
699 * proxy CONNECT loop.
702 CURLcode Curl_http_input_auth(struct connectdata *conn,
704 const char *auth) /* the first non-space */
707 * This resource requires authentication
709 struct SessionHandle *data = conn->data;
711 unsigned long *availp;
714 if(httpcode == 407) {
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, (bool)(httpcode == 407), 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, (httpcode == 407)?TRUE:FALSE, 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, (httpcode == 407)?TRUE:FALSE, 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 */
1059 if(conn->handler->flags & PROTOPT_SSL) {
1060 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1061 when we speak HTTPS, as if only a fraction of it is sent now, this data
1062 needs to fit into the normal read-callback buffer later on and that
1063 buffer is using this size.
1066 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1068 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1069 library when we attempt to re-send this buffer. Sending the same data
1070 is not enough, we must use the exact same address. For this reason, we
1071 must copy the data to the uploadbuffer first, since that is the buffer
1072 we will be using if this send is retried later.
1074 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1075 ptr = conn->data->state.uploadbuffer;
1080 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1082 if(CURLE_OK == res) {
1084 * Note that we may not send the entire chunk at once, and we have a set
1085 * number of data bytes at the end of the big buffer (out of which we may
1086 * only send away a part).
1088 /* how much of the header that was sent */
1089 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1090 size_t bodylen = amount - headlen;
1092 if(conn->data->set.verbose) {
1093 /* this data _may_ contain binary stuff */
1094 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1096 /* there was body data sent beyond the initial header part, pass that
1097 on to the debug callback too */
1098 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1099 ptr+headlen, bodylen, conn);
1103 /* since we sent a piece of the body here, up the byte counter for it
1105 http->writebytecount += bodylen;
1107 /* 'amount' can never be a very large value here so typecasting it so a
1108 signed 31 bit value should not cause problems even if ssize_t is
1110 *bytes_written += (long)amount;
1113 if((size_t)amount != size) {
1114 /* The whole request could not be sent in one system call. We must
1115 queue it up and send it later when we get the chance. We must not
1116 loop here and wait until it might work again. */
1120 ptr = in->buffer + amount;
1122 /* backup the currently set pointers */
1123 http->backup.fread_func = conn->fread_func;
1124 http->backup.fread_in = conn->fread_in;
1125 http->backup.postdata = http->postdata;
1126 http->backup.postsize = http->postsize;
1128 /* set the new pointers for the request-sending */
1129 conn->fread_func = (curl_read_callback)readmoredata;
1130 conn->fread_in = (void *)conn;
1131 http->postdata = ptr;
1132 http->postsize = (curl_off_t)size;
1134 http->send_buffer = in;
1135 http->sending = HTTPSEND_REQUEST;
1139 http->sending = HTTPSEND_BODY;
1140 /* the full buffer was sent, clean up and return */
1143 if((size_t)amount != size)
1144 /* We have no continue-send mechanism now, fail. This can only happen
1145 when this function is used from the CONNECT sending function. We
1146 currently (stupidly) assume that the whole request is always sent
1147 away in the first single chunk.
1151 return CURLE_SEND_ERROR;
1153 conn->writechannel_inuse = FALSE;
1165 * add_bufferf() add the formatted input to the buffer.
1167 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1172 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1176 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1180 /* If we failed, we cleanup the whole buffer and return error */
1184 return CURLE_OUT_OF_MEMORY;
1188 * add_buffer() appends a memory chunk to the existing buffer
1190 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1195 if(~size < in->size_used) {
1196 /* If resulting used size of send buffer would wrap size_t, cleanup
1197 the whole buffer and return error. Otherwise the required buffer
1198 size will fit into a single allocatable memory chunk */
1199 Curl_safefree(in->buffer);
1201 return CURLE_OUT_OF_MEMORY;
1205 ((in->size_used + size) > (in->size_max - 1))) {
1207 /* If current buffer size isn't enough to hold the result, use a
1208 buffer size that doubles the required size. If this new size
1209 would wrap size_t, then just use the largest possible one */
1211 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1212 (~(size*2) < (in->size_used*2)))
1213 new_size = (size_t)-1;
1215 new_size = (in->size_used+size)*2;
1218 /* we have a buffer, enlarge the existing one */
1219 new_rb = realloc(in->buffer, new_size);
1221 /* create a new buffer */
1222 new_rb = malloc(new_size);
1225 /* If we failed, we cleanup the whole buffer and return error */
1226 Curl_safefree(in->buffer);
1228 return CURLE_OUT_OF_MEMORY;
1231 in->buffer = new_rb;
1232 in->size_max = new_size;
1234 memcpy(&in->buffer[in->size_used], inptr, size);
1236 in->size_used += size;
1241 /* end of the add_buffer functions */
1242 /* ------------------------------------------------------------------------- */
1247 * Curl_compareheader()
1249 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1250 * Pass headers WITH the colon.
1253 Curl_compareheader(const char *headerline, /* line to check */
1254 const char *header, /* header keyword _with_ colon */
1255 const char *content) /* content string to find */
1257 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1258 * by a colon (":") and the field value. Field names are case-insensitive.
1259 * The field value MAY be preceded by any amount of LWS, though a single SP
1262 size_t hlen = strlen(header);
1268 if(!Curl_raw_nequal(headerline, header, hlen))
1269 return FALSE; /* doesn't start with header */
1271 /* pass the header */
1272 start = &headerline[hlen];
1274 /* pass all white spaces */
1275 while(*start && ISSPACE(*start))
1278 /* find the end of the header line */
1279 end = strchr(start, '\r'); /* lines end with CRLF */
1281 /* in case there's a non-standard compliant line here */
1282 end = strchr(start, '\n');
1285 /* hm, there's no line ending here, use the zero byte! */
1286 end = strchr(start, '\0');
1289 len = end-start; /* length of the content part of the input line */
1290 clen = strlen(content); /* length of the word to find */
1292 /* find the content string in the rest of the line */
1293 for(;len>=clen;len--, start++) {
1294 if(Curl_raw_nequal(start, content, clen))
1295 return TRUE; /* match! */
1298 return FALSE; /* no match */
1302 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1303 * the generic Curl_connect().
1305 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1309 /* We default to persistent connections. We set this already in this connect
1310 function to make the re-use checks properly be able to check this bit. */
1311 conn->bits.close = FALSE;
1313 /* the CONNECT procedure might not have been completed */
1314 result = Curl_proxy_connect(conn);
1318 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1319 /* nothing else to do except wait right now - we're not done here. */
1322 if(conn->given->flags & PROTOPT_SSL) {
1323 /* perform SSL initialization */
1324 result = https_connecting(conn, done);
1334 /* this returns the socket to wait for in the DO and DOING state for the multi
1335 interface and then we're always _sending_ a request and thus we wait for
1336 the single socket to become writable only */
1337 static int http_getsock_do(struct connectdata *conn,
1338 curl_socket_t *socks,
1342 (void)numsocks; /* unused, we trust it to be at least 1 */
1343 socks[0] = conn->sock[FIRSTSOCKET];
1344 return GETSOCK_WRITESOCK(0);
1348 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1351 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1353 /* perform SSL initialization for this socket */
1354 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1356 conn->bits.close = TRUE; /* a failed connection is marked for closure
1357 to prevent (bad) re-use or similar */
1362 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
1363 defined(USE_DARWINSSL)
1364 /* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only.
1365 It should be made to query the generic SSL layer instead. */
1366 static int https_getsock(struct connectdata *conn,
1367 curl_socket_t *socks,
1370 if(conn->handler->flags & PROTOPT_SSL) {
1371 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1374 return GETSOCK_BLANK;
1376 if(connssl->connecting_state == ssl_connect_2_writing) {
1378 socks[0] = conn->sock[FIRSTSOCKET];
1379 return GETSOCK_WRITESOCK(0);
1381 else if(connssl->connecting_state == ssl_connect_2_reading) {
1383 socks[0] = conn->sock[FIRSTSOCKET];
1384 return GETSOCK_READSOCK(0);
1391 static int https_getsock(struct connectdata *conn,
1392 curl_socket_t *socks,
1398 return GETSOCK_BLANK;
1400 #endif /* USE_SSL */
1401 #endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
1404 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1405 * has been performed.
1408 CURLcode Curl_http_done(struct connectdata *conn,
1409 CURLcode status, bool premature)
1411 struct SessionHandle *data = conn->data;
1412 struct HTTP *http =data->req.protop;
1414 Curl_unencode_cleanup(conn);
1416 /* set the proper values (possibly modified on POST) */
1417 conn->fread_func = data->set.fread_func; /* restore */
1418 conn->fread_in = data->set.in; /* restore */
1419 conn->seek_func = data->set.seek_func; /* restore */
1420 conn->seek_client = data->set.seek_client; /* restore */
1425 if(http->send_buffer) {
1426 Curl_send_buffer *buff = http->send_buffer;
1430 http->send_buffer = NULL; /* clear the pointer */
1433 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1434 data->req.bytecount = http->readbytecount + http->writebytecount;
1436 Curl_formclean(&http->sendit); /* Now free that whole lot */
1438 /* a file being uploaded was left opened, close it! */
1439 fclose(http->form.fp);
1440 http->form.fp = NULL;
1443 else if(HTTPREQ_PUT == data->set.httpreq)
1444 data->req.bytecount = http->readbytecount + http->writebytecount;
1446 if(status != CURLE_OK)
1449 if(!premature && /* this check is pointless when DONE is called before the
1450 entire operation is complete */
1451 !conn->bits.retry &&
1452 !data->set.connect_only &&
1453 ((http->readbytecount +
1454 data->req.headerbytecount -
1455 data->req.deductheadercount)) <= 0) {
1456 /* If this connection isn't simply closed to be retried, AND nothing was
1457 read from the HTTP server (that counts), this can't be right so we
1458 return an error here */
1459 failf(data, "Empty reply from server");
1460 return CURLE_GOT_NOTHING;
1468 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1469 * to avoid it include:
1471 * - if the user specifically requested HTTP 1.0
1472 * - if the server we are connected to only supports 1.0
1473 * - if any server previously contacted to handle this request only supports
1476 static bool use_http_1_1plus(const struct SessionHandle *data,
1477 const struct connectdata *conn)
1479 return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
1480 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1481 ((conn->httpversion == 11) ||
1482 ((conn->httpversion != 10) &&
1483 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1486 /* check and possibly add an Expect: header */
1487 static CURLcode expect100(struct SessionHandle *data,
1488 struct connectdata *conn,
1489 Curl_send_buffer *req_buffer)
1491 CURLcode result = CURLE_OK;
1493 data->state.expect100header = FALSE; /* default to false unless it is set
1495 if(use_http_1_1plus(data, conn)) {
1496 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1497 100-continue to the headers which actually speeds up post operations
1498 (as there is one packet coming back from the web server) */
1499 ptr = Curl_checkheaders(data, "Expect:");
1501 data->state.expect100header =
1502 Curl_compareheader(ptr, "Expect:", "100-continue");
1505 result = Curl_add_bufferf(req_buffer,
1506 "Expect: 100-continue\r\n");
1507 if(result == CURLE_OK)
1508 data->state.expect100header = TRUE;
1514 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1515 Curl_send_buffer *req_buffer)
1518 struct curl_slist *headers=conn->data->set.headers;
1521 ptr = strchr(headers->data, ':');
1523 /* we require a colon for this to be a true header */
1525 ptr++; /* pass the colon */
1526 while(*ptr && ISSPACE(*ptr))
1530 /* only send this if the contents was non-blank */
1532 if(conn->allocptr.host &&
1533 /* a Host: header was sent already, don't pass on any custom Host:
1534 header as that will produce *two* in the same request! */
1535 checkprefix("Host:", headers->data))
1537 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
1538 /* this header (extended by formdata.c) is sent later */
1539 checkprefix("Content-Type:", headers->data))
1541 else if(conn->bits.authneg &&
1542 /* while doing auth neg, don't allow the custom length since
1543 we will force length zero then */
1544 checkprefix("Content-Length", headers->data))
1546 else if(conn->allocptr.te &&
1547 /* when asking for Transfer-Encoding, don't pass on a custom
1549 checkprefix("Connection", headers->data))
1552 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1560 ptr = strchr(headers->data, ';');
1563 ptr++; /* pass the semicolon */
1564 while(*ptr && ISSPACE(*ptr))
1568 /* this may be used for something else in the future */
1571 if(*(--ptr) == ';') {
1574 /* send no-value custom header if terminated by semicolon */
1576 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1584 headers = headers->next;
1589 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1590 Curl_send_buffer *req_buffer)
1592 const struct tm *tm;
1593 char *buf = data->state.buffer;
1594 CURLcode result = CURLE_OK;
1597 result = Curl_gmtime(data->set.timevalue, &keeptime);
1599 failf(data, "Invalid TIMEVALUE");
1604 /* The If-Modified-Since header family should have their times set in
1605 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1606 * represented in Greenwich Mean Time (GMT), without exception. For the
1607 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1608 * Time)." (see page 20 of RFC2616).
1611 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1612 snprintf(buf, BUFSIZE-1,
1613 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1614 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1616 Curl_month[tm->tm_mon],
1622 switch(data->set.timecondition) {
1623 case CURL_TIMECOND_IFMODSINCE:
1625 result = Curl_add_bufferf(req_buffer,
1626 "If-Modified-Since: %s\r\n", buf);
1628 case CURL_TIMECOND_IFUNMODSINCE:
1629 result = Curl_add_bufferf(req_buffer,
1630 "If-Unmodified-Since: %s\r\n", buf);
1632 case CURL_TIMECOND_LASTMOD:
1633 result = Curl_add_bufferf(req_buffer,
1634 "Last-Modified: %s\r\n", buf);
1642 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1643 * request is to be performed. This creates and sends a properly constructed
1646 CURLcode Curl_http(struct connectdata *conn, bool *done)
1648 struct SessionHandle *data=conn->data;
1649 CURLcode result=CURLE_OK;
1651 const char *ppath = data->state.path;
1652 bool paste_ftp_userpwd = FALSE;
1653 char ftp_typecode[sizeof("/;type=?")] = "";
1654 const char *host = conn->host.name;
1655 const char *te = ""; /* transfer-encoding */
1657 const char *request;
1658 Curl_HttpReq httpreq = data->set.httpreq;
1659 char *addcookies = NULL;
1660 curl_off_t included_body = 0;
1661 const char *httpstring;
1662 Curl_send_buffer *req_buffer;
1663 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1664 int seekerr = CURL_SEEKFUNC_OK;
1666 /* Always consider the DO phase done after this function call, even if there
1667 may be parts of the request that is not yet sent, since we can deal with
1668 the rest of the request in the PERFORM phase. */
1671 http = data->req.protop;
1673 if(!data->state.this_is_a_follow) {
1674 /* this is not a followed location, get the original host name */
1675 if(data->state.first_host)
1676 /* Free to avoid leaking memory on multiple requests*/
1677 free(data->state.first_host);
1679 data->state.first_host = strdup(conn->host.name);
1680 if(!data->state.first_host)
1681 return CURLE_OUT_OF_MEMORY;
1683 http->writebytecount = http->readbytecount = 0;
1685 if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
1687 httpreq = HTTPREQ_PUT;
1690 /* Now set the 'request' pointer to the proper request string */
1691 if(data->set.str[STRING_CUSTOMREQUEST])
1692 request = data->set.str[STRING_CUSTOMREQUEST];
1694 if(data->set.opt_no_body)
1697 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1700 case HTTPREQ_POST_FORM:
1706 default: /* this should never happen */
1717 /* The User-Agent string might have been allocated in url.c already, because
1718 it might have been used in the proxy connect, but if we have got a header
1719 with the user-agent string specified, we erase the previously made string
1721 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
1722 free(conn->allocptr.uagent);
1723 conn->allocptr.uagent=NULL;
1726 /* setup the authentication headers */
1727 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1731 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1732 (httpreq != HTTPREQ_GET) &&
1733 (httpreq != HTTPREQ_HEAD)) {
1734 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1735 with content-length zero as a "probe". */
1736 conn->bits.authneg = TRUE;
1739 conn->bits.authneg = FALSE;
1741 Curl_safefree(conn->allocptr.ref);
1742 if(data->change.referer && !Curl_checkheaders(data, "Referer:")) {
1743 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1744 if(!conn->allocptr.ref)
1745 return CURLE_OUT_OF_MEMORY;
1748 conn->allocptr.ref = NULL;
1750 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
1751 addcookies = data->set.str[STRING_COOKIE];
1753 if(!Curl_checkheaders(data, "Accept-Encoding:") &&
1754 data->set.str[STRING_ENCODING]) {
1755 Curl_safefree(conn->allocptr.accept_encoding);
1756 conn->allocptr.accept_encoding =
1757 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1758 if(!conn->allocptr.accept_encoding)
1759 return CURLE_OUT_OF_MEMORY;
1763 /* we only consider transfer-encoding magic if libz support is built-in */
1765 if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) {
1766 /* When we are to insert a TE: header in the request, we must also insert
1767 TE in a Connection: header, so we need to merge the custom provided
1768 Connection: header and prevent the original to get sent. Note that if
1769 the user has inserted his/hers own TE: header we don't do this magic
1770 but then assume that the user will handle it all! */
1771 char *cptr = Curl_checkheaders(data, "Connection:");
1772 #define TE_HEADER "TE: gzip\r\n"
1774 Curl_safefree(conn->allocptr.te);
1776 /* Create the (updated) Connection: header */
1777 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1778 strdup("Connection: TE\r\n" TE_HEADER);
1780 if(!conn->allocptr.te)
1781 return CURLE_OUT_OF_MEMORY;
1785 ptr = Curl_checkheaders(data, "Transfer-Encoding:");
1787 /* Some kind of TE is requested, check if 'chunked' is chosen */
1788 data->req.upload_chunky =
1789 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1792 if((conn->handler->protocol&CURLPROTO_HTTP) &&
1794 (data->set.infilesize == -1)) {
1795 if(conn->bits.authneg)
1796 /* don't enable chunked during auth neg */
1798 else if(use_http_1_1plus(data, conn)) {
1799 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1800 data->req.upload_chunky = TRUE;
1803 failf(data, "Chunky upload is not supported by HTTP 1.0");
1804 return CURLE_UPLOAD_FAILED;
1808 /* else, no chunky upload */
1809 data->req.upload_chunky = FALSE;
1812 if(data->req.upload_chunky)
1813 te = "Transfer-Encoding: chunked\r\n";
1816 Curl_safefree(conn->allocptr.host);
1818 ptr = Curl_checkheaders(data, "Host:");
1819 if(ptr && (!data->state.this_is_a_follow ||
1820 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1821 #if !defined(CURL_DISABLE_COOKIES)
1822 /* If we have a given custom Host: header, we extract the host name in
1823 order to possibly use it for cookie reasons later on. We only allow the
1824 custom Host: header if this is NOT a redirect, as setting Host: in the
1825 redirected request is being out on thin ice. Except if the host name
1826 is the same as the first one! */
1827 char *cookiehost = copy_header_value(ptr);
1829 return CURLE_OUT_OF_MEMORY;
1831 /* ignore empty data */
1834 /* If the host begins with '[', we start searching for the port after
1835 the bracket has been closed */
1836 int startsearch = 0;
1837 if(*cookiehost == '[') {
1838 char *closingbracket;
1839 /* since the 'cookiehost' is an allocated memory area that will be
1840 freed later we cannot simply increment the pointer */
1841 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
1842 closingbracket = strchr(cookiehost, ']');
1844 *closingbracket = 0;
1847 char *colon = strchr(cookiehost + startsearch, ':');
1849 *colon = 0; /* The host must not include an embedded port number */
1851 Curl_safefree(conn->allocptr.cookiehost);
1852 conn->allocptr.cookiehost = cookiehost;
1856 conn->allocptr.host = NULL;
1859 /* When building Host: headers, we must put the host name within
1860 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
1862 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
1863 (conn->remote_port == PORT_HTTPS)) ||
1864 ((conn->given->protocol&CURLPROTO_HTTP) &&
1865 (conn->remote_port == PORT_HTTP)) )
1866 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
1867 the port number in the host string */
1868 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
1869 conn->bits.ipv6_ip?"[":"",
1871 conn->bits.ipv6_ip?"]":"");
1873 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
1874 conn->bits.ipv6_ip?"[":"",
1876 conn->bits.ipv6_ip?"]":"",
1879 if(!conn->allocptr.host)
1880 /* without Host: we can't make a nice request */
1881 return CURLE_OUT_OF_MEMORY;
1884 #ifndef CURL_DISABLE_PROXY
1885 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
1886 /* Using a proxy but does not tunnel through it */
1888 /* The path sent to the proxy is in fact the entire URL. But if the remote
1889 host is a IDN-name, we must make sure that the request we produce only
1890 uses the encoded host name! */
1891 if(conn->host.dispname != conn->host.name) {
1892 char *url = data->change.url;
1893 ptr = strstr(url, conn->host.dispname);
1895 /* This is where the display name starts in the URL, now replace this
1896 part with the encoded name. TODO: This method of replacing the host
1897 name is rather crude as I believe there's a slight risk that the
1898 user has entered a user name or password that contain the host name
1900 size_t currlen = strlen(conn->host.dispname);
1901 size_t newlen = strlen(conn->host.name);
1902 size_t urllen = strlen(url);
1906 newurl = malloc(urllen + newlen - currlen + 1);
1908 /* copy the part before the host name */
1909 memcpy(newurl, url, ptr - url);
1910 /* append the new host name instead of the old */
1911 memcpy(newurl + (ptr - url), conn->host.name, newlen);
1912 /* append the piece after the host name */
1913 memcpy(newurl + newlen + (ptr - url),
1914 ptr + currlen, /* copy the trailing zero byte too */
1915 urllen - (ptr-url) - currlen + 1);
1916 if(data->change.url_alloc) {
1917 Curl_safefree(data->change.url);
1918 data->change.url_alloc = FALSE;
1920 data->change.url = newurl;
1921 data->change.url_alloc = TRUE;
1924 return CURLE_OUT_OF_MEMORY;
1927 ppath = data->change.url;
1928 if(checkprefix("ftp://", ppath)) {
1929 if(data->set.proxy_transfer_mode) {
1930 /* when doing ftp, append ;type=<a|i> if not present */
1931 char *type = strstr(ppath, ";type=");
1932 if(type && type[6] && type[7] == 0) {
1933 switch (Curl_raw_toupper(type[6])) {
1943 char *p = ftp_typecode;
1944 /* avoid sending invalid URLs like ftp://example.com;type=i if the
1945 * user specified ftp://example.com without the slash */
1946 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
1949 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
1950 data->set.prefer_ascii ? 'a' : 'i');
1953 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
1954 paste_ftp_userpwd = TRUE;
1957 #endif /* CURL_DISABLE_PROXY */
1959 if(HTTPREQ_POST_FORM == httpreq) {
1960 /* we must build the whole post sequence first, so that we have a size of
1961 the whole transfer before we start to send it */
1962 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
1963 Curl_checkheaders(data, "Content-Type:"),
1969 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
1971 if(( (HTTPREQ_POST == httpreq) ||
1972 (HTTPREQ_POST_FORM == httpreq) ||
1973 (HTTPREQ_PUT == httpreq) ) &&
1974 data->state.resume_from) {
1975 /**********************************************************************
1976 * Resuming upload in HTTP means that we PUT or POST and that we have
1977 * got a resume_from value set. The resume value has already created
1978 * a Range: header that will be passed along. We need to "fast forward"
1979 * the file the given number of bytes and decrease the assume upload
1980 * file size before we continue this venture in the dark lands of HTTP.
1981 *********************************************************************/
1983 if(data->state.resume_from < 0 ) {
1985 * This is meant to get the size of the present remote-file by itself.
1986 * We don't support this now. Bail out!
1988 data->state.resume_from = 0;
1991 if(data->state.resume_from && !data->state.this_is_a_follow) {
1992 /* do we still game? */
1994 /* Now, let's read off the proper amount of bytes from the
1996 if(conn->seek_func) {
1997 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2001 if(seekerr != CURL_SEEKFUNC_OK) {
2002 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2003 failf(data, "Could not seek stream");
2004 return CURLE_READ_ERROR;
2006 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2008 curl_off_t passed=0;
2010 size_t readthisamountnow =
2011 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2012 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2014 size_t actuallyread =
2015 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2018 passed += actuallyread;
2019 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2020 /* this checks for greater-than only to make sure that the
2021 CURL_READFUNC_ABORT return code still aborts */
2022 failf(data, "Could only read %" FORMAT_OFF_T
2023 " bytes from the input",
2025 return CURLE_READ_ERROR;
2027 } while(passed < data->state.resume_from);
2031 /* now, decrease the size of the read */
2032 if(data->set.infilesize>0) {
2033 data->set.infilesize -= data->state.resume_from;
2035 if(data->set.infilesize <= 0) {
2036 failf(data, "File already completely uploaded");
2037 return CURLE_PARTIAL_FILE;
2040 /* we've passed, proceed as normal */
2043 if(data->state.use_range) {
2045 * A range is selected. We use different headers whether we're downloading
2046 * or uploading and we always let customized headers override our internal
2047 * ones if any such are specified.
2049 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2050 !Curl_checkheaders(data, "Range:")) {
2051 /* if a line like this was already allocated, free the previous one */
2052 if(conn->allocptr.rangeline)
2053 free(conn->allocptr.rangeline);
2054 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2057 else if((httpreq != HTTPREQ_GET) &&
2058 !Curl_checkheaders(data, "Content-Range:")) {
2060 /* if a line like this was already allocated, free the previous one */
2061 if(conn->allocptr.rangeline)
2062 free(conn->allocptr.rangeline);
2064 if(data->set.set_resume_from < 0) {
2065 /* Upload resume was asked for, but we don't know the size of the
2066 remote part so we tell the server (and act accordingly) that we
2067 upload the whole file (again) */
2068 conn->allocptr.rangeline =
2069 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T
2070 "/%" FORMAT_OFF_T "\r\n",
2071 data->set.infilesize - 1, data->set.infilesize);
2074 else if(data->state.resume_from) {
2075 /* This is because "resume" was selected */
2076 curl_off_t total_expected_size=
2077 data->state.resume_from + data->set.infilesize;
2078 conn->allocptr.rangeline =
2079 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2080 "/%" FORMAT_OFF_T "\r\n",
2081 data->state.range, total_expected_size-1,
2082 total_expected_size);
2085 /* Range was selected and then we just pass the incoming range and
2086 append total size */
2087 conn->allocptr.rangeline =
2088 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2089 data->state.range, data->set.infilesize);
2091 if(!conn->allocptr.rangeline)
2092 return CURLE_OUT_OF_MEMORY;
2096 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2098 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
2100 /* initialize a dynamic send-buffer */
2101 req_buffer = Curl_add_buffer_init();
2104 return CURLE_OUT_OF_MEMORY;
2106 /* add the main request stuff */
2107 /* GET/HEAD/POST/PUT */
2108 result = Curl_add_bufferf(req_buffer, "%s ", request);
2113 if(paste_ftp_userpwd)
2114 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2115 conn->user, conn->passwd,
2116 ppath + sizeof("ftp://") - 1);
2118 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2123 Curl_add_bufferf(req_buffer,
2124 "%s" /* ftp typecode (;type=x) */
2125 " HTTP/%s\r\n" /* HTTP version */
2126 "%s" /* proxyuserpwd */
2129 "%s" /* user agent */
2133 "%s" /* accept-encoding */
2135 "%s" /* Proxy-Connection */
2136 "%s",/* transfer-encoding */
2140 conn->allocptr.proxyuserpwd?
2141 conn->allocptr.proxyuserpwd:"",
2142 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2143 (data->state.use_range && conn->allocptr.rangeline)?
2144 conn->allocptr.rangeline:"",
2145 (data->set.str[STRING_USERAGENT] &&
2146 *data->set.str[STRING_USERAGENT] &&
2147 conn->allocptr.uagent)?
2148 conn->allocptr.uagent:"",
2149 (conn->allocptr.host?conn->allocptr.host:""),
2150 http->p_accept?http->p_accept:"",
2151 conn->allocptr.te?conn->allocptr.te:"",
2152 (data->set.str[STRING_ENCODING] &&
2153 *data->set.str[STRING_ENCODING] &&
2154 conn->allocptr.accept_encoding)?
2155 conn->allocptr.accept_encoding:"",
2156 (data->change.referer && conn->allocptr.ref)?
2157 conn->allocptr.ref:"" /* Referer: <data> */,
2158 (conn->bits.httpproxy &&
2159 !conn->bits.tunnel_proxy &&
2160 !Curl_checkheaders(data, "Proxy-Connection:"))?
2161 "Proxy-Connection: Keep-Alive\r\n":"",
2166 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2167 * with basic and digest, it will be freed anyway by the next request
2170 Curl_safefree (conn->allocptr.userpwd);
2171 conn->allocptr.userpwd = NULL;
2176 if(!(conn->handler->flags&PROTOPT_SSL) &&
2177 (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
2178 /* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
2180 result = Curl_http2_request(req_buffer, conn);
2185 #if !defined(CURL_DISABLE_COOKIES)
2186 if(data->cookies || addcookies) {
2187 struct Cookie *co=NULL; /* no cookies from start */
2191 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2192 co = Curl_cookie_getlist(data->cookies,
2193 conn->allocptr.cookiehost?
2194 conn->allocptr.cookiehost:host,
2196 (conn->handler->protocol&CURLPROTO_HTTPS)?
2198 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2201 struct Cookie *store=co;
2202 /* now loop through all cookies that matched */
2206 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2210 result = Curl_add_bufferf(req_buffer,
2211 "%s%s=%s", count?"; ":"",
2212 co->name, co->value);
2217 co = co->next; /* next cookie please */
2219 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2221 if(addcookies && (CURLE_OK == result)) {
2223 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2224 if(CURLE_OK == result) {
2225 result = Curl_add_bufferf(req_buffer, "%s%s",
2231 if(count && (CURLE_OK == result))
2232 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2239 if(data->set.timecondition) {
2240 result = Curl_add_timecondition(data, req_buffer);
2245 result = Curl_add_custom_headers(conn, req_buffer);
2249 http->postdata = NULL; /* nothing to post at this point */
2250 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2252 /* If 'authdone' is FALSE, we must not set the write socket index to the
2253 Curl_transfer() call below, as we're not ready to actually upload any
2258 case HTTPREQ_POST_FORM:
2259 if(!http->sendit || conn->bits.authneg) {
2260 /* nothing to post! */
2261 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2265 result = Curl_add_buffer_send(req_buffer, conn,
2266 &data->info.request_size, 0, FIRSTSOCKET);
2268 failf(data, "Failed sending POST request");
2270 /* setup variables for the upcoming transfer */
2271 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2276 if(Curl_FormInit(&http->form, http->sendit)) {
2277 failf(data, "Internal HTTP POST error!");
2278 return CURLE_HTTP_POST_ERROR;
2281 /* Get the currently set callback function pointer and store that in the
2282 form struct since we might want the actual user-provided callback later
2283 on. The conn->fread_func pointer itself will be changed for the
2284 multipart case to the function that returns a multipart formatted
2286 http->form.fread_func = conn->fread_func;
2288 /* Set the read function to read from the generated form data */
2289 conn->fread_func = (curl_read_callback)Curl_FormReader;
2290 conn->fread_in = &http->form;
2292 http->sending = HTTPSEND_BODY;
2294 if(!data->req.upload_chunky &&
2295 !Curl_checkheaders(data, "Content-Length:")) {
2296 /* only add Content-Length if not uploading chunked */
2297 result = Curl_add_bufferf(req_buffer,
2298 "Content-Length: %" FORMAT_OFF_T "\r\n",
2304 result = expect100(data, conn, req_buffer);
2310 /* Get Content-Type: line from Curl_formpostheader.
2313 size_t linelength=0;
2314 contentType = Curl_formpostheader((void *)&http->form,
2317 failf(data, "Could not get Content-Type header line!");
2318 return CURLE_HTTP_POST_ERROR;
2321 result = Curl_add_buffer(req_buffer, contentType, linelength);
2326 /* make the request end in a true CRLF */
2327 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2331 /* set upload size to the progress meter */
2332 Curl_pgrsSetUploadSize(data, http->postsize);
2334 /* fire away the whole request to the server */
2335 result = Curl_add_buffer_send(req_buffer, conn,
2336 &data->info.request_size, 0, FIRSTSOCKET);
2338 failf(data, "Failed sending POST request");
2340 /* setup variables for the upcoming transfer */
2341 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2342 &http->readbytecount, FIRSTSOCKET,
2343 &http->writebytecount);
2346 Curl_formclean(&http->sendit); /* free that whole lot */
2350 /* convert the form data */
2351 result = Curl_convert_form(data, http->sendit);
2353 Curl_formclean(&http->sendit); /* free that whole lot */
2359 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2361 if(conn->bits.authneg)
2364 postsize = data->set.infilesize;
2366 if((postsize != -1) && !data->req.upload_chunky &&
2367 !Curl_checkheaders(data, "Content-Length:")) {
2368 /* only add Content-Length if not uploading chunked */
2369 result = Curl_add_bufferf(req_buffer,
2370 "Content-Length: %" FORMAT_OFF_T "\r\n",
2376 result = expect100(data, conn, req_buffer);
2380 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2384 /* set the upload size to the progress meter */
2385 Curl_pgrsSetUploadSize(data, postsize);
2387 /* this sends the buffer and frees all the buffer resources */
2388 result = Curl_add_buffer_send(req_buffer, conn,
2389 &data->info.request_size, 0, FIRSTSOCKET);
2391 failf(data, "Failed sending PUT request");
2393 /* prepare for transfer */
2394 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2395 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2396 postsize?&http->writebytecount:NULL);
2402 /* this is the simple POST, using x-www-form-urlencoded style */
2404 if(conn->bits.authneg)
2407 /* figure out the size of the postfields */
2408 postsize = (data->set.postfieldsize != -1)?
2409 data->set.postfieldsize:
2410 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2412 if(!data->req.upload_chunky) {
2413 /* We only set Content-Length and allow a custom Content-Length if
2414 we don't upload data chunked, as RFC2616 forbids us to set both
2415 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2417 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
2418 /* we allow replacing this header if not during auth negotiation,
2419 although it isn't very wise to actually set your own */
2420 result = Curl_add_bufferf(req_buffer,
2421 "Content-Length: %" FORMAT_OFF_T"\r\n",
2428 if(!Curl_checkheaders(data, "Content-Type:")) {
2429 result = Curl_add_bufferf(req_buffer,
2430 "Content-Type: application/"
2431 "x-www-form-urlencoded\r\n");
2436 /* For really small posts we don't use Expect: headers at all, and for
2437 the somewhat bigger ones we allow the app to disable it. Just make
2438 sure that the expect100header is always set to the preferred value
2440 ptr = Curl_checkheaders(data, "Expect:");
2442 data->state.expect100header =
2443 Curl_compareheader(ptr, "Expect:", "100-continue");
2445 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2446 result = expect100(data, conn, req_buffer);
2451 data->state.expect100header = FALSE;
2453 if(data->set.postfields) {
2455 if(!data->state.expect100header &&
2456 (postsize < MAX_INITIAL_POST_SIZE)) {
2457 /* if we don't use expect: 100 AND
2458 postsize is less than MAX_INITIAL_POST_SIZE
2460 then append the post data to the HTTP request header. This limit
2461 is no magic limit but only set to prevent really huge POSTs to
2462 get the data duplicated with malloc() and family. */
2464 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2468 if(!data->req.upload_chunky) {
2469 /* We're not sending it 'chunked', append it to the request
2470 already now to reduce the number if send() calls */
2471 result = Curl_add_buffer(req_buffer, data->set.postfields,
2473 included_body = postsize;
2477 /* Append the POST data chunky-style */
2478 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2479 if(CURLE_OK == result) {
2480 result = Curl_add_buffer(req_buffer, data->set.postfields,
2482 if(CURLE_OK == result)
2483 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2484 included_body = postsize + 2;
2487 if(CURLE_OK == result)
2488 result = Curl_add_buffer(req_buffer,
2489 "\x30\x0d\x0a\x0d\x0a", 5);
2495 /* Make sure the progress information is accurate */
2496 Curl_pgrsSetUploadSize(data, postsize);
2499 /* A huge POST coming up, do data separate from the request */
2500 http->postsize = postsize;
2501 http->postdata = data->set.postfields;
2503 http->sending = HTTPSEND_BODY;
2505 conn->fread_func = (curl_read_callback)readmoredata;
2506 conn->fread_in = (void *)conn;
2508 /* set the upload size to the progress meter */
2509 Curl_pgrsSetUploadSize(data, http->postsize);
2511 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2517 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2521 if(data->req.upload_chunky && conn->bits.authneg) {
2522 /* Chunky upload is selected and we're negotiating auth still, send
2524 result = Curl_add_buffer(req_buffer,
2525 "\x30\x0d\x0a\x0d\x0a", 5);
2531 else if(data->set.postfieldsize) {
2532 /* set the upload size to the progress meter */
2533 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2535 /* set the pointer to mark that we will send the post body using the
2536 read callback, but only if we're not in authenticate
2538 if(!conn->bits.authneg) {
2539 http->postdata = (char *)&http->postdata;
2540 http->postsize = postsize;
2544 /* issue the request */
2545 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2546 (size_t)included_body, FIRSTSOCKET);
2549 failf(data, "Failed sending HTTP POST request");
2551 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2552 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2553 http->postdata?&http->writebytecount:NULL);
2557 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2561 /* issue the request */
2562 result = Curl_add_buffer_send(req_buffer, conn,
2563 &data->info.request_size, 0, FIRSTSOCKET);
2566 failf(data, "Failed sending HTTP request");
2568 /* HTTP GET/HEAD download: */
2569 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2570 http->postdata?FIRSTSOCKET:-1,
2571 http->postdata?&http->writebytecount:NULL);
2576 if(http->writebytecount) {
2577 /* if a request-body has been sent off, we make sure this progress is noted
2579 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2580 if(Curl_pgrsUpdate(conn))
2581 result = CURLE_ABORTED_BY_CALLBACK;
2583 if(http->writebytecount >= postsize) {
2584 /* already sent the entire request body, mark the "upload" as
2586 infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of "
2587 "%" FORMAT_OFF_T " bytes\n",
2588 http->writebytecount, postsize);
2589 data->req.upload_done = TRUE;
2590 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2591 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2601 * Returns TRUE if member of the list matches prefix of string
2604 checkhttpprefix(struct SessionHandle *data,
2607 struct curl_slist *head = data->set.http200aliases;
2609 #ifdef CURL_DOES_CONVERSIONS
2610 /* convert from the network encoding using a scratch area */
2611 char *scratch = strdup(s);
2612 if(NULL == scratch) {
2613 failf (data, "Failed to allocate memory for conversion!");
2614 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2616 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2617 /* Curl_convert_from_network calls failf if unsuccessful */
2619 return FALSE; /* can't return CURLE_foobar so return FALSE */
2622 #endif /* CURL_DOES_CONVERSIONS */
2625 if(checkprefix(head->data, s)) {
2632 if(!rc && (checkprefix("HTTP/", s)))
2635 #ifdef CURL_DOES_CONVERSIONS
2637 #endif /* CURL_DOES_CONVERSIONS */
2641 #ifndef CURL_DISABLE_RTSP
2643 checkrtspprefix(struct SessionHandle *data,
2647 #ifdef CURL_DOES_CONVERSIONS
2648 /* convert from the network encoding using a scratch area */
2649 char *scratch = strdup(s);
2650 if(NULL == scratch) {
2651 failf (data, "Failed to allocate memory for conversion!");
2652 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2654 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2655 /* Curl_convert_from_network calls failf if unsuccessful */
2657 return FALSE; /* can't return CURLE_foobar so return FALSE */
2661 (void)data; /* unused */
2662 #endif /* CURL_DOES_CONVERSIONS */
2663 if(checkprefix("RTSP/", s))
2668 #endif /* CURL_DISABLE_RTSP */
2671 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2674 #ifndef CURL_DISABLE_RTSP
2675 if(conn->handler->protocol & CURLPROTO_RTSP)
2676 return checkrtspprefix(data, s);
2679 #endif /* CURL_DISABLE_RTSP */
2681 return checkhttpprefix(data, s);
2685 * header_append() copies a chunk of data to the end of the already received
2686 * header. We make sure that the full string fit in the allocated header
2687 * buffer, or else we enlarge it.
2689 static CURLcode header_append(struct SessionHandle *data,
2690 struct SingleRequest *k,
2693 if(k->hbuflen + length >= data->state.headersize) {
2694 /* We enlarge the header buffer as it is too small */
2699 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2700 /* The reason to have a max limit for this is to avoid the risk of a bad
2701 server feeding libcurl with a never-ending header that will cause
2702 reallocs infinitely */
2703 failf (data, "Avoided giant realloc for header (max is %d)!",
2704 CURL_MAX_HTTP_HEADER);
2705 return CURLE_OUT_OF_MEMORY;
2708 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2709 hbufp_index = k->hbufp - data->state.headerbuff;
2710 newbuff = realloc(data->state.headerbuff, newsize);
2712 failf (data, "Failed to alloc memory for big header!");
2713 return CURLE_OUT_OF_MEMORY;
2715 data->state.headersize=newsize;
2716 data->state.headerbuff = newbuff;
2717 k->hbufp = data->state.headerbuff + hbufp_index;
2719 memcpy(k->hbufp, k->str_start, length);
2721 k->hbuflen += length;
2727 static void print_http_error(struct SessionHandle *data)
2729 struct SingleRequest *k = &data->req;
2732 /* make sure that data->req.p points to the HTTP status line */
2733 if(!strncmp(beg, "HTTP", 4)) {
2735 /* skip to HTTP status code */
2736 beg = strchr(beg, ' ');
2739 /* find trailing CR */
2740 char end_char = '\r';
2741 char *end = strchr(beg, end_char);
2743 /* try to find LF (workaround for non-compliant HTTP servers) */
2745 end = strchr(beg, end_char);
2749 /* temporarily replace CR or LF by NUL and print the error message */
2751 failf(data, "The requested URL returned error: %s", beg);
2753 /* restore the previously replaced CR or LF */
2760 /* fall-back to printing the HTTP status code only */
2761 failf(data, "The requested URL returned error: %d", k->httpcode);
2765 * Read any HTTP header lines from the server and pass them to the client app.
2767 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2768 struct connectdata *conn,
2773 struct SingleRequest *k = &data->req;
2775 /* header line within buffer loop */
2781 /* str_start is start of line within buf */
2782 k->str_start = k->str;
2784 /* data is in network encoding so use 0x0a instead of '\n' */
2785 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2788 /* Not a complete header line within buffer, append the data to
2789 the end of the headerbuff. */
2790 result = header_append(data, k, *nread);
2794 if(!k->headerline && (k->hbuflen>5)) {
2795 /* make a first check that this looks like a protocol header */
2796 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2797 /* this is not the beginning of a protocol first header line */
2799 k->badheader = HEADER_ALLBAD;
2804 break; /* read more and try again */
2807 /* decrease the size of the remaining (supposed) header line */
2808 rest_length = (k->end_ptr - k->str)+1;
2809 *nread -= (ssize_t)rest_length;
2811 k->str = k->end_ptr + 1; /* move past new line */
2813 full_length = k->str - k->str_start;
2815 result = header_append(data, k, full_length);
2819 k->end_ptr = k->hbufp;
2820 k->p = data->state.headerbuff;
2823 * We now have a FULL header line that p points to
2826 if(!k->headerline) {
2827 /* the first read header */
2828 if((k->hbuflen>5) &&
2829 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2830 /* this is not the beginning of a protocol first header line */
2833 /* since there's more, this is a partial bad header */
2834 k->badheader = HEADER_PARTHEADER;
2836 /* this was all we read so it's all a bad header */
2837 k->badheader = HEADER_ALLBAD;
2838 *nread = (ssize_t)rest_length;
2844 /* headers are in network encoding so
2845 use 0x0a and 0x0d instead of '\n' and '\r' */
2846 if((0x0a == *k->p) || (0x0d == *k->p)) {
2848 /* Zero-length header line means end of headers! */
2850 #ifdef CURL_DOES_CONVERSIONS
2852 *k->p = '\r'; /* replace with CR in host encoding */
2853 k->p++; /* pass the CR byte */
2856 *k->p = '\n'; /* replace with LF in host encoding */
2857 k->p++; /* pass the LF byte */
2861 k->p++; /* pass the \r byte */
2863 k->p++; /* pass the \n byte */
2864 #endif /* CURL_DOES_CONVERSIONS */
2866 if(100 <= k->httpcode && 199 >= k->httpcode) {
2868 * We have made a HTTP PUT or POST and this is 1.1-lingo
2869 * that tells us that the server is OK with this and ready
2870 * to receive the data.
2871 * However, we'll get more headers now so we must get
2872 * back into the header-parsing state!
2875 k->headerline = 0; /* restart the header line counter */
2877 /* if we did wait for this do enable write now! */
2879 k->exp100 = EXP100_SEND_DATA;
2880 k->keepon |= KEEP_SEND;
2884 k->header = FALSE; /* no more header to parse! */
2886 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2887 (conn->httpversion >= 11) &&
2888 !(conn->handler->protocol & CURLPROTO_RTSP) &&
2889 data->set.httpreq != HTTPREQ_HEAD) {
2890 /* On HTTP 1.1, when connection is not to get closed, but no
2891 Content-Length nor Content-Encoding chunked have been
2892 received, according to RFC2616 section 4.4 point 5, we
2893 assume that the server will close the connection to
2894 signal the end of the document. */
2895 infof(data, "no chunk, no close, no size. Assume close to "
2897 conn->bits.close = TRUE;
2902 * When all the headers have been parsed, see if we should give
2903 * up and return an error.
2905 if(http_should_fail(conn)) {
2906 failf (data, "The requested URL returned error: %d",
2908 return CURLE_HTTP_RETURNED_ERROR;
2911 /* now, only output this if the header AND body are requested:
2913 writetype = CLIENTWRITE_HEADER;
2914 if(data->set.include_header)
2915 writetype |= CLIENTWRITE_BODY;
2917 headerlen = k->p - data->state.headerbuff;
2919 result = Curl_client_write(conn, writetype,
2920 data->state.headerbuff,
2925 data->info.header_size += (long)headerlen;
2926 data->req.headerbytecount += (long)headerlen;
2928 data->req.deductheadercount =
2929 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2931 if(!*stop_reading) {
2932 /* Curl_http_auth_act() checks what authentication methods
2933 * that are available and decides which one (if any) to
2934 * use. It will set 'newurl' if an auth method was picked. */
2935 result = Curl_http_auth_act(conn);
2940 if(k->httpcode >= 300) {
2941 if((!conn->bits.authneg) && !conn->bits.close &&
2942 !conn->bits.rewindaftersend) {
2944 * General treatment of errors when about to send data. Including :
2945 * "417 Expectation Failed", while waiting for 100-continue.
2947 * The check for close above is done simply because of something
2948 * else has already deemed the connection to get closed then
2949 * something else should've considered the big picture and we
2952 * rewindaftersend indicates that something has told libcurl to
2953 * continue sending even if it gets discarded
2956 switch(data->set.httpreq) {
2959 case HTTPREQ_POST_FORM:
2960 /* We got an error response. If this happened before the whole
2961 * request body has been sent we stop sending and mark the
2962 * connection for closure after we've read the entire response.
2964 if(!k->upload_done) {
2965 infof(data, "HTTP error before end of send, stop sending\n");
2966 conn->bits.close = TRUE; /* close after this */
2967 k->upload_done = TRUE;
2968 k->keepon &= ~KEEP_SEND; /* don't send */
2969 if(data->state.expect100header)
2970 k->exp100 = EXP100_FAILED;
2974 default: /* default label present to avoid compiler warnings */
2980 if(conn->bits.rewindaftersend) {
2981 /* We rewind after a complete send, so thus we continue
2983 infof(data, "Keep sending data to get tossed away!\n");
2984 k->keepon |= KEEP_SEND;
2990 * really end-of-headers.
2992 * If we requested a "no body", this is a good time to get
2993 * out and return home.
2995 if(data->set.opt_no_body)
2996 *stop_reading = TRUE;
2998 /* If we know the expected size of this document, we set the
2999 maximum download size to the size of the expected
3000 document or else, we won't know when to stop reading!
3002 Note that we set the download maximum even if we read a
3003 "Connection: close" header, to make sure that
3004 "Content-Length: 0" still prevents us from attempting to
3005 read the (missing) response-body.
3007 /* According to RFC2616 section 4.4, we MUST ignore
3008 Content-Length: headers if we are now receiving data
3009 using chunked Transfer-Encoding.
3012 k->maxdownload = k->size = -1;
3015 /* We do this operation even if no_body is true, since this
3016 data might be retrieved later with curl_easy_getinfo()
3017 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3019 Curl_pgrsSetDownloadSize(data, k->size);
3020 k->maxdownload = k->size;
3023 /* If max download size is *zero* (nothing) we already
3024 have nothing and can safely return ok now! */
3025 if(0 == k->maxdownload)
3026 *stop_reading = TRUE;
3029 /* we make sure that this socket isn't read more now */
3030 k->keepon &= ~KEEP_RECV;
3033 if(data->set.verbose)
3034 Curl_debug(data, CURLINFO_HEADER_IN,
3035 k->str_start, headerlen, conn);
3036 break; /* exit header line loop */
3039 /* We continue reading headers, so reset the line-based
3040 header parsing variables hbufp && hbuflen */
3041 k->hbufp = data->state.headerbuff;
3047 * Checks for special headers coming up.
3050 if(!k->headerline++) {
3051 /* This is the first header, it MUST be the error code line
3052 or else we consider this to be the body right away! */
3053 int httpversion_major;
3054 int rtspversion_major;
3056 #ifdef CURL_DOES_CONVERSIONS
3057 #define HEADER1 scratch
3058 #define SCRATCHSIZE 21
3060 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3061 /* We can't really convert this yet because we
3062 don't know if it's the 1st header line or the body.
3063 So we do a partial conversion into a scratch area,
3064 leaving the data at k->p as-is.
3066 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3067 scratch[SCRATCHSIZE] = 0; /* null terminate */
3068 res = Curl_convert_from_network(data,
3072 /* Curl_convert_from_network calls failf if unsuccessful */
3075 #define HEADER1 k->p /* no conversion needed, just use k->p */
3076 #endif /* CURL_DOES_CONVERSIONS */
3078 if(conn->handler->protocol & CURLPROTO_HTTP) {
3079 nc = sscanf(HEADER1,
3085 conn->httpversion += 10 * httpversion_major;
3088 /* this is the real world, not a Nirvana
3089 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3091 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3092 conn->httpversion = 10;
3094 /* If user has set option HTTP200ALIASES,
3095 compare header line against list of aliases
3098 if(checkhttpprefix(data, k->p)) {
3101 conn->httpversion = 10;
3106 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3107 nc = sscanf(HEADER1,
3113 conn->rtspversion += 10 * rtspversion_major;
3114 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3117 /* TODO: do we care about the other cases here? */
3123 data->info.httpcode = k->httpcode;
3125 data->info.httpversion = conn->httpversion;
3126 if(!data->state.httpversion ||
3127 data->state.httpversion > conn->httpversion)
3128 /* store the lowest server version we encounter */
3129 data->state.httpversion = conn->httpversion;
3132 * This code executes as part of processing the header. As a
3133 * result, it's not totally clear how to interpret the
3134 * response code yet as that depends on what other headers may
3135 * be present. 401 and 407 may be errors, but may be OK
3136 * depending on how authentication is working. Other codes
3137 * are definitely errors, so give up here.
3139 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3140 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3141 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3143 if(data->state.resume_from &&
3144 (data->set.httpreq==HTTPREQ_GET) &&
3145 (k->httpcode == 416)) {
3146 /* "Requested Range Not Satisfiable", just proceed and
3147 pretend this is no error */
3150 /* serious error, go home! */
3151 print_http_error(data);
3152 return CURLE_HTTP_RETURNED_ERROR;
3156 if(conn->httpversion == 10) {
3157 /* Default action for HTTP/1.0 must be to close, unless
3158 we get one of those fancy headers that tell us the
3159 server keeps it open for us! */
3160 infof(data, "HTTP 1.0, assume close after body\n");
3161 conn->bits.close = TRUE;
3163 else if(conn->httpversion >= 11 &&
3164 !conn->bits.close) {
3165 struct connectbundle *cb_ptr;
3167 /* If HTTP version is >= 1.1 and connection is persistent
3168 server supports pipelining. */
3170 "HTTP 1.1 or later with persistent connection, "
3171 "pipelining supported\n"));
3172 /* Activate pipelining if needed */
3173 cb_ptr = conn->bundle;
3175 if(!Curl_pipeline_site_blacklisted(data, conn))
3176 cb_ptr->server_supports_pipelining = TRUE;
3180 switch(k->httpcode) {
3182 /* (quote from RFC2616, section 10.2.5): The server has
3183 * fulfilled the request but does not need to return an
3184 * entity-body ... The 204 response MUST NOT include a
3185 * message-body, and thus is always terminated by the first
3186 * empty line after the header fields. */
3189 /* (quote from RFC2616, section 10.3.5): The 304 response
3190 * MUST NOT contain a message-body, and thus is always
3191 * terminated by the first empty line after the header
3193 if(data->set.timecondition)
3194 data->info.timecond = TRUE;
3197 k->ignorecl = TRUE; /* ignore Content-Length headers */
3205 k->header = FALSE; /* this is not a header line */
3210 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3211 /* Curl_convert_from_network calls failf if unsuccessful */
3215 /* Check for Content-Length: header lines to get size */
3216 if(!k->ignorecl && !data->set.ignorecl &&
3217 checkprefix("Content-Length:", k->p)) {
3218 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3219 if(data->set.max_filesize &&
3220 contentlength > data->set.max_filesize) {
3221 failf(data, "Maximum file size exceeded");
3222 return CURLE_FILESIZE_EXCEEDED;
3224 if(contentlength >= 0) {
3225 k->size = contentlength;
3226 k->maxdownload = k->size;
3227 /* we set the progress download size already at this point
3228 just to make it easier for apps/callbacks to extract this
3229 info as soon as possible */
3230 Curl_pgrsSetDownloadSize(data, k->size);
3233 /* Negative Content-Length is really odd, and we know it
3234 happens for example when older Apache servers send large
3236 conn->bits.close = TRUE;
3237 infof(data, "Negative content-length: %" FORMAT_OFF_T
3238 ", closing after transfer\n", contentlength);
3241 /* check for Content-Type: header lines to get the MIME-type */
3242 else if(checkprefix("Content-Type:", k->p)) {
3243 char *contenttype = copy_header_value(k->p);
3245 return CURLE_OUT_OF_MEMORY;
3247 /* ignore empty data */
3250 Curl_safefree(data->info.contenttype);
3251 data->info.contenttype = contenttype;
3254 else if(checkprefix("Server:", k->p)) {
3255 char *server_name = copy_header_value(k->p);
3257 /* Turn off pipelining if the server version is blacklisted */
3258 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3259 if(Curl_pipeline_server_blacklisted(data, server_name))
3260 conn->bundle->server_supports_pipelining = FALSE;
3262 Curl_safefree(server_name);
3264 else if((conn->httpversion == 10) &&
3265 conn->bits.httpproxy &&
3266 Curl_compareheader(k->p,
3267 "Proxy-Connection:", "keep-alive")) {
3269 * When a HTTP/1.0 reply comes when using a proxy, the
3270 * 'Proxy-Connection: keep-alive' line tells us the
3271 * connection will be kept alive for our pleasure.
3272 * Default action for 1.0 is to close.
3274 conn->bits.close = FALSE; /* don't close when done */
3275 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3277 else if((conn->httpversion == 11) &&
3278 conn->bits.httpproxy &&
3279 Curl_compareheader(k->p,
3280 "Proxy-Connection:", "close")) {
3282 * We get a HTTP/1.1 response from a proxy and it says it'll
3283 * close down after this transfer.
3285 conn->bits.close = TRUE; /* close when done */
3286 infof(data, "HTTP/1.1 proxy connection set close!\n");
3288 else if((conn->httpversion == 10) &&
3289 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3291 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3292 * tells us the connection will be kept alive for our
3293 * pleasure. Default action for 1.0 is to close.
3295 * [RFC2068, section 19.7.1] */
3296 conn->bits.close = FALSE; /* don't close when done */
3297 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3299 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3301 * [RFC 2616, section 8.1.2.1]
3302 * "Connection: close" is HTTP/1.1 language and means that
3303 * the connection will close when this request has been
3306 conn->bits.close = TRUE; /* close when done */
3308 else if(checkprefix("Transfer-Encoding:", k->p)) {
3309 /* One or more encodings. We check for chunked and/or a compression
3312 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3313 * means that the server will send a series of "chunks". Each
3314 * chunk starts with line with info (including size of the
3315 * coming block) (terminated with CRLF), then a block of data
3316 * with the previously mentioned size. There can be any amount
3317 * of chunks, and a chunk-data set to zero signals the
3322 /* Find the first non-space letter */
3326 /* skip whitespaces and commas */
3327 while(*start && (ISSPACE(*start) || (*start == ',')))
3330 if(checkprefix("chunked", start)) {
3331 k->chunk = TRUE; /* chunks coming our way */
3333 /* init our chunky engine */
3334 Curl_httpchunk_init(conn);
3339 if(k->auto_decoding)
3340 /* TODO: we only support the first mentioned compression for now */
3343 if(checkprefix("identity", start)) {
3344 k->auto_decoding = IDENTITY;
3347 else if(checkprefix("deflate", start)) {
3348 k->auto_decoding = DEFLATE;
3351 else if(checkprefix("gzip", start)) {
3352 k->auto_decoding = GZIP;
3355 else if(checkprefix("x-gzip", start)) {
3356 k->auto_decoding = GZIP;
3359 else if(checkprefix("compress", start)) {
3360 k->auto_decoding = COMPRESS;
3363 else if(checkprefix("x-compress", start)) {
3364 k->auto_decoding = COMPRESS;
3374 else if(checkprefix("Content-Encoding:", k->p) &&
3375 data->set.str[STRING_ENCODING]) {
3377 * Process Content-Encoding. Look for the values: identity,
3378 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3379 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3380 * 2616). zlib cannot handle compress. However, errors are
3381 * handled further down when the response body is processed
3385 /* Find the first non-space letter */
3387 while(*start && ISSPACE(*start))
3390 /* Record the content-encoding for later use */
3391 if(checkprefix("identity", start))
3392 k->auto_decoding = IDENTITY;
3393 else if(checkprefix("deflate", start))
3394 k->auto_decoding = DEFLATE;
3395 else if(checkprefix("gzip", start)
3396 || checkprefix("x-gzip", start))
3397 k->auto_decoding = GZIP;
3398 else if(checkprefix("compress", start)
3399 || checkprefix("x-compress", start))
3400 k->auto_decoding = COMPRESS;
3402 else if(checkprefix("Content-Range:", k->p)) {
3403 /* Content-Range: bytes [num]-
3404 Content-Range: bytes: [num]-
3405 Content-Range: [num]-
3407 The second format was added since Sun's webserver
3408 JavaWebServer/1.1.1 obviously sends the header this way!
3409 The third added since some servers use that!
3412 char *ptr = k->p + 14;
3414 /* Move forward until first digit */
3415 while(*ptr && !ISDIGIT(*ptr))
3418 k->offset = curlx_strtoofft(ptr, NULL, 10);
3420 if(data->state.resume_from == k->offset)
3421 /* we asked for a resume and we got it */
3422 k->content_range = TRUE;
3424 #if !defined(CURL_DISABLE_COOKIES)
3425 else if(data->cookies &&
3426 checkprefix("Set-Cookie:", k->p)) {
3427 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3428 CURL_LOCK_ACCESS_SINGLE);
3429 Curl_cookie_add(data,
3430 data->cookies, TRUE, k->p+11,
3431 /* If there is a custom-set Host: name, use it
3432 here, or else use real peer host name. */
3433 conn->allocptr.cookiehost?
3434 conn->allocptr.cookiehost:conn->host.name,
3436 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3439 else if(checkprefix("Last-Modified:", k->p) &&
3440 (data->set.timecondition || data->set.get_filetime) ) {
3441 time_t secs=time(NULL);
3442 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3444 if(data->set.get_filetime)
3445 data->info.filetime = (long)k->timeofdoc;
3447 else if((checkprefix("WWW-Authenticate:", k->p) &&
3448 (401 == k->httpcode)) ||
3449 (checkprefix("Proxy-authenticate:", k->p) &&
3450 (407 == k->httpcode))) {
3451 char *auth = copy_header_value(k->p);
3453 return CURLE_OUT_OF_MEMORY;
3455 result = Curl_http_input_auth(conn, k->httpcode, auth);
3457 Curl_safefree(auth);
3462 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3463 checkprefix("Location:", k->p) &&
3464 !data->req.location) {
3465 /* this is the URL that the server advises us to use instead */
3466 char *location = copy_header_value(k->p);
3468 return CURLE_OUT_OF_MEMORY;
3470 /* ignore empty data */
3473 data->req.location = location;
3475 if(data->set.http_follow_location) {
3476 DEBUGASSERT(!data->req.newurl);
3477 data->req.newurl = strdup(data->req.location); /* clone */
3478 if(!data->req.newurl)
3479 return CURLE_OUT_OF_MEMORY;
3481 /* some cases of POST and PUT etc needs to rewind the data
3482 stream at this point */
3483 result = http_perhapsrewind(conn);
3489 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3490 result = Curl_rtsp_parseheader(conn, k->p);
3496 * End of header-checks. Write them to the client.
3499 writetype = CLIENTWRITE_HEADER;
3500 if(data->set.include_header)
3501 writetype |= CLIENTWRITE_BODY;
3503 if(data->set.verbose)
3504 Curl_debug(data, CURLINFO_HEADER_IN,
3505 k->p, (size_t)k->hbuflen, conn);
3507 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3511 data->info.header_size += (long)k->hbuflen;
3512 data->req.headerbytecount += (long)k->hbuflen;
3514 /* reset hbufp pointer && hbuflen */
3515 k->hbufp = data->state.headerbuff;
3518 while(!*stop_reading && *k->str); /* header line within buffer */
3520 /* We might have reached the end of the header part here, but
3521 there might be a non-header part left in the end of the read
3527 #endif /* CURL_DISABLE_HTTP */