1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, 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.2 2007/03/15 19:22:13 andy Exp $
22 ***************************************************************************/
26 #ifndef CURL_DISABLE_HTTP
27 /* -- WIN32 approved -- */
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
36 #ifdef HAVE_SYS_STAT_H
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
47 #ifdef HAVE_NETINET_IN_H
48 #include <netinet/in.h>
50 #ifdef HAVE_SYS_TIME_H
55 #ifdef TIME_WITH_SYS_TIME
64 #ifdef HAVE_ARPA_INET_H
65 #include <arpa/inet.h>
70 #include <sys/ioctl.h>
73 #ifdef HAVE_SYS_PARAM_H
74 #include <sys/param.h>
80 #include <curl/curl.h>
83 #include "easyif.h" /* for Curl_convert_... prototypes */
90 #include "http_digest.h"
91 #include "http_ntlm.h"
92 #include "http_negotiate.h"
99 #include "parsedate.h" /* for the week day and month names */
100 #include "strtoofft.h"
103 #define _MPRINTF_REPLACE /* use our functions only */
104 #include <curl/mprintf.h>
106 /* The last #include file should be: */
107 #include "memdebug.h"
110 * checkheaders() checks the linked list of custom HTTP headers for a
111 * particular header (prefix).
113 * Returns a pointer to the first matching header or NULL if none matched.
115 static char *checkheaders(struct SessionHandle
*data
, const char *thisheader
)
117 struct curl_slist
*head
;
118 size_t thislen
= strlen(thisheader
);
120 for(head
= data
->set
.headers
; head
; head
=head
->next
) {
121 if(strnequal(head
->data
, thisheader
, thislen
))
128 * Curl_output_basic() sets up an Authorization: header (or the proxy version)
129 * for HTTP Basic authentication.
133 static CURLcode
Curl_output_basic(struct connectdata
*conn
, bool proxy
)
136 struct SessionHandle
*data
=conn
->data
;
142 userp
= &conn
->allocptr
.proxyuserpwd
;
143 user
= conn
->proxyuser
;
144 pwd
= conn
->proxypasswd
;
147 userp
= &conn
->allocptr
.userpwd
;
152 snprintf(data
->state
.buffer
, sizeof(data
->state
.buffer
), "%s:%s", user
, pwd
);
153 if(Curl_base64_encode(data
, data
->state
.buffer
,
154 strlen(data
->state
.buffer
),
155 &authorization
) > 0) {
158 *userp
= aprintf( "%sAuthorization: Basic %s\r\n",
164 return CURLE_OUT_OF_MEMORY
;
168 /* pickoneauth() selects the most favourable authentication method from the
169 * ones available and the ones we want.
171 * return TRUE if one was picked
173 static bool pickoneauth(struct auth
*pick
)
176 /* only deal with authentication we want */
177 long avail
= pick
->avail
& pick
->want
;
180 /* The order of these checks is highly relevant, as this will be the order
181 of preference in case of the existance of multiple accepted types. */
182 if(avail
& CURLAUTH_GSSNEGOTIATE
)
183 pick
->picked
= CURLAUTH_GSSNEGOTIATE
;
184 else if(avail
& CURLAUTH_DIGEST
)
185 pick
->picked
= CURLAUTH_DIGEST
;
186 else if(avail
& CURLAUTH_NTLM
)
187 pick
->picked
= CURLAUTH_NTLM
;
188 else if(avail
& CURLAUTH_BASIC
)
189 pick
->picked
= CURLAUTH_BASIC
;
191 pick
->picked
= CURLAUTH_PICKNONE
; /* we select to use nothing */
194 pick
->avail
= CURLAUTH_NONE
; /* clear it here */
202 * If we are doing POST or PUT {
203 * If we have more data to send {
204 * If we are doing NTLM {
205 * Keep sending since we must not disconnect
208 * If there is more than just a little data left to send, close
209 * the current connection by force.
212 * If we have sent any data {
213 * If we don't have track of all the data {
214 * call app to tell it to rewind
217 * rewind internally so that the operation can restart fine
222 static CURLcode
perhapsrewind(struct connectdata
*conn
)
224 struct SessionHandle
*data
= conn
->data
;
225 struct HTTP
*http
= data
->reqdata
.proto
.http
;
226 struct Curl_transfer_keeper
*k
= &data
->reqdata
.keep
;
227 curl_off_t bytessent
;
228 curl_off_t expectsend
= -1; /* default is unknown */
231 /* If this is still NULL, we have not reach very far and we can
232 safely skip this rewinding stuff */
235 bytessent
= http
->writebytecount
;
237 if(conn
->bits
.authneg
)
238 /* This is a state where we are known to be negotiating and we don't send
242 /* figure out how much data we are expected to send */
243 switch(data
->set
.httpreq
) {
245 if(data
->set
.postfieldsize
!= -1)
246 expectsend
= data
->set
.postfieldsize
;
249 if(data
->set
.infilesize
!= -1)
250 expectsend
= data
->set
.infilesize
;
252 case HTTPREQ_POST_FORM
:
253 expectsend
= http
->postsize
;
260 conn
->bits
.rewindaftersend
= FALSE
; /* default */
262 if((expectsend
== -1) || (expectsend
> bytessent
)) {
263 /* There is still data left to send */
264 if((data
->state
.authproxy
.picked
== CURLAUTH_NTLM
) ||
265 (data
->state
.authhost
.picked
== CURLAUTH_NTLM
)) {
266 if(((expectsend
- bytessent
) < 2000) ||
267 (conn
->ntlm
.state
!= NTLMSTATE_NONE
)) {
268 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
269 data left to send, keep on sending. */
271 /* rewind data when completely done sending! */
272 if(!conn
->bits
.authneg
)
273 conn
->bits
.rewindaftersend
= TRUE
;
278 /* this is already marked to get closed */
281 infof(data
, "NTLM send, close instead of sending %" FORMAT_OFF_T
282 " bytes\n", (curl_off_t
)(expectsend
- bytessent
));
285 /* This is not NTLM or NTLM with many bytes left to send: close
287 conn
->bits
.close
= TRUE
;
288 k
->size
= 0; /* don't download any more than 0 bytes */
292 return Curl_readrewind(conn
);
298 * Curl_http_auth_act() gets called when a all HTTP headers have been received
299 * and it checks what authentication methods that are available and decides
300 * which one (if any) to use. It will set 'newurl' if an auth metod was
304 CURLcode
Curl_http_auth_act(struct connectdata
*conn
)
306 struct SessionHandle
*data
= conn
->data
;
307 bool pickhost
= FALSE
;
308 bool pickproxy
= FALSE
;
309 CURLcode code
= CURLE_OK
;
311 if(100 == data
->reqdata
.keep
.httpcode
)
312 /* this is a transient response code, ignore */
315 if(data
->state
.authproblem
)
316 return data
->set
.http_fail_on_error
?CURLE_HTTP_RETURNED_ERROR
:CURLE_OK
;
318 if(conn
->bits
.user_passwd
&&
319 ((data
->reqdata
.keep
.httpcode
== 401) ||
320 (conn
->bits
.authneg
&& data
->reqdata
.keep
.httpcode
< 300))) {
321 pickhost
= pickoneauth(&data
->state
.authhost
);
323 data
->state
.authproblem
= TRUE
;
325 if(conn
->bits
.proxy_user_passwd
&&
326 ((data
->reqdata
.keep
.httpcode
== 407) ||
327 (conn
->bits
.authneg
&& data
->reqdata
.keep
.httpcode
< 300))) {
328 pickproxy
= pickoneauth(&data
->state
.authproxy
);
330 data
->state
.authproblem
= TRUE
;
333 if(pickhost
|| pickproxy
) {
334 data
->reqdata
.newurl
= strdup(data
->change
.url
); /* clone URL */
336 if((data
->set
.httpreq
!= HTTPREQ_GET
) &&
337 (data
->set
.httpreq
!= HTTPREQ_HEAD
) &&
338 !conn
->bits
.rewindaftersend
) {
339 code
= perhapsrewind(conn
);
345 else if((data
->reqdata
.keep
.httpcode
< 300) &&
346 (!data
->state
.authhost
.done
) &&
347 conn
->bits
.authneg
) {
348 /* no (known) authentication available,
349 authentication is not "done" yet and
350 no authentication seems to be required and
351 we didn't try HEAD or GET */
352 if((data
->set
.httpreq
!= HTTPREQ_GET
) &&
353 (data
->set
.httpreq
!= HTTPREQ_HEAD
)) {
354 data
->reqdata
.newurl
= strdup(data
->change
.url
); /* clone URL */
355 data
->state
.authhost
.done
= TRUE
;
358 if (Curl_http_should_fail(conn
)) {
359 failf (data
, "The requested URL returned error: %d",
360 data
->reqdata
.keep
.httpcode
);
361 code
= CURLE_HTTP_RETURNED_ERROR
;
368 * Curl_http_output_auth() setups the authentication headers for the
369 * host/proxy and the correct authentication
370 * method. conn->data->state.authdone is set to TRUE when authentication is
373 * @param conn all information about the current connection
374 * @param request pointer to the request keyword
375 * @param path pointer to the requested path
376 * @param proxytunnel boolean if this is the request setting up a "proxy
382 Curl_http_output_auth(struct connectdata
*conn
,
385 bool proxytunnel
) /* TRUE if this is the request setting
386 up the proxy tunnel */
388 CURLcode result
= CURLE_OK
;
389 struct SessionHandle
*data
= conn
->data
;
391 struct auth
*authhost
;
392 struct auth
*authproxy
;
396 authhost
= &data
->state
.authhost
;
397 authproxy
= &data
->state
.authproxy
;
399 if((conn
->bits
.httpproxy
&& conn
->bits
.proxy_user_passwd
) ||
400 conn
->bits
.user_passwd
)
401 /* continue please */ ;
403 authhost
->done
= TRUE
;
404 authproxy
->done
= TRUE
;
405 return CURLE_OK
; /* no authentication with no user or password */
408 if(authhost
->want
&& !authhost
->picked
)
409 /* The app has selected one or more methods, but none has been picked
410 so far by a server round-trip. Then we set the picked one to the
411 want one, and if this is one single bit it'll be used instantly. */
412 authhost
->picked
= authhost
->want
;
414 if(authproxy
->want
&& !authproxy
->picked
)
415 /* The app has selected one or more methods, but none has been picked so
416 far by a proxy round-trip. Then we set the picked one to the want one,
417 and if this is one single bit it'll be used instantly. */
418 authproxy
->picked
= authproxy
->want
;
420 /* Send proxy authentication header if needed */
421 if (conn
->bits
.httpproxy
&&
422 (conn
->bits
.tunnel_proxy
== proxytunnel
)) {
424 if(authproxy
->picked
== CURLAUTH_NTLM
) {
426 result
= Curl_output_ntlm(conn
, TRUE
);
432 if(authproxy
->picked
== CURLAUTH_BASIC
) {
434 if(conn
->bits
.proxy_user_passwd
&&
435 !checkheaders(data
, "Proxy-authorization:")) {
436 auth
=(char *)"Basic";
437 result
= Curl_output_basic(conn
, TRUE
);
441 /* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth
442 functions work that way */
443 authproxy
->done
= TRUE
;
445 #ifndef CURL_DISABLE_CRYPTO_AUTH
446 else if(authproxy
->picked
== CURLAUTH_DIGEST
) {
447 auth
=(char *)"Digest";
448 result
= Curl_output_digest(conn
,
450 (unsigned char *)request
,
451 (unsigned char *)path
);
457 infof(data
, "Proxy auth using %s with user '%s'\n",
458 auth
, conn
->proxyuser
?conn
->proxyuser
:"");
459 authproxy
->multi
= (bool)(!authproxy
->done
);
462 authproxy
->multi
= FALSE
;
465 /* we have no proxy so let's pretend we're done authenticating
467 authproxy
->done
= TRUE
;
469 /* To prevent the user+password to get sent to other than the original
470 host due to a location-follow, we do some weirdo checks here */
471 if(!data
->state
.this_is_a_follow
||
473 !data
->state
.first_host
||
474 curl_strequal(data
->state
.first_host
, conn
->host
.name
) ||
475 data
->set
.http_disable_hostname_check_before_authentication
) {
477 /* Send web authentication header if needed */
481 if((authhost
->picked
== CURLAUTH_GSSNEGOTIATE
) &&
482 data
->state
.negotiate
.context
&&
483 !GSS_ERROR(data
->state
.negotiate
.status
)) {
484 auth
=(char *)"GSS-Negotiate";
485 result
= Curl_output_negotiate(conn
);
488 authhost
->done
= TRUE
;
493 if(authhost
->picked
== CURLAUTH_NTLM
) {
495 result
= Curl_output_ntlm(conn
, FALSE
);
502 #ifndef CURL_DISABLE_CRYPTO_AUTH
503 if(authhost
->picked
== CURLAUTH_DIGEST
) {
504 auth
=(char *)"Digest";
505 result
= Curl_output_digest(conn
,
506 FALSE
, /* not a proxy */
507 (unsigned char *)request
,
508 (unsigned char *)path
);
513 if(authhost
->picked
== CURLAUTH_BASIC
) {
514 if(conn
->bits
.user_passwd
&&
515 !checkheaders(data
, "Authorization:")) {
516 auth
=(char *)"Basic";
517 result
= Curl_output_basic(conn
, FALSE
);
521 /* basic is always ready */
522 authhost
->done
= TRUE
;
526 infof(data
, "Server auth using %s with user '%s'\n",
529 authhost
->multi
= (bool)(!authhost
->done
);
532 authhost
->multi
= FALSE
;
536 authhost
->done
= TRUE
;
543 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
544 * headers. They are dealt with both in the transfer.c main loop and in the
545 * proxy CONNECT loop.
548 CURLcode
Curl_http_input_auth(struct connectdata
*conn
,
550 char *header
) /* the first non-space */
553 * This resource requires authentication
555 struct SessionHandle
*data
= conn
->data
;
561 if (httpcode
== 407) {
562 start
= header
+strlen("Proxy-authenticate:");
563 availp
= &data
->info
.proxyauthavail
;
564 authp
= &data
->state
.authproxy
;
567 start
= header
+strlen("WWW-Authenticate:");
568 availp
= &data
->info
.httpauthavail
;
569 authp
= &data
->state
.authhost
;
572 /* pass all white spaces */
573 while(*start
&& ISSPACE(*start
))
577 * Here we check if we want the specific single authentication (using ==) and
578 * if we do, we initiate usage of it.
580 * If the provided authentication is wanted as one out of several accepted
581 * types (using &), we OR this authentication type to the authavail
586 if (checkprefix("GSS-Negotiate", start
) ||
587 checkprefix("Negotiate", start
)) {
588 *availp
|= CURLAUTH_GSSNEGOTIATE
;
589 authp
->avail
|= CURLAUTH_GSSNEGOTIATE
;
590 if(authp
->picked
== CURLAUTH_GSSNEGOTIATE
) {
591 /* if exactly this is wanted, go */
592 int neg
= Curl_input_negotiate(conn
, start
);
594 data
->reqdata
.newurl
= strdup(data
->change
.url
);
595 data
->state
.authproblem
= (data
->reqdata
.newurl
== NULL
);
598 infof(data
, "Authentication problem. Ignoring this.\n");
599 data
->state
.authproblem
= TRUE
;
606 /* NTLM support requires the SSL crypto libs */
607 if(checkprefix("NTLM", start
)) {
608 *availp
|= CURLAUTH_NTLM
;
609 authp
->avail
|= CURLAUTH_NTLM
;
610 if(authp
->picked
== CURLAUTH_NTLM
) {
611 /* NTLM authentication is picked and activated */
613 Curl_input_ntlm(conn
, (bool)(httpcode
== 407), start
);
615 if(CURLNTLM_BAD
!= ntlm
)
616 data
->state
.authproblem
= FALSE
;
618 infof(data
, "Authentication problem. Ignoring this.\n");
619 data
->state
.authproblem
= TRUE
;
625 #ifndef CURL_DISABLE_CRYPTO_AUTH
626 if(checkprefix("Digest", start
)) {
627 if((authp
->avail
& CURLAUTH_DIGEST
) != 0) {
628 infof(data
, "Ignoring duplicate digest auth header.\n");
632 *availp
|= CURLAUTH_DIGEST
;
633 authp
->avail
|= CURLAUTH_DIGEST
;
635 /* We call this function on input Digest headers even if Digest
636 * authentication isn't activated yet, as we need to store the
637 * incoming data from this header in case we are gonna use Digest. */
638 dig
= Curl_input_digest(conn
, (bool)(httpcode
== 407), start
);
640 if(CURLDIGEST_FINE
!= dig
) {
641 infof(data
, "Authentication problem. Ignoring this.\n");
642 data
->state
.authproblem
= TRUE
;
648 if(checkprefix("Basic", start
)) {
649 *availp
|= CURLAUTH_BASIC
;
650 authp
->avail
|= CURLAUTH_BASIC
;
651 if(authp
->picked
== CURLAUTH_BASIC
) {
652 /* We asked for Basic authentication but got a 40X back
653 anyway, which basicly means our name+password isn't
655 authp
->avail
= CURLAUTH_NONE
;
656 infof(data
, "Authentication problem. Ignoring this.\n");
657 data
->state
.authproblem
= TRUE
;
665 * Curl_http_should_fail() determines whether an HTTP response has gotten us
666 * into an error state or not.
668 * @param conn all information about the current connection
670 * @retval 0 communications should continue
672 * @retval 1 communications should not continue
674 int Curl_http_should_fail(struct connectdata
*conn
)
676 struct SessionHandle
*data
;
677 struct Curl_transfer_keeper
*k
;
686 k
= &data
->reqdata
.keep
;
689 ** If we haven't been asked to fail on error,
692 if (!data
->set
.http_fail_on_error
)
696 ** Any code < 400 is never terminal.
698 if (k
->httpcode
< 400)
701 if (data
->reqdata
.resume_from
&&
702 (data
->set
.httpreq
==HTTPREQ_GET
) &&
703 (k
->httpcode
== 416)) {
704 /* "Requested Range Not Satisfiable", just proceed and
705 pretend this is no error */
710 ** Any code >= 400 that's not 401 or 407 is always
713 if ((k
->httpcode
!= 401) &&
714 (k
->httpcode
!= 407))
718 ** All we have left to deal with is 401 and 407
720 curlassert((k
->httpcode
== 401) || (k
->httpcode
== 407));
723 ** Examine the current authentication state to see if this
724 ** is an error. The idea is for this function to get
725 ** called after processing all the headers in a response
726 ** message. So, if we've been to asked to authenticate a
727 ** particular stage, and we've done it, we're OK. But, if
728 ** we're already completely authenticated, it's not OK to
729 ** get another 401 or 407.
731 ** It is possible for authentication to go stale such that
732 ** the client needs to reauthenticate. Once that info is
733 ** available, use it here.
735 #if 0 /* set to 1 when debugging this functionality */
736 infof(data
,"%s: authstage = %d\n",__FUNCTION__
,data
->state
.authstage
);
737 infof(data
,"%s: authwant = 0x%08x\n",__FUNCTION__
,data
->state
.authwant
);
738 infof(data
,"%s: authavail = 0x%08x\n",__FUNCTION__
,data
->state
.authavail
);
739 infof(data
,"%s: httpcode = %d\n",__FUNCTION__
,k
->httpcode
);
740 infof(data
,"%s: authdone = %d\n",__FUNCTION__
,data
->state
.authdone
);
741 infof(data
,"%s: newurl = %s\n",__FUNCTION__
,data
->reqdata
.newurl
? data
->reqdata
.newurl
: "(null)");
742 infof(data
,"%s: authproblem = %d\n",__FUNCTION__
,data
->state
.authproblem
);
746 ** Either we're not authenticating, or we're supposed to
747 ** be authenticating something else. This is an error.
749 if((k
->httpcode
== 401) && !conn
->bits
.user_passwd
)
751 if((k
->httpcode
== 407) && !conn
->bits
.proxy_user_passwd
)
754 return data
->state
.authproblem
;
758 * readmoredata() is a "fread() emulation" to provide POST and/or request
759 * data. It is used when a huge POST is to be made and the entire chunk wasn't
760 * sent in the first send(). This function will then be called from the
761 * transfer.c loop when more data is to be sent to the peer.
763 * Returns the amount of bytes it filled the buffer with.
765 static size_t readmoredata(char *buffer
,
770 struct connectdata
*conn
= (struct connectdata
*)userp
;
771 struct HTTP
*http
= conn
->data
->reqdata
.proto
.http
;
772 size_t fullsize
= size
* nitems
;
774 if(0 == http
->postsize
)
775 /* nothing to return */
778 /* make sure that a HTTP request is never sent away chunked! */
779 conn
->bits
.forbidchunk
= (bool)(http
->sending
== HTTPSEND_REQUEST
);
781 if(http
->postsize
<= (curl_off_t
)fullsize
) {
782 memcpy(buffer
, http
->postdata
, (size_t)http
->postsize
);
783 fullsize
= (size_t)http
->postsize
;
785 if(http
->backup
.postsize
) {
786 /* move backup data into focus and continue on that */
787 http
->postdata
= http
->backup
.postdata
;
788 http
->postsize
= http
->backup
.postsize
;
789 conn
->fread
= http
->backup
.fread
;
790 conn
->fread_in
= http
->backup
.fread_in
;
792 http
->sending
++; /* move one step up */
794 http
->backup
.postsize
=0;
802 memcpy(buffer
, http
->postdata
, fullsize
);
803 http
->postdata
+= fullsize
;
804 http
->postsize
-= fullsize
;
809 /* ------------------------------------------------------------------------- */
811 * The add_buffer series of functions are used to build one large memory chunk
812 * from repeated function invokes. Used so that the entire HTTP request can
821 typedef struct send_buffer send_buffer
;
823 static CURLcode
add_custom_headers(struct connectdata
*conn
,
824 send_buffer
*req_buffer
);
826 add_buffer(send_buffer
*in
, const void *inptr
, size_t size
);
829 * add_buffer_init() sets up and returns a fine buffer struct
832 send_buffer
*add_buffer_init(void)
835 blonk
=(send_buffer
*)malloc(sizeof(send_buffer
));
837 memset(blonk
, 0, sizeof(send_buffer
));
840 return NULL
; /* failed, go home */
844 * add_buffer_send() sends a header buffer and frees all associated memory.
845 * Body data may be appended to the header data if desired.
850 CURLcode
add_buffer_send(send_buffer
*in
,
851 struct connectdata
*conn
,
852 long *bytes_written
, /* add the number of sent
853 bytes to this counter */
854 size_t included_body_bytes
, /* how much of the buffer
855 contains body data (for log tracing) */
863 struct HTTP
*http
= conn
->data
->reqdata
.proto
.http
;
865 curl_socket_t sockfd
;
867 curlassert(socketindex
<= SECONDARYSOCKET
);
869 sockfd
= conn
->sock
[socketindex
];
871 /* The looping below is required since we use non-blocking sockets, but due
872 to the circumstances we will just loop and try again and again etc */
875 size
= in
->size_used
;
877 #ifdef CURL_DOES_CONVERSIONS
878 if(size
- included_body_bytes
> 0) {
879 res
= Curl_convert_to_network(conn
->data
, ptr
, size
- included_body_bytes
);
880 /* Curl_convert_to_network calls failf if unsuccessful */
881 if(res
!= CURLE_OK
) {
882 /* conversion failed, free memory and return to the caller */
889 #endif /* CURL_DOES_CONVERSIONS */
891 if(conn
->protocol
& PROT_HTTPS
) {
892 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
893 when we speak HTTPS, as if only a fraction of it is sent now, this data
894 needs to fit into the normal read-callback buffer later on and that
895 buffer is using this size.
898 sendsize
= (size
> CURL_MAX_WRITE_SIZE
)?CURL_MAX_WRITE_SIZE
:size
;
900 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
901 library when we attempt to re-send this buffer. Sending the same data
902 is not enough, we must use the exact same address. For this reason, we
903 must copy the data to the uploadbuffer first, since that is the buffer
904 we will be using if this send is retried later.
906 memcpy(conn
->data
->state
.uploadbuffer
, ptr
, sendsize
);
907 ptr
= conn
->data
->state
.uploadbuffer
;
912 res
= Curl_write(conn
, sockfd
, ptr
, sendsize
, &amount
);
914 if(CURLE_OK
== res
) {
916 if(conn
->data
->set
.verbose
) {
917 /* this data _may_ contain binary stuff */
918 Curl_debug(conn
->data
, CURLINFO_HEADER_OUT
, ptr
,
919 (size_t)(amount
-included_body_bytes
), conn
);
920 if (included_body_bytes
)
921 Curl_debug(conn
->data
, CURLINFO_DATA_OUT
,
922 ptr
+amount
-included_body_bytes
,
923 (size_t)included_body_bytes
, conn
);
926 *bytes_written
+= amount
;
929 if((size_t)amount
!= size
) {
930 /* The whole request could not be sent in one system call. We must
931 queue it up and send it later when we get the chance. We must not
932 loop here and wait until it might work again. */
936 ptr
= in
->buffer
+ amount
;
938 /* backup the currently set pointers */
939 http
->backup
.fread
= conn
->fread
;
940 http
->backup
.fread_in
= conn
->fread_in
;
941 http
->backup
.postdata
= http
->postdata
;
942 http
->backup
.postsize
= http
->postsize
;
944 /* set the new pointers for the request-sending */
945 conn
->fread
= (curl_read_callback
)readmoredata
;
946 conn
->fread_in
= (void *)conn
;
947 http
->postdata
= ptr
;
948 http
->postsize
= (curl_off_t
)size
;
950 http
->send_buffer
= in
;
951 http
->sending
= HTTPSEND_REQUEST
;
955 http
->sending
= HTTPSEND_BODY
;
956 /* the full buffer was sent, clean up and return */
959 if((size_t)amount
!= size
)
960 /* We have no continue-send mechanism now, fail. This can only happen
961 when this function is used from the CONNECT sending function. We
962 currently (stupidly) assume that the whole request is always sent
963 away in the first single chunk.
967 return CURLE_SEND_ERROR
;
969 conn
->writechannel_inuse
= FALSE
;
981 * add_bufferf() add the formatted input to the buffer.
984 CURLcode
add_bufferf(send_buffer
*in
, const char *fmt
, ...)
989 s
= vaprintf(fmt
, ap
); /* this allocs a new string to append */
993 CURLcode result
= add_buffer(in
, s
, strlen(s
));
995 if(CURLE_OK
== result
)
998 /* If we failed, we cleanup the whole buffer and return error */
1002 return CURLE_OUT_OF_MEMORY
;
1006 * add_buffer() appends a memory chunk to the existing buffer
1009 CURLcode
add_buffer(send_buffer
*in
, const void *inptr
, size_t size
)
1015 ((in
->size_used
+ size
) > (in
->size_max
- 1))) {
1016 new_size
= (in
->size_used
+size
)*2;
1018 /* we have a buffer, enlarge the existing one */
1019 new_rb
= (char *)realloc(in
->buffer
, new_size
);
1021 /* create a new buffer */
1022 new_rb
= (char *)malloc(new_size
);
1025 return CURLE_OUT_OF_MEMORY
;
1027 in
->buffer
= new_rb
;
1028 in
->size_max
= new_size
;
1030 memcpy(&in
->buffer
[in
->size_used
], inptr
, size
);
1032 in
->size_used
+= size
;
1037 /* end of the add_buffer functions */
1038 /* ------------------------------------------------------------------------- */
1041 * Curl_compareheader()
1043 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1044 * Pass headers WITH the colon.
1047 Curl_compareheader(char *headerline
, /* line to check */
1048 const char *header
, /* header keyword _with_ colon */
1049 const char *content
) /* content string to find */
1051 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1052 * by a colon (":") and the field value. Field names are case-insensitive.
1053 * The field value MAY be preceded by any amount of LWS, though a single SP
1056 size_t hlen
= strlen(header
);
1062 if(!strnequal(headerline
, header
, hlen
))
1063 return FALSE
; /* doesn't start with header */
1065 /* pass the header */
1066 start
= &headerline
[hlen
];
1068 /* pass all white spaces */
1069 while(*start
&& ISSPACE(*start
))
1072 /* find the end of the header line */
1073 end
= strchr(start
, '\r'); /* lines end with CRLF */
1075 /* in case there's a non-standard compliant line here */
1076 end
= strchr(start
, '\n');
1079 /* hm, there's no line ending here, use the zero byte! */
1080 end
= strchr(start
, '\0');
1083 len
= end
-start
; /* length of the content part of the input line */
1084 clen
= strlen(content
); /* length of the word to find */
1086 /* find the content string in the rest of the line */
1087 for(;len
>=clen
;len
--, start
++) {
1088 if(strnequal(start
, content
, clen
))
1089 return TRUE
; /* match! */
1092 return FALSE
; /* no match */
1096 * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
1097 * function will issue the necessary commands to get a seamless tunnel through
1098 * this proxy. After that, the socket can be used just as a normal socket.
1100 * This badly needs to be rewritten. CONNECT should be sent and dealt with
1101 * like any ordinary HTTP request, and not specially crafted like this. This
1102 * function only remains here like this for now since the rewrite is a bit too
1103 * much work to do at the moment.
1105 * This function is BLOCKING which is nasty for all multi interface using apps.
1108 CURLcode
Curl_proxyCONNECT(struct connectdata
*conn
,
1114 struct SessionHandle
*data
=conn
->data
;
1115 struct Curl_transfer_keeper
*k
= &data
->reqdata
.keep
;
1118 size_t nread
; /* total size read */
1119 int perline
; /* count bytes per line */
1124 data
->set
.timeout
?data
->set
.timeout
:3600; /* in seconds */
1127 curl_socket_t tunnelsocket
= conn
->sock
[sockindex
];
1128 send_buffer
*req_buffer
;
1130 bool closeConnection
= FALSE
;
1133 #define SELECT_ERROR 1
1134 #define SELECT_TIMEOUT 2
1135 int error
= SELECT_OK
;
1137 infof(data
, "Establish HTTP proxy tunnel to %s:%d\n", hostname
, remote_port
);
1138 conn
->bits
.proxy_connect_closed
= FALSE
;
1141 if(data
->reqdata
.newurl
) {
1142 /* This only happens if we've looped here due to authentication reasons,
1143 and we don't really use the newly cloned URL here then. Just free()
1145 free(data
->reqdata
.newurl
);
1146 data
->reqdata
.newurl
= NULL
;
1149 /* initialize a dynamic send-buffer */
1150 req_buffer
= add_buffer_init();
1153 return CURLE_OUT_OF_MEMORY
;
1155 host_port
= aprintf("%s:%d", hostname
, remote_port
);
1157 return CURLE_OUT_OF_MEMORY
;
1159 /* Setup the proxy-authorization header, if any */
1160 result
= Curl_http_output_auth(conn
, (char *)"CONNECT", host_port
, TRUE
);
1162 if(CURLE_OK
== result
) {
1163 char *host
=(char *)"";
1164 const char *proxyconn
="";
1165 const char *useragent
="";
1167 if(!checkheaders(data
, "Host:")) {
1168 host
= aprintf("Host: %s\r\n", host_port
);
1170 result
= CURLE_OUT_OF_MEMORY
;
1172 if(!checkheaders(data
, "Proxy-Connection:"))
1173 proxyconn
= "Proxy-Connection: Keep-Alive\r\n";
1175 if(!checkheaders(data
, "User-Agent:") && data
->set
.useragent
)
1176 useragent
= conn
->allocptr
.uagent
;
1178 if(CURLE_OK
== result
) {
1179 /* Send the connect request to the proxy */
1182 add_bufferf(req_buffer
,
1183 "CONNECT %s:%d HTTP/1.0\r\n"
1185 "%s" /* Proxy-Authorization */
1186 "%s" /* User-Agent */
1187 "%s", /* Proxy-Connection */
1188 hostname
, remote_port
,
1190 conn
->allocptr
.proxyuserpwd
?
1191 conn
->allocptr
.proxyuserpwd
:"",
1195 if(CURLE_OK
== result
)
1196 result
= add_custom_headers(conn
, req_buffer
);
1201 if(CURLE_OK
== result
)
1202 /* CRLF terminate the request */
1203 result
= add_bufferf(req_buffer
, "\r\n");
1205 if(CURLE_OK
== result
)
1206 /* Now send off the request */
1207 result
= add_buffer_send(req_buffer
, conn
,
1208 &data
->info
.request_size
, 0, sockindex
);
1211 failf(data
, "Failed sending CONNECT to proxy");
1217 ptr
=data
->state
.buffer
;
1224 while((nread
<BUFSIZE
) && (keepon
&& !error
)) {
1226 /* if timeout is requested, find out how much remaining time we have */
1227 long check
= timeout
- /* timeout time */
1228 Curl_tvdiff(Curl_tvnow(), conn
->now
)/1000; /* spent time */
1230 failf(data
, "Proxy CONNECT aborted due to timeout");
1231 error
= SELECT_TIMEOUT
; /* already too little time */
1235 /* timeout each second and check the timeout */
1236 switch (Curl_select(tunnelsocket
, CURL_SOCKET_BAD
, 1000)) {
1237 case -1: /* select() error, stop reading */
1238 error
= SELECT_ERROR
;
1239 failf(data
, "Proxy CONNECT aborted due to select() error");
1241 case 0: /* timeout */
1244 res
= Curl_read(conn
, tunnelsocket
, ptr
, BUFSIZE
-nread
, &gotbytes
);
1247 continue; /* go loop yourself */
1250 else if(gotbytes
<= 0) {
1252 error
= SELECT_ERROR
;
1253 failf(data
, "Proxy CONNECT aborted");
1257 * We got a whole chunk of data, which can be anything from one byte
1258 * to a set of lines and possibly just a piece of the last line.
1265 /* This means we are currently ignoring a response-body, so we
1266 simply count down our counter and make sure to break out of the
1267 loop when we're done! */
1275 for(i
= 0; i
< gotbytes
; ptr
++, i
++) {
1276 perline
++; /* amount of bytes in this line so far */
1281 /* output debug if that is requested */
1282 if(data
->set
.verbose
)
1283 Curl_debug(data
, CURLINFO_HEADER_IN
,
1284 line_start
, (size_t)perline
, conn
);
1286 /* send the header to the callback */
1287 writetype
= CLIENTWRITE_HEADER
;
1288 if(data
->set
.include_header
)
1289 writetype
|= CLIENTWRITE_BODY
;
1291 result
= Curl_client_write(conn
, writetype
, line_start
, perline
);
1295 /* Newlines are CRLF, so the CR is ignored as the line isn't
1296 really terminated until the LF comes. Treat a following CR
1297 as end-of-headers as well.*/
1299 if(('\r' == line_start
[0]) ||
1300 ('\n' == line_start
[0])) {
1301 /* end of response-headers from the proxy */
1302 if(cl
&& (407 == k
->httpcode
) && !data
->state
.authproblem
) {
1303 /* If we get a 407 response code with content length when we
1304 * have no auth problem, we must ignore the whole
1307 infof(data
, "Ignore %" FORMAT_OFF_T
1308 " bytes of response-body\n", cl
);
1309 cl
-= (gotbytes
- i
);/* remove the remaining chunk of what
1312 /* if the whole thing was already read, we are done! */
1317 break; /* breaks out of for-loop, not switch() */
1320 /* keep a backup of the position we are about to blank */
1321 letter
= line_start
[perline
];
1322 line_start
[perline
]=0; /* zero terminate the buffer */
1323 if((checkprefix("WWW-Authenticate:", line_start
) &&
1324 (401 == k
->httpcode
)) ||
1325 (checkprefix("Proxy-authenticate:", line_start
) &&
1326 (407 == k
->httpcode
))) {
1327 result
= Curl_http_input_auth(conn
, k
->httpcode
, line_start
);
1331 else if(checkprefix("Content-Length:", line_start
)) {
1332 cl
= curlx_strtoofft(line_start
+ strlen("Content-Length:"),
1335 else if(Curl_compareheader(line_start
,
1336 "Connection:", "close"))
1337 closeConnection
= TRUE
;
1338 else if(2 == sscanf(line_start
, "HTTP/1.%d %d",
1341 /* store the HTTP code from the proxy */
1342 data
->info
.httpproxycode
= k
->httpcode
;
1344 /* put back the letter we blanked out before */
1345 line_start
[perline
]= letter
;
1347 perline
=0; /* line starts over here */
1348 line_start
= ptr
+1; /* this skips the zero byte we wrote */
1354 } /* while there's buffer left and loop is requested */
1357 return CURLE_RECV_ERROR
;
1359 if(data
->info
.httpproxycode
!= 200)
1360 /* Deal with the possibly already received authenticate
1361 headers. 'newurl' is set to a new URL if we must loop. */
1362 Curl_http_auth_act(conn
);
1364 if (closeConnection
&& data
->reqdata
.newurl
) {
1365 /* Connection closed by server. Don't use it anymore */
1366 sclose(conn
->sock
[sockindex
]);
1367 conn
->sock
[sockindex
] = CURL_SOCKET_BAD
;
1370 } while(data
->reqdata
.newurl
);
1372 if(200 != k
->httpcode
) {
1373 failf(data
, "Received HTTP code %d from proxy after CONNECT",
1376 if (closeConnection
&& data
->reqdata
.newurl
)
1377 conn
->bits
.proxy_connect_closed
= TRUE
;
1379 return CURLE_RECV_ERROR
;
1382 /* If a proxy-authorization header was used for the proxy, then we should
1383 make sure that it isn't accidentally used for the document request
1384 after we've connected. So let's free and clear it here. */
1385 Curl_safefree(conn
->allocptr
.proxyuserpwd
);
1386 conn
->allocptr
.proxyuserpwd
= NULL
;
1388 data
->state
.authproxy
.done
= TRUE
;
1390 infof (data
, "Proxy replied OK to CONNECT request\n");
1395 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1396 * the generic Curl_connect().
1398 CURLcode
Curl_http_connect(struct connectdata
*conn
, bool *done
)
1400 struct SessionHandle
*data
;
1405 /* If we are not using a proxy and we want a secure connection, perform SSL
1406 * initialization & connection now. If using a proxy with https, then we
1407 * must tell the proxy to CONNECT to the host we want to talk to. Only
1408 * after the connect has occurred, can we start talking SSL
1411 if(conn
->bits
.tunnel_proxy
&& conn
->bits
.httpproxy
) {
1413 /* either SSL over proxy, or explicitly asked for */
1414 result
= Curl_proxyCONNECT(conn
, FIRSTSOCKET
,
1417 if(CURLE_OK
!= result
)
1421 if(!data
->state
.this_is_a_follow
) {
1422 /* this is not a followed location, get the original host name */
1423 if (data
->state
.first_host
)
1424 /* Free to avoid leaking memory on multiple requests*/
1425 free(data
->state
.first_host
);
1427 data
->state
.first_host
= strdup(conn
->host
.name
);
1428 if(!data
->state
.first_host
)
1429 return CURLE_OUT_OF_MEMORY
;
1432 if(conn
->protocol
& PROT_HTTPS
) {
1433 /* perform SSL initialization */
1434 if(data
->state
.used_interface
== Curl_if_multi
) {
1435 result
= Curl_https_connecting(conn
, done
);
1441 result
= Curl_ssl_connect(conn
, FIRSTSOCKET
);
1454 CURLcode
Curl_https_connecting(struct connectdata
*conn
, bool *done
)
1457 curlassert(conn
->protocol
& PROT_HTTPS
);
1459 /* perform SSL initialization for this socket */
1460 result
= Curl_ssl_connect_nonblocking(conn
, FIRSTSOCKET
, done
);
1468 /* This function is OpenSSL-specific. It should be made to query the generic
1469 SSL layer instead. */
1470 int Curl_https_getsock(struct connectdata
*conn
,
1471 curl_socket_t
*socks
,
1474 if (conn
->protocol
& PROT_HTTPS
) {
1475 struct ssl_connect_data
*connssl
= &conn
->ssl
[FIRSTSOCKET
];
1478 return GETSOCK_BLANK
;
1480 if (connssl
->connecting_state
== ssl_connect_2_writing
) {
1482 socks
[0] = conn
->sock
[FIRSTSOCKET
];
1483 return GETSOCK_WRITESOCK(0);
1485 else if (connssl
->connecting_state
== ssl_connect_2_reading
) {
1487 socks
[0] = conn
->sock
[FIRSTSOCKET
];
1488 return GETSOCK_READSOCK(0);
1495 int Curl_https_getsock(struct connectdata
*conn
,
1496 curl_socket_t
*socks
,
1502 return GETSOCK_BLANK
;
1508 * Curl_http_done() gets called from Curl_done() after a single HTTP request
1509 * has been performed.
1512 CURLcode
Curl_http_done(struct connectdata
*conn
,
1513 CURLcode status
, bool premature
)
1515 struct SessionHandle
*data
= conn
->data
;
1516 struct HTTP
*http
=data
->reqdata
.proto
.http
;
1517 struct Curl_transfer_keeper
*k
= &data
->reqdata
.keep
;
1518 (void)premature
; /* not used */
1520 /* set the proper values (possibly modified on POST) */
1521 conn
->fread
= data
->set
.fread
; /* restore */
1522 conn
->fread_in
= data
->set
.in
; /* restore */
1527 if(http
->send_buffer
) {
1528 send_buffer
*buff
= http
->send_buffer
;
1532 http
->send_buffer
= NULL
; /* clear the pointer */
1535 if(HTTPREQ_POST_FORM
== data
->set
.httpreq
) {
1536 k
->bytecount
= http
->readbytecount
+ http
->writebytecount
;
1538 Curl_formclean(&http
->sendit
); /* Now free that whole lot */
1540 /* a file being uploaded was left opened, close it! */
1541 fclose(http
->form
.fp
);
1542 http
->form
.fp
= NULL
;
1545 else if(HTTPREQ_PUT
== data
->set
.httpreq
)
1546 k
->bytecount
= http
->readbytecount
+ http
->writebytecount
;
1548 if (status
!= CURLE_OK
)
1551 if(!conn
->bits
.retry
&&
1552 ((http
->readbytecount
+
1553 conn
->headerbytecount
-
1554 conn
->deductheadercount
)) <= 0) {
1555 /* If this connection isn't simply closed to be retried, AND nothing was
1556 read from the HTTP server (that counts), this can't be right so we
1557 return an error here */
1558 failf(data
, "Empty reply from server");
1559 return CURLE_GOT_NOTHING
;
1565 /* check and possibly add an Expect: header */
1566 static CURLcode
expect100(struct SessionHandle
*data
,
1567 send_buffer
*req_buffer
)
1569 CURLcode result
= CURLE_OK
;
1570 data
->state
.expect100header
= FALSE
; /* default to false unless it is set
1572 if((data
->set
.httpversion
!= CURL_HTTP_VERSION_1_0
) &&
1573 !checkheaders(data
, "Expect:")) {
1574 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
1575 100-continue to the headers which actually speeds up post
1576 operations (as there is one packet coming back from the web
1578 result
= add_bufferf(req_buffer
,
1579 "Expect: 100-continue\r\n");
1580 if(result
== CURLE_OK
)
1581 data
->state
.expect100header
= TRUE
;
1586 static CURLcode
add_custom_headers(struct connectdata
*conn
,
1587 send_buffer
*req_buffer
)
1589 CURLcode result
= CURLE_OK
;
1591 struct curl_slist
*headers
=conn
->data
->set
.headers
;
1594 ptr
= strchr(headers
->data
, ':');
1596 /* we require a colon for this to be a true header */
1598 ptr
++; /* pass the colon */
1599 while(*ptr
&& ISSPACE(*ptr
))
1603 /* only send this if the contents was non-blank */
1605 if(conn
->allocptr
.host
&&
1606 /* a Host: header was sent already, don't pass on any custom Host:
1607 header as that will produce *two* in the same request! */
1608 curl_strnequal("Host:", headers
->data
, 5))
1610 else if(conn
->data
->set
.httpreq
== HTTPREQ_POST_FORM
&&
1611 /* this header (extended by formdata.c) is sent later */
1612 curl_strnequal("Content-Type:", headers
->data
,
1613 strlen("Content-Type:")))
1616 result
= add_bufferf(req_buffer
, "%s\r\n", headers
->data
);
1622 headers
= headers
->next
;
1628 * Curl_http() gets called from the generic Curl_do() function when a HTTP
1629 * request is to be performed. This creates and sends a properly constructed
1632 CURLcode
Curl_http(struct connectdata
*conn
, bool *done
)
1634 struct SessionHandle
*data
=conn
->data
;
1635 char *buf
= data
->state
.buffer
; /* this is a short cut to the buffer */
1636 CURLcode result
=CURLE_OK
;
1638 char *ppath
= data
->reqdata
.path
;
1639 char *host
= conn
->host
.name
;
1640 const char *te
= ""; /* transfer-encoding */
1643 Curl_HttpReq httpreq
= data
->set
.httpreq
;
1644 char *addcookies
= NULL
;
1645 curl_off_t included_body
= 0;
1647 /* Always consider the DO phase done after this function call, even if there
1648 may be parts of the request that is not yet sent, since we can deal with
1649 the rest of the request in the PERFORM phase. */
1652 if(!data
->reqdata
.proto
.http
) {
1653 /* Only allocate this struct if we don't already have it! */
1655 http
= (struct HTTP
*)malloc(sizeof(struct HTTP
));
1657 return CURLE_OUT_OF_MEMORY
;
1658 memset(http
, 0, sizeof(struct HTTP
));
1659 data
->reqdata
.proto
.http
= http
;
1662 http
= data
->reqdata
.proto
.http
;
1664 /* We default to persistent connections */
1665 conn
->bits
.close
= FALSE
;
1667 if ( (conn
->protocol
&(PROT_HTTP
|PROT_FTP
)) &&
1669 httpreq
= HTTPREQ_PUT
;
1672 /* Now set the 'request' pointer to the proper request string */
1673 if(data
->set
.customrequest
)
1674 request
= data
->set
.customrequest
;
1676 if(conn
->bits
.no_body
)
1677 request
= (char *)"HEAD";
1679 curlassert((httpreq
> HTTPREQ_NONE
) && (httpreq
< HTTPREQ_LAST
));
1682 case HTTPREQ_POST_FORM
:
1683 request
= (char *)"POST";
1686 request
= (char *)"PUT";
1688 default: /* this should never happen */
1690 request
= (char *)"GET";
1693 request
= (char *)"HEAD";
1699 /* The User-Agent string might have been allocated in url.c already, because
1700 it might have been used in the proxy connect, but if we have got a header
1701 with the user-agent string specified, we erase the previously made string
1703 if(checkheaders(data
, "User-Agent:") && conn
->allocptr
.uagent
) {
1704 free(conn
->allocptr
.uagent
);
1705 conn
->allocptr
.uagent
=NULL
;
1708 /* setup the authentication headers */
1709 result
= Curl_http_output_auth(conn
, request
, ppath
, FALSE
);
1713 if((data
->state
.authhost
.multi
|| data
->state
.authproxy
.multi
) &&
1714 (httpreq
!= HTTPREQ_GET
) &&
1715 (httpreq
!= HTTPREQ_HEAD
)) {
1716 /* Auth is required and we are not authenticated yet. Make a PUT or POST
1717 with content-length zero as a "probe". */
1718 conn
->bits
.authneg
= TRUE
;
1721 conn
->bits
.authneg
= FALSE
;
1723 Curl_safefree(conn
->allocptr
.ref
);
1724 if(data
->change
.referer
&& !checkheaders(data
, "Referer:"))
1725 conn
->allocptr
.ref
= aprintf("Referer: %s\r\n", data
->change
.referer
);
1727 conn
->allocptr
.ref
= NULL
;
1729 if(data
->set
.cookie
&& !checkheaders(data
, "Cookie:"))
1730 addcookies
= data
->set
.cookie
;
1732 if(!checkheaders(data
, "Accept-Encoding:") &&
1733 data
->set
.encoding
) {
1734 Curl_safefree(conn
->allocptr
.accept_encoding
);
1735 conn
->allocptr
.accept_encoding
=
1736 aprintf("Accept-Encoding: %s\r\n", data
->set
.encoding
);
1737 if(!conn
->allocptr
.accept_encoding
)
1738 return CURLE_OUT_OF_MEMORY
;
1741 ptr
= checkheaders(data
, "Transfer-Encoding:");
1743 /* Some kind of TE is requested, check if 'chunked' is chosen */
1744 conn
->bits
.upload_chunky
=
1745 Curl_compareheader(ptr
, "Transfer-Encoding:", "chunked");
1748 if (httpreq
== HTTPREQ_GET
)
1749 conn
->bits
.upload_chunky
= FALSE
;
1750 if(conn
->bits
.upload_chunky
)
1751 te
= "Transfer-Encoding: chunked\r\n";
1754 Curl_safefree(conn
->allocptr
.host
);
1756 ptr
= checkheaders(data
, "Host:");
1757 if(ptr
&& (!data
->state
.this_is_a_follow
||
1758 curl_strequal(data
->state
.first_host
, conn
->host
.name
))) {
1759 #if !defined(CURL_DISABLE_COOKIES)
1760 /* If we have a given custom Host: header, we extract the host name in
1761 order to possibly use it for cookie reasons later on. We only allow the
1762 custom Host: header if this is NOT a redirect, as setting Host: in the
1763 redirected request is being out on thin ice. Except if the host name
1764 is the same as the first one! */
1765 char *start
= ptr
+strlen("Host:");
1766 while(*start
&& ISSPACE(*start
))
1768 ptr
= start
; /* start host-scanning here */
1770 /* scan through the string to find the end (space or colon) */
1771 while(*ptr
&& !ISSPACE(*ptr
) && !(':'==*ptr
))
1775 size_t len
=ptr
-start
;
1776 Curl_safefree(conn
->allocptr
.cookiehost
);
1777 conn
->allocptr
.cookiehost
= malloc(len
+1);
1778 if(!conn
->allocptr
.cookiehost
)
1779 return CURLE_OUT_OF_MEMORY
;
1780 memcpy(conn
->allocptr
.cookiehost
, start
, len
);
1781 conn
->allocptr
.cookiehost
[len
]=0;
1785 conn
->allocptr
.host
= NULL
;
1788 /* When building Host: headers, we must put the host name within
1789 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
1791 if(((conn
->protocol
&PROT_HTTPS
) && (conn
->remote_port
== PORT_HTTPS
)) ||
1792 (!(conn
->protocol
&PROT_HTTPS
) && (conn
->remote_port
== PORT_HTTP
)) )
1793 /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
1794 the port number in the host string */
1795 conn
->allocptr
.host
= aprintf("Host: %s%s%s\r\n",
1796 conn
->bits
.ipv6_ip
?"[":"",
1798 conn
->bits
.ipv6_ip
?"]":"");
1800 conn
->allocptr
.host
= aprintf("Host: %s%s%s:%d\r\n",
1801 conn
->bits
.ipv6_ip
?"[":"",
1803 conn
->bits
.ipv6_ip
?"]":"",
1806 if(!conn
->allocptr
.host
)
1807 /* without Host: we can't make a nice request */
1808 return CURLE_OUT_OF_MEMORY
;
1811 if (conn
->bits
.httpproxy
&& !conn
->bits
.tunnel_proxy
) {
1812 /* Using a proxy but does not tunnel through it */
1814 /* The path sent to the proxy is in fact the entire URL. But if the remote
1815 host is a IDN-name, we must make sure that the request we produce only
1816 uses the encoded host name! */
1817 if(conn
->host
.dispname
!= conn
->host
.name
) {
1818 char *url
= data
->change
.url
;
1819 ptr
= strstr(url
, conn
->host
.dispname
);
1821 /* This is where the display name starts in the URL, now replace this
1822 part with the encoded name. TODO: This method of replacing the host
1823 name is rather crude as I believe there's a slight risk that the
1824 user has entered a user name or password that contain the host name
1826 size_t currlen
= strlen(conn
->host
.dispname
);
1827 size_t newlen
= strlen(conn
->host
.name
);
1828 size_t urllen
= strlen(url
);
1832 newurl
= malloc(urllen
+ newlen
- currlen
+ 1);
1834 /* copy the part before the host name */
1835 memcpy(newurl
, url
, ptr
- url
);
1836 /* append the new host name instead of the old */
1837 memcpy(newurl
+ (ptr
- url
), conn
->host
.name
, newlen
);
1838 /* append the piece after the host name */
1839 memcpy(newurl
+ newlen
+ (ptr
- url
),
1840 ptr
+ currlen
, /* copy the trailing zero byte too */
1841 urllen
- (ptr
-url
) - currlen
+ 1);
1842 if(data
->change
.url_alloc
)
1843 free(data
->change
.url
);
1844 data
->change
.url
= newurl
;
1845 data
->change
.url_alloc
= TRUE
;
1848 return CURLE_OUT_OF_MEMORY
;
1851 ppath
= data
->change
.url
;
1853 if(HTTPREQ_POST_FORM
== httpreq
) {
1854 /* we must build the whole darned post sequence first, so that we have
1855 a size of the whole shebang before we start to send it */
1856 result
= Curl_getFormData(&http
->sendit
, data
->set
.httppost
,
1857 checkheaders(data
, "Content-Type:"),
1859 if(CURLE_OK
!= result
) {
1860 /* Curl_getFormData() doesn't use failf() */
1861 failf(data
, "failed creating formpost data");
1868 (!checkheaders(data
, "Pragma:") &&
1869 (conn
->bits
.httpproxy
&& !conn
->bits
.tunnel_proxy
) )?
1870 "Pragma: no-cache\r\n":NULL
;
1872 if(!checkheaders(data
, "Accept:"))
1873 http
->p_accept
= "Accept: */*\r\n";
1875 if(( (HTTPREQ_POST
== httpreq
) ||
1876 (HTTPREQ_POST_FORM
== httpreq
) ||
1877 (HTTPREQ_PUT
== httpreq
) ) &&
1878 data
->reqdata
.resume_from
) {
1879 /**********************************************************************
1880 * Resuming upload in HTTP means that we PUT or POST and that we have
1881 * got a resume_from value set. The resume value has already created
1882 * a Range: header that will be passed along. We need to "fast forward"
1883 * the file the given number of bytes and decrease the assume upload
1884 * file size before we continue this venture in the dark lands of HTTP.
1885 *********************************************************************/
1887 if(data
->reqdata
.resume_from
< 0 ) {
1889 * This is meant to get the size of the present remote-file by itself.
1890 * We don't support this now. Bail out!
1892 data
->reqdata
.resume_from
= 0;
1895 if(data
->reqdata
.resume_from
) {
1896 /* do we still game? */
1897 curl_off_t passed
=0;
1899 /* Now, let's read off the proper amount of bytes from the
1900 input. If we knew it was a proper file we could've just
1901 fseek()ed but we only have a stream here */
1903 size_t readthisamountnow
= (size_t)(data
->reqdata
.resume_from
- passed
);
1904 size_t actuallyread
;
1906 if(readthisamountnow
> BUFSIZE
)
1907 readthisamountnow
= BUFSIZE
;
1910 data
->set
.fread(data
->state
.buffer
, 1, (size_t)readthisamountnow
,
1913 passed
+= actuallyread
;
1914 if(actuallyread
!= readthisamountnow
) {
1915 failf(data
, "Could only read %" FORMAT_OFF_T
1916 " bytes from the input",
1918 return CURLE_READ_ERROR
;
1920 } while(passed
!= data
->reqdata
.resume_from
); /* loop until done */
1922 /* now, decrease the size of the read */
1923 if(data
->set
.infilesize
>0) {
1924 data
->set
.infilesize
-= data
->reqdata
.resume_from
;
1926 if(data
->set
.infilesize
<= 0) {
1927 failf(data
, "File already completely uploaded");
1928 return CURLE_PARTIAL_FILE
;
1931 /* we've passed, proceed as normal */
1934 if(data
->reqdata
.use_range
) {
1936 * A range is selected. We use different headers whether we're downloading
1937 * or uploading and we always let customized headers override our internal
1938 * ones if any such are specified.
1940 if((httpreq
== HTTPREQ_GET
) &&
1941 !checkheaders(data
, "Range:")) {
1942 /* if a line like this was already allocated, free the previous one */
1943 if(conn
->allocptr
.rangeline
)
1944 free(conn
->allocptr
.rangeline
);
1945 conn
->allocptr
.rangeline
= aprintf("Range: bytes=%s\r\n", data
->reqdata
.range
);
1947 else if((httpreq
!= HTTPREQ_GET
) &&
1948 !checkheaders(data
, "Content-Range:")) {
1950 if(data
->reqdata
.resume_from
) {
1951 /* This is because "resume" was selected */
1952 curl_off_t total_expected_size
=
1953 data
->reqdata
.resume_from
+ data
->set
.infilesize
;
1954 conn
->allocptr
.rangeline
=
1955 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
1956 "/%" FORMAT_OFF_T
"\r\n",
1957 data
->reqdata
.range
, total_expected_size
-1,
1958 total_expected_size
);
1961 /* Range was selected and then we just pass the incoming range and
1962 append total size */
1963 conn
->allocptr
.rangeline
=
1964 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T
"\r\n",
1965 data
->reqdata
.range
, data
->set
.infilesize
);
1971 /* Use 1.1 unless the use specificly asked for 1.0 */
1972 const char *httpstring
=
1973 data
->set
.httpversion
==CURL_HTTP_VERSION_1_0
?"1.0":"1.1";
1975 send_buffer
*req_buffer
;
1976 curl_off_t postsize
; /* off_t type to be able to hold a large file size */
1978 /* initialize a dynamic send-buffer */
1979 req_buffer
= add_buffer_init();
1982 return CURLE_OUT_OF_MEMORY
;
1984 /* add the main request stuff */
1986 add_bufferf(req_buffer
,
1987 "%s " /* GET/HEAD/POST/PUT */
1988 "%s HTTP/%s\r\n" /* path + HTTP version */
1989 "%s" /* proxyuserpwd */
1992 "%s" /* user agent */
1996 "%s" /* accept-encoding */
1998 "%s" /* Proxy-Connection */
1999 "%s",/* transfer-encoding */
2004 conn
->allocptr
.proxyuserpwd
?
2005 conn
->allocptr
.proxyuserpwd
:"",
2006 conn
->allocptr
.userpwd
?conn
->allocptr
.userpwd
:"",
2007 (data
->reqdata
.use_range
&& conn
->allocptr
.rangeline
)?
2008 conn
->allocptr
.rangeline
:"",
2009 (data
->set
.useragent
&& *data
->set
.useragent
&& conn
->allocptr
.uagent
)?
2010 conn
->allocptr
.uagent
:"",
2011 (conn
->allocptr
.host
?conn
->allocptr
.host
:""), /* Host: host */
2012 http
->p_pragma
?http
->p_pragma
:"",
2013 http
->p_accept
?http
->p_accept
:"",
2014 (data
->set
.encoding
&& *data
->set
.encoding
&& conn
->allocptr
.accept_encoding
)?
2015 conn
->allocptr
.accept_encoding
:"",
2016 (data
->change
.referer
&& conn
->allocptr
.ref
)?conn
->allocptr
.ref
:"" /* Referer: <data> */,
2017 (conn
->bits
.httpproxy
&&
2018 !conn
->bits
.tunnel_proxy
&&
2019 !checkheaders(data
, "Proxy-Connection:"))?
2020 "Proxy-Connection: Keep-Alive\r\n":"",
2027 #if !defined(CURL_DISABLE_COOKIES)
2028 if(data
->cookies
|| addcookies
) {
2029 struct Cookie
*co
=NULL
; /* no cookies from start */
2033 Curl_share_lock(data
, CURL_LOCK_DATA_COOKIE
, CURL_LOCK_ACCESS_SINGLE
);
2034 co
= Curl_cookie_getlist(data
->cookies
,
2035 conn
->allocptr
.cookiehost
?
2036 conn
->allocptr
.cookiehost
:host
, data
->reqdata
.path
,
2037 (bool)(conn
->protocol
&PROT_HTTPS
?TRUE
:FALSE
));
2038 Curl_share_unlock(data
, CURL_LOCK_DATA_COOKIE
);
2041 struct Cookie
*store
=co
;
2042 /* now loop through all cookies that matched */
2046 result
= add_bufferf(req_buffer
, "Cookie: ");
2050 result
= add_bufferf(req_buffer
,
2051 "%s%s=%s", count
?"; ":"",
2052 co
->name
, co
->value
);
2057 co
= co
->next
; /* next cookie please */
2059 Curl_cookie_freelist(store
); /* free the cookie list */
2061 if(addcookies
&& (CURLE_OK
== result
)) {
2063 result
= add_bufferf(req_buffer
, "Cookie: ");
2064 if(CURLE_OK
== result
) {
2065 result
= add_bufferf(req_buffer
, "%s%s",
2071 if(count
&& (CURLE_OK
== result
))
2072 result
= add_buffer(req_buffer
, "\r\n", 2);
2079 if(data
->set
.timecondition
) {
2082 /* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since
2083 * header family should have their times set in GMT as RFC2616 defines:
2084 * "All HTTP date/time stamps MUST be represented in Greenwich Mean Time
2085 * (GMT), without exception. For the purposes of HTTP, GMT is exactly
2086 * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616).
2089 #ifdef HAVE_GMTIME_R
2090 /* thread-safe version */
2092 tm
= (struct tm
*)gmtime_r(&data
->set
.timevalue
, &keeptime
);
2094 tm
= gmtime(&data
->set
.timevalue
);
2097 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
2098 snprintf(buf
, BUFSIZE
-1,
2099 "%s, %02d %s %4d %02d:%02d:%02d GMT",
2100 Curl_wkday
[tm
->tm_wday
?tm
->tm_wday
-1:6],
2102 Curl_month
[tm
->tm_mon
],
2108 switch(data
->set
.timecondition
) {
2109 case CURL_TIMECOND_IFMODSINCE
:
2111 result
= add_bufferf(req_buffer
,
2112 "If-Modified-Since: %s\r\n", buf
);
2114 case CURL_TIMECOND_IFUNMODSINCE
:
2115 result
= add_bufferf(req_buffer
,
2116 "If-Unmodified-Since: %s\r\n", buf
);
2118 case CURL_TIMECOND_LASTMOD
:
2119 result
= add_bufferf(req_buffer
,
2120 "Last-Modified: %s\r\n", buf
);
2127 result
= add_custom_headers(conn
, req_buffer
);
2131 http
->postdata
= NULL
; /* nothing to post at this point */
2132 Curl_pgrsSetUploadSize(data
, 0); /* upload size is 0 atm */
2134 /* If 'authdone' is FALSE, we must not set the write socket index to the
2135 Curl_transfer() call below, as we're not ready to actually upload any
2140 case HTTPREQ_POST_FORM
:
2141 if(!http
->sendit
|| conn
->bits
.authneg
) {
2142 /* nothing to post! */
2143 result
= add_bufferf(req_buffer
, "Content-Length: 0\r\n\r\n");
2147 result
= add_buffer_send(req_buffer
, conn
,
2148 &data
->info
.request_size
, 0, FIRSTSOCKET
);
2150 failf(data
, "Failed sending POST request");
2152 /* setup variables for the upcoming transfer */
2153 result
= Curl_setup_transfer(conn
, FIRSTSOCKET
, -1, TRUE
,
2154 &http
->readbytecount
,
2159 if(Curl_FormInit(&http
->form
, http
->sendit
)) {
2160 failf(data
, "Internal HTTP POST error!");
2161 return CURLE_HTTP_POST_ERROR
;
2164 /* set the read function to read from the generated form data */
2165 conn
->fread
= (curl_read_callback
)Curl_FormReader
;
2166 conn
->fread_in
= &http
->form
;
2168 http
->sending
= HTTPSEND_BODY
;
2170 if(!conn
->bits
.upload_chunky
) {
2171 /* only add Content-Length if not uploading chunked */
2172 result
= add_bufferf(req_buffer
,
2173 "Content-Length: %" FORMAT_OFF_T
"\r\n",
2179 result
= expect100(data
, req_buffer
);
2185 /* Get Content-Type: line from Curl_formpostheader.
2188 size_t linelength
=0;
2189 contentType
= Curl_formpostheader((void *)&http
->form
,
2192 failf(data
, "Could not get Content-Type header line!");
2193 return CURLE_HTTP_POST_ERROR
;
2196 result
= add_buffer(req_buffer
, contentType
, linelength
);
2201 /* make the request end in a true CRLF */
2202 result
= add_buffer(req_buffer
, "\r\n", 2);
2206 /* set upload size to the progress meter */
2207 Curl_pgrsSetUploadSize(data
, http
->postsize
);
2209 /* fire away the whole request to the server */
2210 result
= add_buffer_send(req_buffer
, conn
,
2211 &data
->info
.request_size
, 0, FIRSTSOCKET
);
2213 failf(data
, "Failed sending POST request");
2215 /* setup variables for the upcoming transfer */
2216 result
= Curl_setup_transfer(conn
, FIRSTSOCKET
, -1, TRUE
,
2217 &http
->readbytecount
,
2219 &http
->writebytecount
);
2222 Curl_formclean(&http
->sendit
); /* free that whole lot */
2225 #ifdef CURL_DOES_CONVERSIONS
2226 /* time to convert the form data... */
2227 result
= Curl_formconvert(data
, http
->sendit
);
2229 Curl_formclean(&http
->sendit
); /* free that whole lot */
2232 #endif /* CURL_DOES_CONVERSIONS */
2235 case HTTPREQ_PUT
: /* Let's PUT the data to the server! */
2237 if(conn
->bits
.authneg
)
2240 postsize
= data
->set
.infilesize
;
2242 if((postsize
!= -1) && !conn
->bits
.upload_chunky
) {
2243 /* only add Content-Length if not uploading chunked */
2244 result
= add_bufferf(req_buffer
,
2245 "Content-Length: %" FORMAT_OFF_T
"\r\n",
2251 result
= expect100(data
, req_buffer
);
2255 result
= add_buffer(req_buffer
, "\r\n", 2); /* end of headers */
2259 /* set the upload size to the progress meter */
2260 Curl_pgrsSetUploadSize(data
, postsize
);
2262 /* this sends the buffer and frees all the buffer resources */
2263 result
= add_buffer_send(req_buffer
, conn
,
2264 &data
->info
.request_size
, 0, FIRSTSOCKET
);
2266 failf(data
, "Failed sending PUT request");
2268 /* prepare for transfer */
2269 result
= Curl_setup_transfer(conn
, FIRSTSOCKET
, -1, TRUE
,
2270 &http
->readbytecount
,
2271 postsize
?FIRSTSOCKET
:-1,
2272 postsize
?&http
->writebytecount
:NULL
);
2278 /* this is the simple POST, using x-www-form-urlencoded style */
2280 if(conn
->bits
.authneg
)
2283 /* figure out the size of the postfields */
2284 postsize
= (data
->set
.postfieldsize
!= -1)?
2285 data
->set
.postfieldsize
:
2286 (data
->set
.postfields
?(curl_off_t
)strlen(data
->set
.postfields
):0);
2288 if(!conn
->bits
.upload_chunky
) {
2289 /* We only set Content-Length and allow a custom Content-Length if
2290 we don't upload data chunked, as RFC2616 forbids us to set both
2291 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2293 if(!checkheaders(data
, "Content-Length:")) {
2294 /* we allow replacing this header, although it isn't very wise to
2295 actually set your own */
2296 result
= add_bufferf(req_buffer
,
2297 "Content-Length: %" FORMAT_OFF_T
"\r\n",
2304 if(!checkheaders(data
, "Content-Type:")) {
2305 result
= add_bufferf(req_buffer
,
2306 "Content-Type: application/x-www-form-urlencoded\r\n");
2311 if(data
->set
.postfields
) {
2313 /* for really small posts we don't use Expect: headers at all, and for
2314 the somewhat bigger ones we allow the app to disable it */
2315 if(postsize
> TINY_INITIAL_POST_SIZE
) {
2316 result
= expect100(data
, req_buffer
);
2321 data
->state
.expect100header
= FALSE
;
2323 if(!data
->state
.expect100header
&&
2324 (postsize
< MAX_INITIAL_POST_SIZE
)) {
2325 /* if we don't use expect:-100 AND
2326 postsize is less than MAX_INITIAL_POST_SIZE
2328 then append the post data to the HTTP request header. This limit
2329 is no magic limit but only set to prevent really huge POSTs to
2330 get the data duplicated with malloc() and family. */
2332 result
= add_buffer(req_buffer
, "\r\n", 2); /* end of headers! */
2336 if(!conn
->bits
.upload_chunky
) {
2337 /* We're not sending it 'chunked', append it to the request
2338 already now to reduce the number if send() calls */
2339 result
= add_buffer(req_buffer
, data
->set
.postfields
,
2341 included_body
= postsize
;
2344 /* Append the POST data chunky-style */
2345 result
= add_bufferf(req_buffer
, "%x\r\n", (int)postsize
);
2346 if(CURLE_OK
== result
)
2347 result
= add_buffer(req_buffer
, data
->set
.postfields
,
2349 if(CURLE_OK
== result
)
2350 result
= add_buffer(req_buffer
,
2351 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
2352 /* CR LF 0 CR LF CR LF */
2353 included_body
= postsize
+ 7;
2359 /* A huge POST coming up, do data separate from the request */
2360 http
->postsize
= postsize
;
2361 http
->postdata
= data
->set
.postfields
;
2363 http
->sending
= HTTPSEND_BODY
;
2365 conn
->fread
= (curl_read_callback
)readmoredata
;
2366 conn
->fread_in
= (void *)conn
;
2368 /* set the upload size to the progress meter */
2369 Curl_pgrsSetUploadSize(data
, http
->postsize
);
2371 add_buffer(req_buffer
, "\r\n", 2); /* end of headers! */
2375 add_buffer(req_buffer
, "\r\n", 2); /* end of headers! */
2377 if(data
->set
.postfieldsize
) {
2378 /* set the upload size to the progress meter */
2379 Curl_pgrsSetUploadSize(data
, postsize
?postsize
:-1);
2381 /* set the pointer to mark that we will send the post body using
2382 the read callback */
2383 http
->postdata
= (char *)&http
->postdata
;
2386 /* issue the request */
2387 result
= add_buffer_send(req_buffer
, conn
, &data
->info
.request_size
,
2388 (size_t)included_body
, FIRSTSOCKET
);
2391 failf(data
, "Failed sending HTTP POST request");
2394 Curl_setup_transfer(conn
, FIRSTSOCKET
, -1, TRUE
,
2395 &http
->readbytecount
,
2396 http
->postdata
?FIRSTSOCKET
:-1,
2397 http
->postdata
?&http
->writebytecount
:NULL
);
2401 add_buffer(req_buffer
, "\r\n", 2);
2403 /* issue the request */
2404 result
= add_buffer_send(req_buffer
, conn
,
2405 &data
->info
.request_size
, 0, FIRSTSOCKET
);
2408 failf(data
, "Failed sending HTTP request");
2410 /* HTTP GET/HEAD download: */
2411 result
= Curl_setup_transfer(conn
, FIRSTSOCKET
, -1, TRUE
,
2412 &http
->readbytecount
,
2413 http
->postdata
?FIRSTSOCKET
:-1,
2414 http
->postdata
?&http
->writebytecount
:NULL
);