Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl-7.19.0 / lib / http.c
blob23deb98857c5e76d97cd41762c251e18d737d2c9
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2008, 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 * $Id: http.c,v 1.1.1.1 2008-09-23 16:32:05 hoffman Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 #ifndef CURL_DISABLE_HTTP
27 /* -- WIN32 approved -- */
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #ifdef WIN32
35 #include <time.h>
36 #include <io.h>
37 #else
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
40 #endif
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
43 #endif
44 #ifdef HAVE_SYS_TIME_H
45 #include <sys/time.h>
46 #endif
48 #ifdef HAVE_TIME_H
49 #ifdef TIME_WITH_SYS_TIME
50 #include <time.h>
51 #endif
52 #endif
54 #ifdef HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif
63 #ifdef HAVE_NET_IF_H
64 #include <net/if.h>
65 #endif
66 #ifdef HAVE_SYS_IOCTL_H
67 #include <sys/ioctl.h>
68 #endif
69 #include <signal.h>
71 #ifdef HAVE_SYS_PARAM_H
72 #include <sys/param.h>
73 #endif
75 #endif
77 #include "urldata.h"
78 #include <curl/curl.h>
79 #include "transfer.h"
80 #include "sendf.h"
81 #include "easyif.h" /* for Curl_convert_... prototypes */
82 #include "formdata.h"
83 #include "progress.h"
84 #include "curl_base64.h"
85 #include "cookie.h"
86 #include "strequal.h"
87 #include "sslgen.h"
88 #include "http_digest.h"
89 #include "http_ntlm.h"
90 #include "http_negotiate.h"
91 #include "url.h"
92 #include "share.h"
93 #include "hostip.h"
94 #include "http.h"
95 #include "memory.h"
96 #include "select.h"
97 #include "parsedate.h" /* for the week day and month names */
98 #include "strtoofft.h"
99 #include "multiif.h"
101 #define _MPRINTF_REPLACE /* use our functions only */
102 #include <curl/mprintf.h>
104 /* The last #include file should be: */
105 #include "memdebug.h"
107 /* Default proxy timeout in milliseconds */
108 #define PROXY_TIMEOUT (3600*1000)
111 * Forward declarations.
114 static int http_getsock_do(struct connectdata *conn,
115 curl_socket_t *socks,
116 int numsocks);
117 static CURLcode https_connecting(struct connectdata *conn, bool *done);
118 #ifdef USE_SSL
119 static int https_getsock(struct connectdata *conn,
120 curl_socket_t *socks,
121 int numsocks);
122 #endif
125 * HTTP handler interface.
127 const struct Curl_handler Curl_handler_http = {
128 "HTTP", /* scheme */
129 ZERO_NULL, /* setup_connection */
130 Curl_http, /* do_it */
131 Curl_http_done, /* done */
132 ZERO_NULL, /* do_more */
133 Curl_http_connect, /* connect_it */
134 ZERO_NULL, /* connecting */
135 ZERO_NULL, /* doing */
136 ZERO_NULL, /* proto_getsock */
137 http_getsock_do, /* doing_getsock */
138 ZERO_NULL, /* disconnect */
139 PORT_HTTP, /* defport */
140 PROT_HTTP, /* protocol */
143 #ifdef USE_SSL
145 * HTTPS handler interface.
147 const struct Curl_handler Curl_handler_https = {
148 "HTTPS", /* scheme */
149 ZERO_NULL, /* setup_connection */
150 Curl_http, /* do_it */
151 Curl_http_done, /* done */
152 ZERO_NULL, /* do_more */
153 Curl_http_connect, /* connect_it */
154 https_connecting, /* connecting */
155 ZERO_NULL, /* doing */
156 https_getsock, /* proto_getsock */
157 http_getsock_do, /* doing_getsock */
158 ZERO_NULL, /* disconnect */
159 PORT_HTTPS, /* defport */
160 PROT_HTTP | PROT_HTTPS | PROT_SSL /* protocol */
162 #endif
166 * checkheaders() checks the linked list of custom HTTP headers for a
167 * particular header (prefix).
169 * Returns a pointer to the first matching header or NULL if none matched.
171 static char *checkheaders(struct SessionHandle *data, const char *thisheader)
173 struct curl_slist *head;
174 size_t thislen = strlen(thisheader);
176 for(head = data->set.headers; head; head=head->next) {
177 if(strnequal(head->data, thisheader, thislen))
178 return head->data;
180 return NULL;
184 * Strip off leading and trailing whitespace from the value in the
185 * given HTTP header line and return a strdupped copy. Returns NULL in
186 * case of allocation failure. Returns an empty string if the header value
187 * consists entirely of whitespace.
189 char *Curl_copy_header_value(const char *h)
191 const char *start;
192 const char *end;
193 char *value;
194 size_t len;
196 DEBUGASSERT(h);
198 /* Find the end of the header name */
199 while (*h && (*h != ':'))
200 ++h;
202 if (*h)
203 /* Skip over colon */
204 ++h;
206 /* Find the first non-space letter */
207 for(start=h;
208 *start && ISSPACE(*start);
209 start++)
210 ; /* empty loop */
212 /* data is in the host encoding so
213 use '\r' and '\n' instead of 0x0d and 0x0a */
214 end = strchr(start, '\r');
215 if(!end)
216 end = strchr(start, '\n');
217 if(!end)
218 end = strchr(start, '\0');
220 /* skip all trailing space letters */
221 for(; ISSPACE(*end) && (end > start); end--)
222 ; /* empty loop */
224 /* get length of the type */
225 len = end-start+1;
227 value = malloc(len + 1);
228 if(!value)
229 return NULL;
231 memcpy(value, start, len);
232 value[len] = 0; /* zero terminate */
234 return value;
238 * http_output_basic() sets up an Authorization: header (or the proxy version)
239 * for HTTP Basic authentication.
241 * Returns CURLcode.
243 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
245 char *authorization;
246 struct SessionHandle *data=conn->data;
247 char **userp;
248 char *user;
249 char *pwd;
251 if(proxy) {
252 userp = &conn->allocptr.proxyuserpwd;
253 user = conn->proxyuser;
254 pwd = conn->proxypasswd;
256 else {
257 userp = &conn->allocptr.userpwd;
258 user = conn->user;
259 pwd = conn->passwd;
262 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
263 if(Curl_base64_encode(data, data->state.buffer,
264 strlen(data->state.buffer),
265 &authorization) > 0) {
266 if(*userp)
267 free(*userp);
268 *userp = aprintf( "%sAuthorization: Basic %s\r\n",
269 proxy?"Proxy-":"",
270 authorization);
271 free(authorization);
272 if(!*userp)
273 return CURLE_OUT_OF_MEMORY;
275 else
276 return CURLE_OUT_OF_MEMORY;
277 return CURLE_OK;
280 /* pickoneauth() selects the most favourable authentication method from the
281 * ones available and the ones we want.
283 * return TRUE if one was picked
285 static bool pickoneauth(struct auth *pick)
287 bool picked;
288 /* only deal with authentication we want */
289 long avail = pick->avail & pick->want;
290 picked = TRUE;
292 /* The order of these checks is highly relevant, as this will be the order
293 of preference in case of the existance of multiple accepted types. */
294 if(avail & CURLAUTH_GSSNEGOTIATE)
295 pick->picked = CURLAUTH_GSSNEGOTIATE;
296 else if(avail & CURLAUTH_DIGEST)
297 pick->picked = CURLAUTH_DIGEST;
298 else if(avail & CURLAUTH_NTLM)
299 pick->picked = CURLAUTH_NTLM;
300 else if(avail & CURLAUTH_BASIC)
301 pick->picked = CURLAUTH_BASIC;
302 else {
303 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
304 picked = FALSE;
306 pick->avail = CURLAUTH_NONE; /* clear it here */
308 return picked;
312 * Curl_http_perhapsrewind()
314 * If we are doing POST or PUT {
315 * If we have more data to send {
316 * If we are doing NTLM {
317 * Keep sending since we must not disconnect
319 * else {
320 * If there is more than just a little data left to send, close
321 * the current connection by force.
324 * If we have sent any data {
325 * If we don't have track of all the data {
326 * call app to tell it to rewind
328 * else {
329 * rewind internally so that the operation can restart fine
334 CURLcode Curl_http_perhapsrewind(struct connectdata *conn)
336 struct SessionHandle *data = conn->data;
337 struct HTTP *http = data->state.proto.http;
338 curl_off_t bytessent;
339 curl_off_t expectsend = -1; /* default is unknown */
341 if(!http || !(conn->protocol & PROT_HTTP))
342 /* If this is still NULL, we have not reach very far and we can
343 safely skip this rewinding stuff, or this is attempted to get used
344 when HTTP isn't activated */
345 return CURLE_OK;
347 switch(data->set.httpreq) {
348 case HTTPREQ_GET:
349 case HTTPREQ_HEAD:
350 return CURLE_OK;
351 default:
352 break;
355 bytessent = http->writebytecount;
357 if(conn->bits.authneg)
358 /* This is a state where we are known to be negotiating and we don't send
359 any data then. */
360 expectsend = 0;
361 else {
362 /* figure out how much data we are expected to send */
363 switch(data->set.httpreq) {
364 case HTTPREQ_POST:
365 if(data->set.postfieldsize != -1)
366 expectsend = data->set.postfieldsize;
367 break;
368 case HTTPREQ_PUT:
369 if(data->set.infilesize != -1)
370 expectsend = data->set.infilesize;
371 break;
372 case HTTPREQ_POST_FORM:
373 expectsend = http->postsize;
374 break;
375 default:
376 break;
380 conn->bits.rewindaftersend = FALSE; /* default */
382 if((expectsend == -1) || (expectsend > bytessent)) {
383 /* There is still data left to send */
384 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
385 (data->state.authhost.picked == CURLAUTH_NTLM)) {
386 if(((expectsend - bytessent) < 2000) ||
387 (conn->ntlm.state != NTLMSTATE_NONE)) {
388 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
389 data left to send, keep on sending. */
391 /* rewind data when completely done sending! */
392 if(!conn->bits.authneg)
393 conn->bits.rewindaftersend = TRUE;
395 return CURLE_OK;
397 if(conn->bits.close)
398 /* this is already marked to get closed */
399 return CURLE_OK;
401 infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T
402 " bytes\n", (curl_off_t)(expectsend - bytessent));
405 /* This is not NTLM or NTLM with many bytes left to send: close
407 conn->bits.close = TRUE;
408 data->req.size = 0; /* don't download any more than 0 bytes */
410 /* There still is data left to send, but this connection is marked for
411 closure so we can safely do the rewind right now */
414 if(bytessent)
415 /* we rewind now at once since if we already sent something */
416 return Curl_readrewind(conn);
418 return CURLE_OK;
422 * Curl_http_auth_act() gets called when a all HTTP headers have been received
423 * and it checks what authentication methods that are available and decides
424 * which one (if any) to use. It will set 'newurl' if an auth metod was
425 * picked.
428 CURLcode Curl_http_auth_act(struct connectdata *conn)
430 struct SessionHandle *data = conn->data;
431 bool pickhost = FALSE;
432 bool pickproxy = FALSE;
433 CURLcode code = CURLE_OK;
435 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
436 /* this is a transient response code, ignore */
437 return CURLE_OK;
439 if(data->state.authproblem)
440 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
442 if(conn->bits.user_passwd &&
443 ((data->req.httpcode == 401) ||
444 (conn->bits.authneg && data->req.httpcode < 300))) {
445 pickhost = pickoneauth(&data->state.authhost);
446 if(!pickhost)
447 data->state.authproblem = TRUE;
449 if(conn->bits.proxy_user_passwd &&
450 ((data->req.httpcode == 407) ||
451 (conn->bits.authneg && data->req.httpcode < 300))) {
452 pickproxy = pickoneauth(&data->state.authproxy);
453 if(!pickproxy)
454 data->state.authproblem = TRUE;
457 if(pickhost || pickproxy) {
458 data->req.newurl = strdup(data->change.url); /* clone URL */
459 if(!data->req.newurl)
460 return CURLE_OUT_OF_MEMORY;
462 if((data->set.httpreq != HTTPREQ_GET) &&
463 (data->set.httpreq != HTTPREQ_HEAD) &&
464 !conn->bits.rewindaftersend) {
465 code = Curl_http_perhapsrewind(conn);
466 if(code)
467 return code;
471 else if((data->req.httpcode < 300) &&
472 (!data->state.authhost.done) &&
473 conn->bits.authneg) {
474 /* no (known) authentication available,
475 authentication is not "done" yet and
476 no authentication seems to be required and
477 we didn't try HEAD or GET */
478 if((data->set.httpreq != HTTPREQ_GET) &&
479 (data->set.httpreq != HTTPREQ_HEAD)) {
480 data->req.newurl = strdup(data->change.url); /* clone URL */
481 if(!data->req.newurl)
482 return CURLE_OUT_OF_MEMORY;
483 data->state.authhost.done = TRUE;
486 if(Curl_http_should_fail(conn)) {
487 failf (data, "The requested URL returned error: %d",
488 data->req.httpcode);
489 code = CURLE_HTTP_RETURNED_ERROR;
492 return code;
496 * Curl_http_output_auth() setups the authentication headers for the
497 * host/proxy and the correct authentication
498 * method. conn->data->state.authdone is set to TRUE when authentication is
499 * done.
501 * @param conn all information about the current connection
502 * @param request pointer to the request keyword
503 * @param path pointer to the requested path
504 * @param proxytunnel boolean if this is the request setting up a "proxy
505 * tunnel"
507 * @returns CURLcode
509 static CURLcode
510 http_output_auth(struct connectdata *conn,
511 const char *request,
512 const char *path,
513 bool proxytunnel) /* TRUE if this is the request setting
514 up the proxy tunnel */
516 CURLcode result = CURLE_OK;
517 struct SessionHandle *data = conn->data;
518 const char *auth=NULL;
519 struct auth *authhost;
520 struct auth *authproxy;
522 DEBUGASSERT(data);
524 authhost = &data->state.authhost;
525 authproxy = &data->state.authproxy;
527 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
528 conn->bits.user_passwd)
529 /* continue please */ ;
530 else {
531 authhost->done = TRUE;
532 authproxy->done = TRUE;
533 return CURLE_OK; /* no authentication with no user or password */
536 if(authhost->want && !authhost->picked)
537 /* The app has selected one or more methods, but none has been picked
538 so far by a server round-trip. Then we set the picked one to the
539 want one, and if this is one single bit it'll be used instantly. */
540 authhost->picked = authhost->want;
542 if(authproxy->want && !authproxy->picked)
543 /* The app has selected one or more methods, but none has been picked so
544 far by a proxy round-trip. Then we set the picked one to the want one,
545 and if this is one single bit it'll be used instantly. */
546 authproxy->picked = authproxy->want;
548 /* Send proxy authentication header if needed */
549 if(conn->bits.httpproxy &&
550 (conn->bits.tunnel_proxy == proxytunnel)) {
551 #ifdef HAVE_GSSAPI
552 if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) &&
553 data->state.negotiate.context &&
554 !GSS_ERROR(data->state.negotiate.status)) {
555 auth="GSS-Negotiate";
556 result = Curl_output_negotiate(conn, TRUE);
557 if(result)
558 return result;
559 authproxy->done = TRUE;
561 else
562 #endif
563 #ifdef USE_NTLM
564 if(authproxy->picked == CURLAUTH_NTLM) {
565 auth="NTLM";
566 result = Curl_output_ntlm(conn, TRUE);
567 if(result)
568 return result;
570 else
571 #endif
572 if(authproxy->picked == CURLAUTH_BASIC) {
573 /* Basic */
574 if(conn->bits.proxy_user_passwd &&
575 !checkheaders(data, "Proxy-authorization:")) {
576 auth="Basic";
577 result = http_output_basic(conn, TRUE);
578 if(result)
579 return result;
581 /* NOTE: http_output_basic() should set 'done' TRUE, as the other auth
582 functions work that way */
583 authproxy->done = TRUE;
585 #ifndef CURL_DISABLE_CRYPTO_AUTH
586 else if(authproxy->picked == CURLAUTH_DIGEST) {
587 auth="Digest";
588 result = Curl_output_digest(conn,
589 TRUE, /* proxy */
590 (const unsigned char *)request,
591 (const unsigned char *)path);
592 if(result)
593 return result;
595 #endif
596 if(auth) {
597 infof(data, "Proxy auth using %s with user '%s'\n",
598 auth, conn->proxyuser?conn->proxyuser:"");
599 authproxy->multi = (bool)(!authproxy->done);
601 else
602 authproxy->multi = FALSE;
604 else
605 /* we have no proxy so let's pretend we're done authenticating
606 with it */
607 authproxy->done = TRUE;
609 /* To prevent the user+password to get sent to other than the original
610 host due to a location-follow, we do some weirdo checks here */
611 if(!data->state.this_is_a_follow ||
612 conn->bits.netrc ||
613 !data->state.first_host ||
614 curl_strequal(data->state.first_host, conn->host.name) ||
615 data->set.http_disable_hostname_check_before_authentication) {
617 /* Send web authentication header if needed */
619 auth = NULL;
620 #ifdef HAVE_GSSAPI
621 if((authhost->picked == CURLAUTH_GSSNEGOTIATE) &&
622 data->state.negotiate.context &&
623 !GSS_ERROR(data->state.negotiate.status)) {
624 auth="GSS-Negotiate";
625 result = Curl_output_negotiate(conn, FALSE);
626 if(result)
627 return result;
628 authhost->done = TRUE;
630 else
631 #endif
632 #ifdef USE_NTLM
633 if(authhost->picked == CURLAUTH_NTLM) {
634 auth="NTLM";
635 result = Curl_output_ntlm(conn, FALSE);
636 if(result)
637 return result;
639 else
640 #endif
642 #ifndef CURL_DISABLE_CRYPTO_AUTH
643 if(authhost->picked == CURLAUTH_DIGEST) {
644 auth="Digest";
645 result = Curl_output_digest(conn,
646 FALSE, /* not a proxy */
647 (const unsigned char *)request,
648 (const unsigned char *)path);
649 if(result)
650 return result;
651 } else
652 #endif
653 if(authhost->picked == CURLAUTH_BASIC) {
654 if(conn->bits.user_passwd &&
655 !checkheaders(data, "Authorization:")) {
656 auth="Basic";
657 result = http_output_basic(conn, FALSE);
658 if(result)
659 return result;
661 /* basic is always ready */
662 authhost->done = TRUE;
665 if(auth) {
666 infof(data, "Server auth using %s with user '%s'\n",
667 auth, conn->user);
669 authhost->multi = (bool)(!authhost->done);
671 else
672 authhost->multi = FALSE;
675 else
676 authhost->done = TRUE;
678 return result;
683 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
684 * headers. They are dealt with both in the transfer.c main loop and in the
685 * proxy CONNECT loop.
688 CURLcode Curl_http_input_auth(struct connectdata *conn,
689 int httpcode,
690 const char *header) /* the first non-space */
693 * This resource requires authentication
695 struct SessionHandle *data = conn->data;
697 long *availp;
698 const char *start;
699 struct auth *authp;
701 if(httpcode == 407) {
702 start = header+strlen("Proxy-authenticate:");
703 availp = &data->info.proxyauthavail;
704 authp = &data->state.authproxy;
706 else {
707 start = header+strlen("WWW-Authenticate:");
708 availp = &data->info.httpauthavail;
709 authp = &data->state.authhost;
712 /* pass all white spaces */
713 while(*start && ISSPACE(*start))
714 start++;
717 * Here we check if we want the specific single authentication (using ==) and
718 * if we do, we initiate usage of it.
720 * If the provided authentication is wanted as one out of several accepted
721 * types (using &), we OR this authentication type to the authavail
722 * variable.
725 #ifdef HAVE_GSSAPI
726 if(checkprefix("GSS-Negotiate", start) ||
727 checkprefix("Negotiate", start)) {
728 *availp |= CURLAUTH_GSSNEGOTIATE;
729 authp->avail |= CURLAUTH_GSSNEGOTIATE;
730 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
731 /* if exactly this is wanted, go */
732 int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
733 if(neg == 0) {
734 DEBUGASSERT(!data->req.newurl);
735 data->req.newurl = strdup(data->change.url);
736 data->state.authproblem = (data->req.newurl == NULL);
738 else {
739 infof(data, "Authentication problem. Ignoring this.\n");
740 data->state.authproblem = TRUE;
744 else
745 #endif
746 #ifdef USE_NTLM
747 /* NTLM support requires the SSL crypto libs */
748 if(checkprefix("NTLM", start)) {
749 *availp |= CURLAUTH_NTLM;
750 authp->avail |= CURLAUTH_NTLM;
751 if(authp->picked == CURLAUTH_NTLM) {
752 /* NTLM authentication is picked and activated */
753 CURLntlm ntlm =
754 Curl_input_ntlm(conn, (bool)(httpcode == 407), start);
756 if(CURLNTLM_BAD != ntlm)
757 data->state.authproblem = FALSE;
758 else {
759 infof(data, "Authentication problem. Ignoring this.\n");
760 data->state.authproblem = TRUE;
764 else
765 #endif
766 #ifndef CURL_DISABLE_CRYPTO_AUTH
767 if(checkprefix("Digest", start)) {
768 if((authp->avail & CURLAUTH_DIGEST) != 0) {
769 infof(data, "Ignoring duplicate digest auth header.\n");
771 else {
772 CURLdigest dig;
773 *availp |= CURLAUTH_DIGEST;
774 authp->avail |= CURLAUTH_DIGEST;
776 /* We call this function on input Digest headers even if Digest
777 * authentication isn't activated yet, as we need to store the
778 * incoming data from this header in case we are gonna use Digest. */
779 dig = Curl_input_digest(conn, (bool)(httpcode == 407), start);
781 if(CURLDIGEST_FINE != dig) {
782 infof(data, "Authentication problem. Ignoring this.\n");
783 data->state.authproblem = TRUE;
787 else
788 #endif
789 if(checkprefix("Basic", start)) {
790 *availp |= CURLAUTH_BASIC;
791 authp->avail |= CURLAUTH_BASIC;
792 if(authp->picked == CURLAUTH_BASIC) {
793 /* We asked for Basic authentication but got a 40X back
794 anyway, which basicly means our name+password isn't
795 valid. */
796 authp->avail = CURLAUTH_NONE;
797 infof(data, "Authentication problem. Ignoring this.\n");
798 data->state.authproblem = TRUE;
802 return CURLE_OK;
806 * Curl_http_should_fail() determines whether an HTTP response has gotten us
807 * into an error state or not.
809 * @param conn all information about the current connection
811 * @retval 0 communications should continue
813 * @retval 1 communications should not continue
815 int Curl_http_should_fail(struct connectdata *conn)
817 struct SessionHandle *data;
818 int httpcode;
820 DEBUGASSERT(conn);
821 data = conn->data;
822 DEBUGASSERT(data);
824 httpcode = data->req.httpcode;
827 ** If we haven't been asked to fail on error,
828 ** don't fail.
830 if(!data->set.http_fail_on_error)
831 return 0;
834 ** Any code < 400 is never terminal.
836 if(httpcode < 400)
837 return 0;
839 if(data->state.resume_from &&
840 (data->set.httpreq==HTTPREQ_GET) &&
841 (httpcode == 416)) {
842 /* "Requested Range Not Satisfiable", just proceed and
843 pretend this is no error */
844 return 0;
848 ** Any code >= 400 that's not 401 or 407 is always
849 ** a terminal error
851 if((httpcode != 401) &&
852 (httpcode != 407))
853 return 1;
856 ** All we have left to deal with is 401 and 407
858 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
861 ** Examine the current authentication state to see if this
862 ** is an error. The idea is for this function to get
863 ** called after processing all the headers in a response
864 ** message. So, if we've been to asked to authenticate a
865 ** particular stage, and we've done it, we're OK. But, if
866 ** we're already completely authenticated, it's not OK to
867 ** get another 401 or 407.
869 ** It is possible for authentication to go stale such that
870 ** the client needs to reauthenticate. Once that info is
871 ** available, use it here.
873 #if 0 /* set to 1 when debugging this functionality */
874 infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage);
875 infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant);
876 infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
877 infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
878 infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
879 infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ?
880 data->req.newurl : "(null)");
881 infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
882 #endif
885 ** Either we're not authenticating, or we're supposed to
886 ** be authenticating something else. This is an error.
888 if((httpcode == 401) && !conn->bits.user_passwd)
889 return TRUE;
890 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
891 return TRUE;
893 return data->state.authproblem;
897 * readmoredata() is a "fread() emulation" to provide POST and/or request
898 * data. It is used when a huge POST is to be made and the entire chunk wasn't
899 * sent in the first send(). This function will then be called from the
900 * transfer.c loop when more data is to be sent to the peer.
902 * Returns the amount of bytes it filled the buffer with.
904 static size_t readmoredata(char *buffer,
905 size_t size,
906 size_t nitems,
907 void *userp)
909 struct connectdata *conn = (struct connectdata *)userp;
910 struct HTTP *http = conn->data->state.proto.http;
911 size_t fullsize = size * nitems;
913 if(0 == http->postsize)
914 /* nothing to return */
915 return 0;
917 /* make sure that a HTTP request is never sent away chunked! */
918 conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST);
920 if(http->postsize <= (curl_off_t)fullsize) {
921 memcpy(buffer, http->postdata, (size_t)http->postsize);
922 fullsize = (size_t)http->postsize;
924 if(http->backup.postsize) {
925 /* move backup data into focus and continue on that */
926 http->postdata = http->backup.postdata;
927 http->postsize = http->backup.postsize;
928 conn->fread_func = http->backup.fread_func;
929 conn->fread_in = http->backup.fread_in;
931 http->sending++; /* move one step up */
933 http->backup.postsize=0;
935 else
936 http->postsize = 0;
938 return fullsize;
941 memcpy(buffer, http->postdata, fullsize);
942 http->postdata += fullsize;
943 http->postsize -= fullsize;
945 return fullsize;
948 /* ------------------------------------------------------------------------- */
950 * The add_buffer series of functions are used to build one large memory chunk
951 * from repeated function invokes. Used so that the entire HTTP request can
952 * be sent in one go.
955 struct send_buffer {
956 char *buffer;
957 size_t size_max;
958 size_t size_used;
960 typedef struct send_buffer send_buffer;
962 static CURLcode add_custom_headers(struct connectdata *conn,
963 send_buffer *req_buffer);
964 static CURLcode
965 add_buffer(send_buffer *in, const void *inptr, size_t size);
968 * add_buffer_init() sets up and returns a fine buffer struct
970 static
971 send_buffer *add_buffer_init(void)
973 send_buffer *blonk;
974 blonk=(send_buffer *)malloc(sizeof(send_buffer));
975 if(blonk) {
976 memset(blonk, 0, sizeof(send_buffer));
977 return blonk;
979 return NULL; /* failed, go home */
983 * add_buffer_send() sends a header buffer and frees all associated memory.
984 * Body data may be appended to the header data if desired.
986 * Returns CURLcode
988 static
989 CURLcode add_buffer_send(send_buffer *in,
990 struct connectdata *conn,
991 long *bytes_written, /* add the number of sent bytes
992 to this counter */
993 size_t included_body_bytes, /* how much of the buffer
994 contains body data */
995 int socketindex)
998 ssize_t amount;
999 CURLcode res;
1000 char *ptr;
1001 size_t size;
1002 struct HTTP *http = conn->data->state.proto.http;
1003 size_t sendsize;
1004 curl_socket_t sockfd;
1005 size_t headersize;
1007 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1009 sockfd = conn->sock[socketindex];
1011 /* The looping below is required since we use non-blocking sockets, but due
1012 to the circumstances we will just loop and try again and again etc */
1014 ptr = in->buffer;
1015 size = in->size_used;
1017 headersize = size - included_body_bytes; /* the initial part that isn't body
1018 is header */
1020 DEBUGASSERT(size > included_body_bytes);
1022 #ifdef CURL_DOES_CONVERSIONS
1023 res = Curl_convert_to_network(conn->data, ptr, headersize);
1024 /* Curl_convert_to_network calls failf if unsuccessful */
1025 if(res != CURLE_OK) {
1026 /* conversion failed, free memory and return to the caller */
1027 if(in->buffer)
1028 free(in->buffer);
1029 free(in);
1030 return res;
1032 #endif /* CURL_DOES_CONVERSIONS */
1034 if(conn->protocol & PROT_HTTPS) {
1035 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
1036 when we speak HTTPS, as if only a fraction of it is sent now, this data
1037 needs to fit into the normal read-callback buffer later on and that
1038 buffer is using this size.
1041 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
1043 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1044 library when we attempt to re-send this buffer. Sending the same data
1045 is not enough, we must use the exact same address. For this reason, we
1046 must copy the data to the uploadbuffer first, since that is the buffer
1047 we will be using if this send is retried later.
1049 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
1050 ptr = conn->data->state.uploadbuffer;
1052 else
1053 sendsize = size;
1055 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
1057 if(CURLE_OK == res) {
1059 * Note that we may not send the entire chunk at once, and we have a set
1060 * number of data bytes at the end of the big buffer (out of which we may
1061 * only send away a part).
1063 /* how much of the header that was sent */
1064 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
1065 size_t bodylen = amount - headlen;
1067 if(conn->data->set.verbose) {
1068 /* this data _may_ contain binary stuff */
1069 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
1070 if((size_t)amount > headlen) {
1071 /* there was body data sent beyond the initial header part, pass that
1072 on to the debug callback too */
1073 Curl_debug(conn->data, CURLINFO_DATA_OUT,
1074 ptr+headlen, bodylen, conn);
1077 if(bodylen)
1078 /* since we sent a piece of the body here, up the byte counter for it
1079 accordingly */
1080 http->writebytecount += bodylen;
1082 *bytes_written += amount;
1084 if(http) {
1085 if((size_t)amount != size) {
1086 /* The whole request could not be sent in one system call. We must
1087 queue it up and send it later when we get the chance. We must not
1088 loop here and wait until it might work again. */
1090 size -= amount;
1092 ptr = in->buffer + amount;
1094 /* backup the currently set pointers */
1095 http->backup.fread_func = conn->fread_func;
1096 http->backup.fread_in = conn->fread_in;
1097 http->backup.postdata = http->postdata;
1098 http->backup.postsize = http->postsize;
1100 /* set the new pointers for the request-sending */
1101 conn->fread_func = (curl_read_callback)readmoredata;
1102 conn->fread_in = (void *)conn;
1103 http->postdata = ptr;
1104 http->postsize = (curl_off_t)size;
1106 http->send_buffer = in;
1107 http->sending = HTTPSEND_REQUEST;
1109 return CURLE_OK;
1111 http->sending = HTTPSEND_BODY;
1112 /* the full buffer was sent, clean up and return */
1114 else {
1115 if((size_t)amount != size)
1116 /* We have no continue-send mechanism now, fail. This can only happen
1117 when this function is used from the CONNECT sending function. We
1118 currently (stupidly) assume that the whole request is always sent
1119 away in the first single chunk.
1121 This needs FIXing.
1123 return CURLE_SEND_ERROR;
1124 else
1125 conn->writechannel_inuse = FALSE;
1128 if(in->buffer)
1129 free(in->buffer);
1130 free(in);
1132 return res;
1137 * add_bufferf() add the formatted input to the buffer.
1139 static
1140 CURLcode add_bufferf(send_buffer *in, const char *fmt, ...)
1142 char *s;
1143 va_list ap;
1144 va_start(ap, fmt);
1145 s = vaprintf(fmt, ap); /* this allocs a new string to append */
1146 va_end(ap);
1148 if(s) {
1149 CURLcode result = add_buffer(in, s, strlen(s));
1150 free(s);
1151 return result;
1153 /* If we failed, we cleanup the whole buffer and return error */
1154 if(in->buffer)
1155 free(in->buffer);
1156 free(in);
1157 return CURLE_OUT_OF_MEMORY;
1161 * add_buffer() appends a memory chunk to the existing buffer
1163 static
1164 CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
1166 char *new_rb;
1167 size_t new_size;
1169 if(~size < in->size_used) {
1170 /* If resulting used size of send buffer would wrap size_t, cleanup
1171 the whole buffer and return error. Otherwise the required buffer
1172 size will fit into a single allocatable memory chunk */
1173 Curl_safefree(in->buffer);
1174 free(in);
1175 return CURLE_OUT_OF_MEMORY;
1178 if(!in->buffer ||
1179 ((in->size_used + size) > (in->size_max - 1))) {
1181 /* If current buffer size isn't enough to hold the result, use a
1182 buffer size that doubles the required size. If this new size
1183 would wrap size_t, then just use the largest possible one */
1185 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1186 (~(size*2) < (in->size_used*2)))
1187 new_size = (size_t)-1;
1188 else
1189 new_size = (in->size_used+size)*2;
1191 if(in->buffer)
1192 /* we have a buffer, enlarge the existing one */
1193 new_rb = (char *)realloc(in->buffer, new_size);
1194 else
1195 /* create a new buffer */
1196 new_rb = (char *)malloc(new_size);
1198 if(!new_rb) {
1199 /* If we failed, we cleanup the whole buffer and return error */
1200 Curl_safefree(in->buffer);
1201 free(in);
1202 return CURLE_OUT_OF_MEMORY;
1205 in->buffer = new_rb;
1206 in->size_max = new_size;
1208 memcpy(&in->buffer[in->size_used], inptr, size);
1210 in->size_used += size;
1212 return CURLE_OK;
1215 /* end of the add_buffer functions */
1216 /* ------------------------------------------------------------------------- */
1219 * Curl_compareheader()
1221 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1222 * Pass headers WITH the colon.
1224 bool
1225 Curl_compareheader(const char *headerline, /* line to check */
1226 const char *header, /* header keyword _with_ colon */
1227 const char *content) /* content string to find */
1229 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1230 * by a colon (":") and the field value. Field names are case-insensitive.
1231 * The field value MAY be preceded by any amount of LWS, though a single SP
1232 * is preferred." */
1234 size_t hlen = strlen(header);
1235 size_t clen;
1236 size_t len;
1237 const char *start;
1238 const char *end;
1240 if(!strnequal(headerline, header, hlen))
1241 return FALSE; /* doesn't start with header */
1243 /* pass the header */
1244 start = &headerline[hlen];
1246 /* pass all white spaces */
1247 while(*start && ISSPACE(*start))
1248 start++;
1250 /* find the end of the header line */
1251 end = strchr(start, '\r'); /* lines end with CRLF */
1252 if(!end) {
1253 /* in case there's a non-standard compliant line here */
1254 end = strchr(start, '\n');
1256 if(!end)
1257 /* hm, there's no line ending here, use the zero byte! */
1258 end = strchr(start, '\0');
1261 len = end-start; /* length of the content part of the input line */
1262 clen = strlen(content); /* length of the word to find */
1264 /* find the content string in the rest of the line */
1265 for(;len>=clen;len--, start++) {
1266 if(strnequal(start, content, clen))
1267 return TRUE; /* match! */
1270 return FALSE; /* no match */
1274 * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
1275 * function will issue the necessary commands to get a seamless tunnel through
1276 * this proxy. After that, the socket can be used just as a normal socket.
1278 * This badly needs to be rewritten. CONNECT should be sent and dealt with
1279 * like any ordinary HTTP request, and not specially crafted like this. This
1280 * function only remains here like this for now since the rewrite is a bit too
1281 * much work to do at the moment.
1283 * This function is BLOCKING which is nasty for all multi interface using apps.
1286 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
1287 int sockindex,
1288 const char *hostname,
1289 unsigned short remote_port)
1291 int subversion=0;
1292 struct SessionHandle *data=conn->data;
1293 struct SingleRequest *k = &data->req;
1294 CURLcode result;
1295 int res;
1296 long timeout =
1297 data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
1298 curl_socket_t tunnelsocket = conn->sock[sockindex];
1299 curl_off_t cl=0;
1300 bool closeConnection = FALSE;
1301 bool chunked_encoding = FALSE;
1302 long check;
1304 #define SELECT_OK 0
1305 #define SELECT_ERROR 1
1306 #define SELECT_TIMEOUT 2
1307 int error = SELECT_OK;
1309 conn->bits.proxy_connect_closed = FALSE;
1311 do {
1312 if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
1313 char *host_port;
1314 send_buffer *req_buffer;
1316 infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
1317 hostname, remote_port);
1319 if(data->req.newurl) {
1320 /* This only happens if we've looped here due to authentication
1321 reasons, and we don't really use the newly cloned URL here
1322 then. Just free() it. */
1323 free(data->req.newurl);
1324 data->req.newurl = NULL;
1327 /* initialize a dynamic send-buffer */
1328 req_buffer = add_buffer_init();
1330 if(!req_buffer)
1331 return CURLE_OUT_OF_MEMORY;
1333 host_port = aprintf("%s:%d", hostname, remote_port);
1334 if(!host_port) {
1335 free(req_buffer);
1336 return CURLE_OUT_OF_MEMORY;
1339 /* Setup the proxy-authorization header, if any */
1340 result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
1342 if(CURLE_OK == result) {
1343 char *host=(char *)"";
1344 const char *proxyconn="";
1345 const char *useragent="";
1347 if(!checkheaders(data, "Host:")) {
1348 host = aprintf("Host: %s\r\n", host_port);
1349 if(!host) {
1350 free(req_buffer);
1351 free(host_port);
1352 return CURLE_OUT_OF_MEMORY;
1355 if(!checkheaders(data, "Proxy-Connection:"))
1356 proxyconn = "Proxy-Connection: Keep-Alive\r\n";
1358 if(!checkheaders(data, "User-Agent:") &&
1359 data->set.str[STRING_USERAGENT])
1360 useragent = conn->allocptr.uagent;
1362 /* Send the connect request to the proxy */
1363 /* BLOCKING */
1364 result =
1365 add_bufferf(req_buffer,
1366 "CONNECT %s:%d HTTP/1.0\r\n"
1367 "%s" /* Host: */
1368 "%s" /* Proxy-Authorization */
1369 "%s" /* User-Agent */
1370 "%s", /* Proxy-Connection */
1371 hostname, remote_port,
1372 host,
1373 conn->allocptr.proxyuserpwd?
1374 conn->allocptr.proxyuserpwd:"",
1375 useragent,
1376 proxyconn);
1378 if(host && *host)
1379 free(host);
1381 if(CURLE_OK == result)
1382 result = add_custom_headers(conn, req_buffer);
1384 if(CURLE_OK == result)
1385 /* CRLF terminate the request */
1386 result = add_bufferf(req_buffer, "\r\n");
1388 if(CURLE_OK == result) {
1389 /* Now send off the request */
1390 result = add_buffer_send(req_buffer, conn,
1391 &data->info.request_size, 0, sockindex);
1393 req_buffer = NULL;
1394 if(result)
1395 failf(data, "Failed sending CONNECT to proxy");
1397 free(host_port);
1398 Curl_safefree(req_buffer);
1399 if(result)
1400 return result;
1402 conn->bits.tunnel_connecting = TRUE;
1403 } /* END CONNECT PHASE */
1405 /* now we've issued the CONNECT and we're waiting to hear back -
1406 we try not to block here in multi-mode because that might be a LONG
1407 wait if the proxy cannot connect-through to the remote host. */
1409 /* if timeout is requested, find out how much remaining time we have */
1410 check = timeout - /* timeout time */
1411 Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
1412 if(check <=0 ) {
1413 failf(data, "Proxy CONNECT aborted due to timeout");
1414 error = SELECT_TIMEOUT; /* already too little time */
1415 break;
1418 /* if we're in multi-mode and we would block, return instead for a retry */
1419 if(Curl_if_multi == data->state.used_interface) {
1420 if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
1421 /* return so we'll be called again polling-style */
1422 return CURLE_OK;
1423 else {
1424 DEBUGF(infof(data,
1425 "Multi mode finished polling for response from "
1426 "proxy CONNECT."));
1429 else {
1430 DEBUGF(infof(data, "Easy mode waiting for response from proxy CONNECT."));
1433 /* at this point, either:
1434 1) we're in easy-mode and so it's okay to block waiting for a CONNECT
1435 response
1436 2) we're in multi-mode and we didn't block - it's either an error or we
1437 now have some data waiting.
1438 In any case, the tunnel_connecting phase is over. */
1439 conn->bits.tunnel_connecting = FALSE;
1441 { /* BEGIN NEGOTIATION PHASE */
1442 size_t nread; /* total size read */
1443 int perline; /* count bytes per line */
1444 int keepon=TRUE;
1445 ssize_t gotbytes;
1446 char *ptr;
1447 char *line_start;
1449 ptr=data->state.buffer;
1450 line_start = ptr;
1452 nread=0;
1453 perline=0;
1454 keepon=TRUE;
1456 while((nread<BUFSIZE) && (keepon && !error)) {
1458 /* if timeout is requested, find out how much remaining time we have */
1459 check = timeout - /* timeout time */
1460 Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
1461 if(check <= 0) {
1462 failf(data, "Proxy CONNECT aborted due to timeout");
1463 error = SELECT_TIMEOUT; /* already too little time */
1464 break;
1467 /* loop every second at least, less if the timeout is near */
1468 switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
1469 check<1000L?(int)check:1000)) {
1470 case -1: /* select() error, stop reading */
1471 error = SELECT_ERROR;
1472 failf(data, "Proxy CONNECT aborted due to select/poll error");
1473 break;
1474 case 0: /* timeout */
1475 break;
1476 default:
1477 DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
1478 res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
1479 if(res< 0)
1480 /* EWOULDBLOCK */
1481 continue; /* go loop yourself */
1482 else if(res)
1483 keepon = FALSE;
1484 else if(gotbytes <= 0) {
1485 keepon = FALSE;
1486 if(data->set.proxyauth && data->state.authproxy.avail) {
1487 /* proxy auth was requested and there was proxy auth available,
1488 then deem this as "mere" proxy disconnect */
1489 conn->bits.proxy_connect_closed = TRUE;
1491 else {
1492 error = SELECT_ERROR;
1493 failf(data, "Proxy CONNECT aborted");
1496 else {
1498 * We got a whole chunk of data, which can be anything from one
1499 * byte to a set of lines and possibly just a piece of the last
1500 * line.
1502 int i;
1504 nread += gotbytes;
1506 if(keepon > TRUE) {
1507 /* This means we are currently ignoring a response-body */
1509 nread = 0; /* make next read start over in the read buffer */
1510 ptr=data->state.buffer;
1511 if(cl) {
1512 /* A Content-Length based body: simply count down the counter
1513 and make sure to break out of the loop when we're done! */
1514 cl -= gotbytes;
1515 if(cl<=0) {
1516 keepon = FALSE;
1517 break;
1520 else {
1521 /* chunked-encoded body, so we need to do the chunked dance
1522 properly to know when the end of the body is reached */
1523 CHUNKcode r;
1524 ssize_t tookcareof=0;
1526 /* now parse the chunked piece of data so that we can
1527 properly tell when the stream ends */
1528 r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
1529 if(r == CHUNKE_STOP) {
1530 /* we're done reading chunks! */
1531 infof(data, "chunk reading DONE\n");
1532 keepon = FALSE;
1534 else
1535 infof(data, "Read %d bytes of chunk, continue\n",
1536 tookcareof);
1539 else
1540 for(i = 0; i < gotbytes; ptr++, i++) {
1541 perline++; /* amount of bytes in this line so far */
1542 if(*ptr=='\n') {
1543 char letter;
1544 int writetype;
1546 /* output debug if that is requested */
1547 if(data->set.verbose)
1548 Curl_debug(data, CURLINFO_HEADER_IN,
1549 line_start, (size_t)perline, conn);
1551 /* send the header to the callback */
1552 writetype = CLIENTWRITE_HEADER;
1553 if(data->set.include_header)
1554 writetype |= CLIENTWRITE_BODY;
1556 result = Curl_client_write(conn, writetype, line_start,
1557 perline);
1558 if(result)
1559 return result;
1561 /* Newlines are CRLF, so the CR is ignored as the line isn't
1562 really terminated until the LF comes. Treat a following CR
1563 as end-of-headers as well.*/
1565 if(('\r' == line_start[0]) ||
1566 ('\n' == line_start[0])) {
1567 /* end of response-headers from the proxy */
1568 nread = 0; /* make next read start over in the read
1569 buffer */
1570 ptr=data->state.buffer;
1571 if((407 == k->httpcode) && !data->state.authproblem) {
1572 /* If we get a 407 response code with content length
1573 when we have no auth problem, we must ignore the
1574 whole response-body */
1575 keepon = 2;
1577 if(cl) {
1579 infof(data, "Ignore %" FORMAT_OFF_T
1580 " bytes of response-body\n", cl);
1581 /* remove the remaining chunk of what we already
1582 read */
1583 cl -= (gotbytes - i);
1585 if(cl<=0)
1586 /* if the whole thing was already read, we are done!
1588 keepon=FALSE;
1590 else if(chunked_encoding) {
1591 CHUNKcode r;
1592 /* We set ignorebody true here since the chunked
1593 decoder function will acknowledge that. Pay
1594 attention so that this is cleared again when this
1595 function returns! */
1596 k->ignorebody = TRUE;
1597 infof(data, "%d bytes of chunk left\n", gotbytes-i);
1599 if(line_start[1] == '\n') {
1600 /* this can only be a LF if the letter at index 0
1601 was a CR */
1602 line_start++;
1603 i++;
1606 /* now parse the chunked piece of data so that we can
1607 properly tell when the stream ends */
1608 r = Curl_httpchunk_read(conn, line_start+1,
1609 gotbytes -i, &gotbytes);
1610 if(r == CHUNKE_STOP) {
1611 /* we're done reading chunks! */
1612 infof(data, "chunk reading DONE\n");
1613 keepon = FALSE;
1615 else
1616 infof(data, "Read %d bytes of chunk, continue\n",
1617 gotbytes);
1619 else {
1620 /* without content-length or chunked encoding, we
1621 can't keep the connection alive since the close is
1622 the end signal so we bail out at once instead */
1623 keepon=FALSE;
1626 else
1627 keepon = FALSE;
1628 break; /* breaks out of for-loop, not switch() */
1631 /* keep a backup of the position we are about to blank */
1632 letter = line_start[perline];
1633 line_start[perline]=0; /* zero terminate the buffer */
1634 if((checkprefix("WWW-Authenticate:", line_start) &&
1635 (401 == k->httpcode)) ||
1636 (checkprefix("Proxy-authenticate:", line_start) &&
1637 (407 == k->httpcode))) {
1638 result = Curl_http_input_auth(conn, k->httpcode,
1639 line_start);
1640 if(result)
1641 return result;
1643 else if(checkprefix("Content-Length:", line_start)) {
1644 cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
1645 NULL, 10);
1647 else if(Curl_compareheader(line_start,
1648 "Connection:", "close"))
1649 closeConnection = TRUE;
1650 else if(Curl_compareheader(line_start,
1651 "Transfer-Encoding:", "chunked")) {
1652 infof(data, "CONNECT responded chunked\n");
1653 chunked_encoding = TRUE;
1654 /* init our chunky engine */
1655 Curl_httpchunk_init(conn);
1657 else if(Curl_compareheader(line_start,
1658 "Proxy-Connection:", "close"))
1659 closeConnection = TRUE;
1660 else if(2 == sscanf(line_start, "HTTP/1.%d %d",
1661 &subversion,
1662 &k->httpcode)) {
1663 /* store the HTTP code from the proxy */
1664 data->info.httpproxycode = k->httpcode;
1666 /* put back the letter we blanked out before */
1667 line_start[perline]= letter;
1669 perline=0; /* line starts over here */
1670 line_start = ptr+1; /* this skips the zero byte we wrote */
1674 break;
1675 } /* switch */
1676 if(Curl_pgrsUpdate(conn))
1677 return CURLE_ABORTED_BY_CALLBACK;
1678 } /* while there's buffer left and loop is requested */
1680 if(error)
1681 return CURLE_RECV_ERROR;
1683 if(data->info.httpproxycode != 200) {
1684 /* Deal with the possibly already received authenticate
1685 headers. 'newurl' is set to a new URL if we must loop. */
1686 result = Curl_http_auth_act(conn);
1687 if(result)
1688 return result;
1690 if(conn->bits.close)
1691 /* the connection has been marked for closure, most likely in the
1692 Curl_http_auth_act() function and thus we can kill it at once
1693 below
1695 closeConnection = TRUE;
1698 if(closeConnection && data->req.newurl) {
1699 /* Connection closed by server. Don't use it anymore */
1700 sclose(conn->sock[sockindex]);
1701 conn->sock[sockindex] = CURL_SOCKET_BAD;
1702 break;
1704 } /* END NEGOTIATION PHASE */
1705 } while(data->req.newurl);
1707 if(200 != data->req.httpcode) {
1708 failf(data, "Received HTTP code %d from proxy after CONNECT",
1709 data->req.httpcode);
1711 if(closeConnection && data->req.newurl)
1712 conn->bits.proxy_connect_closed = TRUE;
1714 return CURLE_RECV_ERROR;
1717 /* If a proxy-authorization header was used for the proxy, then we should
1718 make sure that it isn't accidentally used for the document request
1719 after we've connected. So let's free and clear it here. */
1720 Curl_safefree(conn->allocptr.proxyuserpwd);
1721 conn->allocptr.proxyuserpwd = NULL;
1723 data->state.authproxy.done = TRUE;
1725 infof (data, "Proxy replied OK to CONNECT request\n");
1726 data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
1727 return CURLE_OK;
1731 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1732 * the generic Curl_connect().
1734 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
1736 struct SessionHandle *data;
1737 CURLcode result;
1739 data=conn->data;
1741 /* We default to persistent connections. We set this already in this connect
1742 function to make the re-use checks properly be able to check this bit. */
1743 conn->bits.close = FALSE;
1745 /* If we are not using a proxy and we want a secure connection, perform SSL
1746 * initialization & connection now. If using a proxy with https, then we
1747 * must tell the proxy to CONNECT to the host we want to talk to. Only
1748 * after the connect has occurred, can we start talking SSL
1751 if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
1753 /* either SSL over proxy, or explicitly asked for */
1754 result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
1755 conn->host.name,
1756 conn->remote_port);
1757 if(CURLE_OK != result)
1758 return result;
1761 if(conn->bits.tunnel_connecting) {
1762 /* nothing else to do except wait right now - we're not done here. */
1763 return CURLE_OK;
1766 if(!data->state.this_is_a_follow) {
1767 /* this is not a followed location, get the original host name */
1768 if(data->state.first_host)
1769 /* Free to avoid leaking memory on multiple requests*/
1770 free(data->state.first_host);
1772 data->state.first_host = strdup(conn->host.name);
1773 if(!data->state.first_host)
1774 return CURLE_OUT_OF_MEMORY;
1777 if(conn->protocol & PROT_HTTPS) {
1778 /* perform SSL initialization */
1779 if(data->state.used_interface == Curl_if_multi) {
1780 result = https_connecting(conn, done);
1781 if(result)
1782 return result;
1784 else {
1785 /* BLOCKING */
1786 result = Curl_ssl_connect(conn, FIRSTSOCKET);
1787 if(result)
1788 return result;
1789 *done = TRUE;
1792 else {
1793 *done = TRUE;
1796 return CURLE_OK;
1799 /* this returns the socket to wait for in the DO and DOING state for the multi
1800 interface and then we're always _sending_ a request and thus we wait for
1801 the single socket to become writable only */
1802 static int http_getsock_do(struct connectdata *conn,
1803 curl_socket_t *socks,
1804 int numsocks)
1806 /* write mode */
1807 (void)numsocks; /* unused, we trust it to be at least 1 */
1808 socks[0] = conn->sock[FIRSTSOCKET];
1809 return GETSOCK_WRITESOCK(0);
1812 static CURLcode https_connecting(struct connectdata *conn, bool *done)
1814 CURLcode result;
1815 DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS));
1817 /* perform SSL initialization for this socket */
1818 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
1819 if(result) {
1820 conn->bits.close = TRUE; /* a failed connection is marked for closure
1821 to prevent (bad) re-use or similar */
1822 return result;
1825 return CURLE_OK;
1828 #ifdef USE_SSLEAY
1829 /* This function is OpenSSL-specific. It should be made to query the generic
1830 SSL layer instead. */
1831 static int https_getsock(struct connectdata *conn,
1832 curl_socket_t *socks,
1833 int numsocks)
1835 if(conn->protocol & PROT_HTTPS) {
1836 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1838 if(!numsocks)
1839 return GETSOCK_BLANK;
1841 if(connssl->connecting_state == ssl_connect_2_writing) {
1842 /* write mode */
1843 socks[0] = conn->sock[FIRSTSOCKET];
1844 return GETSOCK_WRITESOCK(0);
1846 else if(connssl->connecting_state == ssl_connect_2_reading) {
1847 /* read mode */
1848 socks[0] = conn->sock[FIRSTSOCKET];
1849 return GETSOCK_READSOCK(0);
1852 return CURLE_OK;
1854 #else
1855 #ifdef USE_GNUTLS
1856 static int https_getsock(struct connectdata *conn,
1857 curl_socket_t *socks,
1858 int numsocks)
1860 (void)conn;
1861 (void)socks;
1862 (void)numsocks;
1863 return GETSOCK_BLANK;
1865 #else
1866 #ifdef USE_NSS
1867 static int https_getsock(struct connectdata *conn,
1868 curl_socket_t *socks,
1869 int numsocks)
1871 (void)conn;
1872 (void)socks;
1873 (void)numsocks;
1874 return GETSOCK_BLANK;
1876 #else
1877 #ifdef USE_QSOSSL
1878 static int https_getsock(struct connectdata *conn,
1879 curl_socket_t *socks,
1880 int numsocks)
1882 (void)conn;
1883 (void)socks;
1884 (void)numsocks;
1885 return GETSOCK_BLANK;
1887 #endif
1888 #endif
1889 #endif
1890 #endif
1893 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1894 * has been performed.
1897 CURLcode Curl_http_done(struct connectdata *conn,
1898 CURLcode status, bool premature)
1900 struct SessionHandle *data = conn->data;
1901 struct HTTP *http =data->state.proto.http;
1902 (void)premature; /* not used */
1904 /* set the proper values (possibly modified on POST) */
1905 conn->fread_func = data->set.fread_func; /* restore */
1906 conn->fread_in = data->set.in; /* restore */
1907 conn->seek_func = data->set.seek_func; /* restore */
1908 conn->seek_client = data->set.seek_client; /* restore */
1910 if(http == NULL)
1911 return CURLE_OK;
1913 if(http->send_buffer) {
1914 send_buffer *buff = http->send_buffer;
1916 free(buff->buffer);
1917 free(buff);
1918 http->send_buffer = NULL; /* clear the pointer */
1921 if(HTTPREQ_POST_FORM == data->set.httpreq) {
1922 data->req.bytecount = http->readbytecount + http->writebytecount;
1924 Curl_formclean(&http->sendit); /* Now free that whole lot */
1925 if(http->form.fp) {
1926 /* a file being uploaded was left opened, close it! */
1927 fclose(http->form.fp);
1928 http->form.fp = NULL;
1931 else if(HTTPREQ_PUT == data->set.httpreq)
1932 data->req.bytecount = http->readbytecount + http->writebytecount;
1934 if(status != CURLE_OK)
1935 return (status);
1937 if(!premature && /* this check is pointless when DONE is called before the
1938 entire operation is complete */
1939 !conn->bits.retry &&
1940 ((http->readbytecount +
1941 data->req.headerbytecount -
1942 data->req.deductheadercount)) <= 0) {
1943 /* If this connection isn't simply closed to be retried, AND nothing was
1944 read from the HTTP server (that counts), this can't be right so we
1945 return an error here */
1946 failf(data, "Empty reply from server");
1947 return CURLE_GOT_NOTHING;
1950 return CURLE_OK;
1953 /* check and possibly add an Expect: header */
1954 static CURLcode expect100(struct SessionHandle *data,
1955 send_buffer *req_buffer)
1957 CURLcode result = CURLE_OK;
1958 data->state.expect100header = FALSE; /* default to false unless it is set
1959 to TRUE below */
1960 if((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
1961 !checkheaders(data, "Expect:")) {
1962 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1963 100-continue to the headers which actually speeds up post
1964 operations (as there is one packet coming back from the web
1965 server) */
1966 result = add_bufferf(req_buffer,
1967 "Expect: 100-continue\r\n");
1968 if(result == CURLE_OK)
1969 data->state.expect100header = TRUE;
1971 return result;
1974 static CURLcode add_custom_headers(struct connectdata *conn,
1975 send_buffer *req_buffer)
1977 char *ptr;
1978 struct curl_slist *headers=conn->data->set.headers;
1980 while(headers) {
1981 ptr = strchr(headers->data, ':');
1982 if(ptr) {
1983 /* we require a colon for this to be a true header */
1985 ptr++; /* pass the colon */
1986 while(*ptr && ISSPACE(*ptr))
1987 ptr++;
1989 if(*ptr) {
1990 /* only send this if the contents was non-blank */
1992 if(conn->allocptr.host &&
1993 /* a Host: header was sent already, don't pass on any custom Host:
1994 header as that will produce *two* in the same request! */
1995 curl_strnequal("Host:", headers->data, 5))
1997 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
1998 /* this header (extended by formdata.c) is sent later */
1999 curl_strnequal("Content-Type:", headers->data,
2000 strlen("Content-Type:")))
2002 else {
2003 CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data);
2004 if(result)
2005 return result;
2009 headers = headers->next;
2011 return CURLE_OK;
2015 * Curl_http() gets called from the generic Curl_do() function when a HTTP
2016 * request is to be performed. This creates and sends a properly constructed
2017 * HTTP request.
2019 CURLcode Curl_http(struct connectdata *conn, bool *done)
2021 struct SessionHandle *data=conn->data;
2022 char *buf = data->state.buffer; /* this is a short cut to the buffer */
2023 CURLcode result=CURLE_OK;
2024 struct HTTP *http;
2025 char *ppath = data->state.path;
2026 char ftp_typecode[sizeof(";type=?")] = "";
2027 char *host = conn->host.name;
2028 const char *te = ""; /* transfer-encoding */
2029 char *ptr;
2030 char *request;
2031 Curl_HttpReq httpreq = data->set.httpreq;
2032 char *addcookies = NULL;
2033 curl_off_t included_body = 0;
2034 const char *httpstring;
2035 send_buffer *req_buffer;
2036 curl_off_t postsize; /* off_t type to be able to hold a large file size */
2039 /* Always consider the DO phase done after this function call, even if there
2040 may be parts of the request that is not yet sent, since we can deal with
2041 the rest of the request in the PERFORM phase. */
2042 *done = TRUE;
2044 /* If there already is a protocol-specific struct allocated for this
2045 sessionhandle, deal with it */
2046 Curl_reset_reqproto(conn);
2048 if(!data->state.proto.http) {
2049 /* Only allocate this struct if we don't already have it! */
2051 http = (struct HTTP *)calloc(sizeof(struct HTTP), 1);
2052 if(!http)
2053 return CURLE_OUT_OF_MEMORY;
2054 data->state.proto.http = http;
2056 else
2057 http = data->state.proto.http;
2059 if( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
2060 data->set.upload) {
2061 httpreq = HTTPREQ_PUT;
2064 /* Now set the 'request' pointer to the proper request string */
2065 if(data->set.str[STRING_CUSTOMREQUEST])
2066 request = data->set.str[STRING_CUSTOMREQUEST];
2067 else {
2068 if(data->set.opt_no_body)
2069 request = (char *)"HEAD";
2070 else {
2071 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
2072 switch(httpreq) {
2073 case HTTPREQ_POST:
2074 case HTTPREQ_POST_FORM:
2075 request = (char *)"POST";
2076 break;
2077 case HTTPREQ_PUT:
2078 request = (char *)"PUT";
2079 break;
2080 default: /* this should never happen */
2081 case HTTPREQ_GET:
2082 request = (char *)"GET";
2083 break;
2084 case HTTPREQ_HEAD:
2085 request = (char *)"HEAD";
2086 break;
2091 /* The User-Agent string might have been allocated in url.c already, because
2092 it might have been used in the proxy connect, but if we have got a header
2093 with the user-agent string specified, we erase the previously made string
2094 here. */
2095 if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
2096 free(conn->allocptr.uagent);
2097 conn->allocptr.uagent=NULL;
2100 /* setup the authentication headers */
2101 result = http_output_auth(conn, request, ppath, FALSE);
2102 if(result)
2103 return result;
2105 if((data->state.authhost.multi || data->state.authproxy.multi) &&
2106 (httpreq != HTTPREQ_GET) &&
2107 (httpreq != HTTPREQ_HEAD)) {
2108 /* Auth is required and we are not authenticated yet. Make a PUT or POST
2109 with content-length zero as a "probe". */
2110 conn->bits.authneg = TRUE;
2112 else
2113 conn->bits.authneg = FALSE;
2115 Curl_safefree(conn->allocptr.ref);
2116 if(data->change.referer && !checkheaders(data, "Referer:"))
2117 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
2118 else
2119 conn->allocptr.ref = NULL;
2121 if(data->set.str[STRING_COOKIE] && !checkheaders(data, "Cookie:"))
2122 addcookies = data->set.str[STRING_COOKIE];
2124 if(!checkheaders(data, "Accept-Encoding:") &&
2125 data->set.str[STRING_ENCODING]) {
2126 Curl_safefree(conn->allocptr.accept_encoding);
2127 conn->allocptr.accept_encoding =
2128 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
2129 if(!conn->allocptr.accept_encoding)
2130 return CURLE_OUT_OF_MEMORY;
2133 ptr = checkheaders(data, "Transfer-Encoding:");
2134 if(ptr) {
2135 /* Some kind of TE is requested, check if 'chunked' is chosen */
2136 data->req.upload_chunky =
2137 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
2139 else {
2140 if((conn->protocol&PROT_HTTP) &&
2141 data->set.upload &&
2142 (data->set.infilesize == -1) &&
2143 (data->set.httpversion != CURL_HTTP_VERSION_1_0)) {
2144 /* HTTP, upload, unknown file size and not HTTP 1.0 */
2145 data->req.upload_chunky = TRUE;
2147 else {
2148 /* else, no chunky upload */
2149 data->req.upload_chunky = FALSE;
2152 if(data->req.upload_chunky)
2153 te = "Transfer-Encoding: chunked\r\n";
2156 Curl_safefree(conn->allocptr.host);
2158 ptr = checkheaders(data, "Host:");
2159 if(ptr && (!data->state.this_is_a_follow ||
2160 curl_strequal(data->state.first_host, conn->host.name))) {
2161 #if !defined(CURL_DISABLE_COOKIES)
2162 /* If we have a given custom Host: header, we extract the host name in
2163 order to possibly use it for cookie reasons later on. We only allow the
2164 custom Host: header if this is NOT a redirect, as setting Host: in the
2165 redirected request is being out on thin ice. Except if the host name
2166 is the same as the first one! */
2167 char *cookiehost = Curl_copy_header_value(ptr);
2168 if (!cookiehost)
2169 return CURLE_OUT_OF_MEMORY;
2170 if (!*cookiehost)
2171 /* ignore empty data */
2172 free(cookiehost);
2173 else {
2174 char *colon = strchr(cookiehost, ':');
2175 if (colon)
2176 *colon = 0; /* The host must not include an embedded port number */
2177 Curl_safefree(conn->allocptr.cookiehost);
2178 conn->allocptr.cookiehost = cookiehost;
2180 #endif
2182 conn->allocptr.host = NULL;
2184 else {
2185 /* When building Host: headers, we must put the host name within
2186 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
2188 if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
2189 (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
2190 /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
2191 the port number in the host string */
2192 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2193 conn->bits.ipv6_ip?"[":"",
2194 host,
2195 conn->bits.ipv6_ip?"]":"");
2196 else
2197 conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
2198 conn->bits.ipv6_ip?"[":"",
2199 host,
2200 conn->bits.ipv6_ip?"]":"",
2201 conn->remote_port);
2203 if(!conn->allocptr.host)
2204 /* without Host: we can't make a nice request */
2205 return CURLE_OUT_OF_MEMORY;
2208 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2209 /* Using a proxy but does not tunnel through it */
2211 /* The path sent to the proxy is in fact the entire URL. But if the remote
2212 host is a IDN-name, we must make sure that the request we produce only
2213 uses the encoded host name! */
2214 if(conn->host.dispname != conn->host.name) {
2215 char *url = data->change.url;
2216 ptr = strstr(url, conn->host.dispname);
2217 if(ptr) {
2218 /* This is where the display name starts in the URL, now replace this
2219 part with the encoded name. TODO: This method of replacing the host
2220 name is rather crude as I believe there's a slight risk that the
2221 user has entered a user name or password that contain the host name
2222 string. */
2223 size_t currlen = strlen(conn->host.dispname);
2224 size_t newlen = strlen(conn->host.name);
2225 size_t urllen = strlen(url);
2227 char *newurl;
2229 newurl = malloc(urllen + newlen - currlen + 1);
2230 if(newurl) {
2231 /* copy the part before the host name */
2232 memcpy(newurl, url, ptr - url);
2233 /* append the new host name instead of the old */
2234 memcpy(newurl + (ptr - url), conn->host.name, newlen);
2235 /* append the piece after the host name */
2236 memcpy(newurl + newlen + (ptr - url),
2237 ptr + currlen, /* copy the trailing zero byte too */
2238 urllen - (ptr-url) - currlen + 1);
2239 if(data->change.url_alloc)
2240 free(data->change.url);
2241 data->change.url = newurl;
2242 data->change.url_alloc = TRUE;
2244 else
2245 return CURLE_OUT_OF_MEMORY;
2248 ppath = data->change.url;
2249 if (data->set.proxy_transfer_mode) {
2250 /* when doing ftp, append ;type=<a|i> if not present */
2251 if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
2252 char *p = strstr(ppath, ";type=");
2253 if(p && p[6] && p[7] == 0) {
2254 switch (toupper((int)((unsigned char)p[6]))) {
2255 case 'A':
2256 case 'D':
2257 case 'I':
2258 break;
2259 default:
2260 p = NULL;
2263 if(!p)
2264 snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c",
2265 data->set.prefer_ascii ? 'a' : 'i');
2269 if(HTTPREQ_POST_FORM == httpreq) {
2270 /* we must build the whole darned post sequence first, so that we have
2271 a size of the whole shebang before we start to send it */
2272 result = Curl_getFormData(&http->sendit, data->set.httppost,
2273 checkheaders(data, "Content-Type:"),
2274 &http->postsize);
2275 if(CURLE_OK != result) {
2276 /* Curl_getFormData() doesn't use failf() */
2277 failf(data, "failed creating formpost data");
2278 return result;
2283 http->p_pragma =
2284 (!checkheaders(data, "Pragma:") &&
2285 (conn->bits.httpproxy && !conn->bits.tunnel_proxy) )?
2286 "Pragma: no-cache\r\n":NULL;
2288 http->p_accept = checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
2290 if(( (HTTPREQ_POST == httpreq) ||
2291 (HTTPREQ_POST_FORM == httpreq) ||
2292 (HTTPREQ_PUT == httpreq) ) &&
2293 data->state.resume_from) {
2294 /**********************************************************************
2295 * Resuming upload in HTTP means that we PUT or POST and that we have
2296 * got a resume_from value set. The resume value has already created
2297 * a Range: header that will be passed along. We need to "fast forward"
2298 * the file the given number of bytes and decrease the assume upload
2299 * file size before we continue this venture in the dark lands of HTTP.
2300 *********************************************************************/
2302 if(data->state.resume_from < 0 ) {
2304 * This is meant to get the size of the present remote-file by itself.
2305 * We don't support this now. Bail out!
2307 data->state.resume_from = 0;
2310 if(data->state.resume_from && !data->state.this_is_a_follow) {
2311 /* do we still game? */
2313 /* Now, let's read off the proper amount of bytes from the
2314 input. */
2315 if(conn->seek_func) {
2316 curl_off_t readthisamountnow = data->state.resume_from;
2318 if(conn->seek_func(conn->seek_client,
2319 readthisamountnow, SEEK_SET) != 0) {
2320 failf(data, "Could not seek stream");
2321 return CURLE_READ_ERROR;
2324 else {
2325 curl_off_t passed=0;
2327 do {
2328 size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
2329 size_t actuallyread;
2331 if(readthisamountnow > BUFSIZE)
2332 readthisamountnow = BUFSIZE;
2334 actuallyread = data->set.fread_func(data->state.buffer, 1,
2335 (size_t)readthisamountnow,
2336 data->set.in);
2338 passed += actuallyread;
2339 if(actuallyread != readthisamountnow) {
2340 failf(data, "Could only read %" FORMAT_OFF_T
2341 " bytes from the input",
2342 passed);
2343 return CURLE_READ_ERROR;
2345 } while(passed != data->state.resume_from); /* loop until done */
2348 /* now, decrease the size of the read */
2349 if(data->set.infilesize>0) {
2350 data->set.infilesize -= data->state.resume_from;
2352 if(data->set.infilesize <= 0) {
2353 failf(data, "File already completely uploaded");
2354 return CURLE_PARTIAL_FILE;
2357 /* we've passed, proceed as normal */
2360 if(data->state.use_range) {
2362 * A range is selected. We use different headers whether we're downloading
2363 * or uploading and we always let customized headers override our internal
2364 * ones if any such are specified.
2366 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2367 !checkheaders(data, "Range:")) {
2368 /* if a line like this was already allocated, free the previous one */
2369 if(conn->allocptr.rangeline)
2370 free(conn->allocptr.rangeline);
2371 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2372 data->state.range);
2374 else if((httpreq != HTTPREQ_GET) &&
2375 !checkheaders(data, "Content-Range:")) {
2377 /* if a line like this was already allocated, free the previous one */
2378 if(conn->allocptr.rangeline)
2379 free(conn->allocptr.rangeline);
2381 if(data->set.set_resume_from < 0) {
2382 /* Upload resume was asked for, but we don't know the size of the
2383 remote part so we tell the server (and act accordingly) that we
2384 upload the whole file (again) */
2385 conn->allocptr.rangeline =
2386 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T
2387 "/%" FORMAT_OFF_T "\r\n",
2388 data->set.infilesize - 1, data->set.infilesize);
2391 else if(data->state.resume_from) {
2392 /* This is because "resume" was selected */
2393 curl_off_t total_expected_size=
2394 data->state.resume_from + data->set.infilesize;
2395 conn->allocptr.rangeline =
2396 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2397 "/%" FORMAT_OFF_T "\r\n",
2398 data->state.range, total_expected_size-1,
2399 total_expected_size);
2401 else {
2402 /* Range was selected and then we just pass the incoming range and
2403 append total size */
2404 conn->allocptr.rangeline =
2405 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2406 data->state.range, data->set.infilesize);
2408 if(!conn->allocptr.rangeline)
2409 return CURLE_OUT_OF_MEMORY;
2413 /* Use 1.1 unless the use specificly asked for 1.0 */
2414 httpstring= data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1";
2416 /* initialize a dynamic send-buffer */
2417 req_buffer = add_buffer_init();
2419 if(!req_buffer)
2420 return CURLE_OUT_OF_MEMORY;
2422 /* add the main request stuff */
2423 result =
2424 add_bufferf(req_buffer,
2425 "%s " /* GET/HEAD/POST/PUT */
2426 "%s%s HTTP/%s\r\n" /* path + HTTP version */
2427 "%s" /* proxyuserpwd */
2428 "%s" /* userpwd */
2429 "%s" /* range */
2430 "%s" /* user agent */
2431 "%s" /* host */
2432 "%s" /* pragma */
2433 "%s" /* accept */
2434 "%s" /* accept-encoding */
2435 "%s" /* referer */
2436 "%s" /* Proxy-Connection */
2437 "%s",/* transfer-encoding */
2439 request,
2440 ppath,
2441 ftp_typecode,
2442 httpstring,
2443 conn->allocptr.proxyuserpwd?
2444 conn->allocptr.proxyuserpwd:"",
2445 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2446 (data->state.use_range && conn->allocptr.rangeline)?
2447 conn->allocptr.rangeline:"",
2448 (data->set.str[STRING_USERAGENT] &&
2449 *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
2450 conn->allocptr.uagent:"",
2451 (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
2452 http->p_pragma?http->p_pragma:"",
2453 http->p_accept?http->p_accept:"",
2454 (data->set.str[STRING_ENCODING] &&
2455 *data->set.str[STRING_ENCODING] &&
2456 conn->allocptr.accept_encoding)?
2457 conn->allocptr.accept_encoding:"",
2458 (data->change.referer && conn->allocptr.ref)?
2459 conn->allocptr.ref:"" /* Referer: <data> */,
2460 (conn->bits.httpproxy &&
2461 !conn->bits.tunnel_proxy &&
2462 !checkheaders(data, "Proxy-Connection:"))?
2463 "Proxy-Connection: Keep-Alive\r\n":"",
2468 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
2469 * with basic and digest, it will be freed anyway by the next request
2472 Curl_safefree (conn->allocptr.userpwd);
2473 conn->allocptr.userpwd = NULL;
2475 if(result)
2476 return result;
2478 #if !defined(CURL_DISABLE_COOKIES)
2479 if(data->cookies || addcookies) {
2480 struct Cookie *co=NULL; /* no cookies from start */
2481 int count=0;
2483 if(data->cookies) {
2484 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2485 co = Curl_cookie_getlist(data->cookies,
2486 conn->allocptr.cookiehost?
2487 conn->allocptr.cookiehost:host,
2488 data->state.path,
2489 (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
2490 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2492 if(co) {
2493 struct Cookie *store=co;
2494 /* now loop through all cookies that matched */
2495 while(co) {
2496 if(co->value) {
2497 if(0 == count) {
2498 result = add_bufferf(req_buffer, "Cookie: ");
2499 if(result)
2500 break;
2502 result = add_bufferf(req_buffer,
2503 "%s%s=%s", count?"; ":"",
2504 co->name, co->value);
2505 if(result)
2506 break;
2507 count++;
2509 co = co->next; /* next cookie please */
2511 Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2513 if(addcookies && (CURLE_OK == result)) {
2514 if(!count)
2515 result = add_bufferf(req_buffer, "Cookie: ");
2516 if(CURLE_OK == result) {
2517 result = add_bufferf(req_buffer, "%s%s",
2518 count?"; ":"",
2519 addcookies);
2520 count++;
2523 if(count && (CURLE_OK == result))
2524 result = add_buffer(req_buffer, "\r\n", 2);
2526 if(result)
2527 return result;
2529 #endif
2531 if(data->set.timecondition) {
2532 struct tm *tm;
2534 /* The If-Modified-Since header family should have their times set in
2535 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
2536 * represented in Greenwich Mean Time (GMT), without exception. For the
2537 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
2538 * Time)." (see page 20 of RFC2616).
2541 #ifdef HAVE_GMTIME_R
2542 /* thread-safe version */
2543 struct tm keeptime;
2544 tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
2545 #else
2546 tm = gmtime(&data->set.timevalue);
2547 #endif
2549 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
2550 snprintf(buf, BUFSIZE-1,
2551 "%s, %02d %s %4d %02d:%02d:%02d GMT",
2552 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
2553 tm->tm_mday,
2554 Curl_month[tm->tm_mon],
2555 tm->tm_year + 1900,
2556 tm->tm_hour,
2557 tm->tm_min,
2558 tm->tm_sec);
2560 switch(data->set.timecondition) {
2561 case CURL_TIMECOND_IFMODSINCE:
2562 default:
2563 result = add_bufferf(req_buffer,
2564 "If-Modified-Since: %s\r\n", buf);
2565 break;
2566 case CURL_TIMECOND_IFUNMODSINCE:
2567 result = add_bufferf(req_buffer,
2568 "If-Unmodified-Since: %s\r\n", buf);
2569 break;
2570 case CURL_TIMECOND_LASTMOD:
2571 result = add_bufferf(req_buffer,
2572 "Last-Modified: %s\r\n", buf);
2573 break;
2575 if(result)
2576 return result;
2579 result = add_custom_headers(conn, req_buffer);
2580 if(result)
2581 return result;
2583 http->postdata = NULL; /* nothing to post at this point */
2584 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
2586 /* If 'authdone' is FALSE, we must not set the write socket index to the
2587 Curl_transfer() call below, as we're not ready to actually upload any
2588 data yet. */
2590 switch(httpreq) {
2592 case HTTPREQ_POST_FORM:
2593 if(!http->sendit || conn->bits.authneg) {
2594 /* nothing to post! */
2595 result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
2596 if(result)
2597 return result;
2599 result = add_buffer_send(req_buffer, conn,
2600 &data->info.request_size, 0, FIRSTSOCKET);
2601 if(result)
2602 failf(data, "Failed sending POST request");
2603 else
2604 /* setup variables for the upcoming transfer */
2605 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2606 &http->readbytecount,
2607 -1, NULL);
2608 break;
2611 if(Curl_FormInit(&http->form, http->sendit)) {
2612 failf(data, "Internal HTTP POST error!");
2613 return CURLE_HTTP_POST_ERROR;
2616 /* Get the currently set callback function pointer and store that in the
2617 form struct since we might want the actual user-provided callback later
2618 on. The conn->fread_func pointer itself will be changed for the
2619 multipart case to the function that returns a multipart formatted
2620 stream. */
2621 http->form.fread_func = conn->fread_func;
2623 /* Set the read function to read from the generated form data */
2624 conn->fread_func = (curl_read_callback)Curl_FormReader;
2625 conn->fread_in = &http->form;
2627 http->sending = HTTPSEND_BODY;
2629 if(!data->req.upload_chunky) {
2630 /* only add Content-Length if not uploading chunked */
2631 result = add_bufferf(req_buffer,
2632 "Content-Length: %" FORMAT_OFF_T "\r\n",
2633 http->postsize);
2634 if(result)
2635 return result;
2638 result = expect100(data, req_buffer);
2639 if(result)
2640 return result;
2644 /* Get Content-Type: line from Curl_formpostheader.
2646 char *contentType;
2647 size_t linelength=0;
2648 contentType = Curl_formpostheader((void *)&http->form,
2649 &linelength);
2650 if(!contentType) {
2651 failf(data, "Could not get Content-Type header line!");
2652 return CURLE_HTTP_POST_ERROR;
2655 result = add_buffer(req_buffer, contentType, linelength);
2656 if(result)
2657 return result;
2660 /* make the request end in a true CRLF */
2661 result = add_buffer(req_buffer, "\r\n", 2);
2662 if(result)
2663 return result;
2665 /* set upload size to the progress meter */
2666 Curl_pgrsSetUploadSize(data, http->postsize);
2668 /* fire away the whole request to the server */
2669 result = add_buffer_send(req_buffer, conn,
2670 &data->info.request_size, 0, FIRSTSOCKET);
2671 if(result)
2672 failf(data, "Failed sending POST request");
2673 else
2674 /* setup variables for the upcoming transfer */
2675 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2676 &http->readbytecount,
2677 FIRSTSOCKET,
2678 &http->writebytecount);
2680 if(result) {
2681 Curl_formclean(&http->sendit); /* free that whole lot */
2682 return result;
2684 #ifdef CURL_DOES_CONVERSIONS
2685 /* time to convert the form data... */
2686 result = Curl_formconvert(data, http->sendit);
2687 if(result) {
2688 Curl_formclean(&http->sendit); /* free that whole lot */
2689 return result;
2691 #endif /* CURL_DOES_CONVERSIONS */
2692 break;
2694 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2696 if(conn->bits.authneg)
2697 postsize = 0;
2698 else
2699 postsize = data->set.infilesize;
2701 if((postsize != -1) && !data->req.upload_chunky) {
2702 /* only add Content-Length if not uploading chunked */
2703 result = add_bufferf(req_buffer,
2704 "Content-Length: %" FORMAT_OFF_T "\r\n",
2705 postsize );
2706 if(result)
2707 return result;
2710 result = expect100(data, req_buffer);
2711 if(result)
2712 return result;
2714 result = add_buffer(req_buffer, "\r\n", 2); /* end of headers */
2715 if(result)
2716 return result;
2718 /* set the upload size to the progress meter */
2719 Curl_pgrsSetUploadSize(data, postsize);
2721 /* this sends the buffer and frees all the buffer resources */
2722 result = add_buffer_send(req_buffer, conn,
2723 &data->info.request_size, 0, FIRSTSOCKET);
2724 if(result)
2725 failf(data, "Failed sending PUT request");
2726 else
2727 /* prepare for transfer */
2728 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2729 &http->readbytecount,
2730 postsize?FIRSTSOCKET:-1,
2731 postsize?&http->writebytecount:NULL);
2732 if(result)
2733 return result;
2734 break;
2736 case HTTPREQ_POST:
2737 /* this is the simple POST, using x-www-form-urlencoded style */
2739 if(conn->bits.authneg)
2740 postsize = 0;
2741 else
2742 /* figure out the size of the postfields */
2743 postsize = (data->set.postfieldsize != -1)?
2744 data->set.postfieldsize:
2745 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
2747 if(!data->req.upload_chunky) {
2748 /* We only set Content-Length and allow a custom Content-Length if
2749 we don't upload data chunked, as RFC2616 forbids us to set both
2750 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2752 if(!checkheaders(data, "Content-Length:")) {
2753 /* we allow replacing this header, although it isn't very wise to
2754 actually set your own */
2755 result = add_bufferf(req_buffer,
2756 "Content-Length: %" FORMAT_OFF_T"\r\n",
2757 postsize);
2758 if(result)
2759 return result;
2763 if(!checkheaders(data, "Content-Type:")) {
2764 result = add_bufferf(req_buffer,
2765 "Content-Type: application/x-www-form-urlencoded\r\n");
2766 if(result)
2767 return result;
2770 /* For really small posts we don't use Expect: headers at all, and for
2771 the somewhat bigger ones we allow the app to disable it. Just make
2772 sure that the expect100header is always set to the preferred value
2773 here. */
2774 if(postsize > TINY_INITIAL_POST_SIZE) {
2775 result = expect100(data, req_buffer);
2776 if(result)
2777 return result;
2779 else
2780 data->state.expect100header = FALSE;
2782 if(data->set.postfields) {
2784 if(!data->state.expect100header &&
2785 (postsize < MAX_INITIAL_POST_SIZE)) {
2786 /* if we don't use expect: 100 AND
2787 postsize is less than MAX_INITIAL_POST_SIZE
2789 then append the post data to the HTTP request header. This limit
2790 is no magic limit but only set to prevent really huge POSTs to
2791 get the data duplicated with malloc() and family. */
2793 result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2794 if(result)
2795 return result;
2797 if(!data->req.upload_chunky) {
2798 /* We're not sending it 'chunked', append it to the request
2799 already now to reduce the number if send() calls */
2800 result = add_buffer(req_buffer, data->set.postfields,
2801 (size_t)postsize);
2802 included_body = postsize;
2804 else {
2805 /* Append the POST data chunky-style */
2806 result = add_bufferf(req_buffer, "%x\r\n", (int)postsize);
2807 if(CURLE_OK == result)
2808 result = add_buffer(req_buffer, data->set.postfields,
2809 (size_t)postsize);
2810 if(CURLE_OK == result)
2811 result = add_buffer(req_buffer,
2812 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2813 /* CR LF 0 CR LF CR LF */
2814 included_body = postsize + 7;
2816 if(result)
2817 return result;
2819 else {
2820 /* A huge POST coming up, do data separate from the request */
2821 http->postsize = postsize;
2822 http->postdata = data->set.postfields;
2824 http->sending = HTTPSEND_BODY;
2826 conn->fread_func = (curl_read_callback)readmoredata;
2827 conn->fread_in = (void *)conn;
2829 /* set the upload size to the progress meter */
2830 Curl_pgrsSetUploadSize(data, http->postsize);
2832 result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2833 if(result)
2834 return result;
2837 else {
2838 result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
2839 if(result)
2840 return result;
2842 if(data->set.postfieldsize) {
2843 /* set the upload size to the progress meter */
2844 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2846 /* set the pointer to mark that we will send the post body using the
2847 read callback, but only if we're not in authenticate
2848 negotiation */
2849 if(!conn->bits.authneg) {
2850 http->postdata = (char *)&http->postdata;
2851 http->postsize = postsize;
2855 /* issue the request */
2856 result = add_buffer_send(req_buffer, conn, &data->info.request_size,
2857 (size_t)included_body, FIRSTSOCKET);
2859 if(result)
2860 failf(data, "Failed sending HTTP POST request");
2861 else
2862 result =
2863 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2864 &http->readbytecount,
2865 http->postdata?FIRSTSOCKET:-1,
2866 http->postdata?&http->writebytecount:NULL);
2867 break;
2869 default:
2870 result = add_buffer(req_buffer, "\r\n", 2);
2871 if(result)
2872 return result;
2874 /* issue the request */
2875 result = add_buffer_send(req_buffer, conn,
2876 &data->info.request_size, 0, FIRSTSOCKET);
2878 if(result)
2879 failf(data, "Failed sending HTTP request");
2880 else
2881 /* HTTP GET/HEAD download: */
2882 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
2883 &http->readbytecount,
2884 http->postdata?FIRSTSOCKET:-1,
2885 http->postdata?&http->writebytecount:NULL);
2887 if(result)
2888 return result;
2890 if(http->writebytecount) {
2891 /* if a request-body has been sent off, we make sure this progress is noted
2892 properly */
2893 Curl_pgrsSetUploadCounter(data, http->writebytecount);
2894 if(Curl_pgrsUpdate(conn))
2895 result = CURLE_ABORTED_BY_CALLBACK;
2898 return result;
2900 #endif