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"
57 #include "vtls/vtls.h"
58 #include "http_digest.h"
59 #include "curl_ntlm.h"
60 #include "curl_ntlm_wb.h"
61 #include "http_negotiate.h"
66 #include "curl_memory.h"
68 #include "parsedate.h" /* for the week day and month names */
69 #include "strtoofft.h"
72 #include "content_encoding.h"
73 #include "http_proxy.h"
75 #include "non-ascii.h"
80 #define _MPRINTF_REPLACE /* use our functions only */
81 #include <curl/mprintf.h>
83 /* The last #include file should be: */
87 * Forward declarations.
90 static int http_getsock_do(struct connectdata *conn,
93 static int http_should_fail(struct connectdata *conn);
96 static CURLcode https_connecting(struct connectdata *conn, bool *done);
97 static int https_getsock(struct connectdata *conn,
101 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
105 * HTTP handler interface.
107 const struct Curl_handler Curl_handler_http = {
109 Curl_http_setup_conn, /* setup_connection */
110 Curl_http, /* do_it */
111 Curl_http_done, /* done */
112 ZERO_NULL, /* do_more */
113 Curl_http_connect, /* connect_it */
114 ZERO_NULL, /* connecting */
115 ZERO_NULL, /* doing */
116 ZERO_NULL, /* proto_getsock */
117 http_getsock_do, /* doing_getsock */
118 ZERO_NULL, /* domore_getsock */
119 ZERO_NULL, /* perform_getsock */
120 ZERO_NULL, /* disconnect */
121 ZERO_NULL, /* readwrite */
122 PORT_HTTP, /* defport */
123 CURLPROTO_HTTP, /* protocol */
124 PROTOPT_NONE /* flags */
129 * HTTPS handler interface.
131 const struct Curl_handler Curl_handler_https = {
132 "HTTPS", /* scheme */
133 Curl_http_setup_conn, /* setup_connection */
134 Curl_http, /* do_it */
135 Curl_http_done, /* done */
136 ZERO_NULL, /* do_more */
137 Curl_http_connect, /* connect_it */
138 https_connecting, /* connecting */
139 ZERO_NULL, /* doing */
140 https_getsock, /* proto_getsock */
141 http_getsock_do, /* doing_getsock */
142 ZERO_NULL, /* domore_getsock */
143 ZERO_NULL, /* perform_getsock */
144 ZERO_NULL, /* disconnect */
145 ZERO_NULL, /* readwrite */
146 PORT_HTTPS, /* defport */
147 CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */
148 PROTOPT_SSL /* flags */
153 CURLcode Curl_http_setup_conn(struct connectdata *conn)
155 /* allocate the HTTP-specific struct for the SessionHandle, only to survive
156 during this request */
157 DEBUGASSERT(conn->data->req.protop == NULL);
159 conn->data->req.protop = calloc(1, sizeof(struct HTTP));
160 if(!conn->data->req.protop)
161 return CURLE_OUT_OF_MEMORY;
167 * checkheaders() checks the linked list of custom HTTP headers for a
168 * particular header (prefix).
170 * Returns a pointer to the first matching header or NULL if none matched.
172 char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
174 struct curl_slist *head;
175 size_t thislen = strlen(thisheader);
177 for(head = data->set.headers; head; head=head->next) {
178 if(Curl_raw_nequal(head->data, thisheader, thislen))
185 * Strip off leading and trailing whitespace from the value in the
186 * given HTTP header line and return a strdupped copy. Returns NULL in
187 * case of allocation failure. Returns an empty string if the header value
188 * consists entirely of whitespace.
190 char *Curl_copy_header_value(const char *header)
199 /* Find the end of the header name */
200 while(*header && (*header != ':'))
204 /* Skip over colon */
207 /* Find the first non-space letter */
209 while(*start && ISSPACE(*start))
212 /* data is in the host encoding so
213 use '\r' and '\n' instead of 0x0d and 0x0a */
214 end = strchr(start, '\r');
216 end = strchr(start, '\n');
218 end = strchr(start, '\0');
222 /* skip all trailing space letters */
223 while((end > start) && ISSPACE(*end))
226 /* get length of the type */
227 len = end - start + 1;
229 value = malloc(len + 1);
233 memcpy(value, start, len);
234 value[len] = 0; /* zero terminate */
240 * http_output_basic() sets up an Authorization: header (or the proxy version)
241 * for HTTP Basic authentication.
245 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
248 char *authorization = NULL;
249 struct SessionHandle *data = conn->data;
256 userp = &conn->allocptr.proxyuserpwd;
257 user = conn->proxyuser;
258 pwd = conn->proxypasswd;
261 userp = &conn->allocptr.userpwd;
266 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
268 error = Curl_base64_encode(data,
269 data->state.buffer, strlen(data->state.buffer),
270 &authorization, &size);
275 return CURLE_REMOTE_ACCESS_DENIED;
277 Curl_safefree(*userp);
278 *userp = aprintf("%sAuthorization: Basic %s\r\n",
283 return CURLE_OUT_OF_MEMORY;
288 /* pickoneauth() selects the most favourable authentication method from the
289 * ones available and the ones we want.
291 * return TRUE if one was picked
293 static bool pickoneauth(struct auth *pick)
296 /* only deal with authentication we want */
297 unsigned long avail = pick->avail & pick->want;
300 /* The order of these checks is highly relevant, as this will be the order
301 of preference in case of the existence of multiple accepted types. */
302 if(avail & CURLAUTH_GSSNEGOTIATE)
303 pick->picked = CURLAUTH_GSSNEGOTIATE;
304 else if(avail & CURLAUTH_DIGEST)
305 pick->picked = CURLAUTH_DIGEST;
306 else if(avail & CURLAUTH_NTLM)
307 pick->picked = CURLAUTH_NTLM;
308 else if(avail & CURLAUTH_NTLM_WB)
309 pick->picked = CURLAUTH_NTLM_WB;
310 else if(avail & CURLAUTH_BASIC)
311 pick->picked = CURLAUTH_BASIC;
313 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
316 pick->avail = CURLAUTH_NONE; /* clear it here */
322 * Curl_http_perhapsrewind()
324 * If we are doing POST or PUT {
325 * If we have more data to send {
326 * If we are doing NTLM {
327 * Keep sending since we must not disconnect
330 * If there is more than just a little data left to send, close
331 * the current connection by force.
334 * If we have sent any data {
335 * If we don't have track of all the data {
336 * call app to tell it to rewind
339 * rewind internally so that the operation can restart fine
344 static CURLcode http_perhapsrewind(struct connectdata *conn)
346 struct SessionHandle *data = conn->data;
347 struct HTTP *http = data->req.protop;
348 curl_off_t bytessent;
349 curl_off_t expectsend = -1; /* default is unknown */
352 /* If this is still NULL, we have not reach very far and we can safely
353 skip this rewinding stuff */
356 switch(data->set.httpreq) {
364 bytessent = http->writebytecount;
366 if(conn->bits.authneg)
367 /* This is a state where we are known to be negotiating and we don't send
371 /* figure out how much data we are expected to send */
372 switch(data->set.httpreq) {
374 if(data->set.postfieldsize != -1)
375 expectsend = data->set.postfieldsize;
376 else if(data->set.postfields)
377 expectsend = (curl_off_t)strlen(data->set.postfields);
380 if(data->set.infilesize != -1)
381 expectsend = data->set.infilesize;
383 case HTTPREQ_POST_FORM:
384 expectsend = http->postsize;
391 conn->bits.rewindaftersend = FALSE; /* default */
393 if((expectsend == -1) || (expectsend > bytessent)) {
394 /* There is still data left to send */
395 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
396 (data->state.authhost.picked == CURLAUTH_NTLM) ||
397 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
398 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
399 if(((expectsend - bytessent) < 2000) ||
400 (conn->ntlm.state != NTLMSTATE_NONE) ||
401 (conn->proxyntlm.state != NTLMSTATE_NONE)) {
402 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
403 data left to send, keep on sending. */
405 /* rewind data when completely done sending! */
406 if(!conn->bits.authneg) {
407 conn->bits.rewindaftersend = TRUE;
408 infof(data, "Rewind stream after send\n");
414 /* this is already marked to get closed */
417 infof(data, "NTLM send, close instead of sending %"
418 CURL_FORMAT_CURL_OFF_T " bytes\n",
419 (curl_off_t)(expectsend - bytessent));
422 /* This is not NTLM or many bytes left to send: close
424 conn->bits.close = TRUE;
425 data->req.size = 0; /* don't download any more than 0 bytes */
427 /* There still is data left to send, but this connection is marked for
428 closure so we can safely do the rewind right now */
432 /* we rewind now at once since if we already sent something */
433 return Curl_readrewind(conn);
439 * Curl_http_auth_act() gets called when all HTTP headers have been received
440 * and it checks what authentication methods that are available and decides
441 * which one (if any) to use. It will set 'newurl' if an auth method was
445 CURLcode Curl_http_auth_act(struct connectdata *conn)
447 struct SessionHandle *data = conn->data;
448 bool pickhost = FALSE;
449 bool pickproxy = FALSE;
450 CURLcode code = CURLE_OK;
452 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
453 /* this is a transient response code, ignore */
456 if(data->state.authproblem)
457 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
459 if(conn->bits.user_passwd &&
460 ((data->req.httpcode == 401) ||
461 (conn->bits.authneg && data->req.httpcode < 300))) {
462 pickhost = pickoneauth(&data->state.authhost);
464 data->state.authproblem = TRUE;
466 if(conn->bits.proxy_user_passwd &&
467 ((data->req.httpcode == 407) ||
468 (conn->bits.authneg && data->req.httpcode < 300))) {
469 pickproxy = pickoneauth(&data->state.authproxy);
471 data->state.authproblem = TRUE;
474 if(pickhost || pickproxy) {
475 /* In case this is GSS auth, the newurl field is already allocated so
476 we must make sure to free it before allocating a new one. As figured
477 out in bug #2284386 */
478 Curl_safefree(data->req.newurl);
479 data->req.newurl = strdup(data->change.url); /* clone URL */
480 if(!data->req.newurl)
481 return CURLE_OUT_OF_MEMORY;
483 if((data->set.httpreq != HTTPREQ_GET) &&
484 (data->set.httpreq != HTTPREQ_HEAD) &&
485 !conn->bits.rewindaftersend) {
486 code = http_perhapsrewind(conn);
492 else if((data->req.httpcode < 300) &&
493 (!data->state.authhost.done) &&
494 conn->bits.authneg) {
495 /* no (known) authentication available,
496 authentication is not "done" yet and
497 no authentication seems to be required and
498 we didn't try HEAD or GET */
499 if((data->set.httpreq != HTTPREQ_GET) &&
500 (data->set.httpreq != HTTPREQ_HEAD)) {
501 data->req.newurl = strdup(data->change.url); /* clone URL */
502 if(!data->req.newurl)
503 return CURLE_OUT_OF_MEMORY;
504 data->state.authhost.done = TRUE;
507 if(http_should_fail(conn)) {
508 failf (data, "The requested URL returned error: %d",
510 code = CURLE_HTTP_RETURNED_ERROR;
518 * Output the correct authentication header depending on the auth type
519 * and whether or not it is to a proxy.
522 output_auth_headers(struct connectdata *conn,
523 struct auth *authstatus,
528 struct SessionHandle *data = conn->data;
529 const char *auth=NULL;
530 CURLcode result = CURLE_OK;
531 #ifdef USE_HTTP_NEGOTIATE
532 struct negotiatedata *negdata = proxy?
533 &data->state.proxyneg:&data->state.negotiate;
536 #ifdef CURL_DISABLE_CRYPTO_AUTH
541 #ifdef USE_HTTP_NEGOTIATE
542 negdata->state = GSS_AUTHNONE;
543 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
544 negdata->context && !GSS_ERROR(negdata->status)) {
545 auth="GSS-Negotiate";
546 result = Curl_output_negotiate(conn, proxy);
549 authstatus->done = TRUE;
550 negdata->state = GSS_AUTHSENT;
555 if(authstatus->picked == CURLAUTH_NTLM) {
557 result = Curl_output_ntlm(conn, proxy);
563 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
564 if(authstatus->picked == CURLAUTH_NTLM_WB) {
566 result = Curl_output_ntlm_wb(conn, proxy);
572 #ifndef CURL_DISABLE_CRYPTO_AUTH
573 if(authstatus->picked == CURLAUTH_DIGEST) {
575 result = Curl_output_digest(conn,
577 (const unsigned char *)request,
578 (const unsigned char *)path);
584 if(authstatus->picked == CURLAUTH_BASIC) {
586 if((proxy && conn->bits.proxy_user_passwd &&
587 !Curl_checkheaders(data, "Proxy-authorization:")) ||
588 (!proxy && conn->bits.user_passwd &&
589 !Curl_checkheaders(data, "Authorization:"))) {
591 result = http_output_basic(conn, proxy);
595 /* NOTE: this function should set 'done' TRUE, as the other auth
596 functions work that way */
597 authstatus->done = TRUE;
601 infof(data, "%s auth using %s with user '%s'\n",
602 proxy?"Proxy":"Server", auth,
603 proxy?(conn->proxyuser?conn->proxyuser:""):
604 (conn->user?conn->user:""));
605 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
608 authstatus->multi = FALSE;
614 * Curl_http_output_auth() setups the authentication headers for the
615 * host/proxy and the correct authentication
616 * method. conn->data->state.authdone is set to TRUE when authentication is
619 * @param conn all information about the current connection
620 * @param request pointer to the request keyword
621 * @param path pointer to the requested path
622 * @param proxytunnel boolean if this is the request setting up a "proxy
628 Curl_http_output_auth(struct connectdata *conn,
631 bool proxytunnel) /* TRUE if this is the request setting
632 up the proxy tunnel */
634 CURLcode result = CURLE_OK;
635 struct SessionHandle *data = conn->data;
636 struct auth *authhost;
637 struct auth *authproxy;
641 authhost = &data->state.authhost;
642 authproxy = &data->state.authproxy;
644 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
645 conn->bits.user_passwd)
646 /* continue please */ ;
648 authhost->done = TRUE;
649 authproxy->done = TRUE;
650 return CURLE_OK; /* no authentication with no user or password */
653 if(authhost->want && !authhost->picked)
654 /* The app has selected one or more methods, but none has been picked
655 so far by a server round-trip. Then we set the picked one to the
656 want one, and if this is one single bit it'll be used instantly. */
657 authhost->picked = authhost->want;
659 if(authproxy->want && !authproxy->picked)
660 /* The app has selected one or more methods, but none has been picked so
661 far by a proxy round-trip. Then we set the picked one to the want one,
662 and if this is one single bit it'll be used instantly. */
663 authproxy->picked = authproxy->want;
665 #ifndef CURL_DISABLE_PROXY
666 /* Send proxy authentication header if needed */
667 if(conn->bits.httpproxy &&
668 (conn->bits.tunnel_proxy == proxytunnel)) {
669 result = output_auth_headers(conn, authproxy, request, path, TRUE);
676 #endif /* CURL_DISABLE_PROXY */
677 /* we have no proxy so let's pretend we're done authenticating
679 authproxy->done = TRUE;
681 /* To prevent the user+password to get sent to other than the original
682 host due to a location-follow, we do some weirdo checks here */
683 if(!data->state.this_is_a_follow ||
685 !data->state.first_host ||
686 data->set.http_disable_hostname_check_before_authentication ||
687 Curl_raw_equal(data->state.first_host, conn->host.name)) {
688 result = output_auth_headers(conn, authhost, request, path, FALSE);
691 authhost->done = TRUE;
698 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
699 * headers. They are dealt with both in the transfer.c main loop and in the
700 * proxy CONNECT loop.
703 CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
704 const char *auth) /* the first non-space */
707 * This resource requires authentication
709 struct SessionHandle *data = conn->data;
711 unsigned long *availp;
715 availp = &data->info.proxyauthavail;
716 authp = &data->state.authproxy;
719 availp = &data->info.httpauthavail;
720 authp = &data->state.authhost;
724 * Here we check if we want the specific single authentication (using ==) and
725 * if we do, we initiate usage of it.
727 * If the provided authentication is wanted as one out of several accepted
728 * types (using &), we OR this authentication type to the authavail
733 * ->picked is first set to the 'want' value (one or more bits) before the
734 * request is sent, and then it is again set _after_ all response 401/407
735 * headers have been received but then only to a single preferred method
741 #ifdef USE_HTTP_NEGOTIATE
742 if(checkprefix("GSS-Negotiate", auth) ||
743 checkprefix("Negotiate", auth)) {
745 *availp |= CURLAUTH_GSSNEGOTIATE;
746 authp->avail |= CURLAUTH_GSSNEGOTIATE;
748 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
749 if(data->state.negotiate.state == GSS_AUTHSENT) {
750 /* if we sent GSS authentication in the outgoing request and we get
751 this back, we're in trouble */
752 infof(data, "Authentication problem. Ignoring this.\n");
753 data->state.authproblem = TRUE;
756 neg = Curl_input_negotiate(conn, proxy, auth);
758 DEBUGASSERT(!data->req.newurl);
759 data->req.newurl = strdup(data->change.url);
760 if(!data->req.newurl)
761 return CURLE_OUT_OF_MEMORY;
762 data->state.authproblem = FALSE;
763 /* we received GSS auth info and we dealt with it fine */
764 data->state.negotiate.state = GSS_AUTHRECV;
767 data->state.authproblem = TRUE;
774 /* NTLM support requires the SSL crypto libs */
775 if(checkprefix("NTLM", auth)) {
776 *availp |= CURLAUTH_NTLM;
777 authp->avail |= CURLAUTH_NTLM;
778 if(authp->picked == CURLAUTH_NTLM ||
779 authp->picked == CURLAUTH_NTLM_WB) {
780 /* NTLM authentication is picked and activated */
782 Curl_input_ntlm(conn, proxy, auth);
783 if(CURLE_OK == ntlm) {
784 data->state.authproblem = FALSE;
785 #ifdef NTLM_WB_ENABLED
786 if(authp->picked == CURLAUTH_NTLM_WB) {
787 *availp &= ~CURLAUTH_NTLM;
788 authp->avail &= ~CURLAUTH_NTLM;
789 *availp |= CURLAUTH_NTLM_WB;
790 authp->avail |= CURLAUTH_NTLM_WB;
792 /* Get the challenge-message which will be passed to
793 * ntlm_auth for generating the type 3 message later */
794 while(*auth && ISSPACE(*auth))
796 if(checkprefix("NTLM", auth)) {
797 auth += strlen("NTLM");
798 while(*auth && ISSPACE(*auth))
801 if((conn->challenge_header = strdup(auth)) == NULL)
802 return CURLE_OUT_OF_MEMORY;
808 infof(data, "Authentication problem. Ignoring this.\n");
809 data->state.authproblem = TRUE;
815 #ifndef CURL_DISABLE_CRYPTO_AUTH
816 if(checkprefix("Digest", auth)) {
817 if((authp->avail & CURLAUTH_DIGEST) != 0) {
818 infof(data, "Ignoring duplicate digest auth header.\n");
822 *availp |= CURLAUTH_DIGEST;
823 authp->avail |= CURLAUTH_DIGEST;
825 /* We call this function on input Digest headers even if Digest
826 * authentication isn't activated yet, as we need to store the
827 * incoming data from this header in case we are gonna use
829 dig = Curl_input_digest(conn, proxy, auth);
831 if(CURLDIGEST_FINE != dig) {
832 infof(data, "Authentication problem. Ignoring this.\n");
833 data->state.authproblem = TRUE;
839 if(checkprefix("Basic", auth)) {
840 *availp |= CURLAUTH_BASIC;
841 authp->avail |= CURLAUTH_BASIC;
842 if(authp->picked == CURLAUTH_BASIC) {
843 /* We asked for Basic authentication but got a 40X back
844 anyway, which basically means our name+password isn't
846 authp->avail = CURLAUTH_NONE;
847 infof(data, "Authentication problem. Ignoring this.\n");
848 data->state.authproblem = TRUE;
852 /* there may be multiple methods on one line, so keep reading */
853 while(*auth && *auth != ',') /* read up to the next comma */
855 if(*auth == ',') /* if we're on a comma, skip it */
857 while(*auth && ISSPACE(*auth))
864 * http_should_fail() determines whether an HTTP response has gotten us
865 * into an error state or not.
867 * @param conn all information about the current connection
869 * @retval 0 communications should continue
871 * @retval 1 communications should not continue
873 static int http_should_fail(struct connectdata *conn)
875 struct SessionHandle *data;
882 httpcode = data->req.httpcode;
885 ** If we haven't been asked to fail on error,
888 if(!data->set.http_fail_on_error)
892 ** Any code < 400 is never terminal.
897 if(data->state.resume_from &&
898 (data->set.httpreq==HTTPREQ_GET) &&
900 /* "Requested Range Not Satisfiable", just proceed and
901 pretend this is no error */
906 ** Any code >= 400 that's not 401 or 407 is always
909 if((httpcode != 401) &&
914 ** All we have left to deal with is 401 and 407
916 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
919 ** Examine the current authentication state to see if this
920 ** is an error. The idea is for this function to get
921 ** called after processing all the headers in a response
922 ** message. So, if we've been to asked to authenticate a
923 ** particular stage, and we've done it, we're OK. But, if
924 ** we're already completely authenticated, it's not OK to
925 ** get another 401 or 407.
927 ** It is possible for authentication to go stale such that
928 ** the client needs to reauthenticate. Once that info is
929 ** available, use it here.
933 ** Either we're not authenticating, or we're supposed to
934 ** be authenticating something else. This is an error.
936 if((httpcode == 401) && !conn->bits.user_passwd)
938 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
941 return data->state.authproblem;
945 * readmoredata() is a "fread() emulation" to provide POST and/or request
946 * data. It is used when a huge POST is to be made and the entire chunk wasn't
947 * sent in the first send(). This function will then be called from the
948 * transfer.c loop when more data is to be sent to the peer.
950 * Returns the amount of bytes it filled the buffer with.
952 static size_t readmoredata(char *buffer,
957 struct connectdata *conn = (struct connectdata *)userp;
958 struct HTTP *http = conn->data->req.protop;
959 size_t fullsize = size * nitems;
961 if(0 == http->postsize)
962 /* nothing to return */
965 /* make sure that a HTTP request is never sent away chunked! */
966 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
968 if(http->postsize <= (curl_off_t)fullsize) {
969 memcpy(buffer, http->postdata, (size_t)http->postsize);
970 fullsize = (size_t)http->postsize;
972 if(http->backup.postsize) {
973 /* move backup data into focus and continue on that */
974 http->postdata = http->backup.postdata;
975 http->postsize = http->backup.postsize;
976 conn->fread_func = http->backup.fread_func;
977 conn->fread_in = http->backup.fread_in;
979 http->sending++; /* move one step up */
981 http->backup.postsize=0;
989 memcpy(buffer, http->postdata, fullsize);
990 http->postdata += fullsize;
991 http->postsize -= fullsize;
996 /* ------------------------------------------------------------------------- */
997 /* add_buffer functions */
1000 * Curl_add_buffer_init() sets up and returns a fine buffer struct
1002 Curl_send_buffer *Curl_add_buffer_init(void)
1004 return calloc(1, sizeof(Curl_send_buffer));
1008 * Curl_add_buffer_send() sends a header buffer and frees all associated
1009 * memory. Body data may be appended to the header data if desired.
1013 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
1014 struct connectdata *conn,
1016 /* add the number of sent bytes to this
1018 long *bytes_written,
1020 /* how much of the buffer contains body data */
1021 size_t included_body_bytes,
1029 struct HTTP *http = conn->data->req.protop;
1031 curl_socket_t sockfd;
1034 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1036 sockfd = conn->sock[socketindex];
1038 /* The looping below is required since we use non-blocking sockets, but due
1039 to the circumstances we will just loop and try again and again etc */
1042 size = in->size_used;
1044 headersize = size - included_body_bytes; /* the initial part that isn't body
1047 DEBUGASSERT(size > included_body_bytes);
1049 res = Curl_convert_to_network(conn->data, ptr, headersize);
1050 /* Curl_convert_to_network calls failf if unsuccessful */
1052 /* conversion failed, free memory and return to the caller */
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 = Curl_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 %" CURL_FORMAT_CURL_OFF_T
2023 " bytes from the input", passed);
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-%" CURL_FORMAT_CURL_OFF_T
2069 "/%" CURL_FORMAT_CURL_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%" CURL_FORMAT_CURL_OFF_T
2079 "/%" CURL_FORMAT_CURL_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/%" CURL_FORMAT_CURL_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: %" CURL_FORMAT_CURL_OFF_T
2298 "\r\n", http->postsize);
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: %" CURL_FORMAT_CURL_OFF_T
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);
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) */
2415 if((postsize != -1) && !data->req.upload_chunky &&
2416 !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: %" CURL_FORMAT_CURL_OFF_T
2426 if(!Curl_checkheaders(data, "Content-Type:")) {
2427 result = Curl_add_bufferf(req_buffer,
2428 "Content-Type: application/"
2429 "x-www-form-urlencoded\r\n");
2434 /* For really small posts we don't use Expect: headers at all, and for
2435 the somewhat bigger ones we allow the app to disable it. Just make
2436 sure that the expect100header is always set to the preferred value
2438 ptr = Curl_checkheaders(data, "Expect:");
2440 data->state.expect100header =
2441 Curl_compareheader(ptr, "Expect:", "100-continue");
2443 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2444 result = expect100(data, conn, req_buffer);
2449 data->state.expect100header = FALSE;
2451 if(data->set.postfields) {
2453 if(!data->state.expect100header &&
2454 (postsize < MAX_INITIAL_POST_SIZE)) {
2455 /* if we don't use expect: 100 AND
2456 postsize is less than MAX_INITIAL_POST_SIZE
2458 then append the post data to the HTTP request header. This limit
2459 is no magic limit but only set to prevent really huge POSTs to
2460 get the data duplicated with malloc() and family. */
2462 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2466 if(!data->req.upload_chunky) {
2467 /* We're not sending it 'chunked', append it to the request
2468 already now to reduce the number if send() calls */
2469 result = Curl_add_buffer(req_buffer, data->set.postfields,
2471 included_body = postsize;
2475 /* Append the POST data chunky-style */
2476 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2477 if(CURLE_OK == result) {
2478 result = Curl_add_buffer(req_buffer, data->set.postfields,
2480 if(CURLE_OK == result)
2481 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2482 included_body = postsize + 2;
2485 if(CURLE_OK == result)
2486 result = Curl_add_buffer(req_buffer,
2487 "\x30\x0d\x0a\x0d\x0a", 5);
2493 /* Make sure the progress information is accurate */
2494 Curl_pgrsSetUploadSize(data, postsize);
2497 /* A huge POST coming up, do data separate from the request */
2498 http->postsize = postsize;
2499 http->postdata = data->set.postfields;
2501 http->sending = HTTPSEND_BODY;
2503 conn->fread_func = (curl_read_callback)readmoredata;
2504 conn->fread_in = (void *)conn;
2506 /* set the upload size to the progress meter */
2507 Curl_pgrsSetUploadSize(data, http->postsize);
2509 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2515 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2519 if(data->req.upload_chunky && conn->bits.authneg) {
2520 /* Chunky upload is selected and we're negotiating auth still, send
2522 result = Curl_add_buffer(req_buffer,
2523 "\x30\x0d\x0a\x0d\x0a", 5);
2529 else if(data->set.postfieldsize) {
2530 /* set the upload size to the progress meter */
2531 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2533 /* set the pointer to mark that we will send the post body using the
2534 read callback, but only if we're not in authenticate
2536 if(!conn->bits.authneg) {
2537 http->postdata = (char *)&http->postdata;
2538 http->postsize = postsize;
2542 /* issue the request */
2543 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2544 (size_t)included_body, FIRSTSOCKET);
2547 failf(data, "Failed sending HTTP POST request");
2549 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2550 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2551 http->postdata?&http->writebytecount:NULL);
2555 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2559 /* issue the request */
2560 result = Curl_add_buffer_send(req_buffer, conn,
2561 &data->info.request_size, 0, FIRSTSOCKET);
2564 failf(data, "Failed sending HTTP request");
2566 /* HTTP GET/HEAD download: */
2567 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2568 http->postdata?FIRSTSOCKET:-1,
2569 http->postdata?&http->writebytecount:NULL);
2574 if(http->writebytecount) {
2575 /* if a request-body has been sent off, we make sure this progress is noted
2577 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2578 if(Curl_pgrsUpdate(conn))
2579 result = CURLE_ABORTED_BY_CALLBACK;
2581 if(http->writebytecount >= postsize) {
2582 /* already sent the entire request body, mark the "upload" as
2584 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
2585 " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
2586 http->writebytecount, postsize);
2587 data->req.upload_done = TRUE;
2588 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2589 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2599 * Returns TRUE if member of the list matches prefix of string
2602 checkhttpprefix(struct SessionHandle *data,
2605 struct curl_slist *head = data->set.http200aliases;
2607 #ifdef CURL_DOES_CONVERSIONS
2608 /* convert from the network encoding using a scratch area */
2609 char *scratch = strdup(s);
2610 if(NULL == scratch) {
2611 failf (data, "Failed to allocate memory for conversion!");
2612 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2614 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2615 /* Curl_convert_from_network calls failf if unsuccessful */
2617 return FALSE; /* can't return CURLE_foobar so return FALSE */
2620 #endif /* CURL_DOES_CONVERSIONS */
2623 if(checkprefix(head->data, s)) {
2630 if(!rc && (checkprefix("HTTP/", s)))
2633 #ifdef CURL_DOES_CONVERSIONS
2635 #endif /* CURL_DOES_CONVERSIONS */
2639 #ifndef CURL_DISABLE_RTSP
2641 checkrtspprefix(struct SessionHandle *data,
2645 #ifdef CURL_DOES_CONVERSIONS
2646 /* convert from the network encoding using a scratch area */
2647 char *scratch = strdup(s);
2648 if(NULL == scratch) {
2649 failf (data, "Failed to allocate memory for conversion!");
2650 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2652 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2653 /* Curl_convert_from_network calls failf if unsuccessful */
2655 return FALSE; /* can't return CURLE_foobar so return FALSE */
2659 (void)data; /* unused */
2660 #endif /* CURL_DOES_CONVERSIONS */
2661 if(checkprefix("RTSP/", s))
2666 #endif /* CURL_DISABLE_RTSP */
2669 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2672 #ifndef CURL_DISABLE_RTSP
2673 if(conn->handler->protocol & CURLPROTO_RTSP)
2674 return checkrtspprefix(data, s);
2677 #endif /* CURL_DISABLE_RTSP */
2679 return checkhttpprefix(data, s);
2683 * header_append() copies a chunk of data to the end of the already received
2684 * header. We make sure that the full string fit in the allocated header
2685 * buffer, or else we enlarge it.
2687 static CURLcode header_append(struct SessionHandle *data,
2688 struct SingleRequest *k,
2691 if(k->hbuflen + length >= data->state.headersize) {
2692 /* We enlarge the header buffer as it is too small */
2697 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2698 /* The reason to have a max limit for this is to avoid the risk of a bad
2699 server feeding libcurl with a never-ending header that will cause
2700 reallocs infinitely */
2701 failf (data, "Avoided giant realloc for header (max is %d)!",
2702 CURL_MAX_HTTP_HEADER);
2703 return CURLE_OUT_OF_MEMORY;
2706 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2707 hbufp_index = k->hbufp - data->state.headerbuff;
2708 newbuff = realloc(data->state.headerbuff, newsize);
2710 failf (data, "Failed to alloc memory for big header!");
2711 return CURLE_OUT_OF_MEMORY;
2713 data->state.headersize=newsize;
2714 data->state.headerbuff = newbuff;
2715 k->hbufp = data->state.headerbuff + hbufp_index;
2717 memcpy(k->hbufp, k->str_start, length);
2719 k->hbuflen += length;
2725 static void print_http_error(struct SessionHandle *data)
2727 struct SingleRequest *k = &data->req;
2730 /* make sure that data->req.p points to the HTTP status line */
2731 if(!strncmp(beg, "HTTP", 4)) {
2733 /* skip to HTTP status code */
2734 beg = strchr(beg, ' ');
2737 /* find trailing CR */
2738 char end_char = '\r';
2739 char *end = strchr(beg, end_char);
2741 /* try to find LF (workaround for non-compliant HTTP servers) */
2743 end = strchr(beg, end_char);
2747 /* temporarily replace CR or LF by NUL and print the error message */
2749 failf(data, "The requested URL returned error: %s", beg);
2751 /* restore the previously replaced CR or LF */
2758 /* fall-back to printing the HTTP status code only */
2759 failf(data, "The requested URL returned error: %d", k->httpcode);
2763 * Read any HTTP header lines from the server and pass them to the client app.
2765 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2766 struct connectdata *conn,
2771 struct SingleRequest *k = &data->req;
2773 /* header line within buffer loop */
2779 /* str_start is start of line within buf */
2780 k->str_start = k->str;
2782 /* data is in network encoding so use 0x0a instead of '\n' */
2783 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2786 /* Not a complete header line within buffer, append the data to
2787 the end of the headerbuff. */
2788 result = header_append(data, k, *nread);
2792 if(!k->headerline && (k->hbuflen>5)) {
2793 /* make a first check that this looks like a protocol header */
2794 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2795 /* this is not the beginning of a protocol first header line */
2797 k->badheader = HEADER_ALLBAD;
2802 break; /* read more and try again */
2805 /* decrease the size of the remaining (supposed) header line */
2806 rest_length = (k->end_ptr - k->str)+1;
2807 *nread -= (ssize_t)rest_length;
2809 k->str = k->end_ptr + 1; /* move past new line */
2811 full_length = k->str - k->str_start;
2813 result = header_append(data, k, full_length);
2817 k->end_ptr = k->hbufp;
2818 k->p = data->state.headerbuff;
2821 * We now have a FULL header line that p points to
2824 if(!k->headerline) {
2825 /* the first read header */
2826 if((k->hbuflen>5) &&
2827 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2828 /* this is not the beginning of a protocol first header line */
2831 /* since there's more, this is a partial bad header */
2832 k->badheader = HEADER_PARTHEADER;
2834 /* this was all we read so it's all a bad header */
2835 k->badheader = HEADER_ALLBAD;
2836 *nread = (ssize_t)rest_length;
2842 /* headers are in network encoding so
2843 use 0x0a and 0x0d instead of '\n' and '\r' */
2844 if((0x0a == *k->p) || (0x0d == *k->p)) {
2846 /* Zero-length header line means end of headers! */
2848 #ifdef CURL_DOES_CONVERSIONS
2850 *k->p = '\r'; /* replace with CR in host encoding */
2851 k->p++; /* pass the CR byte */
2854 *k->p = '\n'; /* replace with LF in host encoding */
2855 k->p++; /* pass the LF byte */
2859 k->p++; /* pass the \r byte */
2861 k->p++; /* pass the \n byte */
2862 #endif /* CURL_DOES_CONVERSIONS */
2864 if(100 <= k->httpcode && 199 >= k->httpcode) {
2866 * We have made a HTTP PUT or POST and this is 1.1-lingo
2867 * that tells us that the server is OK with this and ready
2868 * to receive the data.
2869 * However, we'll get more headers now so we must get
2870 * back into the header-parsing state!
2873 k->headerline = 0; /* restart the header line counter */
2875 /* if we did wait for this do enable write now! */
2877 k->exp100 = EXP100_SEND_DATA;
2878 k->keepon |= KEEP_SEND;
2882 k->header = FALSE; /* no more header to parse! */
2884 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2885 (conn->httpversion >= 11) &&
2886 !(conn->handler->protocol & CURLPROTO_RTSP) &&
2887 data->set.httpreq != HTTPREQ_HEAD) {
2888 /* On HTTP 1.1, when connection is not to get closed, but no
2889 Content-Length nor Content-Encoding chunked have been
2890 received, according to RFC2616 section 4.4 point 5, we
2891 assume that the server will close the connection to
2892 signal the end of the document. */
2893 infof(data, "no chunk, no close, no size. Assume close to "
2895 conn->bits.close = TRUE;
2900 * When all the headers have been parsed, see if we should give
2901 * up and return an error.
2903 if(http_should_fail(conn)) {
2904 failf (data, "The requested URL returned error: %d",
2906 return CURLE_HTTP_RETURNED_ERROR;
2909 /* now, only output this if the header AND body are requested:
2911 writetype = CLIENTWRITE_HEADER;
2912 if(data->set.include_header)
2913 writetype |= CLIENTWRITE_BODY;
2915 headerlen = k->p - data->state.headerbuff;
2917 result = Curl_client_write(conn, writetype,
2918 data->state.headerbuff,
2923 data->info.header_size += (long)headerlen;
2924 data->req.headerbytecount += (long)headerlen;
2926 data->req.deductheadercount =
2927 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2929 if(!*stop_reading) {
2930 /* Curl_http_auth_act() checks what authentication methods
2931 * that are available and decides which one (if any) to
2932 * use. It will set 'newurl' if an auth method was picked. */
2933 result = Curl_http_auth_act(conn);
2938 if(k->httpcode >= 300) {
2939 if((!conn->bits.authneg) && !conn->bits.close &&
2940 !conn->bits.rewindaftersend) {
2942 * General treatment of errors when about to send data. Including :
2943 * "417 Expectation Failed", while waiting for 100-continue.
2945 * The check for close above is done simply because of something
2946 * else has already deemed the connection to get closed then
2947 * something else should've considered the big picture and we
2950 * rewindaftersend indicates that something has told libcurl to
2951 * continue sending even if it gets discarded
2954 switch(data->set.httpreq) {
2957 case HTTPREQ_POST_FORM:
2958 /* We got an error response. If this happened before the whole
2959 * request body has been sent we stop sending and mark the
2960 * connection for closure after we've read the entire response.
2962 if(!k->upload_done) {
2963 infof(data, "HTTP error before end of send, stop sending\n");
2964 conn->bits.close = TRUE; /* close after this */
2965 k->upload_done = TRUE;
2966 k->keepon &= ~KEEP_SEND; /* don't send */
2967 if(data->state.expect100header)
2968 k->exp100 = EXP100_FAILED;
2972 default: /* default label present to avoid compiler warnings */
2978 if(conn->bits.rewindaftersend) {
2979 /* We rewind after a complete send, so thus we continue
2981 infof(data, "Keep sending data to get tossed away!\n");
2982 k->keepon |= KEEP_SEND;
2988 * really end-of-headers.
2990 * If we requested a "no body", this is a good time to get
2991 * out and return home.
2993 if(data->set.opt_no_body)
2994 *stop_reading = TRUE;
2996 /* If we know the expected size of this document, we set the
2997 maximum download size to the size of the expected
2998 document or else, we won't know when to stop reading!
3000 Note that we set the download maximum even if we read a
3001 "Connection: close" header, to make sure that
3002 "Content-Length: 0" still prevents us from attempting to
3003 read the (missing) response-body.
3005 /* According to RFC2616 section 4.4, we MUST ignore
3006 Content-Length: headers if we are now receiving data
3007 using chunked Transfer-Encoding.
3010 k->maxdownload = k->size = -1;
3013 /* We do this operation even if no_body is true, since this
3014 data might be retrieved later with curl_easy_getinfo()
3015 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3017 Curl_pgrsSetDownloadSize(data, k->size);
3018 k->maxdownload = k->size;
3021 /* If max download size is *zero* (nothing) we already
3022 have nothing and can safely return ok now! */
3023 if(0 == k->maxdownload)
3024 *stop_reading = TRUE;
3027 /* we make sure that this socket isn't read more now */
3028 k->keepon &= ~KEEP_RECV;
3031 if(data->set.verbose)
3032 Curl_debug(data, CURLINFO_HEADER_IN,
3033 k->str_start, headerlen, conn);
3034 break; /* exit header line loop */
3037 /* We continue reading headers, so reset the line-based
3038 header parsing variables hbufp && hbuflen */
3039 k->hbufp = data->state.headerbuff;
3045 * Checks for special headers coming up.
3048 if(!k->headerline++) {
3049 /* This is the first header, it MUST be the error code line
3050 or else we consider this to be the body right away! */
3051 int httpversion_major;
3052 int rtspversion_major;
3054 #ifdef CURL_DOES_CONVERSIONS
3055 #define HEADER1 scratch
3056 #define SCRATCHSIZE 21
3058 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3059 /* We can't really convert this yet because we
3060 don't know if it's the 1st header line or the body.
3061 So we do a partial conversion into a scratch area,
3062 leaving the data at k->p as-is.
3064 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3065 scratch[SCRATCHSIZE] = 0; /* null terminate */
3066 res = Curl_convert_from_network(data,
3070 /* Curl_convert_from_network calls failf if unsuccessful */
3073 #define HEADER1 k->p /* no conversion needed, just use k->p */
3074 #endif /* CURL_DOES_CONVERSIONS */
3076 if(conn->handler->protocol & CURLPROTO_HTTP) {
3077 nc = sscanf(HEADER1,
3083 conn->httpversion += 10 * httpversion_major;
3086 /* this is the real world, not a Nirvana
3087 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3089 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3090 conn->httpversion = 10;
3092 /* If user has set option HTTP200ALIASES,
3093 compare header line against list of aliases
3096 if(checkhttpprefix(data, k->p)) {
3099 conn->httpversion = 10;
3104 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3105 nc = sscanf(HEADER1,
3111 conn->rtspversion += 10 * rtspversion_major;
3112 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3115 /* TODO: do we care about the other cases here? */
3121 data->info.httpcode = k->httpcode;
3123 data->info.httpversion = conn->httpversion;
3124 if(!data->state.httpversion ||
3125 data->state.httpversion > conn->httpversion)
3126 /* store the lowest server version we encounter */
3127 data->state.httpversion = conn->httpversion;
3130 * This code executes as part of processing the header. As a
3131 * result, it's not totally clear how to interpret the
3132 * response code yet as that depends on what other headers may
3133 * be present. 401 and 407 may be errors, but may be OK
3134 * depending on how authentication is working. Other codes
3135 * are definitely errors, so give up here.
3137 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3138 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3139 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3141 if(data->state.resume_from &&
3142 (data->set.httpreq==HTTPREQ_GET) &&
3143 (k->httpcode == 416)) {
3144 /* "Requested Range Not Satisfiable", just proceed and
3145 pretend this is no error */
3148 /* serious error, go home! */
3149 print_http_error(data);
3150 return CURLE_HTTP_RETURNED_ERROR;
3154 if(conn->httpversion == 10) {
3155 /* Default action for HTTP/1.0 must be to close, unless
3156 we get one of those fancy headers that tell us the
3157 server keeps it open for us! */
3158 infof(data, "HTTP 1.0, assume close after body\n");
3159 conn->bits.close = TRUE;
3161 else if(conn->httpversion >= 11 &&
3162 !conn->bits.close) {
3163 struct connectbundle *cb_ptr;
3165 /* If HTTP version is >= 1.1 and connection is persistent
3166 server supports pipelining. */
3168 "HTTP 1.1 or later with persistent connection, "
3169 "pipelining supported\n"));
3170 /* Activate pipelining if needed */
3171 cb_ptr = conn->bundle;
3173 if(!Curl_pipeline_site_blacklisted(data, conn))
3174 cb_ptr->server_supports_pipelining = TRUE;
3178 switch(k->httpcode) {
3180 /* (quote from RFC2616, section 10.2.5): The server has
3181 * fulfilled the request but does not need to return an
3182 * entity-body ... The 204 response MUST NOT include a
3183 * message-body, and thus is always terminated by the first
3184 * empty line after the header fields. */
3187 /* (quote from RFC2616, section 10.3.5): The 304 response
3188 * MUST NOT contain a message-body, and thus is always
3189 * terminated by the first empty line after the header
3191 if(data->set.timecondition)
3192 data->info.timecond = TRUE;
3195 k->ignorecl = TRUE; /* ignore Content-Length headers */
3203 k->header = FALSE; /* this is not a header line */
3208 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3209 /* Curl_convert_from_network calls failf if unsuccessful */
3213 /* Check for Content-Length: header lines to get size */
3214 if(!k->ignorecl && !data->set.ignorecl &&
3215 checkprefix("Content-Length:", k->p)) {
3216 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3217 if(data->set.max_filesize &&
3218 contentlength > data->set.max_filesize) {
3219 failf(data, "Maximum file size exceeded");
3220 return CURLE_FILESIZE_EXCEEDED;
3222 if(contentlength >= 0) {
3223 k->size = contentlength;
3224 k->maxdownload = k->size;
3225 /* we set the progress download size already at this point
3226 just to make it easier for apps/callbacks to extract this
3227 info as soon as possible */
3228 Curl_pgrsSetDownloadSize(data, k->size);
3231 /* Negative Content-Length is really odd, and we know it
3232 happens for example when older Apache servers send large
3234 conn->bits.close = TRUE;
3235 infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
3236 ", closing after transfer\n", contentlength);
3239 /* check for Content-Type: header lines to get the MIME-type */
3240 else if(checkprefix("Content-Type:", k->p)) {
3241 char *contenttype = Curl_copy_header_value(k->p);
3243 return CURLE_OUT_OF_MEMORY;
3245 /* ignore empty data */
3248 Curl_safefree(data->info.contenttype);
3249 data->info.contenttype = contenttype;
3252 else if(checkprefix("Server:", k->p)) {
3253 char *server_name = Curl_copy_header_value(k->p);
3255 /* Turn off pipelining if the server version is blacklisted */
3256 if(conn->bundle && conn->bundle->server_supports_pipelining) {
3257 if(Curl_pipeline_server_blacklisted(data, server_name))
3258 conn->bundle->server_supports_pipelining = FALSE;
3260 Curl_safefree(server_name);
3262 else if((conn->httpversion == 10) &&
3263 conn->bits.httpproxy &&
3264 Curl_compareheader(k->p,
3265 "Proxy-Connection:", "keep-alive")) {
3267 * When a HTTP/1.0 reply comes when using a proxy, the
3268 * 'Proxy-Connection: keep-alive' line tells us the
3269 * connection will be kept alive for our pleasure.
3270 * Default action for 1.0 is to close.
3272 conn->bits.close = FALSE; /* don't close when done */
3273 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3275 else if((conn->httpversion == 11) &&
3276 conn->bits.httpproxy &&
3277 Curl_compareheader(k->p,
3278 "Proxy-Connection:", "close")) {
3280 * We get a HTTP/1.1 response from a proxy and it says it'll
3281 * close down after this transfer.
3283 conn->bits.close = TRUE; /* close when done */
3284 infof(data, "HTTP/1.1 proxy connection set close!\n");
3286 else if((conn->httpversion == 10) &&
3287 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3289 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3290 * tells us the connection will be kept alive for our
3291 * pleasure. Default action for 1.0 is to close.
3293 * [RFC2068, section 19.7.1] */
3294 conn->bits.close = FALSE; /* don't close when done */
3295 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3297 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3299 * [RFC 2616, section 8.1.2.1]
3300 * "Connection: close" is HTTP/1.1 language and means that
3301 * the connection will close when this request has been
3304 conn->bits.close = TRUE; /* close when done */
3306 else if(checkprefix("Transfer-Encoding:", k->p)) {
3307 /* One or more encodings. We check for chunked and/or a compression
3310 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3311 * means that the server will send a series of "chunks". Each
3312 * chunk starts with line with info (including size of the
3313 * coming block) (terminated with CRLF), then a block of data
3314 * with the previously mentioned size. There can be any amount
3315 * of chunks, and a chunk-data set to zero signals the
3320 /* Find the first non-space letter */
3324 /* skip whitespaces and commas */
3325 while(*start && (ISSPACE(*start) || (*start == ',')))
3328 if(checkprefix("chunked", start)) {
3329 k->chunk = TRUE; /* chunks coming our way */
3331 /* init our chunky engine */
3332 Curl_httpchunk_init(conn);
3337 if(k->auto_decoding)
3338 /* TODO: we only support the first mentioned compression for now */
3341 if(checkprefix("identity", start)) {
3342 k->auto_decoding = IDENTITY;
3345 else if(checkprefix("deflate", start)) {
3346 k->auto_decoding = DEFLATE;
3349 else if(checkprefix("gzip", start)) {
3350 k->auto_decoding = GZIP;
3353 else if(checkprefix("x-gzip", start)) {
3354 k->auto_decoding = GZIP;
3357 else if(checkprefix("compress", start)) {
3358 k->auto_decoding = COMPRESS;
3361 else if(checkprefix("x-compress", start)) {
3362 k->auto_decoding = COMPRESS;
3372 else if(checkprefix("Content-Encoding:", k->p) &&
3373 data->set.str[STRING_ENCODING]) {
3375 * Process Content-Encoding. Look for the values: identity,
3376 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3377 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3378 * 2616). zlib cannot handle compress. However, errors are
3379 * handled further down when the response body is processed
3383 /* Find the first non-space letter */
3385 while(*start && ISSPACE(*start))
3388 /* Record the content-encoding for later use */
3389 if(checkprefix("identity", start))
3390 k->auto_decoding = IDENTITY;
3391 else if(checkprefix("deflate", start))
3392 k->auto_decoding = DEFLATE;
3393 else if(checkprefix("gzip", start)
3394 || checkprefix("x-gzip", start))
3395 k->auto_decoding = GZIP;
3396 else if(checkprefix("compress", start)
3397 || checkprefix("x-compress", start))
3398 k->auto_decoding = COMPRESS;
3400 else if(checkprefix("Content-Range:", k->p)) {
3401 /* Content-Range: bytes [num]-
3402 Content-Range: bytes: [num]-
3403 Content-Range: [num]-
3405 The second format was added since Sun's webserver
3406 JavaWebServer/1.1.1 obviously sends the header this way!
3407 The third added since some servers use that!
3410 char *ptr = k->p + 14;
3412 /* Move forward until first digit */
3413 while(*ptr && !ISDIGIT(*ptr))
3416 k->offset = curlx_strtoofft(ptr, NULL, 10);
3418 if(data->state.resume_from == k->offset)
3419 /* we asked for a resume and we got it */
3420 k->content_range = TRUE;
3422 #if !defined(CURL_DISABLE_COOKIES)
3423 else if(data->cookies &&
3424 checkprefix("Set-Cookie:", k->p)) {
3425 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3426 CURL_LOCK_ACCESS_SINGLE);
3427 Curl_cookie_add(data,
3428 data->cookies, TRUE, k->p+11,
3429 /* If there is a custom-set Host: name, use it
3430 here, or else use real peer host name. */
3431 conn->allocptr.cookiehost?
3432 conn->allocptr.cookiehost:conn->host.name,
3434 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3437 else if(checkprefix("Last-Modified:", k->p) &&
3438 (data->set.timecondition || data->set.get_filetime) ) {
3439 time_t secs=time(NULL);
3440 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3442 if(data->set.get_filetime)
3443 data->info.filetime = (long)k->timeofdoc;
3445 else if((checkprefix("WWW-Authenticate:", k->p) &&
3446 (401 == k->httpcode)) ||
3447 (checkprefix("Proxy-authenticate:", k->p) &&
3448 (407 == k->httpcode))) {
3450 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3451 char *auth = Curl_copy_header_value(k->p);
3453 return CURLE_OUT_OF_MEMORY;
3455 result = Curl_http_input_auth(conn, proxy, 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 = Curl_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 */