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 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 %" 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, bool proxy,
703 const char *auth) /* the first non-space */
706 * This resource requires authentication
708 struct SessionHandle *data = conn->data;
710 unsigned long *availp;
714 availp = &data->info.proxyauthavail;
715 authp = &data->state.authproxy;
718 availp = &data->info.httpauthavail;
719 authp = &data->state.authhost;
723 * Here we check if we want the specific single authentication (using ==) and
724 * if we do, we initiate usage of it.
726 * If the provided authentication is wanted as one out of several accepted
727 * types (using &), we OR this authentication type to the authavail
732 * ->picked is first set to the 'want' value (one or more bits) before the
733 * request is sent, and then it is again set _after_ all response 401/407
734 * headers have been received but then only to a single preferred method
740 #ifdef USE_HTTP_NEGOTIATE
741 if(checkprefix("GSS-Negotiate", auth) ||
742 checkprefix("Negotiate", auth)) {
744 *availp |= CURLAUTH_GSSNEGOTIATE;
745 authp->avail |= CURLAUTH_GSSNEGOTIATE;
747 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
748 if(data->state.negotiate.state == GSS_AUTHSENT) {
749 /* if we sent GSS authentication in the outgoing request and we get
750 this back, we're in trouble */
751 infof(data, "Authentication problem. Ignoring this.\n");
752 data->state.authproblem = TRUE;
755 neg = Curl_input_negotiate(conn, proxy, auth);
757 DEBUGASSERT(!data->req.newurl);
758 data->req.newurl = strdup(data->change.url);
759 if(!data->req.newurl)
760 return CURLE_OUT_OF_MEMORY;
761 data->state.authproblem = FALSE;
762 /* we received GSS auth info and we dealt with it fine */
763 data->state.negotiate.state = GSS_AUTHRECV;
766 data->state.authproblem = TRUE;
773 /* NTLM support requires the SSL crypto libs */
774 if(checkprefix("NTLM", auth)) {
775 *availp |= CURLAUTH_NTLM;
776 authp->avail |= CURLAUTH_NTLM;
777 if(authp->picked == CURLAUTH_NTLM ||
778 authp->picked == CURLAUTH_NTLM_WB) {
779 /* NTLM authentication is picked and activated */
781 Curl_input_ntlm(conn, proxy, auth);
782 if(CURLE_OK == ntlm) {
783 data->state.authproblem = FALSE;
784 #ifdef NTLM_WB_ENABLED
785 if(authp->picked == CURLAUTH_NTLM_WB) {
786 *availp &= ~CURLAUTH_NTLM;
787 authp->avail &= ~CURLAUTH_NTLM;
788 *availp |= CURLAUTH_NTLM_WB;
789 authp->avail |= CURLAUTH_NTLM_WB;
791 /* Get the challenge-message which will be passed to
792 * ntlm_auth for generating the type 3 message later */
793 while(*auth && ISSPACE(*auth))
795 if(checkprefix("NTLM", auth)) {
796 auth += strlen("NTLM");
797 while(*auth && ISSPACE(*auth))
800 if((conn->challenge_header = strdup(auth)) == NULL)
801 return CURLE_OUT_OF_MEMORY;
807 infof(data, "Authentication problem. Ignoring this.\n");
808 data->state.authproblem = TRUE;
814 #ifndef CURL_DISABLE_CRYPTO_AUTH
815 if(checkprefix("Digest", auth)) {
816 if((authp->avail & CURLAUTH_DIGEST) != 0) {
817 infof(data, "Ignoring duplicate digest auth header.\n");
821 *availp |= CURLAUTH_DIGEST;
822 authp->avail |= CURLAUTH_DIGEST;
824 /* We call this function on input Digest headers even if Digest
825 * authentication isn't activated yet, as we need to store the
826 * incoming data from this header in case we are gonna use
828 dig = Curl_input_digest(conn, proxy, auth);
830 if(CURLDIGEST_FINE != dig) {
831 infof(data, "Authentication problem. Ignoring this.\n");
832 data->state.authproblem = TRUE;
838 if(checkprefix("Basic", auth)) {
839 *availp |= CURLAUTH_BASIC;
840 authp->avail |= CURLAUTH_BASIC;
841 if(authp->picked == CURLAUTH_BASIC) {
842 /* We asked for Basic authentication but got a 40X back
843 anyway, which basically means our name+password isn't
845 authp->avail = CURLAUTH_NONE;
846 infof(data, "Authentication problem. Ignoring this.\n");
847 data->state.authproblem = TRUE;
851 /* there may be multiple methods on one line, so keep reading */
852 while(*auth && *auth != ',') /* read up to the next comma */
854 if(*auth == ',') /* if we're on a comma, skip it */
856 while(*auth && ISSPACE(*auth))
863 * http_should_fail() determines whether an HTTP response has gotten us
864 * into an error state or not.
866 * @param conn all information about the current connection
868 * @retval 0 communications should continue
870 * @retval 1 communications should not continue
872 static int http_should_fail(struct connectdata *conn)
874 struct SessionHandle *data;
881 httpcode = data->req.httpcode;
884 ** If we haven't been asked to fail on error,
887 if(!data->set.http_fail_on_error)
891 ** Any code < 400 is never terminal.
896 if(data->state.resume_from &&
897 (data->set.httpreq==HTTPREQ_GET) &&
899 /* "Requested Range Not Satisfiable", just proceed and
900 pretend this is no error */
905 ** Any code >= 400 that's not 401 or 407 is always
908 if((httpcode != 401) &&
913 ** All we have left to deal with is 401 and 407
915 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
918 ** Examine the current authentication state to see if this
919 ** is an error. The idea is for this function to get
920 ** called after processing all the headers in a response
921 ** message. So, if we've been to asked to authenticate a
922 ** particular stage, and we've done it, we're OK. But, if
923 ** we're already completely authenticated, it's not OK to
924 ** get another 401 or 407.
926 ** It is possible for authentication to go stale such that
927 ** the client needs to reauthenticate. Once that info is
928 ** available, use it here.
932 ** Either we're not authenticating, or we're supposed to
933 ** be authenticating something else. This is an error.
935 if((httpcode == 401) && !conn->bits.user_passwd)
937 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
940 return data->state.authproblem;
944 * readmoredata() is a "fread() emulation" to provide POST and/or request
945 * data. It is used when a huge POST is to be made and the entire chunk wasn't
946 * sent in the first send(). This function will then be called from the
947 * transfer.c loop when more data is to be sent to the peer.
949 * Returns the amount of bytes it filled the buffer with.
951 static size_t readmoredata(char *buffer,
956 struct connectdata *conn = (struct connectdata *)userp;
957 struct HTTP *http = conn->data->req.protop;
958 size_t fullsize = size * nitems;
960 if(0 == http->postsize)
961 /* nothing to return */
964 /* make sure that a HTTP request is never sent away chunked! */
965 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
967 if(http->postsize <= (curl_off_t)fullsize) {
968 memcpy(buffer, http->postdata, (size_t)http->postsize);
969 fullsize = (size_t)http->postsize;
971 if(http->backup.postsize) {
972 /* move backup data into focus and continue on that */
973 http->postdata = http->backup.postdata;
974 http->postsize = http->backup.postsize;
975 conn->fread_func = http->backup.fread_func;
976 conn->fread_in = http->backup.fread_in;
978 http->sending++; /* move one step up */
980 http->backup.postsize=0;
988 memcpy(buffer, http->postdata, fullsize);
989 http->postdata += fullsize;
990 http->postsize -= fullsize;
995 /* ------------------------------------------------------------------------- */
996 /* add_buffer functions */
999 * Curl_add_buffer_init() sets up and returns a fine buffer struct
1001 Curl_send_buffer *Curl_add_buffer_init(void)
1003 return calloc(1, sizeof(Curl_send_buffer));
1007 * Curl_add_buffer_send() sends a header buffer and frees all associated
1008 * memory. Body data may be appended to the header data if desired.
1012 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
1013 struct connectdata *conn,
1015 /* add the number of sent bytes to this
1017 long *bytes_written,
1019 /* how much of the buffer contains body data */
1020 size_t included_body_bytes,
1028 struct HTTP *http = conn->data->req.protop;
1030 curl_socket_t sockfd;
1033 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1035 sockfd = conn->sock[socketindex];
1037 /* The looping below is required since we use non-blocking sockets, but due
1038 to the circumstances we will just loop and try again and again etc */
1041 size = in->size_used;
1043 headersize = size - included_body_bytes; /* the initial part that isn't body
1046 DEBUGASSERT(size > included_body_bytes);
1048 res = Curl_convert_to_network(conn->data, ptr, headersize);
1049 /* Curl_convert_to_network calls failf if unsuccessful */
1051 /* conversion failed, free memory and return to the caller */
1058 if(conn->handler->flags & PROTOPT_SSL) {
1059 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1060 when we speak HTTPS, as if only a fraction of it is sent now, this data
1061 needs to fit into the normal read-callback buffer later on and that
1062 buffer is using this size.
1065 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1067 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1068 library when we attempt to re-send this buffer. Sending the same data
1069 is not enough, we must use the exact same address. For this reason, we
1070 must copy the data to the uploadbuffer first, since that is the buffer
1071 we will be using if this send is retried later.
1073 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1074 ptr = conn->data->state.uploadbuffer;
1079 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1081 if(CURLE_OK == res) {
1083 * Note that we may not send the entire chunk at once, and we have a set
1084 * number of data bytes at the end of the big buffer (out of which we may
1085 * only send away a part).
1087 /* how much of the header that was sent */
1088 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1089 size_t bodylen = amount - headlen;
1091 if(conn->data->set.verbose) {
1092 /* this data _may_ contain binary stuff */
1093 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1095 /* there was body data sent beyond the initial header part, pass that
1096 on to the debug callback too */
1097 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1098 ptr+headlen, bodylen, conn);
1102 /* since we sent a piece of the body here, up the byte counter for it
1104 http->writebytecount += bodylen;
1106 /* 'amount' can never be a very large value here so typecasting it so a
1107 signed 31 bit value should not cause problems even if ssize_t is
1109 *bytes_written += (long)amount;
1112 if((size_t)amount != size) {
1113 /* The whole request could not be sent in one system call. We must
1114 queue it up and send it later when we get the chance. We must not
1115 loop here and wait until it might work again. */
1119 ptr = in->buffer + amount;
1121 /* backup the currently set pointers */
1122 http->backup.fread_func = conn->fread_func;
1123 http->backup.fread_in = conn->fread_in;
1124 http->backup.postdata = http->postdata;
1125 http->backup.postsize = http->postsize;
1127 /* set the new pointers for the request-sending */
1128 conn->fread_func = (curl_read_callback)readmoredata;
1129 conn->fread_in = (void *)conn;
1130 http->postdata = ptr;
1131 http->postsize = (curl_off_t)size;
1133 http->send_buffer = in;
1134 http->sending = HTTPSEND_REQUEST;
1138 http->sending = HTTPSEND_BODY;
1139 /* the full buffer was sent, clean up and return */
1142 if((size_t)amount != size)
1143 /* We have no continue-send mechanism now, fail. This can only happen
1144 when this function is used from the CONNECT sending function. We
1145 currently (stupidly) assume that the whole request is always sent
1146 away in the first single chunk.
1150 return CURLE_SEND_ERROR;
1152 conn->writechannel_inuse = FALSE;
1164 * add_bufferf() add the formatted input to the buffer.
1166 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1171 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1175 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1179 /* If we failed, we cleanup the whole buffer and return error */
1183 return CURLE_OUT_OF_MEMORY;
1187 * add_buffer() appends a memory chunk to the existing buffer
1189 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1194 if(~size < in->size_used) {
1195 /* If resulting used size of send buffer would wrap size_t, cleanup
1196 the whole buffer and return error. Otherwise the required buffer
1197 size will fit into a single allocatable memory chunk */
1198 Curl_safefree(in->buffer);
1200 return CURLE_OUT_OF_MEMORY;
1204 ((in->size_used + size) > (in->size_max - 1))) {
1206 /* If current buffer size isn't enough to hold the result, use a
1207 buffer size that doubles the required size. If this new size
1208 would wrap size_t, then just use the largest possible one */
1210 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1211 (~(size*2) < (in->size_used*2)))
1212 new_size = (size_t)-1;
1214 new_size = (in->size_used+size)*2;
1217 /* we have a buffer, enlarge the existing one */
1218 new_rb = realloc(in->buffer, new_size);
1220 /* create a new buffer */
1221 new_rb = malloc(new_size);
1224 /* If we failed, we cleanup the whole buffer and return error */
1225 Curl_safefree(in->buffer);
1227 return CURLE_OUT_OF_MEMORY;
1230 in->buffer = new_rb;
1231 in->size_max = new_size;
1233 memcpy(&in->buffer[in->size_used], inptr, size);
1235 in->size_used += size;
1240 /* end of the add_buffer functions */
1241 /* ------------------------------------------------------------------------- */
1246 * Curl_compareheader()
1248 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1249 * Pass headers WITH the colon.
1252 Curl_compareheader(const char *headerline, /* line to check */
1253 const char *header, /* header keyword _with_ colon */
1254 const char *content) /* content string to find */
1256 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1257 * by a colon (":") and the field value. Field names are case-insensitive.
1258 * The field value MAY be preceded by any amount of LWS, though a single SP
1261 size_t hlen = strlen(header);
1267 if(!Curl_raw_nequal(headerline, header, hlen))
1268 return FALSE; /* doesn't start with header */
1270 /* pass the header */
1271 start = &headerline[hlen];
1273 /* pass all white spaces */
1274 while(*start && ISSPACE(*start))
1277 /* find the end of the header line */
1278 end = strchr(start, '\r'); /* lines end with CRLF */
1280 /* in case there's a non-standard compliant line here */
1281 end = strchr(start, '\n');
1284 /* hm, there's no line ending here, use the zero byte! */
1285 end = strchr(start, '\0');
1288 len = end-start; /* length of the content part of the input line */
1289 clen = strlen(content); /* length of the word to find */
1291 /* find the content string in the rest of the line */
1292 for(;len>=clen;len--, start++) {
1293 if(Curl_raw_nequal(start, content, clen))
1294 return TRUE; /* match! */
1297 return FALSE; /* no match */
1301 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1302 * the generic Curl_connect().
1304 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1308 /* We default to persistent connections. We set this already in this connect
1309 function to make the re-use checks properly be able to check this bit. */
1310 conn->bits.close = FALSE;
1312 /* the CONNECT procedure might not have been completed */
1313 result = Curl_proxy_connect(conn);
1317 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1318 /* nothing else to do except wait right now - we're not done here. */
1321 if(conn->given->flags & PROTOPT_SSL) {
1322 /* perform SSL initialization */
1323 result = https_connecting(conn, done);
1333 /* this returns the socket to wait for in the DO and DOING state for the multi
1334 interface and then we're always _sending_ a request and thus we wait for
1335 the single socket to become writable only */
1336 static int http_getsock_do(struct connectdata *conn,
1337 curl_socket_t *socks,
1341 (void)numsocks; /* unused, we trust it to be at least 1 */
1342 socks[0] = conn->sock[FIRSTSOCKET];
1343 return GETSOCK_WRITESOCK(0);
1347 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1350 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1352 /* perform SSL initialization for this socket */
1353 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1355 conn->bits.close = TRUE; /* a failed connection is marked for closure
1356 to prevent (bad) re-use or similar */
1361 #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
1362 defined(USE_DARWINSSL)
1363 /* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only.
1364 It should be made to query the generic SSL layer instead. */
1365 static int https_getsock(struct connectdata *conn,
1366 curl_socket_t *socks,
1369 if(conn->handler->flags & PROTOPT_SSL) {
1370 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1373 return GETSOCK_BLANK;
1375 if(connssl->connecting_state == ssl_connect_2_writing) {
1377 socks[0] = conn->sock[FIRSTSOCKET];
1378 return GETSOCK_WRITESOCK(0);
1380 else if(connssl->connecting_state == ssl_connect_2_reading) {
1382 socks[0] = conn->sock[FIRSTSOCKET];
1383 return GETSOCK_READSOCK(0);
1390 static int https_getsock(struct connectdata *conn,
1391 curl_socket_t *socks,
1397 return GETSOCK_BLANK;
1399 #endif /* USE_SSL */
1400 #endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
1403 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1404 * has been performed.
1407 CURLcode Curl_http_done(struct connectdata *conn,
1408 CURLcode status, bool premature)
1410 struct SessionHandle *data = conn->data;
1411 struct HTTP *http =data->req.protop;
1413 Curl_unencode_cleanup(conn);
1415 /* set the proper values (possibly modified on POST) */
1416 conn->fread_func = data->set.fread_func; /* restore */
1417 conn->fread_in = data->set.in; /* restore */
1418 conn->seek_func = data->set.seek_func; /* restore */
1419 conn->seek_client = data->set.seek_client; /* restore */
1424 if(http->send_buffer) {
1425 Curl_send_buffer *buff = http->send_buffer;
1429 http->send_buffer = NULL; /* clear the pointer */
1432 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1433 data->req.bytecount = http->readbytecount + http->writebytecount;
1435 Curl_formclean(&http->sendit); /* Now free that whole lot */
1437 /* a file being uploaded was left opened, close it! */
1438 fclose(http->form.fp);
1439 http->form.fp = NULL;
1442 else if(HTTPREQ_PUT == data->set.httpreq)
1443 data->req.bytecount = http->readbytecount + http->writebytecount;
1445 if(status != CURLE_OK)
1448 if(!premature && /* this check is pointless when DONE is called before the
1449 entire operation is complete */
1450 !conn->bits.retry &&
1451 !data->set.connect_only &&
1452 ((http->readbytecount +
1453 data->req.headerbytecount -
1454 data->req.deductheadercount)) <= 0) {
1455 /* If this connection isn't simply closed to be retried, AND nothing was
1456 read from the HTTP server (that counts), this can't be right so we
1457 return an error here */
1458 failf(data, "Empty reply from server");
1459 return CURLE_GOT_NOTHING;
1467 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1468 * to avoid it include:
1470 * - if the user specifically requested HTTP 1.0
1471 * - if the server we are connected to only supports 1.0
1472 * - if any server previously contacted to handle this request only supports
1475 static bool use_http_1_1plus(const struct SessionHandle *data,
1476 const struct connectdata *conn)
1478 return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
1479 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1480 ((conn->httpversion == 11) ||
1481 ((conn->httpversion != 10) &&
1482 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1485 /* check and possibly add an Expect: header */
1486 static CURLcode expect100(struct SessionHandle *data,
1487 struct connectdata *conn,
1488 Curl_send_buffer *req_buffer)
1490 CURLcode result = CURLE_OK;
1492 data->state.expect100header = FALSE; /* default to false unless it is set
1494 if(use_http_1_1plus(data, conn)) {
1495 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1496 100-continue to the headers which actually speeds up post operations
1497 (as there is one packet coming back from the web server) */
1498 ptr = Curl_checkheaders(data, "Expect:");
1500 data->state.expect100header =
1501 Curl_compareheader(ptr, "Expect:", "100-continue");
1504 result = Curl_add_bufferf(req_buffer,
1505 "Expect: 100-continue\r\n");
1506 if(result == CURLE_OK)
1507 data->state.expect100header = TRUE;
1513 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1514 Curl_send_buffer *req_buffer)
1517 struct curl_slist *headers=conn->data->set.headers;
1520 ptr = strchr(headers->data, ':');
1522 /* we require a colon for this to be a true header */
1524 ptr++; /* pass the colon */
1525 while(*ptr && ISSPACE(*ptr))
1529 /* only send this if the contents was non-blank */
1531 if(conn->allocptr.host &&
1532 /* a Host: header was sent already, don't pass on any custom Host:
1533 header as that will produce *two* in the same request! */
1534 checkprefix("Host:", headers->data))
1536 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
1537 /* this header (extended by formdata.c) is sent later */
1538 checkprefix("Content-Type:", headers->data))
1540 else if(conn->bits.authneg &&
1541 /* while doing auth neg, don't allow the custom length since
1542 we will force length zero then */
1543 checkprefix("Content-Length", headers->data))
1545 else if(conn->allocptr.te &&
1546 /* when asking for Transfer-Encoding, don't pass on a custom
1548 checkprefix("Connection", headers->data))
1551 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1559 ptr = strchr(headers->data, ';');
1562 ptr++; /* pass the semicolon */
1563 while(*ptr && ISSPACE(*ptr))
1567 /* this may be used for something else in the future */
1570 if(*(--ptr) == ';') {
1573 /* send no-value custom header if terminated by semicolon */
1575 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1583 headers = headers->next;
1588 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1589 Curl_send_buffer *req_buffer)
1591 const struct tm *tm;
1592 char *buf = data->state.buffer;
1593 CURLcode result = CURLE_OK;
1596 result = Curl_gmtime(data->set.timevalue, &keeptime);
1598 failf(data, "Invalid TIMEVALUE");
1603 /* The If-Modified-Since header family should have their times set in
1604 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1605 * represented in Greenwich Mean Time (GMT), without exception. For the
1606 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1607 * Time)." (see page 20 of RFC2616).
1610 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1611 snprintf(buf, BUFSIZE-1,
1612 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1613 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1615 Curl_month[tm->tm_mon],
1621 switch(data->set.timecondition) {
1622 case CURL_TIMECOND_IFMODSINCE:
1624 result = Curl_add_bufferf(req_buffer,
1625 "If-Modified-Since: %s\r\n", buf);
1627 case CURL_TIMECOND_IFUNMODSINCE:
1628 result = Curl_add_bufferf(req_buffer,
1629 "If-Unmodified-Since: %s\r\n", buf);
1631 case CURL_TIMECOND_LASTMOD:
1632 result = Curl_add_bufferf(req_buffer,
1633 "Last-Modified: %s\r\n", buf);
1641 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1642 * request is to be performed. This creates and sends a properly constructed
1645 CURLcode Curl_http(struct connectdata *conn, bool *done)
1647 struct SessionHandle *data=conn->data;
1648 CURLcode result=CURLE_OK;
1650 const char *ppath = data->state.path;
1651 bool paste_ftp_userpwd = FALSE;
1652 char ftp_typecode[sizeof("/;type=?")] = "";
1653 const char *host = conn->host.name;
1654 const char *te = ""; /* transfer-encoding */
1656 const char *request;
1657 Curl_HttpReq httpreq = data->set.httpreq;
1658 char *addcookies = NULL;
1659 curl_off_t included_body = 0;
1660 const char *httpstring;
1661 Curl_send_buffer *req_buffer;
1662 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1663 int seekerr = CURL_SEEKFUNC_OK;
1665 /* Always consider the DO phase done after this function call, even if there
1666 may be parts of the request that is not yet sent, since we can deal with
1667 the rest of the request in the PERFORM phase. */
1670 http = data->req.protop;
1672 if(!data->state.this_is_a_follow) {
1673 /* this is not a followed location, get the original host name */
1674 if(data->state.first_host)
1675 /* Free to avoid leaking memory on multiple requests*/
1676 free(data->state.first_host);
1678 data->state.first_host = strdup(conn->host.name);
1679 if(!data->state.first_host)
1680 return CURLE_OUT_OF_MEMORY;
1682 http->writebytecount = http->readbytecount = 0;
1684 if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
1686 httpreq = HTTPREQ_PUT;
1689 /* Now set the 'request' pointer to the proper request string */
1690 if(data->set.str[STRING_CUSTOMREQUEST])
1691 request = data->set.str[STRING_CUSTOMREQUEST];
1693 if(data->set.opt_no_body)
1696 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1699 case HTTPREQ_POST_FORM:
1705 default: /* this should never happen */
1716 /* The User-Agent string might have been allocated in url.c already, because
1717 it might have been used in the proxy connect, but if we have got a header
1718 with the user-agent string specified, we erase the previously made string
1720 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
1721 free(conn->allocptr.uagent);
1722 conn->allocptr.uagent=NULL;
1725 /* setup the authentication headers */
1726 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1730 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1731 (httpreq != HTTPREQ_GET) &&
1732 (httpreq != HTTPREQ_HEAD)) {
1733 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1734 with content-length zero as a "probe". */
1735 conn->bits.authneg = TRUE;
1738 conn->bits.authneg = FALSE;
1740 Curl_safefree(conn->allocptr.ref);
1741 if(data->change.referer && !Curl_checkheaders(data, "Referer:")) {
1742 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1743 if(!conn->allocptr.ref)
1744 return CURLE_OUT_OF_MEMORY;
1747 conn->allocptr.ref = NULL;
1749 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
1750 addcookies = data->set.str[STRING_COOKIE];
1752 if(!Curl_checkheaders(data, "Accept-Encoding:") &&
1753 data->set.str[STRING_ENCODING]) {
1754 Curl_safefree(conn->allocptr.accept_encoding);
1755 conn->allocptr.accept_encoding =
1756 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1757 if(!conn->allocptr.accept_encoding)
1758 return CURLE_OUT_OF_MEMORY;
1762 /* we only consider transfer-encoding magic if libz support is built-in */
1764 if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) {
1765 /* When we are to insert a TE: header in the request, we must also insert
1766 TE in a Connection: header, so we need to merge the custom provided
1767 Connection: header and prevent the original to get sent. Note that if
1768 the user has inserted his/hers own TE: header we don't do this magic
1769 but then assume that the user will handle it all! */
1770 char *cptr = Curl_checkheaders(data, "Connection:");
1771 #define TE_HEADER "TE: gzip\r\n"
1773 Curl_safefree(conn->allocptr.te);
1775 /* Create the (updated) Connection: header */
1776 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1777 strdup("Connection: TE\r\n" TE_HEADER);
1779 if(!conn->allocptr.te)
1780 return CURLE_OUT_OF_MEMORY;
1784 ptr = Curl_checkheaders(data, "Transfer-Encoding:");
1786 /* Some kind of TE is requested, check if 'chunked' is chosen */
1787 data->req.upload_chunky =
1788 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1791 if((conn->handler->protocol&CURLPROTO_HTTP) &&
1793 (data->set.infilesize == -1)) {
1794 if(conn->bits.authneg)
1795 /* don't enable chunked during auth neg */
1797 else if(use_http_1_1plus(data, conn)) {
1798 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1799 data->req.upload_chunky = TRUE;
1802 failf(data, "Chunky upload is not supported by HTTP 1.0");
1803 return CURLE_UPLOAD_FAILED;
1807 /* else, no chunky upload */
1808 data->req.upload_chunky = FALSE;
1811 if(data->req.upload_chunky)
1812 te = "Transfer-Encoding: chunked\r\n";
1815 Curl_safefree(conn->allocptr.host);
1817 ptr = Curl_checkheaders(data, "Host:");
1818 if(ptr && (!data->state.this_is_a_follow ||
1819 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1820 #if !defined(CURL_DISABLE_COOKIES)
1821 /* If we have a given custom Host: header, we extract the host name in
1822 order to possibly use it for cookie reasons later on. We only allow the
1823 custom Host: header if this is NOT a redirect, as setting Host: in the
1824 redirected request is being out on thin ice. Except if the host name
1825 is the same as the first one! */
1826 char *cookiehost = Curl_copy_header_value(ptr);
1828 return CURLE_OUT_OF_MEMORY;
1830 /* ignore empty data */
1833 /* If the host begins with '[', we start searching for the port after
1834 the bracket has been closed */
1835 int startsearch = 0;
1836 if(*cookiehost == '[') {
1837 char *closingbracket;
1838 /* since the 'cookiehost' is an allocated memory area that will be
1839 freed later we cannot simply increment the pointer */
1840 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
1841 closingbracket = strchr(cookiehost, ']');
1843 *closingbracket = 0;
1846 char *colon = strchr(cookiehost + startsearch, ':');
1848 *colon = 0; /* The host must not include an embedded port number */
1850 Curl_safefree(conn->allocptr.cookiehost);
1851 conn->allocptr.cookiehost = cookiehost;
1855 conn->allocptr.host = NULL;
1858 /* When building Host: headers, we must put the host name within
1859 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
1861 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
1862 (conn->remote_port == PORT_HTTPS)) ||
1863 ((conn->given->protocol&CURLPROTO_HTTP) &&
1864 (conn->remote_port == PORT_HTTP)) )
1865 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
1866 the port number in the host string */
1867 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
1868 conn->bits.ipv6_ip?"[":"",
1870 conn->bits.ipv6_ip?"]":"");
1872 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
1873 conn->bits.ipv6_ip?"[":"",
1875 conn->bits.ipv6_ip?"]":"",
1878 if(!conn->allocptr.host)
1879 /* without Host: we can't make a nice request */
1880 return CURLE_OUT_OF_MEMORY;
1883 #ifndef CURL_DISABLE_PROXY
1884 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
1885 /* Using a proxy but does not tunnel through it */
1887 /* The path sent to the proxy is in fact the entire URL. But if the remote
1888 host is a IDN-name, we must make sure that the request we produce only
1889 uses the encoded host name! */
1890 if(conn->host.dispname != conn->host.name) {
1891 char *url = data->change.url;
1892 ptr = strstr(url, conn->host.dispname);
1894 /* This is where the display name starts in the URL, now replace this
1895 part with the encoded name. TODO: This method of replacing the host
1896 name is rather crude as I believe there's a slight risk that the
1897 user has entered a user name or password that contain the host name
1899 size_t currlen = strlen(conn->host.dispname);
1900 size_t newlen = strlen(conn->host.name);
1901 size_t urllen = strlen(url);
1905 newurl = malloc(urllen + newlen - currlen + 1);
1907 /* copy the part before the host name */
1908 memcpy(newurl, url, ptr - url);
1909 /* append the new host name instead of the old */
1910 memcpy(newurl + (ptr - url), conn->host.name, newlen);
1911 /* append the piece after the host name */
1912 memcpy(newurl + newlen + (ptr - url),
1913 ptr + currlen, /* copy the trailing zero byte too */
1914 urllen - (ptr-url) - currlen + 1);
1915 if(data->change.url_alloc) {
1916 Curl_safefree(data->change.url);
1917 data->change.url_alloc = FALSE;
1919 data->change.url = newurl;
1920 data->change.url_alloc = TRUE;
1923 return CURLE_OUT_OF_MEMORY;
1926 ppath = data->change.url;
1927 if(checkprefix("ftp://", ppath)) {
1928 if(data->set.proxy_transfer_mode) {
1929 /* when doing ftp, append ;type=<a|i> if not present */
1930 char *type = strstr(ppath, ";type=");
1931 if(type && type[6] && type[7] == 0) {
1932 switch (Curl_raw_toupper(type[6])) {
1942 char *p = ftp_typecode;
1943 /* avoid sending invalid URLs like ftp://example.com;type=i if the
1944 * user specified ftp://example.com without the slash */
1945 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
1948 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
1949 data->set.prefer_ascii ? 'a' : 'i');
1952 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
1953 paste_ftp_userpwd = TRUE;
1956 #endif /* CURL_DISABLE_PROXY */
1958 if(HTTPREQ_POST_FORM == httpreq) {
1959 /* we must build the whole post sequence first, so that we have a size of
1960 the whole transfer before we start to send it */
1961 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
1962 Curl_checkheaders(data, "Content-Type:"),
1968 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
1970 if(( (HTTPREQ_POST == httpreq) ||
1971 (HTTPREQ_POST_FORM == httpreq) ||
1972 (HTTPREQ_PUT == httpreq) ) &&
1973 data->state.resume_from) {
1974 /**********************************************************************
1975 * Resuming upload in HTTP means that we PUT or POST and that we have
1976 * got a resume_from value set. The resume value has already created
1977 * a Range: header that will be passed along. We need to "fast forward"
1978 * the file the given number of bytes and decrease the assume upload
1979 * file size before we continue this venture in the dark lands of HTTP.
1980 *********************************************************************/
1982 if(data->state.resume_from < 0 ) {
1984 * This is meant to get the size of the present remote-file by itself.
1985 * We don't support this now. Bail out!
1987 data->state.resume_from = 0;
1990 if(data->state.resume_from && !data->state.this_is_a_follow) {
1991 /* do we still game? */
1993 /* Now, let's read off the proper amount of bytes from the
1995 if(conn->seek_func) {
1996 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2000 if(seekerr != CURL_SEEKFUNC_OK) {
2001 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2002 failf(data, "Could not seek stream");
2003 return CURLE_READ_ERROR;
2005 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2007 curl_off_t passed=0;
2009 size_t readthisamountnow =
2010 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2011 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2013 size_t actuallyread =
2014 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2017 passed += actuallyread;
2018 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2019 /* this checks for greater-than only to make sure that the
2020 CURL_READFUNC_ABORT return code still aborts */
2021 failf(data, "Could only read %" FORMAT_OFF_T
2022 " bytes from the input",
2024 return CURLE_READ_ERROR;
2026 } while(passed < data->state.resume_from);
2030 /* now, decrease the size of the read */
2031 if(data->set.infilesize>0) {
2032 data->set.infilesize -= data->state.resume_from;
2034 if(data->set.infilesize <= 0) {
2035 failf(data, "File already completely uploaded");
2036 return CURLE_PARTIAL_FILE;
2039 /* we've passed, proceed as normal */
2042 if(data->state.use_range) {
2044 * A range is selected. We use different headers whether we're downloading
2045 * or uploading and we always let customized headers override our internal
2046 * ones if any such are specified.
2048 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2049 !Curl_checkheaders(data, "Range:")) {
2050 /* if a line like this was already allocated, free the previous one */
2051 if(conn->allocptr.rangeline)
2052 free(conn->allocptr.rangeline);
2053 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2056 else if((httpreq != HTTPREQ_GET) &&
2057 !Curl_checkheaders(data, "Content-Range:")) {
2059 /* if a line like this was already allocated, free the previous one */
2060 if(conn->allocptr.rangeline)
2061 free(conn->allocptr.rangeline);
2063 if(data->set.set_resume_from < 0) {
2064 /* Upload resume was asked for, but we don't know the size of the
2065 remote part so we tell the server (and act accordingly) that we
2066 upload the whole file (again) */
2067 conn->allocptr.rangeline =
2068 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T
2069 "/%" FORMAT_OFF_T "\r\n",
2070 data->set.infilesize - 1, data->set.infilesize);
2073 else if(data->state.resume_from) {
2074 /* This is because "resume" was selected */
2075 curl_off_t total_expected_size=
2076 data->state.resume_from + data->set.infilesize;
2077 conn->allocptr.rangeline =
2078 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2079 "/%" FORMAT_OFF_T "\r\n",
2080 data->state.range, total_expected_size-1,
2081 total_expected_size);
2084 /* Range was selected and then we just pass the incoming range and
2085 append total size */
2086 conn->allocptr.rangeline =
2087 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2088 data->state.range, data->set.infilesize);
2090 if(!conn->allocptr.rangeline)
2091 return CURLE_OUT_OF_MEMORY;
2095 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2097 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
2099 /* initialize a dynamic send-buffer */
2100 req_buffer = Curl_add_buffer_init();
2103 return CURLE_OUT_OF_MEMORY;
2105 /* add the main request stuff */
2106 /* GET/HEAD/POST/PUT */
2107 result = Curl_add_bufferf(req_buffer, "%s ", request);
2112 if(paste_ftp_userpwd)
2113 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2114 conn->user, conn->passwd,
2115 ppath + sizeof("ftp://") - 1);
2117 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2122 Curl_add_bufferf(req_buffer,
2123 "%s" /* ftp typecode (;type=x) */
2124 " HTTP/%s\r\n" /* HTTP version */
2125 "%s" /* proxyuserpwd */
2128 "%s" /* user agent */
2132 "%s" /* accept-encoding */
2134 "%s" /* Proxy-Connection */
2135 "%s",/* transfer-encoding */
2139 conn->allocptr.proxyuserpwd?
2140 conn->allocptr.proxyuserpwd:"",
2141 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2142 (data->state.use_range && conn->allocptr.rangeline)?
2143 conn->allocptr.rangeline:"",
2144 (data->set.str[STRING_USERAGENT] &&
2145 *data->set.str[STRING_USERAGENT] &&
2146 conn->allocptr.uagent)?
2147 conn->allocptr.uagent:"",
2148 (conn->allocptr.host?conn->allocptr.host:""),
2149 http->p_accept?http->p_accept:"",
2150 conn->allocptr.te?conn->allocptr.te:"",
2151 (data->set.str[STRING_ENCODING] &&
2152 *data->set.str[STRING_ENCODING] &&
2153 conn->allocptr.accept_encoding)?
2154 conn->allocptr.accept_encoding:"",
2155 (data->change.referer && conn->allocptr.ref)?
2156 conn->allocptr.ref:"" /* Referer: <data> */,
2157 (conn->bits.httpproxy &&
2158 !conn->bits.tunnel_proxy &&
2159 !Curl_checkheaders(data, "Proxy-Connection:"))?
2160 "Proxy-Connection: Keep-Alive\r\n":"",
2165 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2166 * with basic and digest, it will be freed anyway by the next request
2169 Curl_safefree (conn->allocptr.userpwd);
2170 conn->allocptr.userpwd = NULL;
2175 if(!(conn->handler->flags&PROTOPT_SSL) &&
2176 (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
2177 /* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
2179 result = Curl_http2_request(req_buffer, conn);
2184 #if !defined(CURL_DISABLE_COOKIES)
2185 if(data->cookies || addcookies) {
2186 struct Cookie *co=NULL; /* no cookies from start */
2190 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2191 co = Curl_cookie_getlist(data->cookies,
2192 conn->allocptr.cookiehost?
2193 conn->allocptr.cookiehost:host,
2195 (conn->handler->protocol&CURLPROTO_HTTPS)?
2197 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2200 struct Cookie *store=co;
2201 /* now loop through all cookies that matched */
2205 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2209 result = Curl_add_bufferf(req_buffer,
2210 "%s%s=%s", count?"; ":"",
2211 co->name, co->value);
2216 co = co->next; /* next cookie please */
2218 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2220 if(addcookies && (CURLE_OK == result)) {
2222 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2223 if(CURLE_OK == result) {
2224 result = Curl_add_bufferf(req_buffer, "%s%s",
2230 if(count && (CURLE_OK == result))
2231 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2238 if(data->set.timecondition) {
2239 result = Curl_add_timecondition(data, req_buffer);
2244 result = Curl_add_custom_headers(conn, req_buffer);
2248 http->postdata = NULL; /* nothing to post at this point */
2249 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2251 /* If 'authdone' is FALSE, we must not set the write socket index to the
2252 Curl_transfer() call below, as we're not ready to actually upload any
2257 case HTTPREQ_POST_FORM:
2258 if(!http->sendit || conn->bits.authneg) {
2259 /* nothing to post! */
2260 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2264 result = Curl_add_buffer_send(req_buffer, conn,
2265 &data->info.request_size, 0, FIRSTSOCKET);
2267 failf(data, "Failed sending POST request");
2269 /* setup variables for the upcoming transfer */
2270 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2275 if(Curl_FormInit(&http->form, http->sendit)) {
2276 failf(data, "Internal HTTP POST error!");
2277 return CURLE_HTTP_POST_ERROR;
2280 /* Get the currently set callback function pointer and store that in the
2281 form struct since we might want the actual user-provided callback later
2282 on. The conn->fread_func pointer itself will be changed for the
2283 multipart case to the function that returns a multipart formatted
2285 http->form.fread_func = conn->fread_func;
2287 /* Set the read function to read from the generated form data */
2288 conn->fread_func = (curl_read_callback)Curl_FormReader;
2289 conn->fread_in = &http->form;
2291 http->sending = HTTPSEND_BODY;
2293 if(!data->req.upload_chunky &&
2294 !Curl_checkheaders(data, "Content-Length:")) {
2295 /* only add Content-Length if not uploading chunked */
2296 result = Curl_add_bufferf(req_buffer,
2297 "Content-Length: %" FORMAT_OFF_T "\r\n",
2303 result = expect100(data, conn, req_buffer);
2309 /* Get Content-Type: line from Curl_formpostheader.
2312 size_t linelength=0;
2313 contentType = Curl_formpostheader((void *)&http->form,
2316 failf(data, "Could not get Content-Type header line!");
2317 return CURLE_HTTP_POST_ERROR;
2320 result = Curl_add_buffer(req_buffer, contentType, linelength);
2325 /* make the request end in a true CRLF */
2326 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2330 /* set upload size to the progress meter */
2331 Curl_pgrsSetUploadSize(data, http->postsize);
2333 /* fire away the whole request to the server */
2334 result = Curl_add_buffer_send(req_buffer, conn,
2335 &data->info.request_size, 0, FIRSTSOCKET);
2337 failf(data, "Failed sending POST request");
2339 /* setup variables for the upcoming transfer */
2340 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2341 &http->readbytecount, FIRSTSOCKET,
2342 &http->writebytecount);
2345 Curl_formclean(&http->sendit); /* free that whole lot */
2349 /* convert the form data */
2350 result = Curl_convert_form(data, http->sendit);
2352 Curl_formclean(&http->sendit); /* free that whole lot */
2358 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2360 if(conn->bits.authneg)
2363 postsize = data->set.infilesize;
2365 if((postsize != -1) && !data->req.upload_chunky &&
2366 !Curl_checkheaders(data, "Content-Length:")) {
2367 /* only add Content-Length if not uploading chunked */
2368 result = Curl_add_bufferf(req_buffer,
2369 "Content-Length: %" FORMAT_OFF_T "\r\n",
2375 result = expect100(data, conn, req_buffer);
2379 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2383 /* set the upload size to the progress meter */
2384 Curl_pgrsSetUploadSize(data, postsize);
2386 /* this sends the buffer and frees all the buffer resources */
2387 result = Curl_add_buffer_send(req_buffer, conn,
2388 &data->info.request_size, 0, FIRSTSOCKET);
2390 failf(data, "Failed sending PUT request");
2392 /* prepare for transfer */
2393 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2394 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2395 postsize?&http->writebytecount:NULL);
2401 /* this is the simple POST, using x-www-form-urlencoded style */
2403 if(conn->bits.authneg)
2406 /* figure out the size of the postfields */
2407 postsize = (data->set.postfieldsize != -1)?
2408 data->set.postfieldsize:
2409 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2411 if(!data->req.upload_chunky) {
2412 /* We only set Content-Length and allow a custom Content-Length if
2413 we don't upload data chunked, as RFC2616 forbids us to set both
2414 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2416 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
2417 /* we allow replacing this header if not during auth negotiation,
2418 although it isn't very wise to actually set your own */
2419 result = Curl_add_bufferf(req_buffer,
2420 "Content-Length: %" FORMAT_OFF_T"\r\n",
2427 if(!Curl_checkheaders(data, "Content-Type:")) {
2428 result = Curl_add_bufferf(req_buffer,
2429 "Content-Type: application/"
2430 "x-www-form-urlencoded\r\n");
2435 /* For really small posts we don't use Expect: headers at all, and for
2436 the somewhat bigger ones we allow the app to disable it. Just make
2437 sure that the expect100header is always set to the preferred value
2439 ptr = Curl_checkheaders(data, "Expect:");
2441 data->state.expect100header =
2442 Curl_compareheader(ptr, "Expect:", "100-continue");
2444 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2445 result = expect100(data, conn, req_buffer);
2450 data->state.expect100header = FALSE;
2452 if(data->set.postfields) {
2454 if(!data->state.expect100header &&
2455 (postsize < MAX_INITIAL_POST_SIZE)) {
2456 /* if we don't use expect: 100 AND
2457 postsize is less than MAX_INITIAL_POST_SIZE
2459 then append the post data to the HTTP request header. This limit
2460 is no magic limit but only set to prevent really huge POSTs to
2461 get the data duplicated with malloc() and family. */
2463 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2467 if(!data->req.upload_chunky) {
2468 /* We're not sending it 'chunked', append it to the request
2469 already now to reduce the number if send() calls */
2470 result = Curl_add_buffer(req_buffer, data->set.postfields,
2472 included_body = postsize;
2476 /* Append the POST data chunky-style */
2477 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2478 if(CURLE_OK == result) {
2479 result = Curl_add_buffer(req_buffer, data->set.postfields,
2481 if(CURLE_OK == result)
2482 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2483 included_body = postsize + 2;
2486 if(CURLE_OK == result)
2487 result = Curl_add_buffer(req_buffer,
2488 "\x30\x0d\x0a\x0d\x0a", 5);
2494 /* Make sure the progress information is accurate */
2495 Curl_pgrsSetUploadSize(data, postsize);
2498 /* A huge POST coming up, do data separate from the request */
2499 http->postsize = postsize;
2500 http->postdata = data->set.postfields;
2502 http->sending = HTTPSEND_BODY;
2504 conn->fread_func = (curl_read_callback)readmoredata;
2505 conn->fread_in = (void *)conn;
2507 /* set the upload size to the progress meter */
2508 Curl_pgrsSetUploadSize(data, http->postsize);
2510 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2516 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2520 if(data->req.upload_chunky && conn->bits.authneg) {
2521 /* Chunky upload is selected and we're negotiating auth still, send
2523 result = Curl_add_buffer(req_buffer,
2524 "\x30\x0d\x0a\x0d\x0a", 5);
2530 else if(data->set.postfieldsize) {
2531 /* set the upload size to the progress meter */
2532 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2534 /* set the pointer to mark that we will send the post body using the
2535 read callback, but only if we're not in authenticate
2537 if(!conn->bits.authneg) {
2538 http->postdata = (char *)&http->postdata;
2539 http->postsize = postsize;
2543 /* issue the request */
2544 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2545 (size_t)included_body, FIRSTSOCKET);
2548 failf(data, "Failed sending HTTP POST request");
2550 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2551 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2552 http->postdata?&http->writebytecount:NULL);
2556 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2560 /* issue the request */
2561 result = Curl_add_buffer_send(req_buffer, conn,
2562 &data->info.request_size, 0, FIRSTSOCKET);
2565 failf(data, "Failed sending HTTP request");
2567 /* HTTP GET/HEAD download: */
2568 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2569 http->postdata?FIRSTSOCKET:-1,
2570 http->postdata?&http->writebytecount:NULL);
2575 if(http->writebytecount) {
2576 /* if a request-body has been sent off, we make sure this progress is noted
2578 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2579 if(Curl_pgrsUpdate(conn))
2580 result = CURLE_ABORTED_BY_CALLBACK;
2582 if(http->writebytecount >= postsize) {
2583 /* already sent the entire request body, mark the "upload" as
2585 infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of "
2586 "%" FORMAT_OFF_T " bytes\n",
2587 http->writebytecount, postsize);
2588 data->req.upload_done = TRUE;
2589 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2590 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2600 * Returns TRUE if member of the list matches prefix of string
2603 checkhttpprefix(struct SessionHandle *data,
2606 struct curl_slist *head = data->set.http200aliases;
2608 #ifdef CURL_DOES_CONVERSIONS
2609 /* convert from the network encoding using a scratch area */
2610 char *scratch = strdup(s);
2611 if(NULL == scratch) {
2612 failf (data, "Failed to allocate memory for conversion!");
2613 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2615 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2616 /* Curl_convert_from_network calls failf if unsuccessful */
2618 return FALSE; /* can't return CURLE_foobar so return FALSE */
2621 #endif /* CURL_DOES_CONVERSIONS */
2624 if(checkprefix(head->data, s)) {
2631 if(!rc && (checkprefix("HTTP/", s)))
2634 #ifdef CURL_DOES_CONVERSIONS
2636 #endif /* CURL_DOES_CONVERSIONS */
2640 #ifndef CURL_DISABLE_RTSP
2642 checkrtspprefix(struct SessionHandle *data,
2646 #ifdef CURL_DOES_CONVERSIONS
2647 /* convert from the network encoding using a scratch area */
2648 char *scratch = strdup(s);
2649 if(NULL == scratch) {
2650 failf (data, "Failed to allocate memory for conversion!");
2651 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2653 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2654 /* Curl_convert_from_network calls failf if unsuccessful */
2656 return FALSE; /* can't return CURLE_foobar so return FALSE */
2660 (void)data; /* unused */
2661 #endif /* CURL_DOES_CONVERSIONS */
2662 if(checkprefix("RTSP/", s))
2667 #endif /* CURL_DISABLE_RTSP */
2670 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2673 #ifndef CURL_DISABLE_RTSP
2674 if(conn->handler->protocol & CURLPROTO_RTSP)
2675 return checkrtspprefix(data, s);
2678 #endif /* CURL_DISABLE_RTSP */
2680 return checkhttpprefix(data, s);
2684 * header_append() copies a chunk of data to the end of the already received
2685 * header. We make sure that the full string fit in the allocated header
2686 * buffer, or else we enlarge it.
2688 static CURLcode header_append(struct SessionHandle *data,
2689 struct SingleRequest *k,
2692 if(k->hbuflen + length >= data->state.headersize) {
2693 /* We enlarge the header buffer as it is too small */
2698 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2699 /* The reason to have a max limit for this is to avoid the risk of a bad
2700 server feeding libcurl with a never-ending header that will cause
2701 reallocs infinitely */
2702 failf (data, "Avoided giant realloc for header (max is %d)!",
2703 CURL_MAX_HTTP_HEADER);
2704 return CURLE_OUT_OF_MEMORY;
2707 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2708 hbufp_index = k->hbufp - data->state.headerbuff;
2709 newbuff = realloc(data->state.headerbuff, newsize);
2711 failf (data, "Failed to alloc memory for big header!");
2712 return CURLE_OUT_OF_MEMORY;
2714 data->state.headersize=newsize;
2715 data->state.headerbuff = newbuff;
2716 k->hbufp = data->state.headerbuff + hbufp_index;
2718 memcpy(k->hbufp, k->str_start, length);
2720 k->hbuflen += length;
2726 static void print_http_error(struct SessionHandle *data)
2728 struct SingleRequest *k = &data->req;
2731 /* make sure that data->req.p points to the HTTP status line */
2732 if(!strncmp(beg, "HTTP", 4)) {
2734 /* skip to HTTP status code */
2735 beg = strchr(beg, ' ');
2738 /* find trailing CR */
2739 char end_char = '\r';
2740 char *end = strchr(beg, end_char);
2742 /* try to find LF (workaround for non-compliant HTTP servers) */
2744 end = strchr(beg, end_char);
2748 /* temporarily replace CR or LF by NUL and print the error message */
2750 failf(data, "The requested URL returned error: %s", beg);
2752 /* restore the previously replaced CR or LF */
2759 /* fall-back to printing the HTTP status code only */
2760 failf(data, "The requested URL returned error: %d", k->httpcode);
2764 * Read any HTTP header lines from the server and pass them to the client app.
2766 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2767 struct connectdata *conn,
2772 struct SingleRequest *k = &data->req;
2774 /* header line within buffer loop */
2780 /* str_start is start of line within buf */
2781 k->str_start = k->str;
2783 /* data is in network encoding so use 0x0a instead of '\n' */
2784 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2787 /* Not a complete header line within buffer, append the data to
2788 the end of the headerbuff. */
2789 result = header_append(data, k, *nread);
2793 if(!k->headerline && (k->hbuflen>5)) {
2794 /* make a first check that this looks like a protocol header */
2795 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2796 /* this is not the beginning of a protocol first header line */
2798 k->badheader = HEADER_ALLBAD;
2803 break; /* read more and try again */
2806 /* decrease the size of the remaining (supposed) header line */
2807 rest_length = (k->end_ptr - k->str)+1;
2808 *nread -= (ssize_t)rest_length;
2810 k->str = k->end_ptr + 1; /* move past new line */
2812 full_length = k->str - k->str_start;
2814 result = header_append(data, k, full_length);
2818 k->end_ptr = k->hbufp;
2819 k->p = data->state.headerbuff;
2822 * We now have a FULL header line that p points to
2825 if(!k->headerline) {
2826 /* the first read header */
2827 if((k->hbuflen>5) &&
2828 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2829 /* this is not the beginning of a protocol first header line */
2832 /* since there's more, this is a partial bad header */
2833 k->badheader = HEADER_PARTHEADER;
2835 /* this was all we read so it's all a bad header */
2836 k->badheader = HEADER_ALLBAD;
2837 *nread = (ssize_t)rest_length;
2843 /* headers are in network encoding so
2844 use 0x0a and 0x0d instead of '\n' and '\r' */
2845 if((0x0a == *k->p) || (0x0d == *k->p)) {
2847 /* Zero-length header line means end of headers! */
2849 #ifdef CURL_DOES_CONVERSIONS
2851 *k->p = '\r'; /* replace with CR in host encoding */
2852 k->p++; /* pass the CR byte */
2855 *k->p = '\n'; /* replace with LF in host encoding */
2856 k->p++; /* pass the LF byte */
2860 k->p++; /* pass the \r byte */
2862 k->p++; /* pass the \n byte */
2863 #endif /* CURL_DOES_CONVERSIONS */
2865 if(100 <= k->httpcode && 199 >= k->httpcode) {
2867 * We have made a HTTP PUT or POST and this is 1.1-lingo
2868 * that tells us that the server is OK with this and ready
2869 * to receive the data.
2870 * However, we'll get more headers now so we must get
2871 * back into the header-parsing state!
2874 k->headerline = 0; /* restart the header line counter */
2876 /* if we did wait for this do enable write now! */
2878 k->exp100 = EXP100_SEND_DATA;
2879 k->keepon |= KEEP_SEND;
2883 k->header = FALSE; /* no more header to parse! */
2885 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2886 (conn->httpversion >= 11) &&
2887 !(conn->handler->protocol & CURLPROTO_RTSP) &&
2888 data->set.httpreq != HTTPREQ_HEAD) {
2889 /* On HTTP 1.1, when connection is not to get closed, but no
2890 Content-Length nor Content-Encoding chunked have been
2891 received, according to RFC2616 section 4.4 point 5, we
2892 assume that the server will close the connection to
2893 signal the end of the document. */
2894 infof(data, "no chunk, no close, no size. Assume close to "
2896 conn->bits.close = TRUE;
2901 * When all the headers have been parsed, see if we should give
2902 * up and return an error.
2904 if(http_should_fail(conn)) {
2905 failf (data, "The requested URL returned error: %d",
2907 return CURLE_HTTP_RETURNED_ERROR;
2910 /* now, only output this if the header AND body are requested:
2912 writetype = CLIENTWRITE_HEADER;
2913 if(data->set.include_header)
2914 writetype |= CLIENTWRITE_BODY;
2916 headerlen = k->p - data->state.headerbuff;
2918 result = Curl_client_write(conn, writetype,
2919 data->state.headerbuff,
2924 data->info.header_size += (long)headerlen;
2925 data->req.headerbytecount += (long)headerlen;
2927 data->req.deductheadercount =
2928 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2930 if(!*stop_reading) {
2931 /* Curl_http_auth_act() checks what authentication methods
2932 * that are available and decides which one (if any) to
2933 * use. It will set 'newurl' if an auth method was picked. */
2934 result = Curl_http_auth_act(conn);
2939 if(k->httpcode >= 300) {
2940 if((!conn->bits.authneg) && !conn->bits.close &&
2941 !conn->bits.rewindaftersend) {
2943 * General treatment of errors when about to send data. Including :
2944 * "417 Expectation Failed", while waiting for 100-continue.
2946 * The check for close above is done simply because of something
2947 * else has already deemed the connection to get closed then
2948 * something else should've considered the big picture and we
2951 * rewindaftersend indicates that something has told libcurl to
2952 * continue sending even if it gets discarded
2955 switch(data->set.httpreq) {
2958 case HTTPREQ_POST_FORM:
2959 /* We got an error response. If this happened before the whole
2960 * request body has been sent we stop sending and mark the
2961 * connection for closure after we've read the entire response.
2963 if(!k->upload_done) {
2964 infof(data, "HTTP error before end of send, stop sending\n");
2965 conn->bits.close = TRUE; /* close after this */
2966 k->upload_done = TRUE;
2967 k->keepon &= ~KEEP_SEND; /* don't send */
2968 if(data->state.expect100header)
2969 k->exp100 = EXP100_FAILED;
2973 default: /* default label present to avoid compiler warnings */
2979 if(conn->bits.rewindaftersend) {
2980 /* We rewind after a complete send, so thus we continue
2982 infof(data, "Keep sending data to get tossed away!\n");
2983 k->keepon |= KEEP_SEND;
2989 * really end-of-headers.
2991 * If we requested a "no body", this is a good time to get
2992 * out and return home.
2994 if(data->set.opt_no_body)
2995 *stop_reading = TRUE;
2997 /* If we know the expected size of this document, we set the
2998 maximum download size to the size of the expected
2999 document or else, we won't know when to stop reading!
3001 Note that we set the download maximum even if we read a
3002 "Connection: close" header, to make sure that
3003 "Content-Length: 0" still prevents us from attempting to
3004 read the (missing) response-body.
3006 /* According to RFC2616 section 4.4, we MUST ignore
3007 Content-Length: headers if we are now receiving data
3008 using chunked Transfer-Encoding.
3011 k->maxdownload = k->size = -1;
3014 /* We do this operation even if no_body is true, since this
3015 data might be retrieved later with curl_easy_getinfo()
3016 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3018 Curl_pgrsSetDownloadSize(data, k->size);
3019 k->maxdownload = k->size;
3022 /* If max download size is *zero* (nothing) we already
3023 have nothing and can safely return ok now! */
3024 if(0 == k->maxdownload)
3025 *stop_reading = TRUE;
3028 /* we make sure that this socket isn't read more now */
3029 k->keepon &= ~KEEP_RECV;
3032 if(data->set.verbose)
3033 Curl_debug(data, CURLINFO_HEADER_IN,
3034 k->str_start, headerlen, conn);
3035 break; /* exit header line loop */
3038 /* We continue reading headers, so reset the line-based
3039 header parsing variables hbufp && hbuflen */
3040 k->hbufp = data->state.headerbuff;
3046 * Checks for special headers coming up.
3049 if(!k->headerline++) {
3050 /* This is the first header, it MUST be the error code line
3051 or else we consider this to be the body right away! */
3052 int httpversion_major;
3053 int rtspversion_major;
3055 #ifdef CURL_DOES_CONVERSIONS
3056 #define HEADER1 scratch
3057 #define SCRATCHSIZE 21
3059 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3060 /* We can't really convert this yet because we
3061 don't know if it's the 1st header line or the body.
3062 So we do a partial conversion into a scratch area,
3063 leaving the data at k->p as-is.
3065 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3066 scratch[SCRATCHSIZE] = 0; /* null terminate */
3067 res = Curl_convert_from_network(data,
3071 /* Curl_convert_from_network calls failf if unsuccessful */
3074 #define HEADER1 k->p /* no conversion needed, just use k->p */
3075 #endif /* CURL_DOES_CONVERSIONS */
3077 if(conn->handler->protocol & CURLPROTO_HTTP) {
3078 nc = sscanf(HEADER1,
3084 conn->httpversion += 10 * httpversion_major;
3087 /* this is the real world, not a Nirvana
3088 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3090 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3091 conn->httpversion = 10;
3093 /* If user has set option HTTP200ALIASES,
3094 compare header line against list of aliases
3097 if(checkhttpprefix(data, k->p)) {
3100 conn->httpversion = 10;
3105 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3106 nc = sscanf(HEADER1,
3112 conn->rtspversion += 10 * rtspversion_major;
3113 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3116 /* TODO: do we care about the other cases here? */
3122 data->info.httpcode = k->httpcode;
3124 data->info.httpversion = conn->httpversion;
3125 if(!data->state.httpversion ||
3126 data->state.httpversion > conn->httpversion)
3127 /* store the lowest server version we encounter */
3128 data->state.httpversion = conn->httpversion;
3131 * This code executes as part of processing the header. As a
3132 * result, it's not totally clear how to interpret the
3133 * response code yet as that depends on what other headers may
3134 * be present. 401 and 407 may be errors, but may be OK
3135 * depending on how authentication is working. Other codes
3136 * are definitely errors, so give up here.
3138 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3139 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3140 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3142 if(data->state.resume_from &&
3143 (data->set.httpreq==HTTPREQ_GET) &&
3144 (k->httpcode == 416)) {
3145 /* "Requested Range Not Satisfiable", just proceed and
3146 pretend this is no error */
3149 /* serious error, go home! */
3150 print_http_error(data);
3151 return CURLE_HTTP_RETURNED_ERROR;
3155 if(conn->httpversion == 10) {
3156 /* Default action for HTTP/1.0 must be to close, unless
3157 we get one of those fancy headers that tell us the
3158 server keeps it open for us! */
3159 infof(data, "HTTP 1.0, assume close after body\n");
3160 conn->bits.close = TRUE;
3162 else if(conn->httpversion >= 11 &&
3163 !conn->bits.close) {
3164 struct connectbundle *cb_ptr;
3166 /* If HTTP version is >= 1.1 and connection is persistent
3167 server supports pipelining. */
3169 "HTTP 1.1 or later with persistent connection, "
3170 "pipelining supported\n"));
3171 /* Activate pipelining if needed */
3172 cb_ptr = conn->bundle;
3174 if(!Curl_pipeline_site_blacklisted(data, conn))
3175 cb_ptr->server_supports_pipelining = TRUE;
3179 switch(k->httpcode) {
3181 /* (quote from RFC2616, section 10.2.5): The server has
3182 * fulfilled the request but does not need to return an
3183 * entity-body ... The 204 response MUST NOT include a
3184 * message-body, and thus is always terminated by the first
3185 * empty line after the header fields. */
3188 /* (quote from RFC2616, section 10.3.5): The 304 response
3189 * MUST NOT contain a message-body, and thus is always
3190 * terminated by the first empty line after the header
3192 if(data->set.timecondition)
3193 data->info.timecond = TRUE;
3196 k->ignorecl = TRUE; /* ignore Content-Length headers */
3204 k->header = FALSE; /* this is not a header line */
3209 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3210 /* Curl_convert_from_network calls failf if unsuccessful */
3214 /* Check for Content-Length: header lines to get size */
3215 if(!k->ignorecl && !data->set.ignorecl &&
3216 checkprefix("Content-Length:", k->p)) {
3217 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3218 if(data->set.max_filesize &&
3219 contentlength > data->set.max_filesize) {
3220 failf(data, "Maximum file size exceeded");
3221 return CURLE_FILESIZE_EXCEEDED;
3223 if(contentlength >= 0) {
3224 k->size = contentlength;
3225 k->maxdownload = k->size;
3226 /* we set the progress download size already at this point
3227 just to make it easier for apps/callbacks to extract this
3228 info as soon as possible */
3229 Curl_pgrsSetDownloadSize(data, k->size);
3232 /* Negative Content-Length is really odd, and we know it
3233 happens for example when older Apache servers send large
3235 conn->bits.close = TRUE;
3236 infof(data, "Negative content-length: %" FORMAT_OFF_T
3237 ", closing after transfer\n", contentlength);
3240 /* check for Content-Type: header lines to get the MIME-type */
3241 else if(checkprefix("Content-Type:", k->p)) {
3242 char *contenttype = Curl_copy_header_value(k->p);
3244 return CURLE_OUT_OF_MEMORY;
3246 /* ignore empty data */
3249 Curl_safefree(data->info.contenttype);
3250 data->info.contenttype = contenttype;
3253 else if(checkprefix("Server:", k->p)) {
3254 char *server_name = Curl_copy_header_value(k->p);
3256 /* Turn off pipelining if the server version is blacklisted */
3257 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3258 if(Curl_pipeline_server_blacklisted(data, server_name))
3259 conn->bundle->server_supports_pipelining = FALSE;
3261 Curl_safefree(server_name);
3263 else if((conn->httpversion == 10) &&
3264 conn->bits.httpproxy &&
3265 Curl_compareheader(k->p,
3266 "Proxy-Connection:", "keep-alive")) {
3268 * When a HTTP/1.0 reply comes when using a proxy, the
3269 * 'Proxy-Connection: keep-alive' line tells us the
3270 * connection will be kept alive for our pleasure.
3271 * Default action for 1.0 is to close.
3273 conn->bits.close = FALSE; /* don't close when done */
3274 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3276 else if((conn->httpversion == 11) &&
3277 conn->bits.httpproxy &&
3278 Curl_compareheader(k->p,
3279 "Proxy-Connection:", "close")) {
3281 * We get a HTTP/1.1 response from a proxy and it says it'll
3282 * close down after this transfer.
3284 conn->bits.close = TRUE; /* close when done */
3285 infof(data, "HTTP/1.1 proxy connection set close!\n");
3287 else if((conn->httpversion == 10) &&
3288 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3290 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3291 * tells us the connection will be kept alive for our
3292 * pleasure. Default action for 1.0 is to close.
3294 * [RFC2068, section 19.7.1] */
3295 conn->bits.close = FALSE; /* don't close when done */
3296 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3298 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3300 * [RFC 2616, section 8.1.2.1]
3301 * "Connection: close" is HTTP/1.1 language and means that
3302 * the connection will close when this request has been
3305 conn->bits.close = TRUE; /* close when done */
3307 else if(checkprefix("Transfer-Encoding:", k->p)) {
3308 /* One or more encodings. We check for chunked and/or a compression
3311 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3312 * means that the server will send a series of "chunks". Each
3313 * chunk starts with line with info (including size of the
3314 * coming block) (terminated with CRLF), then a block of data
3315 * with the previously mentioned size. There can be any amount
3316 * of chunks, and a chunk-data set to zero signals the
3321 /* Find the first non-space letter */
3325 /* skip whitespaces and commas */
3326 while(*start && (ISSPACE(*start) || (*start == ',')))
3329 if(checkprefix("chunked", start)) {
3330 k->chunk = TRUE; /* chunks coming our way */
3332 /* init our chunky engine */
3333 Curl_httpchunk_init(conn);
3338 if(k->auto_decoding)
3339 /* TODO: we only support the first mentioned compression for now */
3342 if(checkprefix("identity", start)) {
3343 k->auto_decoding = IDENTITY;
3346 else if(checkprefix("deflate", start)) {
3347 k->auto_decoding = DEFLATE;
3350 else if(checkprefix("gzip", start)) {
3351 k->auto_decoding = GZIP;
3354 else if(checkprefix("x-gzip", start)) {
3355 k->auto_decoding = GZIP;
3358 else if(checkprefix("compress", start)) {
3359 k->auto_decoding = COMPRESS;
3362 else if(checkprefix("x-compress", start)) {
3363 k->auto_decoding = COMPRESS;
3373 else if(checkprefix("Content-Encoding:", k->p) &&
3374 data->set.str[STRING_ENCODING]) {
3376 * Process Content-Encoding. Look for the values: identity,
3377 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3378 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3379 * 2616). zlib cannot handle compress. However, errors are
3380 * handled further down when the response body is processed
3384 /* Find the first non-space letter */
3386 while(*start && ISSPACE(*start))
3389 /* Record the content-encoding for later use */
3390 if(checkprefix("identity", start))
3391 k->auto_decoding = IDENTITY;
3392 else if(checkprefix("deflate", start))
3393 k->auto_decoding = DEFLATE;
3394 else if(checkprefix("gzip", start)
3395 || checkprefix("x-gzip", start))
3396 k->auto_decoding = GZIP;
3397 else if(checkprefix("compress", start)
3398 || checkprefix("x-compress", start))
3399 k->auto_decoding = COMPRESS;
3401 else if(checkprefix("Content-Range:", k->p)) {
3402 /* Content-Range: bytes [num]-
3403 Content-Range: bytes: [num]-
3404 Content-Range: [num]-
3406 The second format was added since Sun's webserver
3407 JavaWebServer/1.1.1 obviously sends the header this way!
3408 The third added since some servers use that!
3411 char *ptr = k->p + 14;
3413 /* Move forward until first digit */
3414 while(*ptr && !ISDIGIT(*ptr))
3417 k->offset = curlx_strtoofft(ptr, NULL, 10);
3419 if(data->state.resume_from == k->offset)
3420 /* we asked for a resume and we got it */
3421 k->content_range = TRUE;
3423 #if !defined(CURL_DISABLE_COOKIES)
3424 else if(data->cookies &&
3425 checkprefix("Set-Cookie:", k->p)) {
3426 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3427 CURL_LOCK_ACCESS_SINGLE);
3428 Curl_cookie_add(data,
3429 data->cookies, TRUE, k->p+11,
3430 /* If there is a custom-set Host: name, use it
3431 here, or else use real peer host name. */
3432 conn->allocptr.cookiehost?
3433 conn->allocptr.cookiehost:conn->host.name,
3435 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3438 else if(checkprefix("Last-Modified:", k->p) &&
3439 (data->set.timecondition || data->set.get_filetime) ) {
3440 time_t secs=time(NULL);
3441 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3443 if(data->set.get_filetime)
3444 data->info.filetime = (long)k->timeofdoc;
3446 else if((checkprefix("WWW-Authenticate:", k->p) &&
3447 (401 == k->httpcode)) ||
3448 (checkprefix("Proxy-authenticate:", k->p) &&
3449 (407 == k->httpcode))) {
3451 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3452 char *auth = Curl_copy_header_value(k->p);
3454 return CURLE_OUT_OF_MEMORY;
3456 result = Curl_http_input_auth(conn, proxy, auth);
3458 Curl_safefree(auth);
3463 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3464 checkprefix("Location:", k->p) &&
3465 !data->req.location) {
3466 /* this is the URL that the server advises us to use instead */
3467 char *location = Curl_copy_header_value(k->p);
3469 return CURLE_OUT_OF_MEMORY;
3471 /* ignore empty data */
3474 data->req.location = location;
3476 if(data->set.http_follow_location) {
3477 DEBUGASSERT(!data->req.newurl);
3478 data->req.newurl = strdup(data->req.location); /* clone */
3479 if(!data->req.newurl)
3480 return CURLE_OUT_OF_MEMORY;
3482 /* some cases of POST and PUT etc needs to rewind the data
3483 stream at this point */
3484 result = http_perhapsrewind(conn);
3490 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3491 result = Curl_rtsp_parseheader(conn, k->p);
3497 * End of header-checks. Write them to the client.
3500 writetype = CLIENTWRITE_HEADER;
3501 if(data->set.include_header)
3502 writetype |= CLIENTWRITE_BODY;
3504 if(data->set.verbose)
3505 Curl_debug(data, CURLINFO_HEADER_IN,
3506 k->p, (size_t)k->hbuflen, conn);
3508 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3512 data->info.header_size += (long)k->hbuflen;
3513 data->req.headerbytecount += (long)k->hbuflen;
3515 /* reset hbufp pointer && hbuflen */
3516 k->hbufp = data->state.headerbuff;
3519 while(!*stop_reading && *k->str); /* header line within buffer */
3521 /* We might have reached the end of the header part here, but
3522 there might be a non-header part left in the end of the read
3528 #endif /* CURL_DISABLE_HTTP */