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));
2120 Curl_add_bufferf(req_buffer,
2121 "%s" /* ftp typecode (;type=x) */
2122 " HTTP/%s\r\n" /* HTTP version */
2123 "%s" /* proxyuserpwd */
2126 "%s" /* user agent */
2130 "%s" /* accept-encoding */
2132 "%s" /* Proxy-Connection */
2133 "%s",/* transfer-encoding */
2137 conn->allocptr.proxyuserpwd?
2138 conn->allocptr.proxyuserpwd:"",
2139 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2140 (data->state.use_range && conn->allocptr.rangeline)?
2141 conn->allocptr.rangeline:"",
2142 (data->set.str[STRING_USERAGENT] &&
2143 *data->set.str[STRING_USERAGENT] &&
2144 conn->allocptr.uagent)?
2145 conn->allocptr.uagent:"",
2146 (conn->allocptr.host?conn->allocptr.host:""),
2147 http->p_accept?http->p_accept:"",
2148 conn->allocptr.te?conn->allocptr.te:"",
2149 (data->set.str[STRING_ENCODING] &&
2150 *data->set.str[STRING_ENCODING] &&
2151 conn->allocptr.accept_encoding)?
2152 conn->allocptr.accept_encoding:"",
2153 (data->change.referer && conn->allocptr.ref)?
2154 conn->allocptr.ref:"" /* Referer: <data> */,
2155 (conn->bits.httpproxy &&
2156 !conn->bits.tunnel_proxy &&
2157 !Curl_checkheaders(data, "Proxy-Connection:"))?
2158 "Proxy-Connection: Keep-Alive\r\n":"",
2163 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2164 * with basic and digest, it will be freed anyway by the next request
2167 Curl_safefree (conn->allocptr.userpwd);
2168 conn->allocptr.userpwd = NULL;
2173 #if !defined(CURL_DISABLE_COOKIES)
2174 if(data->cookies || addcookies) {
2175 struct Cookie *co=NULL; /* no cookies from start */
2179 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2180 co = Curl_cookie_getlist(data->cookies,
2181 conn->allocptr.cookiehost?
2182 conn->allocptr.cookiehost:host,
2184 (conn->handler->protocol&CURLPROTO_HTTPS)?
2186 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2189 struct Cookie *store=co;
2190 /* now loop through all cookies that matched */
2194 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2198 result = Curl_add_bufferf(req_buffer,
2199 "%s%s=%s", count?"; ":"",
2200 co->name, co->value);
2205 co = co->next; /* next cookie please */
2207 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2209 if(addcookies && (CURLE_OK == result)) {
2211 result = Curl_add_bufferf(req_buffer, "Cookie: ");
2212 if(CURLE_OK == result) {
2213 result = Curl_add_bufferf(req_buffer, "%s%s",
2219 if(count && (CURLE_OK == result))
2220 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2227 if(data->set.timecondition) {
2228 result = Curl_add_timecondition(data, req_buffer);
2233 result = Curl_add_custom_headers(conn, req_buffer);
2237 http->postdata = NULL; /* nothing to post at this point */
2238 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2240 /* If 'authdone' is FALSE, we must not set the write socket index to the
2241 Curl_transfer() call below, as we're not ready to actually upload any
2246 case HTTPREQ_POST_FORM:
2247 if(!http->sendit || conn->bits.authneg) {
2248 /* nothing to post! */
2249 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2253 result = Curl_add_buffer_send(req_buffer, conn,
2254 &data->info.request_size, 0, FIRSTSOCKET);
2256 failf(data, "Failed sending POST request");
2258 /* setup variables for the upcoming transfer */
2259 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2264 if(Curl_FormInit(&http->form, http->sendit)) {
2265 failf(data, "Internal HTTP POST error!");
2266 return CURLE_HTTP_POST_ERROR;
2269 /* Get the currently set callback function pointer and store that in the
2270 form struct since we might want the actual user-provided callback later
2271 on. The conn->fread_func pointer itself will be changed for the
2272 multipart case to the function that returns a multipart formatted
2274 http->form.fread_func = conn->fread_func;
2276 /* Set the read function to read from the generated form data */
2277 conn->fread_func = (curl_read_callback)Curl_FormReader;
2278 conn->fread_in = &http->form;
2280 http->sending = HTTPSEND_BODY;
2282 if(!data->req.upload_chunky &&
2283 !Curl_checkheaders(data, "Content-Length:")) {
2284 /* only add Content-Length if not uploading chunked */
2285 result = Curl_add_bufferf(req_buffer,
2286 "Content-Length: %" FORMAT_OFF_T "\r\n",
2292 result = expect100(data, conn, req_buffer);
2298 /* Get Content-Type: line from Curl_formpostheader.
2301 size_t linelength=0;
2302 contentType = Curl_formpostheader((void *)&http->form,
2305 failf(data, "Could not get Content-Type header line!");
2306 return CURLE_HTTP_POST_ERROR;
2309 result = Curl_add_buffer(req_buffer, contentType, linelength);
2314 /* make the request end in a true CRLF */
2315 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2319 /* set upload size to the progress meter */
2320 Curl_pgrsSetUploadSize(data, http->postsize);
2322 /* fire away the whole request to the server */
2323 result = Curl_add_buffer_send(req_buffer, conn,
2324 &data->info.request_size, 0, FIRSTSOCKET);
2326 failf(data, "Failed sending POST request");
2328 /* setup variables for the upcoming transfer */
2329 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2330 &http->readbytecount, FIRSTSOCKET,
2331 &http->writebytecount);
2334 Curl_formclean(&http->sendit); /* free that whole lot */
2338 /* convert the form data */
2339 result = Curl_convert_form(data, http->sendit);
2341 Curl_formclean(&http->sendit); /* free that whole lot */
2347 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2349 if(conn->bits.authneg)
2352 postsize = data->set.infilesize;
2354 if((postsize != -1) && !data->req.upload_chunky &&
2355 !Curl_checkheaders(data, "Content-Length:")) {
2356 /* only add Content-Length if not uploading chunked */
2357 result = Curl_add_bufferf(req_buffer,
2358 "Content-Length: %" FORMAT_OFF_T "\r\n",
2364 result = expect100(data, conn, req_buffer);
2368 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2372 /* set the upload size to the progress meter */
2373 Curl_pgrsSetUploadSize(data, postsize);
2375 /* this sends the buffer and frees all the buffer resources */
2376 result = Curl_add_buffer_send(req_buffer, conn,
2377 &data->info.request_size, 0, FIRSTSOCKET);
2379 failf(data, "Failed sending PUT request");
2381 /* prepare for transfer */
2382 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2383 &http->readbytecount, postsize?FIRSTSOCKET:-1,
2384 postsize?&http->writebytecount:NULL);
2390 /* this is the simple POST, using x-www-form-urlencoded style */
2392 if(conn->bits.authneg)
2395 /* figure out the size of the postfields */
2396 postsize = (data->set.postfieldsize != -1)?
2397 data->set.postfieldsize:
2398 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
2400 if(!data->req.upload_chunky) {
2401 /* We only set Content-Length and allow a custom Content-Length if
2402 we don't upload data chunked, as RFC2616 forbids us to set both
2403 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2405 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
2406 /* we allow replacing this header if not during auth negotiation,
2407 although it isn't very wise to actually set your own */
2408 result = Curl_add_bufferf(req_buffer,
2409 "Content-Length: %" FORMAT_OFF_T"\r\n",
2416 if(!Curl_checkheaders(data, "Content-Type:")) {
2417 result = Curl_add_bufferf(req_buffer,
2418 "Content-Type: application/"
2419 "x-www-form-urlencoded\r\n");
2424 /* For really small posts we don't use Expect: headers at all, and for
2425 the somewhat bigger ones we allow the app to disable it. Just make
2426 sure that the expect100header is always set to the preferred value
2428 ptr = Curl_checkheaders(data, "Expect:");
2430 data->state.expect100header =
2431 Curl_compareheader(ptr, "Expect:", "100-continue");
2433 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
2434 result = expect100(data, conn, req_buffer);
2439 data->state.expect100header = FALSE;
2441 if(data->set.postfields) {
2443 if(!data->state.expect100header &&
2444 (postsize < MAX_INITIAL_POST_SIZE)) {
2445 /* if we don't use expect: 100 AND
2446 postsize is less than MAX_INITIAL_POST_SIZE
2448 then append the post data to the HTTP request header. This limit
2449 is no magic limit but only set to prevent really huge POSTs to
2450 get the data duplicated with malloc() and family. */
2452 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2456 if(!data->req.upload_chunky) {
2457 /* We're not sending it 'chunked', append it to the request
2458 already now to reduce the number if send() calls */
2459 result = Curl_add_buffer(req_buffer, data->set.postfields,
2461 included_body = postsize;
2464 /* Append the POST data chunky-style */
2465 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2466 if(CURLE_OK == result)
2467 result = Curl_add_buffer(req_buffer, data->set.postfields,
2469 if(CURLE_OK == result)
2470 result = Curl_add_buffer(req_buffer,
2471 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2472 /* CR LF 0 CR LF CR LF */
2473 included_body = postsize + 7;
2477 /* Make sure the progress information is accurate */
2478 Curl_pgrsSetUploadSize(data, postsize);
2481 /* A huge POST coming up, do data separate from the request */
2482 http->postsize = postsize;
2483 http->postdata = data->set.postfields;
2485 http->sending = HTTPSEND_BODY;
2487 conn->fread_func = (curl_read_callback)readmoredata;
2488 conn->fread_in = (void *)conn;
2490 /* set the upload size to the progress meter */
2491 Curl_pgrsSetUploadSize(data, http->postsize);
2493 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2499 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2503 if(data->req.upload_chunky && conn->bits.authneg) {
2504 /* Chunky upload is selected and we're negotiating auth still, send
2506 result = Curl_add_buffer(req_buffer,
2507 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2508 /* CR LF 0 CR LF CR LF */
2513 else if(data->set.postfieldsize) {
2514 /* set the upload size to the progress meter */
2515 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2517 /* set the pointer to mark that we will send the post body using the
2518 read callback, but only if we're not in authenticate
2520 if(!conn->bits.authneg) {
2521 http->postdata = (char *)&http->postdata;
2522 http->postsize = postsize;
2526 /* issue the request */
2527 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
2528 (size_t)included_body, FIRSTSOCKET);
2531 failf(data, "Failed sending HTTP POST request");
2533 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2534 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
2535 http->postdata?&http->writebytecount:NULL);
2539 result = Curl_add_buffer(req_buffer, "\r\n", 2);
2543 /* issue the request */
2544 result = Curl_add_buffer_send(req_buffer, conn,
2545 &data->info.request_size, 0, FIRSTSOCKET);
2548 failf(data, "Failed sending HTTP request");
2550 /* HTTP GET/HEAD download: */
2551 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
2552 http->postdata?FIRSTSOCKET:-1,
2553 http->postdata?&http->writebytecount:NULL);
2558 if(http->writebytecount) {
2559 /* if a request-body has been sent off, we make sure this progress is noted
2561 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2562 if(Curl_pgrsUpdate(conn))
2563 result = CURLE_ABORTED_BY_CALLBACK;
2565 if(http->writebytecount >= postsize) {
2566 /* already sent the entire request body, mark the "upload" as
2568 infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of "
2569 "%" FORMAT_OFF_T " bytes\n",
2570 http->writebytecount, postsize);
2571 data->req.upload_done = TRUE;
2572 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
2573 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
2583 * Returns TRUE if member of the list matches prefix of string
2586 checkhttpprefix(struct SessionHandle *data,
2589 struct curl_slist *head = data->set.http200aliases;
2591 #ifdef CURL_DOES_CONVERSIONS
2592 /* convert from the network encoding using a scratch area */
2593 char *scratch = strdup(s);
2594 if(NULL == scratch) {
2595 failf (data, "Failed to allocate memory for conversion!");
2596 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2598 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2599 /* Curl_convert_from_network calls failf if unsuccessful */
2601 return FALSE; /* can't return CURLE_foobar so return FALSE */
2604 #endif /* CURL_DOES_CONVERSIONS */
2607 if(checkprefix(head->data, s)) {
2614 if(!rc && (checkprefix("HTTP/", s)))
2617 #ifdef CURL_DOES_CONVERSIONS
2619 #endif /* CURL_DOES_CONVERSIONS */
2623 #ifndef CURL_DISABLE_RTSP
2625 checkrtspprefix(struct SessionHandle *data,
2629 #ifdef CURL_DOES_CONVERSIONS
2630 /* convert from the network encoding using a scratch area */
2631 char *scratch = strdup(s);
2632 if(NULL == scratch) {
2633 failf (data, "Failed to allocate memory for conversion!");
2634 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
2636 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
2637 /* Curl_convert_from_network calls failf if unsuccessful */
2639 return FALSE; /* can't return CURLE_foobar so return FALSE */
2643 (void)data; /* unused */
2644 #endif /* CURL_DOES_CONVERSIONS */
2645 if(checkprefix("RTSP/", s))
2650 #endif /* CURL_DISABLE_RTSP */
2653 checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
2656 #ifndef CURL_DISABLE_RTSP
2657 if(conn->handler->protocol & CURLPROTO_RTSP)
2658 return checkrtspprefix(data, s);
2661 #endif /* CURL_DISABLE_RTSP */
2663 return checkhttpprefix(data, s);
2667 * header_append() copies a chunk of data to the end of the already received
2668 * header. We make sure that the full string fit in the allocated header
2669 * buffer, or else we enlarge it.
2671 static CURLcode header_append(struct SessionHandle *data,
2672 struct SingleRequest *k,
2675 if(k->hbuflen + length >= data->state.headersize) {
2676 /* We enlarge the header buffer as it is too small */
2681 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
2682 /* The reason to have a max limit for this is to avoid the risk of a bad
2683 server feeding libcurl with a never-ending header that will cause
2684 reallocs infinitely */
2685 failf (data, "Avoided giant realloc for header (max is %d)!",
2686 CURL_MAX_HTTP_HEADER);
2687 return CURLE_OUT_OF_MEMORY;
2690 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
2691 hbufp_index = k->hbufp - data->state.headerbuff;
2692 newbuff = realloc(data->state.headerbuff, newsize);
2694 failf (data, "Failed to alloc memory for big header!");
2695 return CURLE_OUT_OF_MEMORY;
2697 data->state.headersize=newsize;
2698 data->state.headerbuff = newbuff;
2699 k->hbufp = data->state.headerbuff + hbufp_index;
2701 memcpy(k->hbufp, k->str_start, length);
2703 k->hbuflen += length;
2711 * Read any HTTP header lines from the server and pass them to the client app.
2713 CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
2714 struct connectdata *conn,
2719 struct SingleRequest *k = &data->req;
2721 /* header line within buffer loop */
2727 /* str_start is start of line within buf */
2728 k->str_start = k->str;
2730 /* data is in network encoding so use 0x0a instead of '\n' */
2731 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
2734 /* Not a complete header line within buffer, append the data to
2735 the end of the headerbuff. */
2736 result = header_append(data, k, *nread);
2740 if(!k->headerline && (k->hbuflen>5)) {
2741 /* make a first check that this looks like a protocol header */
2742 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
2743 /* this is not the beginning of a protocol first header line */
2745 k->badheader = HEADER_ALLBAD;
2750 break; /* read more and try again */
2753 /* decrease the size of the remaining (supposed) header line */
2754 rest_length = (k->end_ptr - k->str)+1;
2755 *nread -= (ssize_t)rest_length;
2757 k->str = k->end_ptr + 1; /* move past new line */
2759 full_length = k->str - k->str_start;
2761 result = header_append(data, k, full_length);
2765 k->end_ptr = k->hbufp;
2766 k->p = data->state.headerbuff;
2769 * We now have a FULL header line that p points to
2772 if(!k->headerline) {
2773 /* the first read header */
2774 if((k->hbuflen>5) &&
2775 !checkprotoprefix(data, conn, data->state.headerbuff)) {
2776 /* this is not the beginning of a protocol first header line */
2779 /* since there's more, this is a partial bad header */
2780 k->badheader = HEADER_PARTHEADER;
2782 /* this was all we read so it's all a bad header */
2783 k->badheader = HEADER_ALLBAD;
2784 *nread = (ssize_t)rest_length;
2790 /* headers are in network encoding so
2791 use 0x0a and 0x0d instead of '\n' and '\r' */
2792 if((0x0a == *k->p) || (0x0d == *k->p)) {
2794 /* Zero-length header line means end of headers! */
2796 #ifdef CURL_DOES_CONVERSIONS
2798 *k->p = '\r'; /* replace with CR in host encoding */
2799 k->p++; /* pass the CR byte */
2802 *k->p = '\n'; /* replace with LF in host encoding */
2803 k->p++; /* pass the LF byte */
2807 k->p++; /* pass the \r byte */
2809 k->p++; /* pass the \n byte */
2810 #endif /* CURL_DOES_CONVERSIONS */
2812 if(100 <= k->httpcode && 199 >= k->httpcode) {
2814 * We have made a HTTP PUT or POST and this is 1.1-lingo
2815 * that tells us that the server is OK with this and ready
2816 * to receive the data.
2817 * However, we'll get more headers now so we must get
2818 * back into the header-parsing state!
2821 k->headerline = 0; /* restart the header line counter */
2823 /* if we did wait for this do enable write now! */
2825 k->exp100 = EXP100_SEND_DATA;
2826 k->keepon |= KEEP_SEND;
2830 k->header = FALSE; /* no more header to parse! */
2832 if((k->size == -1) && !k->chunk && !conn->bits.close &&
2833 (conn->httpversion >= 11) &&
2834 !(conn->handler->protocol & CURLPROTO_RTSP)) {
2835 /* On HTTP 1.1, when connection is not to get closed, but no
2836 Content-Length nor Content-Encoding chunked have been
2837 received, according to RFC2616 section 4.4 point 5, we
2838 assume that the server will close the connection to
2839 signal the end of the document. */
2840 infof(data, "no chunk, no close, no size. Assume close to "
2842 conn->bits.close = TRUE;
2847 * When all the headers have been parsed, see if we should give
2848 * up and return an error.
2850 if(http_should_fail(conn)) {
2851 failf (data, "The requested URL returned error: %d",
2853 return CURLE_HTTP_RETURNED_ERROR;
2856 /* now, only output this if the header AND body are requested:
2858 writetype = CLIENTWRITE_HEADER;
2859 if(data->set.include_header)
2860 writetype |= CLIENTWRITE_BODY;
2862 headerlen = k->p - data->state.headerbuff;
2864 result = Curl_client_write(conn, writetype,
2865 data->state.headerbuff,
2870 data->info.header_size += (long)headerlen;
2871 data->req.headerbytecount += (long)headerlen;
2873 data->req.deductheadercount =
2874 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
2876 if(!*stop_reading) {
2877 /* Curl_http_auth_act() checks what authentication methods
2878 * that are available and decides which one (if any) to
2879 * use. It will set 'newurl' if an auth method was picked. */
2880 result = Curl_http_auth_act(conn);
2885 if(k->httpcode >= 300) {
2886 if((!conn->bits.authneg) && !conn->bits.close &&
2887 !conn->bits.rewindaftersend) {
2889 * General treatment of errors when about to send data. Including :
2890 * "417 Expectation Failed", while waiting for 100-continue.
2892 * The check for close above is done simply because of something
2893 * else has already deemed the connection to get closed then
2894 * something else should've considered the big picture and we
2897 * rewindaftersend indicates that something has told libcurl to
2898 * continue sending even if it gets discarded
2901 switch(data->set.httpreq) {
2904 case HTTPREQ_POST_FORM:
2905 /* We got an error response. If this happened before the whole
2906 * request body has been sent we stop sending and mark the
2907 * connection for closure after we've read the entire response.
2909 if(!k->upload_done) {
2910 infof(data, "HTTP error before end of send, stop sending\n");
2911 conn->bits.close = TRUE; /* close after this */
2912 k->upload_done = TRUE;
2913 k->keepon &= ~KEEP_SEND; /* don't send */
2914 if(data->state.expect100header)
2915 k->exp100 = EXP100_FAILED;
2919 default: /* default label present to avoid compiler warnings */
2925 if(conn->bits.rewindaftersend) {
2926 /* We rewind after a complete send, so thus we continue
2928 infof(data, "Keep sending data to get tossed away!\n");
2929 k->keepon |= KEEP_SEND;
2935 * really end-of-headers.
2937 * If we requested a "no body", this is a good time to get
2938 * out and return home.
2940 if(data->set.opt_no_body)
2941 *stop_reading = TRUE;
2943 /* If we know the expected size of this document, we set the
2944 maximum download size to the size of the expected
2945 document or else, we won't know when to stop reading!
2947 Note that we set the download maximum even if we read a
2948 "Connection: close" header, to make sure that
2949 "Content-Length: 0" still prevents us from attempting to
2950 read the (missing) response-body.
2952 /* According to RFC2616 section 4.4, we MUST ignore
2953 Content-Length: headers if we are now receiving data
2954 using chunked Transfer-Encoding.
2957 k->maxdownload = k->size = -1;
2960 /* We do this operation even if no_body is true, since this
2961 data might be retrieved later with curl_easy_getinfo()
2962 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
2964 Curl_pgrsSetDownloadSize(data, k->size);
2965 k->maxdownload = k->size;
2968 /* If max download size is *zero* (nothing) we already
2969 have nothing and can safely return ok now! */
2970 if(0 == k->maxdownload)
2971 *stop_reading = TRUE;
2974 /* we make sure that this socket isn't read more now */
2975 k->keepon &= ~KEEP_RECV;
2978 if(data->set.verbose)
2979 Curl_debug(data, CURLINFO_HEADER_IN,
2980 k->str_start, headerlen, conn);
2981 break; /* exit header line loop */
2984 /* We continue reading headers, so reset the line-based
2985 header parsing variables hbufp && hbuflen */
2986 k->hbufp = data->state.headerbuff;
2992 * Checks for special headers coming up.
2995 if(!k->headerline++) {
2996 /* This is the first header, it MUST be the error code line
2997 or else we consider this to be the body right away! */
2998 int httpversion_major;
2999 int rtspversion_major;
3001 #ifdef CURL_DOES_CONVERSIONS
3002 #define HEADER1 scratch
3003 #define SCRATCHSIZE 21
3005 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
3006 /* We can't really convert this yet because we
3007 don't know if it's the 1st header line or the body.
3008 So we do a partial conversion into a scratch area,
3009 leaving the data at k->p as-is.
3011 strncpy(&scratch[0], k->p, SCRATCHSIZE);
3012 scratch[SCRATCHSIZE] = 0; /* null terminate */
3013 res = Curl_convert_from_network(data,
3017 /* Curl_convert_from_network calls failf if unsuccessful */
3020 #define HEADER1 k->p /* no conversion needed, just use k->p */
3021 #endif /* CURL_DOES_CONVERSIONS */
3023 if(conn->handler->protocol & CURLPROTO_HTTP) {
3024 nc = sscanf(HEADER1,
3030 conn->httpversion += 10 * httpversion_major;
3033 /* this is the real world, not a Nirvana
3034 NCSA 1.5.x returns this crap when asked for HTTP/1.1
3036 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3037 conn->httpversion = 10;
3039 /* If user has set option HTTP200ALIASES,
3040 compare header line against list of aliases
3043 if(checkhttpprefix(data, k->p)) {
3046 conn->httpversion = 10;
3051 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3052 nc = sscanf(HEADER1,
3058 conn->rtspversion += 10 * rtspversion_major;
3059 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3062 /* TODO: do we care about the other cases here? */
3068 data->info.httpcode = k->httpcode;
3070 data->info.httpversion = conn->httpversion;
3071 if(!data->state.httpversion ||
3072 data->state.httpversion > conn->httpversion)
3073 /* store the lowest server version we encounter */
3074 data->state.httpversion = conn->httpversion;
3077 * This code executes as part of processing the header. As a
3078 * result, it's not totally clear how to interpret the
3079 * response code yet as that depends on what other headers may
3080 * be present. 401 and 407 may be errors, but may be OK
3081 * depending on how authentication is working. Other codes
3082 * are definitely errors, so give up here.
3084 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3085 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3086 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3088 if(data->state.resume_from &&
3089 (data->set.httpreq==HTTPREQ_GET) &&
3090 (k->httpcode == 416)) {
3091 /* "Requested Range Not Satisfiable", just proceed and
3092 pretend this is no error */
3095 /* serious error, go home! */
3096 failf (data, "The requested URL returned error: %d",
3098 return CURLE_HTTP_RETURNED_ERROR;
3102 if(conn->httpversion == 10) {
3103 /* Default action for HTTP/1.0 must be to close, unless
3104 we get one of those fancy headers that tell us the
3105 server keeps it open for us! */
3106 infof(data, "HTTP 1.0, assume close after body\n");
3107 conn->bits.close = TRUE;
3109 else if(conn->httpversion >= 11 &&
3110 !conn->bits.close) {
3111 /* If HTTP version is >= 1.1 and connection is persistent
3112 server supports pipelining. */
3114 "HTTP 1.1 or later with persistent connection, "
3115 "pipelining supported\n"));
3116 conn->server_supports_pipelining = TRUE;
3119 switch(k->httpcode) {
3121 /* (quote from RFC2616, section 10.2.5): The server has
3122 * fulfilled the request but does not need to return an
3123 * entity-body ... The 204 response MUST NOT include a
3124 * message-body, and thus is always terminated by the first
3125 * empty line after the header fields. */
3128 /* (quote from RFC2616, section 10.3.5): The 304 response
3129 * MUST NOT contain a message-body, and thus is always
3130 * terminated by the first empty line after the header
3132 if(data->set.timecondition)
3133 data->info.timecond = TRUE;
3136 k->ignorecl = TRUE; /* ignore Content-Length headers */
3144 k->header = FALSE; /* this is not a header line */
3149 result = Curl_convert_from_network(data, k->p, strlen(k->p));
3150 /* Curl_convert_from_network calls failf if unsuccessful */
3154 /* Check for Content-Length: header lines to get size */
3155 if(!k->ignorecl && !data->set.ignorecl &&
3156 checkprefix("Content-Length:", k->p)) {
3157 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
3158 if(data->set.max_filesize &&
3159 contentlength > data->set.max_filesize) {
3160 failf(data, "Maximum file size exceeded");
3161 return CURLE_FILESIZE_EXCEEDED;
3163 if(contentlength >= 0) {
3164 k->size = contentlength;
3165 k->maxdownload = k->size;
3166 /* we set the progress download size already at this point
3167 just to make it easier for apps/callbacks to extract this
3168 info as soon as possible */
3169 Curl_pgrsSetDownloadSize(data, k->size);
3172 /* Negative Content-Length is really odd, and we know it
3173 happens for example when older Apache servers send large
3175 conn->bits.close = TRUE;
3176 infof(data, "Negative content-length: %" FORMAT_OFF_T
3177 ", closing after transfer\n", contentlength);
3180 /* check for Content-Type: header lines to get the MIME-type */
3181 else if(checkprefix("Content-Type:", k->p)) {
3182 char *contenttype = copy_header_value(k->p);
3184 return CURLE_OUT_OF_MEMORY;
3186 /* ignore empty data */
3189 Curl_safefree(data->info.contenttype);
3190 data->info.contenttype = contenttype;
3193 else if((conn->httpversion == 10) &&
3194 conn->bits.httpproxy &&
3195 Curl_compareheader(k->p,
3196 "Proxy-Connection:", "keep-alive")) {
3198 * When a HTTP/1.0 reply comes when using a proxy, the
3199 * 'Proxy-Connection: keep-alive' line tells us the
3200 * connection will be kept alive for our pleasure.
3201 * Default action for 1.0 is to close.
3203 conn->bits.close = FALSE; /* don't close when done */
3204 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3206 else if((conn->httpversion == 11) &&
3207 conn->bits.httpproxy &&
3208 Curl_compareheader(k->p,
3209 "Proxy-Connection:", "close")) {
3211 * We get a HTTP/1.1 response from a proxy and it says it'll
3212 * close down after this transfer.
3214 conn->bits.close = TRUE; /* close when done */
3215 infof(data, "HTTP/1.1 proxy connection set close!\n");
3217 else if((conn->httpversion == 10) &&
3218 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3220 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3221 * tells us the connection will be kept alive for our
3222 * pleasure. Default action for 1.0 is to close.
3224 * [RFC2068, section 19.7.1] */
3225 conn->bits.close = FALSE; /* don't close when done */
3226 infof(data, "HTTP/1.0 connection set to keep alive!\n");
3228 else if(Curl_compareheader(k->p, "Connection:", "close")) {
3230 * [RFC 2616, section 8.1.2.1]
3231 * "Connection: close" is HTTP/1.1 language and means that
3232 * the connection will close when this request has been
3235 conn->bits.close = TRUE; /* close when done */
3237 else if(checkprefix("Transfer-Encoding:", k->p)) {
3238 /* One or more encodings. We check for chunked and/or a compression
3241 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3242 * means that the server will send a series of "chunks". Each
3243 * chunk starts with line with info (including size of the
3244 * coming block) (terminated with CRLF), then a block of data
3245 * with the previously mentioned size. There can be any amount
3246 * of chunks, and a chunk-data set to zero signals the
3251 /* Find the first non-space letter */
3255 /* skip whitespaces and commas */
3256 while(*start && (ISSPACE(*start) || (*start == ',')))
3259 if(checkprefix("chunked", start)) {
3260 k->chunk = TRUE; /* chunks coming our way */
3262 /* init our chunky engine */
3263 Curl_httpchunk_init(conn);
3268 if(k->auto_decoding)
3269 /* TODO: we only support the first mentioned compression for now */
3272 if(checkprefix("identity", start)) {
3273 k->auto_decoding = IDENTITY;
3276 else if(checkprefix("deflate", start)) {
3277 k->auto_decoding = DEFLATE;
3280 else if(checkprefix("gzip", start)) {
3281 k->auto_decoding = GZIP;
3284 else if(checkprefix("x-gzip", start)) {
3285 k->auto_decoding = GZIP;
3288 else if(checkprefix("compress", start)) {
3289 k->auto_decoding = COMPRESS;
3292 else if(checkprefix("x-compress", start)) {
3293 k->auto_decoding = COMPRESS;
3303 else if(checkprefix("Content-Encoding:", k->p) &&
3304 data->set.str[STRING_ENCODING]) {
3306 * Process Content-Encoding. Look for the values: identity,
3307 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3308 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3309 * 2616). zlib cannot handle compress. However, errors are
3310 * handled further down when the response body is processed
3314 /* Find the first non-space letter */
3316 while(*start && ISSPACE(*start))
3319 /* Record the content-encoding for later use */
3320 if(checkprefix("identity", start))
3321 k->auto_decoding = IDENTITY;
3322 else if(checkprefix("deflate", start))
3323 k->auto_decoding = DEFLATE;
3324 else if(checkprefix("gzip", start)
3325 || checkprefix("x-gzip", start))
3326 k->auto_decoding = GZIP;
3327 else if(checkprefix("compress", start)
3328 || checkprefix("x-compress", start))
3329 k->auto_decoding = COMPRESS;
3331 else if(checkprefix("Content-Range:", k->p)) {
3332 /* Content-Range: bytes [num]-
3333 Content-Range: bytes: [num]-
3334 Content-Range: [num]-
3336 The second format was added since Sun's webserver
3337 JavaWebServer/1.1.1 obviously sends the header this way!
3338 The third added since some servers use that!
3341 char *ptr = k->p + 14;
3343 /* Move forward until first digit */
3344 while(*ptr && !ISDIGIT(*ptr))
3347 k->offset = curlx_strtoofft(ptr, NULL, 10);
3349 if(data->state.resume_from == k->offset)
3350 /* we asked for a resume and we got it */
3351 k->content_range = TRUE;
3353 #if !defined(CURL_DISABLE_COOKIES)
3354 else if(data->cookies &&
3355 checkprefix("Set-Cookie:", k->p)) {
3356 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3357 CURL_LOCK_ACCESS_SINGLE);
3358 Curl_cookie_add(data,
3359 data->cookies, TRUE, k->p+11,
3360 /* If there is a custom-set Host: name, use it
3361 here, or else use real peer host name. */
3362 conn->allocptr.cookiehost?
3363 conn->allocptr.cookiehost:conn->host.name,
3365 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3368 else if(checkprefix("Last-Modified:", k->p) &&
3369 (data->set.timecondition || data->set.get_filetime) ) {
3370 time_t secs=time(NULL);
3371 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
3373 if(data->set.get_filetime)
3374 data->info.filetime = (long)k->timeofdoc;
3376 else if((checkprefix("WWW-Authenticate:", k->p) &&
3377 (401 == k->httpcode)) ||
3378 (checkprefix("Proxy-authenticate:", k->p) &&
3379 (407 == k->httpcode))) {
3380 result = Curl_http_input_auth(conn, k->httpcode, k->p);
3384 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3385 checkprefix("Location:", k->p) &&
3386 !data->req.location) {
3387 /* this is the URL that the server advises us to use instead */
3388 char *location = copy_header_value(k->p);
3390 return CURLE_OUT_OF_MEMORY;
3392 /* ignore empty data */
3395 data->req.location = location;
3397 if(data->set.http_follow_location) {
3398 DEBUGASSERT(!data->req.newurl);
3399 data->req.newurl = strdup(data->req.location); /* clone */
3400 if(!data->req.newurl)
3401 return CURLE_OUT_OF_MEMORY;
3403 /* some cases of POST and PUT etc needs to rewind the data
3404 stream at this point */
3405 result = http_perhapsrewind(conn);
3411 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3412 result = Curl_rtsp_parseheader(conn, k->p);
3418 * End of header-checks. Write them to the client.
3421 writetype = CLIENTWRITE_HEADER;
3422 if(data->set.include_header)
3423 writetype |= CLIENTWRITE_BODY;
3425 if(data->set.verbose)
3426 Curl_debug(data, CURLINFO_HEADER_IN,
3427 k->p, (size_t)k->hbuflen, conn);
3429 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
3433 data->info.header_size += (long)k->hbuflen;
3434 data->req.headerbytecount += (long)k->hbuflen;
3436 /* reset hbufp pointer && hbuflen */
3437 k->hbufp = data->state.headerbuff;
3440 while(!*stop_reading && *k->str); /* header line within buffer */
3442 /* We might have reached the end of the header part here, but
3443 there might be a non-header part left in the end of the read
3449 #endif /* CURL_DISABLE_HTTP */