1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2011, 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 ***************************************************************************/
25 #ifndef CURL_DISABLE_HTTP
27 #ifdef HAVE_SYS_SOCKET_H
28 #include <sys/socket.h>
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
46 #ifdef HAVE_SYS_IOCTL_H
47 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_PARAM_H
51 #include <sys/param.h>
55 #include <curl/curl.h>
60 #include "curl_base64.h"
64 #include "http_digest.h"
65 #include "curl_ntlm.h"
66 #include "curl_ntlm_wb.h"
67 #include "http_negotiate.h"
72 #include "curl_memory.h"
74 #include "parsedate.h" /* for the week day and month names */
75 #include "strtoofft.h"
78 #include "content_encoding.h"
79 #include "http_proxy.h"
81 #include "non-ascii.h"
83 #define _MPRINTF_REPLACE /* use our functions only */
84 #include <curl/mprintf.h>
86 /* The last #include file should be: */
90 * Forward declarations.
93 static int http_getsock_do(struct connectdata *conn,
96 static int http_should_fail(struct connectdata *conn);
99 static CURLcode https_connecting(struct connectdata *conn, bool *done);
100 static int https_getsock(struct connectdata *conn,
101 curl_socket_t *socks,
104 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
108 * HTTP handler interface.
110 const struct Curl_handler Curl_handler_http = {
112 ZERO_NULL, /* setup_connection */
113 Curl_http, /* do_it */
114 Curl_http_done, /* done */
115 ZERO_NULL, /* do_more */
116 Curl_http_connect, /* connect_it */
117 ZERO_NULL, /* connecting */
118 ZERO_NULL, /* doing */
119 ZERO_NULL, /* proto_getsock */
120 http_getsock_do, /* doing_getsock */
121 ZERO_NULL, /* perform_getsock */
122 ZERO_NULL, /* disconnect */
123 ZERO_NULL, /* readwrite */
124 PORT_HTTP, /* defport */
125 CURLPROTO_HTTP, /* protocol */
126 PROTOPT_NONE /* flags */
131 * HTTPS handler interface.
133 const struct Curl_handler Curl_handler_https = {
134 "HTTPS", /* scheme */
135 ZERO_NULL, /* setup_connection */
136 Curl_http, /* do_it */
137 Curl_http_done, /* done */
138 ZERO_NULL, /* do_more */
139 Curl_http_connect, /* connect_it */
140 https_connecting, /* connecting */
141 ZERO_NULL, /* doing */
142 https_getsock, /* proto_getsock */
143 http_getsock_do, /* doing_getsock */
144 ZERO_NULL, /* perform_getsock */
145 ZERO_NULL, /* disconnect */
146 ZERO_NULL, /* readwrite */
147 PORT_HTTPS, /* defport */
148 CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */
149 PROTOPT_SSL /* flags */
155 * checkheaders() checks the linked list of custom HTTP headers for a
156 * particular header (prefix).
158 * Returns a pointer to the first matching header or NULL if none matched.
160 char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
162 struct curl_slist *head;
163 size_t thislen = strlen(thisheader);
165 for(head = data->set.headers; head; head=head->next) {
166 if(Curl_raw_nequal(head->data, thisheader, thislen))
173 * Strip off leading and trailing whitespace from the value in the
174 * given HTTP header line and return a strdupped copy. Returns NULL in
175 * case of allocation failure. Returns an empty string if the header value
176 * consists entirely of whitespace.
178 static char *copy_header_value(const char *h)
187 /* Find the end of the header name */
188 while(*h && (*h != ':'))
192 /* Skip over colon */
195 /* Find the first non-space letter */
197 while(*start && ISSPACE(*start))
200 /* data is in the host encoding so
201 use '\r' and '\n' instead of 0x0d and 0x0a */
202 end = strchr(start, '\r');
204 end = strchr(start, '\n');
206 end = strchr(start, '\0');
210 /* skip all trailing space letters */
211 while((end > start) && ISSPACE(*end))
214 /* get length of the type */
217 value = malloc(len + 1);
221 memcpy(value, start, len);
222 value[len] = 0; /* zero terminate */
228 * http_output_basic() sets up an Authorization: header (or the proxy version)
229 * for HTTP Basic authentication.
233 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
236 char *authorization = NULL;
237 struct SessionHandle *data = conn->data;
244 userp = &conn->allocptr.proxyuserpwd;
245 user = conn->proxyuser;
246 pwd = conn->proxypasswd;
249 userp = &conn->allocptr.userpwd;
254 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
256 error = Curl_base64_encode(data,
257 data->state.buffer, strlen(data->state.buffer),
258 &authorization, &size);
263 return CURLE_REMOTE_ACCESS_DENIED;
265 Curl_safefree(*userp);
266 *userp = aprintf("%sAuthorization: Basic %s\r\n",
271 return CURLE_OUT_OF_MEMORY;
276 /* pickoneauth() selects the most favourable authentication method from the
277 * ones available and the ones we want.
279 * return TRUE if one was picked
281 static bool pickoneauth(struct auth *pick)
284 /* only deal with authentication we want */
285 long avail = pick->avail & pick->want;
288 /* The order of these checks is highly relevant, as this will be the order
289 of preference in case of the existence of multiple accepted types. */
290 if(avail & CURLAUTH_GSSNEGOTIATE)
291 pick->picked = CURLAUTH_GSSNEGOTIATE;
292 else if(avail & CURLAUTH_DIGEST)
293 pick->picked = CURLAUTH_DIGEST;
294 else if(avail & CURLAUTH_NTLM)
295 pick->picked = CURLAUTH_NTLM;
296 else if(avail & CURLAUTH_NTLM_WB)
297 pick->picked = CURLAUTH_NTLM_WB;
298 else if(avail & CURLAUTH_BASIC)
299 pick->picked = CURLAUTH_BASIC;
301 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
304 pick->avail = CURLAUTH_NONE; /* clear it here */
310 * Curl_http_perhapsrewind()
312 * If we are doing POST or PUT {
313 * If we have more data to send {
314 * If we are doing NTLM {
315 * Keep sending since we must not disconnect
318 * If there is more than just a little data left to send, close
319 * the current connection by force.
322 * If we have sent any data {
323 * If we don't have track of all the data {
324 * call app to tell it to rewind
327 * rewind internally so that the operation can restart fine
332 static CURLcode http_perhapsrewind(struct connectdata *conn)
334 struct SessionHandle *data = conn->data;
335 struct HTTP *http = data->state.proto.http;
336 curl_off_t bytessent;
337 curl_off_t expectsend = -1; /* default is unknown */
340 /* If this is still NULL, we have not reach very far and we can safely
341 skip this rewinding stuff */
344 switch(data->set.httpreq) {
352 bytessent = http->writebytecount;
354 if(conn->bits.authneg)
355 /* This is a state where we are known to be negotiating and we don't send
359 /* figure out how much data we are expected to send */
360 switch(data->set.httpreq) {
362 if(data->set.postfieldsize != -1)
363 expectsend = data->set.postfieldsize;
364 else if(data->set.postfields)
365 expectsend = (curl_off_t)strlen(data->set.postfields);
368 if(data->set.infilesize != -1)
369 expectsend = data->set.infilesize;
371 case HTTPREQ_POST_FORM:
372 expectsend = http->postsize;
379 conn->bits.rewindaftersend = FALSE; /* default */
381 if((expectsend == -1) || (expectsend > bytessent)) {
382 /* There is still data left to send */
383 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
384 (data->state.authhost.picked == CURLAUTH_NTLM) ||
385 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
386 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
387 if(((expectsend - bytessent) < 2000) ||
388 (conn->ntlm.state != NTLMSTATE_NONE)) {
389 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
390 data left to send, keep on sending. */
392 /* rewind data when completely done sending! */
393 if(!conn->bits.authneg) {
394 conn->bits.rewindaftersend = TRUE;
395 infof(data, "Rewind stream after send\n");
401 /* this is already marked to get closed */
404 infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T
405 " bytes\n", (curl_off_t)(expectsend - bytessent));
408 /* This is not NTLM or NTLM with many bytes left to send: close
410 conn->bits.close = TRUE;
411 data->req.size = 0; /* don't download any more than 0 bytes */
413 /* There still is data left to send, but this connection is marked for
414 closure so we can safely do the rewind right now */
418 /* we rewind now at once since if we already sent something */
419 return Curl_readrewind(conn);
425 * Curl_http_auth_act() gets called when all HTTP headers have been received
426 * and it checks what authentication methods that are available and decides
427 * which one (if any) to use. It will set 'newurl' if an auth method was
431 CURLcode Curl_http_auth_act(struct connectdata *conn)
433 struct SessionHandle *data = conn->data;
434 bool pickhost = FALSE;
435 bool pickproxy = FALSE;
436 CURLcode code = CURLE_OK;
438 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
439 /* this is a transient response code, ignore */
442 if(data->state.authproblem)
443 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
445 if(conn->bits.user_passwd &&
446 ((data->req.httpcode == 401) ||
447 (conn->bits.authneg && data->req.httpcode < 300))) {
448 pickhost = pickoneauth(&data->state.authhost);
450 data->state.authproblem = TRUE;
452 if(conn->bits.proxy_user_passwd &&
453 ((data->req.httpcode == 407) ||
454 (conn->bits.authneg && data->req.httpcode < 300))) {
455 pickproxy = pickoneauth(&data->state.authproxy);
457 data->state.authproblem = TRUE;
460 if(pickhost || pickproxy) {
461 /* In case this is GSS auth, the newurl field is already allocated so
462 we must make sure to free it before allocating a new one. As figured
463 out in bug #2284386 */
464 Curl_safefree(data->req.newurl);
465 data->req.newurl = strdup(data->change.url); /* clone URL */
466 if(!data->req.newurl)
467 return CURLE_OUT_OF_MEMORY;
469 if((data->set.httpreq != HTTPREQ_GET) &&
470 (data->set.httpreq != HTTPREQ_HEAD) &&
471 !conn->bits.rewindaftersend) {
472 code = http_perhapsrewind(conn);
478 else if((data->req.httpcode < 300) &&
479 (!data->state.authhost.done) &&
480 conn->bits.authneg) {
481 /* no (known) authentication available,
482 authentication is not "done" yet and
483 no authentication seems to be required and
484 we didn't try HEAD or GET */
485 if((data->set.httpreq != HTTPREQ_GET) &&
486 (data->set.httpreq != HTTPREQ_HEAD)) {
487 data->req.newurl = strdup(data->change.url); /* clone URL */
488 if(!data->req.newurl)
489 return CURLE_OUT_OF_MEMORY;
490 data->state.authhost.done = TRUE;
493 if(http_should_fail(conn)) {
494 failf (data, "The requested URL returned error: %d",
496 code = CURLE_HTTP_RETURNED_ERROR;
504 * Output the correct authentication header depending on the auth type
505 * and whether or not it is to a proxy.
508 output_auth_headers(struct connectdata *conn,
509 struct auth *authstatus,
514 struct SessionHandle *data = conn->data;
515 const char *auth=NULL;
516 CURLcode result = CURLE_OK;
517 #ifdef USE_HTTP_NEGOTIATE
518 struct negotiatedata *negdata = proxy?
519 &data->state.proxyneg:&data->state.negotiate;
522 #ifdef CURL_DISABLE_CRYPTO_AUTH
527 #ifdef USE_HTTP_NEGOTIATE
528 negdata->state = GSS_AUTHNONE;
529 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
530 negdata->context && !GSS_ERROR(negdata->status)) {
531 auth="GSS-Negotiate";
532 result = Curl_output_negotiate(conn, proxy);
535 authstatus->done = TRUE;
536 negdata->state = GSS_AUTHSENT;
541 if(authstatus->picked == CURLAUTH_NTLM) {
543 result = Curl_output_ntlm(conn, proxy);
549 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
550 if(authstatus->picked == CURLAUTH_NTLM_WB) {
552 result = Curl_output_ntlm_wb(conn, proxy);
558 #ifndef CURL_DISABLE_CRYPTO_AUTH
559 if(authstatus->picked == CURLAUTH_DIGEST) {
561 result = Curl_output_digest(conn,
563 (const unsigned char *)request,
564 (const unsigned char *)path);
570 if(authstatus->picked == CURLAUTH_BASIC) {
572 if((proxy && conn->bits.proxy_user_passwd &&
573 !Curl_checkheaders(data, "Proxy-authorization:")) ||
574 (!proxy && conn->bits.user_passwd &&
575 !Curl_checkheaders(data, "Authorization:"))) {
577 result = http_output_basic(conn, proxy);
581 /* NOTE: this function should set 'done' TRUE, as the other auth
582 functions work that way */
583 authstatus->done = TRUE;
587 infof(data, "%s auth using %s with user '%s'\n",
588 proxy?"Proxy":"Server", auth,
589 proxy?(conn->proxyuser?conn->proxyuser:""):
590 (conn->user?conn->user:""));
591 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
594 authstatus->multi = FALSE;
600 * Curl_http_output_auth() setups the authentication headers for the
601 * host/proxy and the correct authentication
602 * method. conn->data->state.authdone is set to TRUE when authentication is
605 * @param conn all information about the current connection
606 * @param request pointer to the request keyword
607 * @param path pointer to the requested path
608 * @param proxytunnel boolean if this is the request setting up a "proxy
614 Curl_http_output_auth(struct connectdata *conn,
617 bool proxytunnel) /* TRUE if this is the request setting
618 up the proxy tunnel */
620 CURLcode result = CURLE_OK;
621 struct SessionHandle *data = conn->data;
622 struct auth *authhost;
623 struct auth *authproxy;
627 authhost = &data->state.authhost;
628 authproxy = &data->state.authproxy;
630 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
631 conn->bits.user_passwd)
632 /* continue please */ ;
634 authhost->done = TRUE;
635 authproxy->done = TRUE;
636 return CURLE_OK; /* no authentication with no user or password */
639 if(authhost->want && !authhost->picked)
640 /* The app has selected one or more methods, but none has been picked
641 so far by a server round-trip. Then we set the picked one to the
642 want one, and if this is one single bit it'll be used instantly. */
643 authhost->picked = authhost->want;
645 if(authproxy->want && !authproxy->picked)
646 /* The app has selected one or more methods, but none has been picked so
647 far by a proxy round-trip. Then we set the picked one to the want one,
648 and if this is one single bit it'll be used instantly. */
649 authproxy->picked = authproxy->want;
651 #ifndef CURL_DISABLE_PROXY
652 /* Send proxy authentication header if needed */
653 if(conn->bits.httpproxy &&
654 (conn->bits.tunnel_proxy == proxytunnel)) {
655 result = output_auth_headers(conn, authproxy, request, path, TRUE);
662 #endif /* CURL_DISABLE_PROXY */
663 /* we have no proxy so let's pretend we're done authenticating
665 authproxy->done = TRUE;
667 /* To prevent the user+password to get sent to other than the original
668 host due to a location-follow, we do some weirdo checks here */
669 if(!data->state.this_is_a_follow ||
671 !data->state.first_host ||
672 data->set.http_disable_hostname_check_before_authentication ||
673 Curl_raw_equal(data->state.first_host, conn->host.name)) {
674 result = output_auth_headers(conn, authhost, request, path, FALSE);
677 authhost->done = TRUE;
684 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
685 * headers. They are dealt with both in the transfer.c main loop and in the
686 * proxy CONNECT loop.
689 CURLcode Curl_http_input_auth(struct connectdata *conn,
691 const char *header) /* the first non-space */
694 * This resource requires authentication
696 struct SessionHandle *data = conn->data;
702 if(httpcode == 407) {
703 start = header+strlen("Proxy-authenticate:");
704 availp = &data->info.proxyauthavail;
705 authp = &data->state.authproxy;
708 start = header+strlen("WWW-Authenticate:");
709 availp = &data->info.httpauthavail;
710 authp = &data->state.authhost;
713 /* pass all white spaces */
714 while(*start && ISSPACE(*start))
718 * Here we check if we want the specific single authentication (using ==) and
719 * if we do, we initiate usage of it.
721 * If the provided authentication is wanted as one out of several accepted
722 * types (using &), we OR this authentication type to the authavail
727 * ->picked is first set to the 'want' value (one or more bits) before the
728 * request is sent, and then it is again set _after_ all response 401/407
729 * headers have been received but then only to a single preferred method
734 #ifdef USE_HTTP_NEGOTIATE
735 if(checkprefix("GSS-Negotiate", start) ||
736 checkprefix("Negotiate", start)) {
738 *availp |= CURLAUTH_GSSNEGOTIATE;
739 authp->avail |= CURLAUTH_GSSNEGOTIATE;
741 if(data->state.negotiate.state == GSS_AUTHSENT) {
742 /* if we sent GSS authentication in the outgoing request and we get this
743 back, we're in trouble */
744 infof(data, "Authentication problem. Ignoring this.\n");
745 data->state.authproblem = TRUE;
748 neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start);
750 DEBUGASSERT(!data->req.newurl);
751 data->req.newurl = strdup(data->change.url);
752 if(!data->req.newurl)
753 return CURLE_OUT_OF_MEMORY;
754 data->state.authproblem = FALSE;
755 /* we received GSS auth info and we dealt with it fine */
756 data->state.negotiate.state = GSS_AUTHRECV;
759 data->state.authproblem = TRUE;
766 /* NTLM support requires the SSL crypto libs */
767 if(checkprefix("NTLM", start)) {
768 *availp |= CURLAUTH_NTLM;
769 authp->avail |= CURLAUTH_NTLM;
770 if(authp->picked == CURLAUTH_NTLM ||
771 authp->picked == CURLAUTH_NTLM_WB) {
772 /* NTLM authentication is picked and activated */
774 Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start);
775 if(CURLE_OK == ntlm) {
776 data->state.authproblem = FALSE;
777 #ifdef NTLM_WB_ENABLED
778 if(authp->picked == CURLAUTH_NTLM_WB) {
779 *availp &= ~CURLAUTH_NTLM;
780 authp->avail &= ~CURLAUTH_NTLM;
781 *availp |= CURLAUTH_NTLM_WB;
782 authp->avail |= CURLAUTH_NTLM_WB;
784 /* Get the challenge-message which will be passed to
785 * ntlm_auth for generating the type 3 message later */
786 while(*start && ISSPACE(*start))
788 if(checkprefix("NTLM", start)) {
789 start += strlen("NTLM");
790 while(*start && ISSPACE(*start))
793 if((conn->challenge_header = strdup(start)) == NULL)
794 return CURLE_OUT_OF_MEMORY;
800 infof(data, "Authentication problem. Ignoring this.\n");
801 data->state.authproblem = TRUE;
807 #ifndef CURL_DISABLE_CRYPTO_AUTH
808 if(checkprefix("Digest", start)) {
809 if((authp->avail & CURLAUTH_DIGEST) != 0) {
810 infof(data, "Ignoring duplicate digest auth header.\n");
814 *availp |= CURLAUTH_DIGEST;
815 authp->avail |= CURLAUTH_DIGEST;
817 /* We call this function on input Digest headers even if Digest
818 * authentication isn't activated yet, as we need to store the
819 * incoming data from this header in case we are gonna use Digest. */
820 dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start);
822 if(CURLDIGEST_FINE != dig) {
823 infof(data, "Authentication problem. Ignoring this.\n");
824 data->state.authproblem = TRUE;
830 if(checkprefix("Basic", start)) {
831 *availp |= CURLAUTH_BASIC;
832 authp->avail |= CURLAUTH_BASIC;
833 if(authp->picked == CURLAUTH_BASIC) {
834 /* We asked for Basic authentication but got a 40X back
835 anyway, which basically means our name+password isn't
837 authp->avail = CURLAUTH_NONE;
838 infof(data, "Authentication problem. Ignoring this.\n");
839 data->state.authproblem = TRUE;
847 * http_should_fail() determines whether an HTTP response has gotten us
848 * into an error state or not.
850 * @param conn all information about the current connection
852 * @retval 0 communications should continue
854 * @retval 1 communications should not continue
856 static int http_should_fail(struct connectdata *conn)
858 struct SessionHandle *data;
865 httpcode = data->req.httpcode;
868 ** If we haven't been asked to fail on error,
871 if(!data->set.http_fail_on_error)
875 ** Any code < 400 is never terminal.
880 if(data->state.resume_from &&
881 (data->set.httpreq==HTTPREQ_GET) &&
883 /* "Requested Range Not Satisfiable", just proceed and
884 pretend this is no error */
889 ** Any code >= 400 that's not 401 or 407 is always
892 if((httpcode != 401) &&
897 ** All we have left to deal with is 401 and 407
899 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
902 ** Examine the current authentication state to see if this
903 ** is an error. The idea is for this function to get
904 ** called after processing all the headers in a response
905 ** message. So, if we've been to asked to authenticate a
906 ** particular stage, and we've done it, we're OK. But, if
907 ** we're already completely authenticated, it's not OK to
908 ** get another 401 or 407.
910 ** It is possible for authentication to go stale such that
911 ** the client needs to reauthenticate. Once that info is
912 ** available, use it here.
916 ** Either we're not authenticating, or we're supposed to
917 ** be authenticating something else. This is an error.
919 if((httpcode == 401) && !conn->bits.user_passwd)
921 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
924 return data->state.authproblem;
928 * readmoredata() is a "fread() emulation" to provide POST and/or request
929 * data. It is used when a huge POST is to be made and the entire chunk wasn't
930 * sent in the first send(). This function will then be called from the
931 * transfer.c loop when more data is to be sent to the peer.
933 * Returns the amount of bytes it filled the buffer with.
935 static size_t readmoredata(char *buffer,
940 struct connectdata *conn = (struct connectdata *)userp;
941 struct HTTP *http = conn->data->state.proto.http;
942 size_t fullsize = size * nitems;
944 if(0 == http->postsize)
945 /* nothing to return */
948 /* make sure that a HTTP request is never sent away chunked! */
949 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
951 if(http->postsize <= (curl_off_t)fullsize) {
952 memcpy(buffer, http->postdata, (size_t)http->postsize);
953 fullsize = (size_t)http->postsize;
955 if(http->backup.postsize) {
956 /* move backup data into focus and continue on that */
957 http->postdata = http->backup.postdata;
958 http->postsize = http->backup.postsize;
959 conn->fread_func = http->backup.fread_func;
960 conn->fread_in = http->backup.fread_in;
962 http->sending++; /* move one step up */
964 http->backup.postsize=0;
972 memcpy(buffer, http->postdata, fullsize);
973 http->postdata += fullsize;
974 http->postsize -= fullsize;
979 /* ------------------------------------------------------------------------- */
980 /* add_buffer functions */
983 * Curl_add_buffer_init() sets up and returns a fine buffer struct
985 Curl_send_buffer *Curl_add_buffer_init(void)
987 return calloc(1, sizeof(Curl_send_buffer));
991 * Curl_add_buffer_send() sends a header buffer and frees all associated
992 * memory. Body data may be appended to the header data if desired.
996 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
997 struct connectdata *conn,
999 /* add the number of sent bytes to this
1001 long *bytes_written,
1003 /* how much of the buffer contains body data */
1004 size_t included_body_bytes,
1012 struct HTTP *http = conn->data->state.proto.http;
1014 curl_socket_t sockfd;
1017 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1019 sockfd = conn->sock[socketindex];
1021 /* The looping below is required since we use non-blocking sockets, but due
1022 to the circumstances we will just loop and try again and again etc */
1025 size = in->size_used;
1027 headersize = size - included_body_bytes; /* the initial part that isn't body
1030 DEBUGASSERT(size > included_body_bytes);
1032 res = Curl_convert_to_network(conn->data, ptr, headersize);
1033 /* Curl_convert_to_network calls failf if unsuccessful */
1035 /* conversion failed, free memory and return to the caller */
1042 if(conn->handler->flags & PROTOPT_SSL) {
1043 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1044 when we speak HTTPS, as if only a fraction of it is sent now, this data
1045 needs to fit into the normal read-callback buffer later on and that
1046 buffer is using this size.
1049 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1051 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1052 library when we attempt to re-send this buffer. Sending the same data
1053 is not enough, we must use the exact same address. For this reason, we
1054 must copy the data to the uploadbuffer first, since that is the buffer
1055 we will be using if this send is retried later.
1057 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1058 ptr = conn->data->state.uploadbuffer;
1063 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1065 if(CURLE_OK == res) {
1067 * Note that we may not send the entire chunk at once, and we have a set
1068 * number of data bytes at the end of the big buffer (out of which we may
1069 * only send away a part).
1071 /* how much of the header that was sent */
1072 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1073 size_t bodylen = amount - headlen;
1075 if(conn->data->set.verbose) {
1076 /* this data _may_ contain binary stuff */
1077 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1078 if((size_t)amount > headlen) {
1079 /* there was body data sent beyond the initial header part, pass that
1080 on to the debug callback too */
1081 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1082 ptr+headlen, bodylen, conn);
1086 /* since we sent a piece of the body here, up the byte counter for it
1088 http->writebytecount += bodylen;
1090 /* 'amount' can never be a very large value here so typecasting it so a
1091 signed 31 bit value should not cause problems even if ssize_t is
1093 *bytes_written += (long)amount;
1096 if((size_t)amount != size) {
1097 /* The whole request could not be sent in one system call. We must
1098 queue it up and send it later when we get the chance. We must not
1099 loop here and wait until it might work again. */
1103 ptr = in->buffer + amount;
1105 /* backup the currently set pointers */
1106 http->backup.fread_func = conn->fread_func;
1107 http->backup.fread_in = conn->fread_in;
1108 http->backup.postdata = http->postdata;
1109 http->backup.postsize = http->postsize;
1111 /* set the new pointers for the request-sending */
1112 conn->fread_func = (curl_read_callback)readmoredata;
1113 conn->fread_in = (void *)conn;
1114 http->postdata = ptr;
1115 http->postsize = (curl_off_t)size;
1117 http->send_buffer = in;
1118 http->sending = HTTPSEND_REQUEST;
1122 http->sending = HTTPSEND_BODY;
1123 /* the full buffer was sent, clean up and return */
1126 if((size_t)amount != size)
1127 /* We have no continue-send mechanism now, fail. This can only happen
1128 when this function is used from the CONNECT sending function. We
1129 currently (stupidly) assume that the whole request is always sent
1130 away in the first single chunk.
1134 return CURLE_SEND_ERROR;
1136 conn->writechannel_inuse = FALSE;
1148 * add_bufferf() add the formatted input to the buffer.
1150 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
1155 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1159 CURLcode result = Curl_add_buffer(in, s, strlen(s));
1163 /* If we failed, we cleanup the whole buffer and return error */
1167 return CURLE_OUT_OF_MEMORY;
1171 * add_buffer() appends a memory chunk to the existing buffer
1173 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
1178 if(~size < in->size_used) {
1179 /* If resulting used size of send buffer would wrap size_t, cleanup
1180 the whole buffer and return error. Otherwise the required buffer
1181 size will fit into a single allocatable memory chunk */
1182 Curl_safefree(in->buffer);
1184 return CURLE_OUT_OF_MEMORY;
1188 ((in->size_used + size) > (in->size_max - 1))) {
1190 /* If current buffer size isn't enough to hold the result, use a
1191 buffer size that doubles the required size. If this new size
1192 would wrap size_t, then just use the largest possible one */
1194 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1195 (~(size*2) < (in->size_used*2)))
1196 new_size = (size_t)-1;
1198 new_size = (in->size_used+size)*2;
1201 /* we have a buffer, enlarge the existing one */
1202 new_rb = realloc(in->buffer, new_size);
1204 /* create a new buffer */
1205 new_rb = malloc(new_size);
1208 /* If we failed, we cleanup the whole buffer and return error */
1209 Curl_safefree(in->buffer);
1211 return CURLE_OUT_OF_MEMORY;
1214 in->buffer = new_rb;
1215 in->size_max = new_size;
1217 memcpy(&in->buffer[in->size_used], inptr, size);
1219 in->size_used += size;
1224 /* end of the add_buffer functions */
1225 /* ------------------------------------------------------------------------- */
1230 * Curl_compareheader()
1232 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1233 * Pass headers WITH the colon.
1236 Curl_compareheader(const char *headerline, /* line to check */
1237 const char *header, /* header keyword _with_ colon */
1238 const char *content) /* content string to find */
1240 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1241 * by a colon (":") and the field value. Field names are case-insensitive.
1242 * The field value MAY be preceded by any amount of LWS, though a single SP
1245 size_t hlen = strlen(header);
1251 if(!Curl_raw_nequal(headerline, header, hlen))
1252 return FALSE; /* doesn't start with header */
1254 /* pass the header */
1255 start = &headerline[hlen];
1257 /* pass all white spaces */
1258 while(*start && ISSPACE(*start))
1261 /* find the end of the header line */
1262 end = strchr(start, '\r'); /* lines end with CRLF */
1264 /* in case there's a non-standard compliant line here */
1265 end = strchr(start, '\n');
1268 /* hm, there's no line ending here, use the zero byte! */
1269 end = strchr(start, '\0');
1272 len = end-start; /* length of the content part of the input line */
1273 clen = strlen(content); /* length of the word to find */
1275 /* find the content string in the rest of the line */
1276 for(;len>=clen;len--, start++) {
1277 if(Curl_raw_nequal(start, content, clen))
1278 return TRUE; /* match! */
1281 return FALSE; /* no match */
1285 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1286 * the generic Curl_connect().
1288 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1290 struct SessionHandle *data;
1295 /* We default to persistent connections. We set this already in this connect
1296 function to make the re-use checks properly be able to check this bit. */
1297 conn->bits.close = FALSE;
1299 #ifndef CURL_DISABLE_PROXY
1300 /* If we are not using a proxy and we want a secure connection, perform SSL
1301 * initialization & connection now. If using a proxy with https, then we
1302 * must tell the proxy to CONNECT to the host we want to talk to. Only
1303 * after the connect has occurred, can we start talking SSL
1305 if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
1307 /* either SSL over proxy, or explicitly asked for */
1308 result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
1311 if(CURLE_OK != result)
1315 if(conn->bits.tunnel_connecting) {
1316 /* nothing else to do except wait right now - we're not done here. */
1319 #endif /* CURL_DISABLE_PROXY */
1321 if(conn->given->flags & PROTOPT_SSL) {
1322 /* perform SSL initialization */
1323 if(data->state.used_interface == Curl_if_multi) {
1324 result = https_connecting(conn, done);
1330 result = Curl_ssl_connect(conn, FIRSTSOCKET);
1343 /* this returns the socket to wait for in the DO and DOING state for the multi
1344 interface and then we're always _sending_ a request and thus we wait for
1345 the single socket to become writable only */
1346 static int http_getsock_do(struct connectdata *conn,
1347 curl_socket_t *socks,
1351 (void)numsocks; /* unused, we trust it to be at least 1 */
1352 socks[0] = conn->sock[FIRSTSOCKET];
1353 return GETSOCK_WRITESOCK(0);
1357 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1360 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
1362 /* perform SSL initialization for this socket */
1363 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1365 conn->bits.close = TRUE; /* a failed connection is marked for closure
1366 to prevent (bad) re-use or similar */
1371 #if defined(USE_SSLEAY) || defined(USE_GNUTLS)
1372 /* This function is for OpenSSL and GnuTLS only. It should be made to query
1373 the generic SSL layer instead. */
1374 static int https_getsock(struct connectdata *conn,
1375 curl_socket_t *socks,
1378 if(conn->handler->flags & PROTOPT_SSL) {
1379 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1382 return GETSOCK_BLANK;
1384 if(connssl->connecting_state == ssl_connect_2_writing) {
1386 socks[0] = conn->sock[FIRSTSOCKET];
1387 return GETSOCK_WRITESOCK(0);
1389 else if(connssl->connecting_state == ssl_connect_2_reading) {
1391 socks[0] = conn->sock[FIRSTSOCKET];
1392 return GETSOCK_READSOCK(0);
1398 #if defined(USE_NSS) || defined(USE_QSOSSL) || \
1399 defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL)
1400 static int https_getsock(struct connectdata *conn,
1401 curl_socket_t *socks,
1407 return GETSOCK_BLANK;
1409 #endif /* USE_AXTLS || USE_POLARSSL || USE_QSOSSL || USE_NSS */
1410 #endif /* USE_SSLEAY || USE_GNUTLS */
1413 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1414 * has been performed.
1417 CURLcode Curl_http_done(struct connectdata *conn,
1418 CURLcode status, bool premature)
1420 struct SessionHandle *data = conn->data;
1421 struct HTTP *http =data->state.proto.http;
1423 Curl_unencode_cleanup(conn);
1425 /* set the proper values (possibly modified on POST) */
1426 conn->fread_func = data->set.fread_func; /* restore */
1427 conn->fread_in = data->set.in; /* restore */
1428 conn->seek_func = data->set.seek_func; /* restore */
1429 conn->seek_client = data->set.seek_client; /* restore */
1434 if(http->send_buffer) {
1435 Curl_send_buffer *buff = http->send_buffer;
1439 http->send_buffer = NULL; /* clear the pointer */
1442 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1443 data->req.bytecount = http->readbytecount + http->writebytecount;
1445 Curl_formclean(&http->sendit); /* Now free that whole lot */
1447 /* a file being uploaded was left opened, close it! */
1448 fclose(http->form.fp);
1449 http->form.fp = NULL;
1452 else if(HTTPREQ_PUT == data->set.httpreq)
1453 data->req.bytecount = http->readbytecount + http->writebytecount;
1455 if(status != CURLE_OK)
1458 if(!premature && /* this check is pointless when DONE is called before the
1459 entire operation is complete */
1460 !conn->bits.retry &&
1461 ((http->readbytecount +
1462 data->req.headerbytecount -
1463 data->req.deductheadercount)) <= 0) {
1464 /* If this connection isn't simply closed to be retried, AND nothing was
1465 read from the HTTP server (that counts), this can't be right so we
1466 return an error here */
1467 failf(data, "Empty reply from server");
1468 return CURLE_GOT_NOTHING;
1475 /* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it
1476 are if the user specifically requested HTTP 1.0, if the server we are
1477 connected to only supports 1.0, or if any server previously contacted to
1478 handle this request only supports 1.0. */
1479 static bool use_http_1_1(const struct SessionHandle *data,
1480 const struct connectdata *conn)
1482 return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
1483 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1484 ((conn->httpversion == 11) ||
1485 ((conn->httpversion != 10) &&
1486 (data->state.httpversion != 10))))) ? TRUE : FALSE;
1489 /* check and possibly add an Expect: header */
1490 static CURLcode expect100(struct SessionHandle *data,
1491 struct connectdata *conn,
1492 Curl_send_buffer *req_buffer)
1494 CURLcode result = CURLE_OK;
1496 data->state.expect100header = FALSE; /* default to false unless it is set
1498 if(use_http_1_1(data, conn)) {
1499 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1500 100-continue to the headers which actually speeds up post operations
1501 (as there is one packet coming back from the web server) */
1502 ptr = Curl_checkheaders(data, "Expect:");
1504 data->state.expect100header =
1505 Curl_compareheader(ptr, "Expect:", "100-continue");
1508 result = Curl_add_bufferf(req_buffer,
1509 "Expect: 100-continue\r\n");
1510 if(result == CURLE_OK)
1511 data->state.expect100header = TRUE;
1517 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1518 Curl_send_buffer *req_buffer)
1521 struct curl_slist *headers=conn->data->set.headers;
1524 ptr = strchr(headers->data, ':');
1526 /* we require a colon for this to be a true header */
1528 ptr++; /* pass the colon */
1529 while(*ptr && ISSPACE(*ptr))
1533 /* only send this if the contents was non-blank */
1535 if(conn->allocptr.host &&
1536 /* a Host: header was sent already, don't pass on any custom Host:
1537 header as that will produce *two* in the same request! */
1538 checkprefix("Host:", headers->data))
1540 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
1541 /* this header (extended by formdata.c) is sent later */
1542 checkprefix("Content-Type:", headers->data))
1544 else if(conn->bits.authneg &&
1545 /* while doing auth neg, don't allow the custom length since
1546 we will force length zero then */
1547 checkprefix("Content-Length", headers->data))
1549 else if(conn->allocptr.te &&
1550 /* when asking for Transfer-Encoding, don't pass on a custom
1552 checkprefix("Connection", headers->data))
1555 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
1563 ptr = strchr(headers->data, ';');
1566 ptr++; /* pass the semicolon */
1567 while(*ptr && ISSPACE(*ptr))
1571 /* this may be used for something else in the future */
1574 if(*(--ptr) == ';') {
1577 /* send no-value custom header if terminated by semicolon */
1579 result = Curl_add_bufferf(req_buffer, "%s\r\n",
1587 headers = headers->next;
1592 CURLcode Curl_add_timecondition(struct SessionHandle *data,
1593 Curl_send_buffer *req_buffer)
1595 const struct tm *tm;
1596 char *buf = data->state.buffer;
1597 CURLcode result = CURLE_OK;
1600 result = Curl_gmtime(data->set.timevalue, &keeptime);
1602 failf(data, "Invalid TIMEVALUE\n");
1607 /* The If-Modified-Since header family should have their times set in
1608 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1609 * represented in Greenwich Mean Time (GMT), without exception. For the
1610 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1611 * Time)." (see page 20 of RFC2616).
1614 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1615 snprintf(buf, BUFSIZE-1,
1616 "%s, %02d %s %4d %02d:%02d:%02d GMT",
1617 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1619 Curl_month[tm->tm_mon],
1625 switch(data->set.timecondition) {
1626 case CURL_TIMECOND_IFMODSINCE:
1628 result = Curl_add_bufferf(req_buffer,
1629 "If-Modified-Since: %s\r\n", buf);
1631 case CURL_TIMECOND_IFUNMODSINCE:
1632 result = Curl_add_bufferf(req_buffer,
1633 "If-Unmodified-Since: %s\r\n", buf);
1635 case CURL_TIMECOND_LASTMOD:
1636 result = Curl_add_bufferf(req_buffer,
1637 "Last-Modified: %s\r\n", buf);
1645 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1646 * request is to be performed. This creates and sends a properly constructed
1649 CURLcode Curl_http(struct connectdata *conn, bool *done)
1651 struct SessionHandle *data=conn->data;
1652 CURLcode result=CURLE_OK;
1654 const char *ppath = data->state.path;
1655 bool paste_ftp_userpwd = FALSE;
1656 char ftp_typecode[sizeof("/;type=?")] = "";
1657 const char *host = conn->host.name;
1658 const char *te = ""; /* transfer-encoding */
1660 const char *request;
1661 Curl_HttpReq httpreq = data->set.httpreq;
1662 char *addcookies = NULL;
1663 curl_off_t included_body = 0;
1664 const char *httpstring;
1665 Curl_send_buffer *req_buffer;
1666 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
1667 int seekerr = CURL_SEEKFUNC_OK;
1669 /* Always consider the DO phase done after this function call, even if there
1670 may be parts of the request that is not yet sent, since we can deal with
1671 the rest of the request in the PERFORM phase. */
1674 /* If there already is a protocol-specific struct allocated for this
1675 sessionhandle, deal with it */
1676 Curl_reset_reqproto(conn);
1678 if(!data->state.proto.http) {
1679 /* Only allocate this struct if we don't already have it! */
1681 http = calloc(1, sizeof(struct HTTP));
1683 return CURLE_OUT_OF_MEMORY;
1684 data->state.proto.http = http;
1687 http = data->state.proto.http;
1689 if(!data->state.this_is_a_follow) {
1690 /* this is not a followed location, get the original host name */
1691 if(data->state.first_host)
1692 /* Free to avoid leaking memory on multiple requests*/
1693 free(data->state.first_host);
1695 data->state.first_host = strdup(conn->host.name);
1696 if(!data->state.first_host)
1697 return CURLE_OUT_OF_MEMORY;
1699 http->writebytecount = http->readbytecount = 0;
1701 if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
1703 httpreq = HTTPREQ_PUT;
1706 /* Now set the 'request' pointer to the proper request string */
1707 if(data->set.str[STRING_CUSTOMREQUEST])
1708 request = data->set.str[STRING_CUSTOMREQUEST];
1710 if(data->set.opt_no_body)
1713 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
1716 case HTTPREQ_POST_FORM:
1722 default: /* this should never happen */
1733 /* The User-Agent string might have been allocated in url.c already, because
1734 it might have been used in the proxy connect, but if we have got a header
1735 with the user-agent string specified, we erase the previously made string
1737 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
1738 free(conn->allocptr.uagent);
1739 conn->allocptr.uagent=NULL;
1742 /* setup the authentication headers */
1743 result = Curl_http_output_auth(conn, request, ppath, FALSE);
1747 if((data->state.authhost.multi || data->state.authproxy.multi) &&
1748 (httpreq != HTTPREQ_GET) &&
1749 (httpreq != HTTPREQ_HEAD)) {
1750 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1751 with content-length zero as a "probe". */
1752 conn->bits.authneg = TRUE;
1755 conn->bits.authneg = FALSE;
1757 Curl_safefree(conn->allocptr.ref);
1758 if(data->change.referer && !Curl_checkheaders(data, "Referer:"))
1759 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
1761 conn->allocptr.ref = NULL;
1763 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
1764 addcookies = data->set.str[STRING_COOKIE];
1766 if(!Curl_checkheaders(data, "Accept-Encoding:") &&
1767 data->set.str[STRING_ENCODING]) {
1768 Curl_safefree(conn->allocptr.accept_encoding);
1769 conn->allocptr.accept_encoding =
1770 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1771 if(!conn->allocptr.accept_encoding)
1772 return CURLE_OUT_OF_MEMORY;
1776 /* we only consider transfer-encoding magic if libz support is built-in */
1778 if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) {
1779 /* When we are to insert a TE: header in the request, we must also insert
1780 TE in a Connection: header, so we need to merge the custom provided
1781 Connection: header and prevent the original to get sent. Note that if
1782 the user has inserted his/hers own TE: header we don't do this magic
1783 but then assume that the user will handle it all! */
1784 char *cptr = Curl_checkheaders(data, "Connection:");
1785 #define TE_HEADER "TE: gzip\r\n"
1787 Curl_safefree(conn->allocptr.te);
1789 /* Create the (updated) Connection: header */
1790 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
1791 strdup("Connection: TE\r\n" TE_HEADER);
1793 if(!conn->allocptr.te)
1794 return CURLE_OUT_OF_MEMORY;
1798 ptr = Curl_checkheaders(data, "Transfer-Encoding:");
1800 /* Some kind of TE is requested, check if 'chunked' is chosen */
1801 data->req.upload_chunky =
1802 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1805 if((conn->handler->protocol&CURLPROTO_HTTP) &&
1807 (data->set.infilesize == -1)) {
1808 if(conn->bits.authneg)
1809 /* don't enable chunked during auth neg */
1811 else if(use_http_1_1(data, conn)) {
1812 /* HTTP, upload, unknown file size and not HTTP 1.0 */
1813 data->req.upload_chunky = TRUE;
1816 failf(data, "Chunky upload is not supported by HTTP 1.0");
1817 return CURLE_UPLOAD_FAILED;
1821 /* else, no chunky upload */
1822 data->req.upload_chunky = FALSE;
1825 if(data->req.upload_chunky)
1826 te = "Transfer-Encoding: chunked\r\n";
1829 Curl_safefree(conn->allocptr.host);
1831 ptr = Curl_checkheaders(data, "Host:");
1832 if(ptr && (!data->state.this_is_a_follow ||
1833 Curl_raw_equal(data->state.first_host, conn->host.name))) {
1834 #if !defined(CURL_DISABLE_COOKIES)
1835 /* If we have a given custom Host: header, we extract the host name in
1836 order to possibly use it for cookie reasons later on. We only allow the
1837 custom Host: header if this is NOT a redirect, as setting Host: in the
1838 redirected request is being out on thin ice. Except if the host name
1839 is the same as the first one! */
1840 char *cookiehost = copy_header_value(ptr);
1842 return CURLE_OUT_OF_MEMORY;
1844 /* ignore empty data */
1847 char *colon = strchr(cookiehost, ':');
1849 *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 free(data->change.url);
1917 data->change.url = newurl;
1918 data->change.url_alloc = TRUE;
1921 return CURLE_OUT_OF_MEMORY;
1924 ppath = data->change.url;
1925 if(checkprefix("ftp://", ppath)) {
1926 if(data->set.proxy_transfer_mode) {
1927 /* when doing ftp, append ;type=<a|i> if not present */
1928 char *type = strstr(ppath, ";type=");
1929 if(type && type[6] && type[7] == 0) {
1930 switch (Curl_raw_toupper(type[6])) {
1940 char *p = ftp_typecode;
1941 /* avoid sending invalid URLs like ftp://example.com;type=i if the
1942 * user specified ftp://example.com without the slash */
1943 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
1946 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
1947 data->set.prefer_ascii ? 'a' : 'i');
1950 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
1951 paste_ftp_userpwd = TRUE;
1954 #endif /* CURL_DISABLE_PROXY */
1956 if(HTTPREQ_POST_FORM == httpreq) {
1957 /* we must build the whole post sequence first, so that we have a size of
1958 the whole transfer before we start to send it */
1959 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
1960 Curl_checkheaders(data, "Content-Type:"),
1966 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
1968 if(( (HTTPREQ_POST == httpreq) ||
1969 (HTTPREQ_POST_FORM == httpreq) ||
1970 (HTTPREQ_PUT == httpreq) ) &&
1971 data->state.resume_from) {
1972 /**********************************************************************
1973 * Resuming upload in HTTP means that we PUT or POST and that we have
1974 * got a resume_from value set. The resume value has already created
1975 * a Range: header that will be passed along. We need to "fast forward"
1976 * the file the given number of bytes and decrease the assume upload
1977 * file size before we continue this venture in the dark lands of HTTP.
1978 *********************************************************************/
1980 if(data->state.resume_from < 0 ) {
1982 * This is meant to get the size of the present remote-file by itself.
1983 * We don't support this now. Bail out!
1985 data->state.resume_from = 0;
1988 if(data->state.resume_from && !data->state.this_is_a_follow) {
1989 /* do we still game? */
1991 /* Now, let's read off the proper amount of bytes from the
1993 if(conn->seek_func) {
1994 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1998 if(seekerr != CURL_SEEKFUNC_OK) {
1999 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2000 failf(data, "Could not seek stream");
2001 return CURLE_READ_ERROR;
2003 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2005 curl_off_t passed=0;
2007 size_t readthisamountnow =
2008 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
2009 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
2011 size_t actuallyread =
2012 data->set.fread_func(data->state.buffer, 1, readthisamountnow,
2015 passed += actuallyread;
2016 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2017 /* this checks for greater-than only to make sure that the
2018 CURL_READFUNC_ABORT return code still aborts */
2019 failf(data, "Could only read %" FORMAT_OFF_T
2020 " bytes from the input",
2022 return CURLE_READ_ERROR;
2024 } while(passed < data->state.resume_from);
2028 /* now, decrease the size of the read */
2029 if(data->set.infilesize>0) {
2030 data->set.infilesize -= data->state.resume_from;
2032 if(data->set.infilesize <= 0) {
2033 failf(data, "File already completely uploaded");
2034 return CURLE_PARTIAL_FILE;
2037 /* we've passed, proceed as normal */
2040 if(data->state.use_range) {
2042 * A range is selected. We use different headers whether we're downloading
2043 * or uploading and we always let customized headers override our internal
2044 * ones if any such are specified.
2046 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2047 !Curl_checkheaders(data, "Range:")) {
2048 /* if a line like this was already allocated, free the previous one */
2049 if(conn->allocptr.rangeline)
2050 free(conn->allocptr.rangeline);
2051 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2054 else if((httpreq != HTTPREQ_GET) &&
2055 !Curl_checkheaders(data, "Content-Range:")) {
2057 /* if a line like this was already allocated, free the previous one */
2058 if(conn->allocptr.rangeline)
2059 free(conn->allocptr.rangeline);
2061 if(data->set.set_resume_from < 0) {
2062 /* Upload resume was asked for, but we don't know the size of the
2063 remote part so we tell the server (and act accordingly) that we
2064 upload the whole file (again) */
2065 conn->allocptr.rangeline =
2066 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T
2067 "/%" FORMAT_OFF_T "\r\n",
2068 data->set.infilesize - 1, data->set.infilesize);
2071 else if(data->state.resume_from) {
2072 /* This is because "resume" was selected */
2073 curl_off_t total_expected_size=
2074 data->state.resume_from + data->set.infilesize;
2075 conn->allocptr.rangeline =
2076 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2077 "/%" FORMAT_OFF_T "\r\n",
2078 data->state.range, total_expected_size-1,
2079 total_expected_size);
2082 /* Range was selected and then we just pass the incoming range and
2083 append total size */
2084 conn->allocptr.rangeline =
2085 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2086 data->state.range, data->set.infilesize);
2088 if(!conn->allocptr.rangeline)
2089 return CURLE_OUT_OF_MEMORY;
2093 /* Use 1.1 unless the user specifically asked for 1.0 or the server only
2095 httpstring= use_http_1_1(data, conn)?"1.1":"1.0";
2097 /* initialize a dynamic send-buffer */
2098 req_buffer = Curl_add_buffer_init();
2101 return CURLE_OUT_OF_MEMORY;
2103 /* add the main request stuff */
2104 /* GET/HEAD/POST/PUT */
2105 result = Curl_add_bufferf(req_buffer, "%s ", request);
2110 if(paste_ftp_userpwd)
2111 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
2112 conn->user, conn->passwd,
2113 ppath + sizeof("ftp://") - 1);
2115 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
2119 result = Curl_add_bufferf(req_buffer,
2120 "%s" /* ftp typecode (;type=x) */
2121 " HTTP/%s\r\n" /* HTTP version */
2122 "%s" /* proxyuserpwd */
2125 "%s" /* user agent */
2129 "%s" /* accept-encoding */
2131 "%s" /* Proxy-Connection */
2132 "%s",/* transfer-encoding */
2136 conn->allocptr.proxyuserpwd?
2137 conn->allocptr.proxyuserpwd:"",
2138 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2139 (data->state.use_range && conn->allocptr.rangeline)?
2140 conn->allocptr.rangeline:"",
2141 (data->set.str[STRING_USERAGENT] &&
2142 *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
2143 conn->allocptr.uagent:"",
2144 (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
2145 http->p_accept?http->p_accept:"",
2146 conn->allocptr.te?conn->allocptr.te:"",
2147 (data->set.str[STRING_ENCODING] &&
2148 *data->set.str[STRING_ENCODING] &&
2149 conn->allocptr.accept_encoding)?
2150 conn->allocptr.accept_encoding:"",
2151 (data->change.referer && conn->allocptr.ref)?
2152 conn->allocptr.ref:"" /* Referer: <data> */,
2153 (conn->bits.httpproxy &&
2154 !conn->bits.tunnel_proxy &&
2155 !Curl_checkheaders(data, "Proxy-Connection:"))?
2156 "Proxy-Connection: Keep-Alive\r\n":"",
2161 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2162 * with basic and digest, it will be freed anyway by the next request
2165 Curl_safefree (conn->allocptr.userpwd);
2166 conn->allocptr.userpwd = NULL;
2171 #if !defined(CURL_DISABLE_COOKIES)
2172 if(data->cookies || addcookies) {
2173 struct Cookie *co=NULL; /* no cookies from start */
2177 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2178 co = Curl_cookie_getlist(data->cookies,
2179 conn->allocptr.cookiehost?
2180 conn->allocptr.cookiehost:host,
2182 (conn->handler->protocol&CURLPROTO_HTTPS)?
2184 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2187 struct Cookie *store=co;
2188 /* now loop through all cookies that matched */
2192 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2196 result = Curl_add_bufferf(req_buffer,
2197 "%s%s=%s", count?"; ":"",
2198 co->name, co->value);
2203 co = co->next; /* next cookie please */
2205 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2207 if(addcookies && (CURLE_OK == result)) {
2209 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2210 if(CURLE_OK == result) {
2211 result = Curl_add_bufferf(req_buffer, "%s%s",
2217 if(count && (CURLE_OK == result))
2218 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2225 if(data->set.timecondition) {
2226 result = Curl_add_timecondition(data, req_buffer);
2231 result = Curl_add_custom_headers(conn, req_buffer);
2235 http->postdata = NULL; /* nothing to post at this point */
2236 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2238 /* If 'authdone' is FALSE, we must not set the write socket index to the
2239 Curl_transfer() call below, as we're not ready to actually upload any
2244 case HTTPREQ_POST_FORM:
2245 if(!http->sendit || conn->bits.authneg) {
2246 /* nothing to post! */
2247 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2251 result = Curl_add_buffer_send(req_buffer, conn,
2252 &data->info.request_size, 0, FIRSTSOCKET);
2254 failf(data, "Failed sending POST request");
2256 /* setup variables for the upcoming transfer */
2257 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2262 if(Curl_FormInit(&http->form, http->sendit)) {
2263 failf(data, "Internal HTTP POST error!");
2264 return CURLE_HTTP_POST_ERROR;
2267 /* Get the currently set callback function pointer and store that in the
2268 form struct since we might want the actual user-provided callback later
2269 on. The conn->fread_func pointer itself will be changed for the
2270 multipart case to the function that returns a multipart formatted
2272 http->form.fread_func = conn->fread_func;
2274 /* Set the read function to read from the generated form data */
2275 conn->fread_func = (curl_read_callback)Curl_FormReader;
2276 conn->fread_in = &http->form;
2278 http->sending = HTTPSEND_BODY;
2280 if(!data->req.upload_chunky) {
2281 /* only add Content-Length if not uploading chunked */
2282 result = Curl_add_bufferf(req_buffer,
2283 "Content-Length: %" FORMAT_OFF_T "\r\n",
2289 result = expect100(data, conn, req_buffer);
2295 /* Get Content-Type: line from Curl_formpostheader.
2298 size_t linelength=0;
2299 contentType = Curl_formpostheader((void *)&http->form,
2302 failf(data, "Could not get Content-Type header line!");
2303 return CURLE_HTTP_POST_ERROR;
2306 result = Curl_add_buffer(req_buffer, contentType, linelength);
2311 /* make the request end in a true CRLF */
2312 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2316 /* set upload size to the progress meter */
2317 Curl_pgrsSetUploadSize(data, http->postsize);
2319 /* fire away the whole request to the server */
2320 result = Curl_add_buffer_send(req_buffer, conn,
2321 &data->info.request_size, 0, FIRSTSOCKET);
2323 failf(data, "Failed sending POST request");
2325 /* setup variables for the upcoming transfer */
2326 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2327 &http->readbytecount, FIRSTSOCKET,
2328 &http->writebytecount);
2331 Curl_formclean(&http->sendit); /* free that whole lot */
2335 /* convert the form data */
2336 result = Curl_convert_form(data, http->sendit);
2338 Curl_formclean(&http->sendit); /* free that whole lot */
2344 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2346 if(conn->bits.authneg)
2349 postsize = data->set.infilesize;
2351 if((postsize != -1) && !data->req.upload_chunky) {
2352 /* only add Content-Length if not uploading chunked */
2353 result = Curl_add_bufferf(req_buffer,
2354 "Content-Length: %" FORMAT_OFF_T "\r\n",
2360 result = expect100(data, conn, req_buffer);
2364 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2368 /* set the upload size to the progress meter */
2369 Curl_pgrsSetUploadSize(data, postsize);
2371 /* this sends the buffer and frees all the buffer resources */
2372 result = Curl_add_buffer_send(req_buffer, conn,
2373 &data->info.request_size, 0, FIRSTSOCKET);
2375 failf(data, "Failed sending PUT request");
2377 /* prepare for transfer */
2378 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2379 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2380 postsize?&http->writebytecount:NULL);
2386 /* this is the simple POST, using x-www-form-urlencoded style */
2388 if(conn->bits.authneg)
2391 /* figure out the size of the postfields */
2392 postsize = (data->set.postfieldsize != -1)?
2393 data->set.postfieldsize:
2394 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2396 if(!data->req.upload_chunky) {
2397 /* We only set Content-Length and allow a custom Content-Length if
2398 we don't upload data chunked, as RFC2616 forbids us to set both
2399 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2401 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
2402 /* we allow replacing this header if not during auth negotiation,
2403 although it isn't very wise to actually set your own */
2404 result = Curl_add_bufferf(req_buffer,
2405 "Content-Length: %" FORMAT_OFF_T"\r\n",
2412 if(!Curl_checkheaders(data, "Content-Type:")) {
2413 result = Curl_add_bufferf(req_buffer,
2414 "Content-Type: application/"
2415 "x-www-form-urlencoded\r\n");
2420 /* For really small posts we don't use Expect: headers at all, and for
2421 the somewhat bigger ones we allow the app to disable it. Just make
2422 sure that the expect100header is always set to the preferred value
2424 ptr = Curl_checkheaders(data, "Expect:");
2426 data->state.expect100header =
2427 Curl_compareheader(ptr, "Expect:", "100-continue");
2429 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2430 result = expect100(data, conn, req_buffer);
2435 data->state.expect100header = FALSE;
2437 if(data->set.postfields) {
2439 if(!data->state.expect100header &&
2440 (postsize < MAX_INITIAL_POST_SIZE)) {
2441 /* if we don't use expect: 100 AND
2442 postsize is less than MAX_INITIAL_POST_SIZE
2444 then append the post data to the HTTP request header. This limit
2445 is no magic limit but only set to prevent really huge POSTs to
2446 get the data duplicated with malloc() and family. */
2448 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2452 if(!data->req.upload_chunky) {
2453 /* We're not sending it 'chunked', append it to the request
2454 already now to reduce the number if send() calls */
2455 result = Curl_add_buffer(req_buffer, data->set.postfields,
2457 included_body = postsize;
2460 /* Append the POST data chunky-style */
2461 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2462 if(CURLE_OK == result)
2463 result = Curl_add_buffer(req_buffer, data->set.postfields,
2465 if(CURLE_OK == result)
2466 result = Curl_add_buffer(req_buffer,
2467 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2468 /* CR LF 0 CR LF CR LF */
2469 included_body = postsize + 7;
2473 /* Make sure the progress information is accurate */
2474 Curl_pgrsSetUploadSize(data, postsize);
2477 /* A huge POST coming up, do data separate from the request */
2478 http->postsize = postsize;
2479 http->postdata = data->set.postfields;
2481 http->sending = HTTPSEND_BODY;
2483 conn->fread_func = (curl_read_callback)readmoredata;
2484 conn->fread_in = (void *)conn;
2486 /* set the upload size to the progress meter */
2487 Curl_pgrsSetUploadSize(data, http->postsize);
2489 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2495 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2499 if(data->req.upload_chunky && conn->bits.authneg) {
2500 /* Chunky upload is selected and we're negotiating auth still, send
2502 result = Curl_add_buffer(req_buffer,
2503 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2504 /* CR LF 0 CR LF CR LF */
2509 else if(data->set.postfieldsize) {
2510 /* set the upload size to the progress meter */
2511 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2513 /* set the pointer to mark that we will send the post body using the
2514 read callback, but only if we're not in authenticate
2516 if(!conn->bits.authneg) {
2517 http->postdata = (char *)&http->postdata;
2518 http->postsize = postsize;
2522 /* issue the request */
2523 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2524 (size_t)included_body, FIRSTSOCKET);
2527 failf(data, "Failed sending HTTP POST request");
2529 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2530 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2531 http->postdata?&http->writebytecount:NULL);
2535 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2539 /* issue the request */
2540 result = Curl_add_buffer_send(req_buffer, conn,
2541 &data->info.request_size, 0, FIRSTSOCKET);
2544 failf(data, "Failed sending HTTP request");
2546 /* HTTP GET/HEAD download: */
2547 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2548 http->postdata?FIRSTSOCKET:-1,
2549 http->postdata?&http->writebytecount:NULL);
2554 if(http->writebytecount) {
2555 /* if a request-body has been sent off, we make sure this progress is noted
2557 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2558 if(Curl_pgrsUpdate(conn))
2559 result = CURLE_ABORTED_BY_CALLBACK;
2561 if(http->writebytecount >= postsize) {
2562 /* already sent the entire request body, mark the "upload" as
2564 infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of "
2565 "%" FORMAT_OFF_T " bytes\n",
2566 http->writebytecount, postsize);
2567 data->req.upload_done = TRUE;
2568 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2569 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2579 * Returns TRUE if member of the list matches prefix of string
2582 checkhttpprefix(struct SessionHandle *data,
2585 struct curl_slist *head = data->set.http200aliases;
2587 #ifdef CURL_DOES_CONVERSIONS
2588 /* convert from the network encoding using a scratch area */
2589 char *scratch = strdup(s);
2590 if(NULL == scratch) {
2591 failf (data, "Failed to allocate memory for conversion!");
2592 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2594 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2595 /* Curl_convert_from_network calls failf if unsuccessful */
2597 return FALSE; /* can't return CURLE_foobar so return FALSE */
2600 #endif /* CURL_DOES_CONVERSIONS */
2603 if(checkprefix(head->data, s)) {
2610 if(!rc && (checkprefix("HTTP/", s)))
2613 #ifdef CURL_DOES_CONVERSIONS
2615 #endif /* CURL_DOES_CONVERSIONS */
2619 #ifndef CURL_DISABLE_RTSP
2621 checkrtspprefix(struct SessionHandle *data,
2625 #ifdef CURL_DOES_CONVERSIONS
2626 /* convert from the network encoding using a scratch area */
2627 char *scratch = strdup(s);
2628 if(NULL == scratch) {
2629 failf (data, "Failed to allocate memory for conversion!");
2630 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2632 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2633 /* Curl_convert_from_network calls failf if unsuccessful */
2635 return FALSE; /* can't return CURLE_foobar so return FALSE */
2639 (void)data; /* unused */
2640 #endif /* CURL_DOES_CONVERSIONS */
2641 if(checkprefix("RTSP/", s))
2646 #endif /* CURL_DISABLE_RTSP */
2649 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2652 #ifndef CURL_DISABLE_RTSP
2653 if(conn->handler->protocol & CURLPROTO_RTSP)
2654 return checkrtspprefix(data, s);
2657 #endif /* CURL_DISABLE_RTSP */
2659 return checkhttpprefix(data, s);
2663 * header_append() copies a chunk of data to the end of the already received
2664 * header. We make sure that the full string fit in the allocated header
2665 * buffer, or else we enlarge it.
2667 static CURLcode header_append(struct SessionHandle *data,
2668 struct SingleRequest *k,
2671 if(k->hbuflen + length >= data->state.headersize) {
2672 /* We enlarge the header buffer as it is too small */
2677 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2678 /* The reason to have a max limit for this is to avoid the risk of a bad
2679 server feeding libcurl with a never-ending header that will cause
2680 reallocs infinitely */
2681 failf (data, "Avoided giant realloc for header (max is %d)!",
2682 CURL_MAX_HTTP_HEADER);
2683 return CURLE_OUT_OF_MEMORY;
2686 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2687 hbufp_index = k->hbufp - data->state.headerbuff;
2688 newbuff = realloc(data->state.headerbuff, newsize);
2690 failf (data, "Failed to alloc memory for big header!");
2691 return CURLE_OUT_OF_MEMORY;
2693 data->state.headersize=newsize;
2694 data->state.headerbuff = newbuff;
2695 k->hbufp = data->state.headerbuff + hbufp_index;
2697 memcpy(k->hbufp, k->str_start, length);
2699 k->hbuflen += length;
2707 * Read any HTTP header lines from the server and pass them to the client app.
2709 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2710 struct connectdata *conn,
2715 struct SingleRequest *k = &data->req;
2717 /* header line within buffer loop */
2723 /* str_start is start of line within buf */
2724 k->str_start = k->str;
2726 /* data is in network encoding so use 0x0a instead of '\n' */
2727 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2730 /* Not a complete header line within buffer, append the data to
2731 the end of the headerbuff. */
2732 result = header_append(data, k, *nread);
2736 if(!k->headerline && (k->hbuflen>5)) {
2737 /* make a first check that this looks like a protocol header */
2738 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2739 /* this is not the beginning of a protocol first header line */
2741 k->badheader = HEADER_ALLBAD;
2746 break; /* read more and try again */
2749 /* decrease the size of the remaining (supposed) header line */
2750 rest_length = (k->end_ptr - k->str)+1;
2751 *nread -= (ssize_t)rest_length;
2753 k->str = k->end_ptr + 1; /* move past new line */
2755 full_length = k->str - k->str_start;
2757 result = header_append(data, k, full_length);
2761 k->end_ptr = k->hbufp;
2762 k->p = data->state.headerbuff;
2765 * We now have a FULL header line that p points to
2768 if(!k->headerline) {
2769 /* the first read header */
2770 if((k->hbuflen>5) &&
2771 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2772 /* this is not the beginning of a protocol first header line */
2775 /* since there's more, this is a partial bad header */
2776 k->badheader = HEADER_PARTHEADER;
2778 /* this was all we read so it's all a bad header */
2779 k->badheader = HEADER_ALLBAD;
2780 *nread = (ssize_t)rest_length;
2786 /* headers are in network encoding so
2787 use 0x0a and 0x0d instead of '\n' and '\r' */
2788 if((0x0a == *k->p) || (0x0d == *k->p)) {
2790 /* Zero-length header line means end of headers! */
2792 #ifdef CURL_DOES_CONVERSIONS
2794 *k->p = '\r'; /* replace with CR in host encoding */
2795 k->p++; /* pass the CR byte */
2798 *k->p = '\n'; /* replace with LF in host encoding */
2799 k->p++; /* pass the LF byte */
2803 k->p++; /* pass the \r byte */
2805 k->p++; /* pass the \n byte */
2806 #endif /* CURL_DOES_CONVERSIONS */
2808 if(100 <= k->httpcode && 199 >= k->httpcode) {
2810 * We have made a HTTP PUT or POST and this is 1.1-lingo
2811 * that tells us that the server is OK with this and ready
2812 * to receive the data.
2813 * However, we'll get more headers now so we must get
2814 * back into the header-parsing state!
2817 k->headerline = 0; /* restart the header line counter */
2819 /* if we did wait for this do enable write now! */
2821 k->exp100 = EXP100_SEND_DATA;
2822 k->keepon |= KEEP_SEND;
2826 k->header = FALSE; /* no more header to parse! */
2828 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2829 (conn->httpversion >= 11) &&
2830 !(conn->handler->protocol & CURLPROTO_RTSP)) {
2831 /* On HTTP 1.1, when connection is not to get closed, but no
2832 Content-Length nor Content-Encoding chunked have been
2833 received, according to RFC2616 section 4.4 point 5, we
2834 assume that the server will close the connection to
2835 signal the end of the document. */
2836 infof(data, "no chunk, no close, no size. Assume close to "
2838 conn->bits.close = TRUE;
2843 * When all the headers have been parsed, see if we should give
2844 * up and return an error.
2846 if(http_should_fail(conn)) {
2847 failf (data, "The requested URL returned error: %d",
2849 return CURLE_HTTP_RETURNED_ERROR;
2852 /* now, only output this if the header AND body are requested:
2854 writetype = CLIENTWRITE_HEADER;
2855 if(data->set.include_header)
2856 writetype |= CLIENTWRITE_BODY;
2858 headerlen = k->p - data->state.headerbuff;
2860 result = Curl_client_write(conn, writetype,
2861 data->state.headerbuff,
2866 data->info.header_size += (long)headerlen;
2867 data->req.headerbytecount += (long)headerlen;
2869 data->req.deductheadercount =
2870 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2872 if(!*stop_reading) {
2873 /* Curl_http_auth_act() checks what authentication methods
2874 * that are available and decides which one (if any) to
2875 * use. It will set 'newurl' if an auth method was picked. */
2876 result = Curl_http_auth_act(conn);
2881 if(k->httpcode >= 300) {
2882 if((!conn->bits.authneg) && !conn->bits.close &&
2883 !conn->bits.rewindaftersend) {
2885 * General treatment of errors when about to send data. Including :
2886 * "417 Expectation Failed", while waiting for 100-continue.
2888 * The check for close above is done simply because of something
2889 * else has already deemed the connection to get closed then
2890 * something else should've considered the big picture and we
2893 * rewindaftersend indicates that something has told libcurl to
2894 * continue sending even if it gets discarded
2897 switch(data->set.httpreq) {
2900 case HTTPREQ_POST_FORM:
2901 /* We got an error response. If this happened before the whole
2902 * request body has been sent we stop sending and mark the
2903 * connection for closure after we've read the entire response.
2905 if(!k->upload_done) {
2906 infof(data, "HTTP error before end of send, stop sending\n");
2907 conn->bits.close = TRUE; /* close after this */
2908 k->upload_done = TRUE;
2909 k->keepon &= ~KEEP_SEND; /* don't send */
2910 if(data->state.expect100header)
2911 k->exp100 = EXP100_FAILED;
2915 default: /* default label present to avoid compiler warnings */
2921 if(conn->bits.rewindaftersend) {
2922 /* We rewind after a complete send, so thus we continue
2924 infof(data, "Keep sending data to get tossed away!\n");
2925 k->keepon |= KEEP_SEND;
2931 * really end-of-headers.
2933 * If we requested a "no body", this is a good time to get
2934 * out and return home.
2936 if(data->set.opt_no_body)
2937 *stop_reading = TRUE;
2939 /* If we know the expected size of this document, we set the
2940 maximum download size to the size of the expected
2941 document or else, we won't know when to stop reading!
2943 Note that we set the download maximum even if we read a
2944 "Connection: close" header, to make sure that
2945 "Content-Length: 0" still prevents us from attempting to
2946 read the (missing) response-body.
2948 /* According to RFC2616 section 4.4, we MUST ignore
2949 Content-Length: headers if we are now receiving data
2950 using chunked Transfer-Encoding.
2953 k->maxdownload = k->size = -1;
2956 /* We do this operation even if no_body is true, since this
2957 data might be retrieved later with curl_easy_getinfo()
2958 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
2960 Curl_pgrsSetDownloadSize(data, k->size);
2961 k->maxdownload = k->size;
2964 /* If max download size is *zero* (nothing) we already
2965 have nothing and can safely return ok now! */
2966 if(0 == k->maxdownload)
2967 *stop_reading = TRUE;
2970 /* we make sure that this socket isn't read more now */
2971 k->keepon &= ~KEEP_RECV;
2974 if(data->set.verbose)
2975 Curl_debug(data, CURLINFO_HEADER_IN,
2976 k->str_start, headerlen, conn);
2977 break; /* exit header line loop */
2980 /* We continue reading headers, so reset the line-based
2981 header parsing variables hbufp && hbuflen */
2982 k->hbufp = data->state.headerbuff;
2988 * Checks for special headers coming up.
2991 if(!k->headerline++) {
2992 /* This is the first header, it MUST be the error code line
2993 or else we consider this to be the body right away! */
2994 int httpversion_major;
2995 int rtspversion_major;
2997 #ifdef CURL_DOES_CONVERSIONS
2998 #define HEADER1 scratch
2999 #define SCRATCHSIZE 21
3001 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3002 /* We can't really convert this yet because we
3003 don't know if it's the 1st header line or the body.
3004 So we do a partial conversion into a scratch area,
3005 leaving the data at k->p as-is.
3007 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3008 scratch[SCRATCHSIZE] = 0; /* null terminate */
3009 res = Curl_convert_from_network(data,
3013 /* Curl_convert_from_network calls failf if unsuccessful */
3016 #define HEADER1 k->p /* no conversion needed, just use k->p */
3017 #endif /* CURL_DOES_CONVERSIONS */
3019 if(conn->handler->protocol & CURLPROTO_HTTP) {
3020 nc = sscanf(HEADER1,
3026 conn->httpversion += 10 * httpversion_major;
3029 /* this is the real world, not a Nirvana
3030 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3032 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3033 conn->httpversion = 10;
3035 /* If user has set option HTTP200ALIASES,
3036 compare header line against list of aliases
3039 if(checkhttpprefix(data, k->p)) {
3042 conn->httpversion = 10;
3047 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3048 nc = sscanf(HEADER1,
3054 conn->rtspversion += 10 * rtspversion_major;
3055 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3058 /* TODO: do we care about the other cases here? */
3064 data->info.httpcode = k->httpcode;
3066 data->info.httpversion = conn->httpversion;
3067 if(!data->state.httpversion ||
3068 data->state.httpversion > conn->httpversion)
3069 /* store the lowest server version we encounter */
3070 data->state.httpversion = conn->httpversion;
3073 * This code executes as part of processing the header. As a
3074 * result, it's not totally clear how to interpret the
3075 * response code yet as that depends on what other headers may
3076 * be present. 401 and 407 may be errors, but may be OK
3077 * depending on how authentication is working. Other codes
3078 * are definitely errors, so give up here.
3080 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3081 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3082 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3084 if(data->state.resume_from &&
3085 (data->set.httpreq==HTTPREQ_GET) &&
3086 (k->httpcode == 416)) {
3087 /* "Requested Range Not Satisfiable", just proceed and
3088 pretend this is no error */
3091 /* serious error, go home! */
3092 failf (data, "The requested URL returned error: %d",
3094 return CURLE_HTTP_RETURNED_ERROR;
3098 if(conn->httpversion == 10) {
3099 /* Default action for HTTP/1.0 must be to close, unless
3100 we get one of those fancy headers that tell us the
3101 server keeps it open for us! */
3102 infof(data, "HTTP 1.0, assume close after body\n");
3103 conn->bits.close = TRUE;
3105 else if(conn->httpversion >= 11 &&
3106 !conn->bits.close) {
3107 /* If HTTP version is >= 1.1 and connection is persistent
3108 server supports pipelining. */
3110 "HTTP 1.1 or later with persistent connection, "
3111 "pipelining supported\n"));
3112 conn->server_supports_pipelining = TRUE;
3115 switch(k->httpcode) {
3117 /* (quote from RFC2616, section 10.2.5): The server has
3118 * fulfilled the request but does not need to return an
3119 * entity-body ... The 204 response MUST NOT include a
3120 * message-body, and thus is always terminated by the first
3121 * empty line after the header fields. */
3124 /* (quote from RFC2616, section 10.3.5): The 304 response
3125 * MUST NOT contain a message-body, and thus is always
3126 * terminated by the first empty line after the header
3128 if(data->set.timecondition)
3129 data->info.timecond = TRUE;
3132 k->ignorecl = TRUE; /* ignore Content-Length headers */
3140 k->header = FALSE; /* this is not a header line */
3145 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3146 /* Curl_convert_from_network calls failf if unsuccessful */
3150 /* Check for Content-Length: header lines to get size */
3151 if(!k->ignorecl && !data->set.ignorecl &&
3152 checkprefix("Content-Length:", k->p)) {
3153 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3154 if(data->set.max_filesize &&
3155 contentlength > data->set.max_filesize) {
3156 failf(data, "Maximum file size exceeded");
3157 return CURLE_FILESIZE_EXCEEDED;
3159 if(contentlength >= 0) {
3160 k->size = contentlength;
3161 k->maxdownload = k->size;
3162 /* we set the progress download size already at this point
3163 just to make it easier for apps/callbacks to extract this
3164 info as soon as possible */
3165 Curl_pgrsSetDownloadSize(data, k->size);
3168 /* Negative Content-Length is really odd, and we know it
3169 happens for example when older Apache servers send large
3171 conn->bits.close = TRUE;
3172 infof(data, "Negative content-length: %" FORMAT_OFF_T
3173 ", closing after transfer\n", contentlength);
3176 /* check for Content-Type: header lines to get the MIME-type */
3177 else if(checkprefix("Content-Type:", k->p)) {
3178 char *contenttype = copy_header_value(k->p);
3180 return CURLE_OUT_OF_MEMORY;
3182 /* ignore empty data */
3185 Curl_safefree(data->info.contenttype);
3186 data->info.contenttype = contenttype;
3189 else if((conn->httpversion == 10) &&
3190 conn->bits.httpproxy &&
3191 Curl_compareheader(k->p,
3192 "Proxy-Connection:", "keep-alive")) {
3194 * When a HTTP/1.0 reply comes when using a proxy, the
3195 * 'Proxy-Connection: keep-alive' line tells us the
3196 * connection will be kept alive for our pleasure.
3197 * Default action for 1.0 is to close.
3199 conn->bits.close = FALSE; /* don't close when done */
3200 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3202 else if((conn->httpversion == 11) &&
3203 conn->bits.httpproxy &&
3204 Curl_compareheader(k->p,
3205 "Proxy-Connection:", "close")) {
3207 * We get a HTTP/1.1 response from a proxy and it says it'll
3208 * close down after this transfer.
3210 conn->bits.close = TRUE; /* close when done */
3211 infof(data, "HTTP/1.1 proxy connection set close!\n");
3213 else if((conn->httpversion == 10) &&
3214 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3216 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3217 * tells us the connection will be kept alive for our
3218 * pleasure. Default action for 1.0 is to close.
3220 * [RFC2068, section 19.7.1] */
3221 conn->bits.close = FALSE; /* don't close when done */
3222 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3224 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3226 * [RFC 2616, section 8.1.2.1]
3227 * "Connection: close" is HTTP/1.1 language and means that
3228 * the connection will close when this request has been
3231 conn->bits.close = TRUE; /* close when done */
3233 else if(checkprefix("Transfer-Encoding:", k->p)) {
3234 /* One or more encodings. We check for chunked and/or a compression
3237 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3238 * means that the server will send a series of "chunks". Each
3239 * chunk starts with line with info (including size of the
3240 * coming block) (terminated with CRLF), then a block of data
3241 * with the previously mentioned size. There can be any amount
3242 * of chunks, and a chunk-data set to zero signals the
3247 /* Find the first non-space letter */
3251 /* skip whitespaces and commas */
3252 while(*start && (ISSPACE(*start) || (*start == ',')))
3255 if(checkprefix("chunked", start)) {
3256 k->chunk = TRUE; /* chunks coming our way */
3258 /* init our chunky engine */
3259 Curl_httpchunk_init(conn);
3264 if(k->auto_decoding)
3265 /* TODO: we only support the first mentioned compression for now */
3268 if(checkprefix("identity", start)) {
3269 k->auto_decoding = IDENTITY;
3272 else if(checkprefix("deflate", start)) {
3273 k->auto_decoding = DEFLATE;
3276 else if(checkprefix("gzip", start)) {
3277 k->auto_decoding = GZIP;
3280 else if(checkprefix("x-gzip", start)) {
3281 k->auto_decoding = GZIP;
3284 else if(checkprefix("compress", start)) {
3285 k->auto_decoding = COMPRESS;
3288 else if(checkprefix("x-compress", start)) {
3289 k->auto_decoding = COMPRESS;
3299 else if(checkprefix("Content-Encoding:", k->p) &&
3300 data->set.str[STRING_ENCODING]) {
3302 * Process Content-Encoding. Look for the values: identity,
3303 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3304 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3305 * 2616). zlib cannot handle compress. However, errors are
3306 * handled further down when the response body is processed
3310 /* Find the first non-space letter */
3312 while(*start && ISSPACE(*start))
3315 /* Record the content-encoding for later use */
3316 if(checkprefix("identity", start))
3317 k->auto_decoding = IDENTITY;
3318 else if(checkprefix("deflate", start))
3319 k->auto_decoding = DEFLATE;
3320 else if(checkprefix("gzip", start)
3321 || checkprefix("x-gzip", start))
3322 k->auto_decoding = GZIP;
3323 else if(checkprefix("compress", start)
3324 || checkprefix("x-compress", start))
3325 k->auto_decoding = COMPRESS;
3327 else if(checkprefix("Content-Range:", k->p)) {
3328 /* Content-Range: bytes [num]-
3329 Content-Range: bytes: [num]-
3330 Content-Range: [num]-
3332 The second format was added since Sun's webserver
3333 JavaWebServer/1.1.1 obviously sends the header this way!
3334 The third added since some servers use that!
3337 char *ptr = k->p + 14;
3339 /* Move forward until first digit */
3340 while(*ptr && !ISDIGIT(*ptr))
3343 k->offset = curlx_strtoofft(ptr, NULL, 10);
3345 if(data->state.resume_from == k->offset)
3346 /* we asked for a resume and we got it */
3347 k->content_range = TRUE;
3349 #if !defined(CURL_DISABLE_COOKIES)
3350 else if(data->cookies &&
3351 checkprefix("Set-Cookie:", k->p)) {
3352 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3353 CURL_LOCK_ACCESS_SINGLE);
3354 Curl_cookie_add(data,
3355 data->cookies, TRUE, k->p+11,
3356 /* If there is a custom-set Host: name, use it
3357 here, or else use real peer host name. */
3358 conn->allocptr.cookiehost?
3359 conn->allocptr.cookiehost:conn->host.name,
3361 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3364 else if(checkprefix("Last-Modified:", k->p) &&
3365 (data->set.timecondition || data->set.get_filetime) ) {
3366 time_t secs=time(NULL);
3367 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3369 if(data->set.get_filetime)
3370 data->info.filetime = (long)k->timeofdoc;
3372 else if((checkprefix("WWW-Authenticate:", k->p) &&
3373 (401 == k->httpcode)) ||
3374 (checkprefix("Proxy-authenticate:", k->p) &&
3375 (407 == k->httpcode))) {
3376 result = Curl_http_input_auth(conn, k->httpcode, k->p);
3380 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3381 checkprefix("Location:", k->p) &&
3382 !data->req.location) {
3383 /* this is the URL that the server advises us to use instead */
3384 char *location = copy_header_value(k->p);
3386 return CURLE_OUT_OF_MEMORY;
3388 /* ignore empty data */
3391 data->req.location = location;
3393 if(data->set.http_follow_location) {
3394 DEBUGASSERT(!data->req.newurl);
3395 data->req.newurl = strdup(data->req.location); /* clone */
3396 if(!data->req.newurl)
3397 return CURLE_OUT_OF_MEMORY;
3399 /* some cases of POST and PUT etc needs to rewind the data
3400 stream at this point */
3401 result = http_perhapsrewind(conn);
3407 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3408 result = Curl_rtsp_parseheader(conn, k->p);
3414 * End of header-checks. Write them to the client.
3417 writetype = CLIENTWRITE_HEADER;
3418 if(data->set.include_header)
3419 writetype |= CLIENTWRITE_BODY;
3421 if(data->set.verbose)
3422 Curl_debug(data, CURLINFO_HEADER_IN,
3423 k->p, (size_t)k->hbuflen, conn);
3425 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3429 data->info.header_size += (long)k->hbuflen;
3430 data->req.headerbytecount += (long)k->hbuflen;
3432 /* reset hbufp pointer && hbuflen */
3433 k->hbufp = data->state.headerbuff;
3436 while(!*stop_reading && *k->str); /* header line within buffer */
3438 /* We might have reached the end of the header part here, but
3439 there might be a non-header part left in the end of the read
3445 #endif /* CURL_DISABLE_HTTP */