00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026 #ifndef CURL_DISABLE_HTTP
00027
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdarg.h>
00031 #include <stdlib.h>
00032 #include <ctype.h>
00033
00034 #ifdef WIN32
00035 #include <time.h>
00036 #include <io.h>
00037 #else
00038 #ifdef HAVE_SYS_SOCKET_H
00039 #include <sys/socket.h>
00040 #endif
00041 #ifdef HAVE_NETINET_IN_H
00042 #include <netinet/in.h>
00043 #endif
00044 #ifdef HAVE_SYS_TIME_H
00045 #include <sys/time.h>
00046 #endif
00047
00048 #ifdef HAVE_TIME_H
00049 #ifdef TIME_WITH_SYS_TIME
00050 #include <time.h>
00051 #endif
00052 #endif
00053
00054 #ifdef HAVE_UNISTD_H
00055 #include <unistd.h>
00056 #endif
00057 #ifdef HAVE_NETDB_H
00058 #include <netdb.h>
00059 #endif
00060 #ifdef HAVE_ARPA_INET_H
00061 #include <arpa/inet.h>
00062 #endif
00063 #ifdef HAVE_NET_IF_H
00064 #include <net/if.h>
00065 #endif
00066 #ifdef HAVE_SYS_IOCTL_H
00067 #include <sys/ioctl.h>
00068 #endif
00069 #include <signal.h>
00070
00071 #ifdef HAVE_SYS_PARAM_H
00072 #include <sys/param.h>
00073 #endif
00074
00075 #endif
00076
00077 #include "urldata.h"
00078 #include <curl/curl.h>
00079 #include "transfer.h"
00080 #include "sendf.h"
00081 #include "easyif.h"
00082 #include "formdata.h"
00083 #include "progress.h"
00084 #include "base64.h"
00085 #include "cookie.h"
00086 #include "strequal.h"
00087 #include "sslgen.h"
00088 #include "http_digest.h"
00089 #include "http_ntlm.h"
00090 #include "http_negotiate.h"
00091 #include "url.h"
00092 #include "share.h"
00093 #include "hostip.h"
00094 #include "http.h"
00095 #include "memory.h"
00096 #include "select.h"
00097 #include "parsedate.h"
00098 #include "strtoofft.h"
00099 #include "multiif.h"
00100
00101 #define _MPRINTF_REPLACE
00102 #include <curl/mprintf.h>
00103
00104
00105 #include "memdebug.h"
00106
00107
00108
00109
00110
00111
00112
00113 static char *checkheaders(struct SessionHandle *data, const char *thisheader)
00114 {
00115 struct curl_slist *head;
00116 size_t thislen = strlen(thisheader);
00117
00118 for(head = data->set.headers; head; head=head->next) {
00119 if(strnequal(head->data, thisheader, thislen))
00120 return head->data;
00121 }
00122 return NULL;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
00132 {
00133 char *authorization;
00134 struct SessionHandle *data=conn->data;
00135 char **userp;
00136 char *user;
00137 char *pwd;
00138
00139 if(proxy) {
00140 userp = &conn->allocptr.proxyuserpwd;
00141 user = conn->proxyuser;
00142 pwd = conn->proxypasswd;
00143 }
00144 else {
00145 userp = &conn->allocptr.userpwd;
00146 user = conn->user;
00147 pwd = conn->passwd;
00148 }
00149
00150 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
00151 if(Curl_base64_encode(data, data->state.buffer,
00152 strlen(data->state.buffer),
00153 &authorization) > 0) {
00154 if(*userp)
00155 free(*userp);
00156 *userp = aprintf( "%sAuthorization: Basic %s\r\n",
00157 proxy?"Proxy-":"",
00158 authorization);
00159 free(authorization);
00160 if(!*userp)
00161 return CURLE_OUT_OF_MEMORY;
00162 }
00163 else
00164 return CURLE_OUT_OF_MEMORY;
00165 return CURLE_OK;
00166 }
00167
00168
00169
00170
00171
00172
00173 static bool pickoneauth(struct auth *pick)
00174 {
00175 bool picked;
00176
00177 long avail = pick->avail & pick->want;
00178 picked = TRUE;
00179
00180
00181
00182 if(avail & CURLAUTH_GSSNEGOTIATE)
00183 pick->picked = CURLAUTH_GSSNEGOTIATE;
00184 else if(avail & CURLAUTH_DIGEST)
00185 pick->picked = CURLAUTH_DIGEST;
00186 else if(avail & CURLAUTH_NTLM)
00187 pick->picked = CURLAUTH_NTLM;
00188 else if(avail & CURLAUTH_BASIC)
00189 pick->picked = CURLAUTH_BASIC;
00190 else {
00191 pick->picked = CURLAUTH_PICKNONE;
00192 picked = FALSE;
00193 }
00194 pick->avail = CURLAUTH_NONE;
00195
00196 return picked;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 static CURLcode perhapsrewind(struct connectdata *conn)
00223 {
00224 struct SessionHandle *data = conn->data;
00225 struct HTTP *http = data->reqdata.proto.http;
00226 struct Curl_transfer_keeper *k = &data->reqdata.keep;
00227 curl_off_t bytessent;
00228 curl_off_t expectsend = -1;
00229
00230 if(!http)
00231
00232
00233 return CURLE_OK;
00234
00235 bytessent = http->writebytecount;
00236
00237 if(conn->bits.authneg)
00238
00239
00240 expectsend = 0;
00241 else {
00242
00243 switch(data->set.httpreq) {
00244 case HTTPREQ_POST:
00245 if(data->set.postfieldsize != -1)
00246 expectsend = data->set.postfieldsize;
00247 break;
00248 case HTTPREQ_PUT:
00249 if(data->set.infilesize != -1)
00250 expectsend = data->set.infilesize;
00251 break;
00252 case HTTPREQ_POST_FORM:
00253 expectsend = http->postsize;
00254 break;
00255 default:
00256 break;
00257 }
00258 }
00259
00260 conn->bits.rewindaftersend = FALSE;
00261
00262 if((expectsend == -1) || (expectsend > bytessent)) {
00263
00264 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
00265 (data->state.authhost.picked == CURLAUTH_NTLM)) {
00266 if(((expectsend - bytessent) < 2000) ||
00267 (conn->ntlm.state != NTLMSTATE_NONE)) {
00268
00269
00270
00271
00272 if(!conn->bits.authneg)
00273 conn->bits.rewindaftersend = TRUE;
00274
00275 return CURLE_OK;
00276 }
00277 if(conn->bits.close)
00278
00279 return CURLE_OK;
00280
00281 infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T
00282 " bytes\n", (curl_off_t)(expectsend - bytessent));
00283 }
00284
00285
00286
00287 conn->bits.close = TRUE;
00288 k->size = 0;
00289 }
00290
00291 if(bytessent)
00292 return Curl_readrewind(conn);
00293
00294 return CURLE_OK;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 CURLcode Curl_http_auth_act(struct connectdata *conn)
00305 {
00306 struct SessionHandle *data = conn->data;
00307 bool pickhost = FALSE;
00308 bool pickproxy = FALSE;
00309 CURLcode code = CURLE_OK;
00310
00311 if(100 == data->reqdata.keep.httpcode)
00312
00313 return CURLE_OK;
00314
00315 if(data->state.authproblem)
00316 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
00317
00318 if(conn->bits.user_passwd &&
00319 ((data->reqdata.keep.httpcode == 401) ||
00320 (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
00321 pickhost = pickoneauth(&data->state.authhost);
00322 if(!pickhost)
00323 data->state.authproblem = TRUE;
00324 }
00325 if(conn->bits.proxy_user_passwd &&
00326 ((data->reqdata.keep.httpcode == 407) ||
00327 (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
00328 pickproxy = pickoneauth(&data->state.authproxy);
00329 if(!pickproxy)
00330 data->state.authproblem = TRUE;
00331 }
00332
00333 if(pickhost || pickproxy) {
00334 data->reqdata.newurl = strdup(data->change.url);
00335 if (!data->reqdata.newurl)
00336 return CURLE_OUT_OF_MEMORY;
00337
00338 if((data->set.httpreq != HTTPREQ_GET) &&
00339 (data->set.httpreq != HTTPREQ_HEAD) &&
00340 !conn->bits.rewindaftersend) {
00341 code = perhapsrewind(conn);
00342 if(code)
00343 return code;
00344 }
00345 }
00346
00347 else if((data->reqdata.keep.httpcode < 300) &&
00348 (!data->state.authhost.done) &&
00349 conn->bits.authneg) {
00350
00351
00352
00353
00354 if((data->set.httpreq != HTTPREQ_GET) &&
00355 (data->set.httpreq != HTTPREQ_HEAD)) {
00356 data->reqdata.newurl = strdup(data->change.url);
00357 if (!data->reqdata.newurl)
00358 return CURLE_OUT_OF_MEMORY;
00359 data->state.authhost.done = TRUE;
00360 }
00361 }
00362 if (Curl_http_should_fail(conn)) {
00363 failf (data, "The requested URL returned error: %d",
00364 data->reqdata.keep.httpcode);
00365 code = CURLE_HTTP_RETURNED_ERROR;
00366 }
00367
00368 return code;
00369 }
00370
00385 static CURLcode
00386 Curl_http_output_auth(struct connectdata *conn,
00387 char *request,
00388 char *path,
00389 bool proxytunnel)
00390
00391 {
00392 CURLcode result = CURLE_OK;
00393 struct SessionHandle *data = conn->data;
00394 char *auth=NULL;
00395 struct auth *authhost;
00396 struct auth *authproxy;
00397
00398 DEBUGASSERT(data);
00399
00400 authhost = &data->state.authhost;
00401 authproxy = &data->state.authproxy;
00402
00403 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
00404 conn->bits.user_passwd)
00405 ;
00406 else {
00407 authhost->done = TRUE;
00408 authproxy->done = TRUE;
00409 return CURLE_OK;
00410 }
00411
00412 if(authhost->want && !authhost->picked)
00413
00414
00415
00416 authhost->picked = authhost->want;
00417
00418 if(authproxy->want && !authproxy->picked)
00419
00420
00421
00422 authproxy->picked = authproxy->want;
00423
00424
00425 if (conn->bits.httpproxy &&
00426 (conn->bits.tunnel_proxy == proxytunnel)) {
00427 #ifdef USE_NTLM
00428 if(authproxy->picked == CURLAUTH_NTLM) {
00429 auth=(char *)"NTLM";
00430 result = Curl_output_ntlm(conn, TRUE);
00431 if(result)
00432 return result;
00433 }
00434 else
00435 #endif
00436 if(authproxy->picked == CURLAUTH_BASIC) {
00437
00438 if(conn->bits.proxy_user_passwd &&
00439 !checkheaders(data, "Proxy-authorization:")) {
00440 auth=(char *)"Basic";
00441 result = Curl_output_basic(conn, TRUE);
00442 if(result)
00443 return result;
00444 }
00445
00446
00447 authproxy->done = TRUE;
00448 }
00449 #ifndef CURL_DISABLE_CRYPTO_AUTH
00450 else if(authproxy->picked == CURLAUTH_DIGEST) {
00451 auth=(char *)"Digest";
00452 result = Curl_output_digest(conn,
00453 TRUE,
00454 (unsigned char *)request,
00455 (unsigned char *)path);
00456 if(result)
00457 return result;
00458 }
00459 #endif
00460 if(auth) {
00461 infof(data, "Proxy auth using %s with user '%s'\n",
00462 auth, conn->proxyuser?conn->proxyuser:"");
00463 authproxy->multi = (bool)(!authproxy->done);
00464 }
00465 else
00466 authproxy->multi = FALSE;
00467 }
00468 else
00469
00470
00471 authproxy->done = TRUE;
00472
00473
00474
00475 if(!data->state.this_is_a_follow ||
00476 conn->bits.netrc ||
00477 !data->state.first_host ||
00478 curl_strequal(data->state.first_host, conn->host.name) ||
00479 data->set.http_disable_hostname_check_before_authentication) {
00480
00481
00482 {
00483 auth = NULL;
00484 #ifdef HAVE_GSSAPI
00485 if((authhost->picked == CURLAUTH_GSSNEGOTIATE) &&
00486 data->state.negotiate.context &&
00487 !GSS_ERROR(data->state.negotiate.status)) {
00488 auth=(char *)"GSS-Negotiate";
00489 result = Curl_output_negotiate(conn);
00490 if (result)
00491 return result;
00492 authhost->done = TRUE;
00493 }
00494 else
00495 #endif
00496 #ifdef USE_NTLM
00497 if(authhost->picked == CURLAUTH_NTLM) {
00498 auth=(char *)"NTLM";
00499 result = Curl_output_ntlm(conn, FALSE);
00500 if(result)
00501 return result;
00502 }
00503 else
00504 #endif
00505 {
00506 #ifndef CURL_DISABLE_CRYPTO_AUTH
00507 if(authhost->picked == CURLAUTH_DIGEST) {
00508 auth=(char *)"Digest";
00509 result = Curl_output_digest(conn,
00510 FALSE,
00511 (unsigned char *)request,
00512 (unsigned char *)path);
00513 if(result)
00514 return result;
00515 } else
00516 #endif
00517 if(authhost->picked == CURLAUTH_BASIC) {
00518 if(conn->bits.user_passwd &&
00519 !checkheaders(data, "Authorization:")) {
00520 auth=(char *)"Basic";
00521 result = Curl_output_basic(conn, FALSE);
00522 if(result)
00523 return result;
00524 }
00525
00526 authhost->done = TRUE;
00527 }
00528 }
00529 if(auth) {
00530 infof(data, "Server auth using %s with user '%s'\n",
00531 auth, conn->user);
00532
00533 authhost->multi = (bool)(!authhost->done);
00534 }
00535 else
00536 authhost->multi = FALSE;
00537 }
00538 }
00539 else
00540 authhost->done = TRUE;
00541
00542 return result;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552 CURLcode Curl_http_input_auth(struct connectdata *conn,
00553 int httpcode,
00554 char *header)
00555 {
00556
00557
00558
00559 struct SessionHandle *data = conn->data;
00560
00561 long *availp;
00562 char *start;
00563 struct auth *authp;
00564
00565 if (httpcode == 407) {
00566 start = header+strlen("Proxy-authenticate:");
00567 availp = &data->info.proxyauthavail;
00568 authp = &data->state.authproxy;
00569 }
00570 else {
00571 start = header+strlen("WWW-Authenticate:");
00572 availp = &data->info.httpauthavail;
00573 authp = &data->state.authhost;
00574 }
00575
00576
00577 while(*start && ISSPACE(*start))
00578 start++;
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 #ifdef HAVE_GSSAPI
00590 if (checkprefix("GSS-Negotiate", start) ||
00591 checkprefix("Negotiate", start)) {
00592 *availp |= CURLAUTH_GSSNEGOTIATE;
00593 authp->avail |= CURLAUTH_GSSNEGOTIATE;
00594 if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
00595
00596 int neg = Curl_input_negotiate(conn, start);
00597 if (neg == 0) {
00598 data->reqdata.newurl = strdup(data->change.url);
00599 data->state.authproblem = (data->reqdata.newurl == NULL);
00600 }
00601 else {
00602 infof(data, "Authentication problem. Ignoring this.\n");
00603 data->state.authproblem = TRUE;
00604 }
00605 }
00606 }
00607 else
00608 #endif
00609 #ifdef USE_NTLM
00610
00611 if(checkprefix("NTLM", start)) {
00612 *availp |= CURLAUTH_NTLM;
00613 authp->avail |= CURLAUTH_NTLM;
00614 if(authp->picked == CURLAUTH_NTLM) {
00615
00616 CURLntlm ntlm =
00617 Curl_input_ntlm(conn, (bool)(httpcode == 407), start);
00618
00619 if(CURLNTLM_BAD != ntlm)
00620 data->state.authproblem = FALSE;
00621 else {
00622 infof(data, "Authentication problem. Ignoring this.\n");
00623 data->state.authproblem = TRUE;
00624 }
00625 }
00626 }
00627 else
00628 #endif
00629 #ifndef CURL_DISABLE_CRYPTO_AUTH
00630 if(checkprefix("Digest", start)) {
00631 if((authp->avail & CURLAUTH_DIGEST) != 0) {
00632 infof(data, "Ignoring duplicate digest auth header.\n");
00633 }
00634 else {
00635 CURLdigest dig;
00636 *availp |= CURLAUTH_DIGEST;
00637 authp->avail |= CURLAUTH_DIGEST;
00638
00639
00640
00641
00642 dig = Curl_input_digest(conn, (bool)(httpcode == 407), start);
00643
00644 if(CURLDIGEST_FINE != dig) {
00645 infof(data, "Authentication problem. Ignoring this.\n");
00646 data->state.authproblem = TRUE;
00647 }
00648 }
00649 }
00650 else
00651 #endif
00652 if(checkprefix("Basic", start)) {
00653 *availp |= CURLAUTH_BASIC;
00654 authp->avail |= CURLAUTH_BASIC;
00655 if(authp->picked == CURLAUTH_BASIC) {
00656
00657
00658
00659 authp->avail = CURLAUTH_NONE;
00660 infof(data, "Authentication problem. Ignoring this.\n");
00661 data->state.authproblem = TRUE;
00662 }
00663 }
00664
00665 return CURLE_OK;
00666 }
00667
00678 int Curl_http_should_fail(struct connectdata *conn)
00679 {
00680 struct SessionHandle *data;
00681 struct Curl_transfer_keeper *k;
00682
00683 DEBUGASSERT(conn);
00684 data = conn->data;
00685 DEBUGASSERT(data);
00686
00687
00688
00689
00690 k = &data->reqdata.keep;
00691
00692
00693
00694
00695
00696 if (!data->set.http_fail_on_error)
00697 return 0;
00698
00699
00700
00701
00702 if (k->httpcode < 400)
00703 return 0;
00704
00705 if (data->reqdata.resume_from &&
00706 (data->set.httpreq==HTTPREQ_GET) &&
00707 (k->httpcode == 416)) {
00708
00709
00710 return 0;
00711 }
00712
00713
00714
00715
00716
00717 if ((k->httpcode != 401) &&
00718 (k->httpcode != 407))
00719 return 1;
00720
00721
00722
00723
00724 DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407));
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 #if 0
00740 infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage);
00741 infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant);
00742 infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
00743 infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
00744 infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
00745 infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)");
00746 infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
00747 #endif
00748
00749
00750
00751
00752
00753 if((k->httpcode == 401) && !conn->bits.user_passwd)
00754 return TRUE;
00755 if((k->httpcode == 407) && !conn->bits.proxy_user_passwd)
00756 return TRUE;
00757
00758 return data->state.authproblem;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 static size_t readmoredata(char *buffer,
00770 size_t size,
00771 size_t nitems,
00772 void *userp)
00773 {
00774 struct connectdata *conn = (struct connectdata *)userp;
00775 struct HTTP *http = conn->data->reqdata.proto.http;
00776 size_t fullsize = size * nitems;
00777
00778 if(0 == http->postsize)
00779
00780 return 0;
00781
00782
00783 conn->bits.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST);
00784
00785 if(http->postsize <= (curl_off_t)fullsize) {
00786 memcpy(buffer, http->postdata, (size_t)http->postsize);
00787 fullsize = (size_t)http->postsize;
00788
00789 if(http->backup.postsize) {
00790
00791 http->postdata = http->backup.postdata;
00792 http->postsize = http->backup.postsize;
00793 conn->fread = http->backup.fread;
00794 conn->fread_in = http->backup.fread_in;
00795
00796 http->sending++;
00797
00798 http->backup.postsize=0;
00799 }
00800 else
00801 http->postsize = 0;
00802
00803 return fullsize;
00804 }
00805
00806 memcpy(buffer, http->postdata, fullsize);
00807 http->postdata += fullsize;
00808 http->postsize -= fullsize;
00809
00810 return fullsize;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820 struct send_buffer {
00821 char *buffer;
00822 size_t size_max;
00823 size_t size_used;
00824 };
00825 typedef struct send_buffer send_buffer;
00826
00827 static CURLcode add_custom_headers(struct connectdata *conn,
00828 send_buffer *req_buffer);
00829 static CURLcode
00830 add_buffer(send_buffer *in, const void *inptr, size_t size);
00831
00832
00833
00834
00835 static
00836 send_buffer *add_buffer_init(void)
00837 {
00838 send_buffer *blonk;
00839 blonk=(send_buffer *)malloc(sizeof(send_buffer));
00840 if(blonk) {
00841 memset(blonk, 0, sizeof(send_buffer));
00842 return blonk;
00843 }
00844 return NULL;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853 static
00854 CURLcode add_buffer_send(send_buffer *in,
00855 struct connectdata *conn,
00856 long *bytes_written,
00857
00858 size_t included_body_bytes,
00859
00860 int socketindex)
00861
00862 {
00863 ssize_t amount;
00864 CURLcode res;
00865 char *ptr;
00866 size_t size;
00867 struct HTTP *http = conn->data->reqdata.proto.http;
00868 size_t sendsize;
00869 curl_socket_t sockfd;
00870
00871 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
00872
00873 sockfd = conn->sock[socketindex];
00874
00875
00876
00877
00878 ptr = in->buffer;
00879 size = in->size_used;
00880
00881 #ifdef CURL_DOES_CONVERSIONS
00882 if(size - included_body_bytes > 0) {
00883 res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes);
00884
00885 if(res != CURLE_OK) {
00886
00887 if(in->buffer)
00888 free(in->buffer);
00889 free(in);
00890 return res;
00891 }
00892 }
00893 #endif
00894
00895 if(conn->protocol & PROT_HTTPS) {
00896
00897
00898
00899
00900
00901
00902 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
00903
00904
00905
00906
00907
00908
00909
00910 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
00911 ptr = conn->data->state.uploadbuffer;
00912 }
00913 else
00914 sendsize = size;
00915
00916 res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
00917
00918 if(CURLE_OK == res) {
00919
00920 if(conn->data->set.verbose) {
00921
00922 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
00923 (size_t)(amount-included_body_bytes), conn);
00924 if (included_body_bytes)
00925 Curl_debug(conn->data, CURLINFO_DATA_OUT,
00926 ptr+amount-included_body_bytes,
00927 (size_t)included_body_bytes, conn);
00928 }
00929
00930 *bytes_written += amount;
00931
00932 if(http) {
00933 if((size_t)amount != size) {
00934
00935
00936
00937
00938 size -= amount;
00939
00940 ptr = in->buffer + amount;
00941
00942
00943 http->backup.fread = conn->fread;
00944 http->backup.fread_in = conn->fread_in;
00945 http->backup.postdata = http->postdata;
00946 http->backup.postsize = http->postsize;
00947
00948
00949 conn->fread = (curl_read_callback)readmoredata;
00950 conn->fread_in = (void *)conn;
00951 http->postdata = ptr;
00952 http->postsize = (curl_off_t)size;
00953
00954 http->send_buffer = in;
00955 http->sending = HTTPSEND_REQUEST;
00956
00957 return CURLE_OK;
00958 }
00959 http->sending = HTTPSEND_BODY;
00960
00961 }
00962 else {
00963 if((size_t)amount != size)
00964
00965
00966
00967
00968
00969
00970
00971 return CURLE_SEND_ERROR;
00972 else
00973 conn->writechannel_inuse = FALSE;
00974 }
00975 }
00976 if(in->buffer)
00977 free(in->buffer);
00978 free(in);
00979
00980 return res;
00981 }
00982
00983
00984
00985
00986
00987 static
00988 CURLcode add_bufferf(send_buffer *in, const char *fmt, ...)
00989 {
00990 char *s;
00991 va_list ap;
00992 va_start(ap, fmt);
00993 s = vaprintf(fmt, ap);
00994 va_end(ap);
00995
00996 if(s) {
00997 CURLcode result = add_buffer(in, s, strlen(s));
00998 free(s);
00999 return result;
01000 }
01001
01002 if(in->buffer)
01003 free(in->buffer);
01004 free(in);
01005 return CURLE_OUT_OF_MEMORY;
01006 }
01007
01008
01009
01010
01011 static
01012 CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
01013 {
01014 char *new_rb;
01015 size_t new_size;
01016
01017 if(!in->buffer ||
01018 ((in->size_used + size) > (in->size_max - 1))) {
01019 new_size = (in->size_used+size)*2;
01020 if(in->buffer)
01021
01022 new_rb = (char *)realloc(in->buffer, new_size);
01023 else
01024
01025 new_rb = (char *)malloc(new_size);
01026
01027 if(!new_rb) {
01028
01029 Curl_safefree(in->buffer);
01030 free(in);
01031 return CURLE_OUT_OF_MEMORY;
01032 }
01033
01034 in->buffer = new_rb;
01035 in->size_max = new_size;
01036 }
01037 memcpy(&in->buffer[in->size_used], inptr, size);
01038
01039 in->size_used += size;
01040
01041 return CURLE_OK;
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 bool
01054 Curl_compareheader(char *headerline,
01055 const char *header,
01056 const char *content)
01057 {
01058
01059
01060
01061
01062
01063 size_t hlen = strlen(header);
01064 size_t clen;
01065 size_t len;
01066 char *start;
01067 char *end;
01068
01069 if(!strnequal(headerline, header, hlen))
01070 return FALSE;
01071
01072
01073 start = &headerline[hlen];
01074
01075
01076 while(*start && ISSPACE(*start))
01077 start++;
01078
01079
01080 end = strchr(start, '\r');
01081 if(!end) {
01082
01083 end = strchr(start, '\n');
01084
01085 if(!end)
01086
01087 end = strchr(start, '\0');
01088 }
01089
01090 len = end-start;
01091 clen = strlen(content);
01092
01093
01094 for(;len>=clen;len--, start++) {
01095 if(strnequal(start, content, clen))
01096 return TRUE;
01097 }
01098
01099 return FALSE;
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
01116 int sockindex,
01117 char *hostname,
01118 int remote_port)
01119 {
01120 int subversion=0;
01121 struct SessionHandle *data=conn->data;
01122 struct Curl_transfer_keeper *k = &data->reqdata.keep;
01123 CURLcode result;
01124 int res;
01125 long timeout =
01126 data->set.timeout?data->set.timeout:3600000;
01127 curl_socket_t tunnelsocket = conn->sock[sockindex];
01128 curl_off_t cl=0;
01129 bool closeConnection = FALSE;
01130 long check;
01131
01132 #define SELECT_OK 0
01133 #define SELECT_ERROR 1
01134 #define SELECT_TIMEOUT 2
01135 int error = SELECT_OK;
01136
01137 conn->bits.proxy_connect_closed = FALSE;
01138
01139 do {
01140 if (!conn->bits.tunnel_connecting) {
01141 char *host_port;
01142 send_buffer *req_buffer;
01143
01144 infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
01145 hostname, remote_port);
01146
01147 if(data->reqdata.newurl) {
01148
01149
01150
01151 free(data->reqdata.newurl);
01152 data->reqdata.newurl = NULL;
01153 }
01154
01155
01156 req_buffer = add_buffer_init();
01157
01158 if(!req_buffer)
01159 return CURLE_OUT_OF_MEMORY;
01160
01161 host_port = aprintf("%s:%d", hostname, remote_port);
01162 if(!host_port) {
01163 free(req_buffer);
01164 return CURLE_OUT_OF_MEMORY;
01165 }
01166
01167
01168 result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
01169
01170 if(CURLE_OK == result) {
01171 char *host=(char *)"";
01172 const char *proxyconn="";
01173 const char *useragent="";
01174
01175 if(!checkheaders(data, "Host:")) {
01176 host = aprintf("Host: %s\r\n", host_port);
01177 if(!host) {
01178 free(req_buffer);
01179 free(host_port);
01180 return CURLE_OUT_OF_MEMORY;
01181 }
01182 }
01183 if(!checkheaders(data, "Proxy-Connection:"))
01184 proxyconn = "Proxy-Connection: Keep-Alive\r\n";
01185
01186 if(!checkheaders(data, "User-Agent:") && data->set.useragent)
01187 useragent = conn->allocptr.uagent;
01188
01189
01190
01191 result =
01192 add_bufferf(req_buffer,
01193 "CONNECT %s:%d HTTP/1.0\r\n"
01194 "%s"
01195 "%s"
01196 "%s"
01197 "%s",
01198 hostname, remote_port,
01199 host,
01200 conn->allocptr.proxyuserpwd?
01201 conn->allocptr.proxyuserpwd:"",
01202 useragent,
01203 proxyconn);
01204
01205 if(host && *host)
01206 free(host);
01207
01208 if(CURLE_OK == result)
01209 result = add_custom_headers(conn, req_buffer);
01210
01211 if(CURLE_OK == result)
01212
01213 result = add_bufferf(req_buffer, "\r\n");
01214
01215 if(CURLE_OK == result) {
01216
01217 result = add_buffer_send(req_buffer, conn,
01218 &data->info.request_size, 0, sockindex);
01219 }
01220 req_buffer = NULL;
01221 if(result)
01222 failf(data, "Failed sending CONNECT to proxy");
01223 }
01224 free(host_port);
01225 Curl_safefree(req_buffer);
01226 if(result)
01227 return result;
01228
01229 conn->bits.tunnel_connecting = TRUE;
01230 }
01231
01232
01233
01234
01235
01236
01237 check = timeout -
01238 Curl_tvdiff(Curl_tvnow(), conn->now);
01239 if(check <=0 ) {
01240 failf(data, "Proxy CONNECT aborted due to timeout");
01241 error = SELECT_TIMEOUT;
01242 break;
01243 }
01244
01245
01246 if (Curl_if_multi == data->state.used_interface) {
01247 if (0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
01248
01249 return CURLE_OK;
01250 else {
01251 DEBUGF(infof(data,
01252 "Multi mode finished polling for response from "
01253 "proxy CONNECT."));
01254 }
01255 }
01256 else {
01257 DEBUGF(infof(data, "Easy mode waiting for response from proxy CONNECT."));
01258 }
01259
01260
01261
01262
01263
01264
01265
01266 conn->bits.tunnel_connecting = FALSE;
01267
01268 {
01269 size_t nread;
01270 int perline;
01271 int keepon=TRUE;
01272 ssize_t gotbytes;
01273 char *ptr;
01274 char *line_start;
01275
01276 ptr=data->state.buffer;
01277 line_start = ptr;
01278
01279 nread=0;
01280 perline=0;
01281 keepon=TRUE;
01282
01283 while((nread<BUFSIZE) && (keepon && !error)) {
01284
01285
01286 check = timeout -
01287 Curl_tvdiff(Curl_tvnow(), conn->now);
01288 if(check <= 0) {
01289 failf(data, "Proxy CONNECT aborted due to timeout");
01290 error = SELECT_TIMEOUT;
01291 break;
01292 }
01293
01294
01295 switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
01296 check<1000L?(int)check:1000)) {
01297 case -1:
01298 error = SELECT_ERROR;
01299 failf(data, "Proxy CONNECT aborted due to select/poll error");
01300 break;
01301 case 0:
01302 break;
01303 default:
01304 res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
01305 if(res< 0)
01306
01307 continue;
01308 else if(res)
01309 keepon = FALSE;
01310 else if(gotbytes <= 0) {
01311 keepon = FALSE;
01312 error = SELECT_ERROR;
01313 failf(data, "Proxy CONNECT aborted");
01314 }
01315 else {
01316
01317
01318
01319
01320
01321 int i;
01322
01323 nread += gotbytes;
01324
01325 if(keepon > TRUE) {
01326
01327
01328
01329 cl -= gotbytes;
01330 if(cl<=0) {
01331 keepon = FALSE;
01332 break;
01333 }
01334 }
01335 else
01336 for(i = 0; i < gotbytes; ptr++, i++) {
01337 perline++;
01338 if(*ptr=='\n') {
01339 char letter;
01340 int writetype;
01341
01342
01343 if(data->set.verbose)
01344 Curl_debug(data, CURLINFO_HEADER_IN,
01345 line_start, (size_t)perline, conn);
01346
01347
01348 writetype = CLIENTWRITE_HEADER;
01349 if(data->set.include_header)
01350 writetype |= CLIENTWRITE_BODY;
01351
01352 result = Curl_client_write(conn, writetype, line_start, perline);
01353 if(result)
01354 return result;
01355
01356
01357
01358
01359
01360 if(('\r' == line_start[0]) ||
01361 ('\n' == line_start[0])) {
01362
01363 if(cl && (407 == k->httpcode) &&
01364 !data->state.authproblem) {
01365
01366
01367
01368 keepon = 2;
01369 infof(data, "Ignore %" FORMAT_OFF_T
01370 " bytes of response-body\n", cl);
01371 cl -= (gotbytes - i);
01372
01373 if(cl<=0)
01374
01375 keepon=FALSE;
01376 }
01377 else
01378 keepon = FALSE;
01379 break;
01380 }
01381
01382
01383 letter = line_start[perline];
01384 line_start[perline]=0;
01385 if((checkprefix("WWW-Authenticate:", line_start) &&
01386 (401 == k->httpcode)) ||
01387 (checkprefix("Proxy-authenticate:", line_start) &&
01388 (407 == k->httpcode))) {
01389 result = Curl_http_input_auth(conn, k->httpcode,
01390 line_start);
01391 if(result)
01392 return result;
01393 }
01394 else if(checkprefix("Content-Length:", line_start)) {
01395 cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
01396 NULL, 10);
01397 }
01398 else if(Curl_compareheader(line_start,
01399 "Connection:", "close"))
01400 closeConnection = TRUE;
01401 else if(2 == sscanf(line_start, "HTTP/1.%d %d",
01402 &subversion,
01403 &k->httpcode)) {
01404
01405 data->info.httpproxycode = k->httpcode;
01406 }
01407
01408 line_start[perline]= letter;
01409
01410 perline=0;
01411 line_start = ptr+1;
01412 }
01413 }
01414 }
01415 break;
01416 }
01417 }
01418
01419 if(error)
01420 return CURLE_RECV_ERROR;
01421
01422 if(data->info.httpproxycode != 200)
01423
01424
01425 Curl_http_auth_act(conn);
01426
01427 if (closeConnection && data->reqdata.newurl) {
01428
01429 sclose(conn->sock[sockindex]);
01430 conn->sock[sockindex] = CURL_SOCKET_BAD;
01431 break;
01432 }
01433 }
01434 } while(data->reqdata.newurl);
01435
01436 if(200 != k->httpcode) {
01437 failf(data, "Received HTTP code %d from proxy after CONNECT",
01438 k->httpcode);
01439
01440 if (closeConnection && data->reqdata.newurl)
01441 conn->bits.proxy_connect_closed = TRUE;
01442
01443 return CURLE_RECV_ERROR;
01444 }
01445
01446
01447
01448
01449 Curl_safefree(conn->allocptr.proxyuserpwd);
01450 conn->allocptr.proxyuserpwd = NULL;
01451
01452 data->state.authproxy.done = TRUE;
01453
01454 infof (data, "Proxy replied OK to CONNECT request\n");
01455 return CURLE_OK;
01456 }
01457
01458
01459
01460
01461
01462 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
01463 {
01464 struct SessionHandle *data;
01465 CURLcode result;
01466
01467 data=conn->data;
01468
01469
01470
01471 conn->bits.close = FALSE;
01472
01473
01474
01475
01476
01477
01478
01479 if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
01480
01481
01482 result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
01483 conn->host.name,
01484 conn->remote_port);
01485 if(CURLE_OK != result)
01486 return result;
01487 }
01488
01489 if (conn->bits.tunnel_connecting) {
01490
01491 return CURLE_OK;
01492 }
01493
01494 if(!data->state.this_is_a_follow) {
01495
01496 if (data->state.first_host)
01497
01498 free(data->state.first_host);
01499
01500 data->state.first_host = strdup(conn->host.name);
01501 if(!data->state.first_host)
01502 return CURLE_OUT_OF_MEMORY;
01503 }
01504
01505 if(conn->protocol & PROT_HTTPS) {
01506
01507 if(data->state.used_interface == Curl_if_multi) {
01508 result = Curl_https_connecting(conn, done);
01509 if(result)
01510 return result;
01511 }
01512 else {
01513
01514 result = Curl_ssl_connect(conn, FIRSTSOCKET);
01515 if(result)
01516 return result;
01517 *done = TRUE;
01518 }
01519 }
01520 else {
01521 *done = TRUE;
01522 }
01523
01524 return CURLE_OK;
01525 }
01526
01527 CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
01528 {
01529 CURLcode result;
01530 DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS));
01531
01532
01533 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
01534 if(result)
01535 return result;
01536
01537 return CURLE_OK;
01538 }
01539
01540 #ifdef USE_SSLEAY
01541
01542
01543 int Curl_https_getsock(struct connectdata *conn,
01544 curl_socket_t *socks,
01545 int numsocks)
01546 {
01547 if (conn->protocol & PROT_HTTPS) {
01548 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
01549
01550 if(!numsocks)
01551 return GETSOCK_BLANK;
01552
01553 if (connssl->connecting_state == ssl_connect_2_writing) {
01554
01555 socks[0] = conn->sock[FIRSTSOCKET];
01556 return GETSOCK_WRITESOCK(0);
01557 }
01558 else if (connssl->connecting_state == ssl_connect_2_reading) {
01559
01560 socks[0] = conn->sock[FIRSTSOCKET];
01561 return GETSOCK_READSOCK(0);
01562 }
01563 }
01564 return CURLE_OK;
01565 }
01566 #else
01567 #ifdef USE_GNUTLS
01568 int Curl_https_getsock(struct connectdata *conn,
01569 curl_socket_t *socks,
01570 int numsocks)
01571 {
01572 (void)conn;
01573 (void)socks;
01574 (void)numsocks;
01575 return GETSOCK_BLANK;
01576 }
01577 #else
01578 #ifdef USE_NSS
01579 int Curl_https_getsock(struct connectdata *conn,
01580 curl_socket_t *socks,
01581 int numsocks)
01582 {
01583 (void)conn;
01584 (void)socks;
01585 (void)numsocks;
01586 return GETSOCK_BLANK;
01587 }
01588 #endif
01589 #endif
01590 #endif
01591
01592
01593
01594
01595
01596
01597 CURLcode Curl_http_done(struct connectdata *conn,
01598 CURLcode status, bool premature)
01599 {
01600 struct SessionHandle *data = conn->data;
01601 struct HTTP *http =data->reqdata.proto.http;
01602 struct Curl_transfer_keeper *k = &data->reqdata.keep;
01603 (void)premature;
01604
01605
01606 conn->fread = data->set.fread;
01607 conn->fread_in = data->set.in;
01608
01609 if (http == NULL)
01610 return CURLE_OK;
01611
01612 if(http->send_buffer) {
01613 send_buffer *buff = http->send_buffer;
01614
01615 free(buff->buffer);
01616 free(buff);
01617 http->send_buffer = NULL;
01618 }
01619
01620 if(HTTPREQ_POST_FORM == data->set.httpreq) {
01621 k->bytecount = http->readbytecount + http->writebytecount;
01622
01623 Curl_formclean(&http->sendit);
01624 if(http->form.fp) {
01625
01626 fclose(http->form.fp);
01627 http->form.fp = NULL;
01628 }
01629 }
01630 else if(HTTPREQ_PUT == data->set.httpreq)
01631 k->bytecount = http->readbytecount + http->writebytecount;
01632
01633 if (status != CURLE_OK)
01634 return (status);
01635
01636 if(!conn->bits.retry &&
01637 ((http->readbytecount +
01638 data->reqdata.keep.headerbytecount -
01639 data->reqdata.keep.deductheadercount)) <= 0) {
01640
01641
01642
01643 failf(data, "Empty reply from server");
01644 return CURLE_GOT_NOTHING;
01645 }
01646
01647 return CURLE_OK;
01648 }
01649
01650
01651 static CURLcode expect100(struct SessionHandle *data,
01652 send_buffer *req_buffer)
01653 {
01654 CURLcode result = CURLE_OK;
01655 data->state.expect100header = FALSE;
01656
01657 if((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
01658 !checkheaders(data, "Expect:")) {
01659
01660
01661
01662
01663 result = add_bufferf(req_buffer,
01664 "Expect: 100-continue\r\n");
01665 if(result == CURLE_OK)
01666 data->state.expect100header = TRUE;
01667 }
01668 return result;
01669 }
01670
01671 static CURLcode add_custom_headers(struct connectdata *conn,
01672 send_buffer *req_buffer)
01673 {
01674 char *ptr;
01675 struct curl_slist *headers=conn->data->set.headers;
01676
01677 while(headers) {
01678 ptr = strchr(headers->data, ':');
01679 if(ptr) {
01680
01681
01682 ptr++;
01683 while(*ptr && ISSPACE(*ptr))
01684 ptr++;
01685
01686 if(*ptr) {
01687
01688
01689 if(conn->allocptr.host &&
01690
01691
01692 curl_strnequal("Host:", headers->data, 5))
01693 ;
01694 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM &&
01695
01696 curl_strnequal("Content-Type:", headers->data,
01697 strlen("Content-Type:")))
01698 ;
01699 else {
01700 CURLcode result = add_bufferf(req_buffer, "%s\r\n", headers->data);
01701 if(result)
01702 return result;
01703 }
01704 }
01705 }
01706 headers = headers->next;
01707 }
01708 return CURLE_OK;
01709 }
01710
01711
01712
01713
01714
01715
01716 CURLcode Curl_http(struct connectdata *conn, bool *done)
01717 {
01718 struct SessionHandle *data=conn->data;
01719 char *buf = data->state.buffer;
01720 CURLcode result=CURLE_OK;
01721 struct HTTP *http;
01722 char *ppath = data->reqdata.path;
01723 char *host = conn->host.name;
01724 const char *te = "";
01725 char *ptr;
01726 char *request;
01727 Curl_HttpReq httpreq = data->set.httpreq;
01728 char *addcookies = NULL;
01729 curl_off_t included_body = 0;
01730
01731
01732
01733
01734 *done = TRUE;
01735
01736 if(!data->reqdata.proto.http) {
01737
01738
01739 http = (struct HTTP *)malloc(sizeof(struct HTTP));
01740 if(!http)
01741 return CURLE_OUT_OF_MEMORY;
01742 memset(http, 0, sizeof(struct HTTP));
01743 data->reqdata.proto.http = http;
01744 }
01745 else
01746 http = data->reqdata.proto.http;
01747
01748 if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
01749 data->set.upload) {
01750 httpreq = HTTPREQ_PUT;
01751 }
01752
01753
01754 if(data->set.customrequest)
01755 request = data->set.customrequest;
01756 else {
01757 if(conn->bits.no_body)
01758 request = (char *)"HEAD";
01759 else {
01760 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
01761 switch(httpreq) {
01762 case HTTPREQ_POST:
01763 case HTTPREQ_POST_FORM:
01764 request = (char *)"POST";
01765 break;
01766 case HTTPREQ_PUT:
01767 request = (char *)"PUT";
01768 break;
01769 default:
01770 case HTTPREQ_GET:
01771 request = (char *)"GET";
01772 break;
01773 case HTTPREQ_HEAD:
01774 request = (char *)"HEAD";
01775 break;
01776 }
01777 }
01778 }
01779
01780
01781
01782
01783
01784 if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
01785 free(conn->allocptr.uagent);
01786 conn->allocptr.uagent=NULL;
01787 }
01788
01789
01790 result = Curl_http_output_auth(conn, request, ppath, FALSE);
01791 if(result)
01792 return result;
01793
01794 if((data->state.authhost.multi || data->state.authproxy.multi) &&
01795 (httpreq != HTTPREQ_GET) &&
01796 (httpreq != HTTPREQ_HEAD)) {
01797
01798
01799 conn->bits.authneg = TRUE;
01800 }
01801 else
01802 conn->bits.authneg = FALSE;
01803
01804 Curl_safefree(conn->allocptr.ref);
01805 if(data->change.referer && !checkheaders(data, "Referer:"))
01806 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
01807 else
01808 conn->allocptr.ref = NULL;
01809
01810 if(data->set.cookie && !checkheaders(data, "Cookie:"))
01811 addcookies = data->set.cookie;
01812
01813 if(!checkheaders(data, "Accept-Encoding:") &&
01814 data->set.encoding) {
01815 Curl_safefree(conn->allocptr.accept_encoding);
01816 conn->allocptr.accept_encoding =
01817 aprintf("Accept-Encoding: %s\r\n", data->set.encoding);
01818 if(!conn->allocptr.accept_encoding)
01819 return CURLE_OUT_OF_MEMORY;
01820 }
01821
01822 ptr = checkheaders(data, "Transfer-Encoding:");
01823 if(ptr) {
01824
01825 conn->bits.upload_chunky =
01826 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
01827 }
01828 else {
01829 if (httpreq == HTTPREQ_GET)
01830 conn->bits.upload_chunky = FALSE;
01831 if(conn->bits.upload_chunky)
01832 te = "Transfer-Encoding: chunked\r\n";
01833 }
01834
01835 Curl_safefree(conn->allocptr.host);
01836
01837 ptr = checkheaders(data, "Host:");
01838 if(ptr && (!data->state.this_is_a_follow ||
01839 curl_strequal(data->state.first_host, conn->host.name))) {
01840 #if !defined(CURL_DISABLE_COOKIES)
01841
01842
01843
01844
01845
01846 char *start = ptr+strlen("Host:");
01847 while(*start && ISSPACE(*start ))
01848 start++;
01849 ptr = start;
01850
01851
01852 while(*ptr && !ISSPACE(*ptr) && !(':'==*ptr))
01853 ptr++;
01854
01855 if(ptr != start) {
01856 size_t len=ptr-start;
01857 Curl_safefree(conn->allocptr.cookiehost);
01858 conn->allocptr.cookiehost = malloc(len+1);
01859 if(!conn->allocptr.cookiehost)
01860 return CURLE_OUT_OF_MEMORY;
01861 memcpy(conn->allocptr.cookiehost, start, len);
01862 conn->allocptr.cookiehost[len]=0;
01863 }
01864 #endif
01865
01866 conn->allocptr.host = NULL;
01867 }
01868 else {
01869
01870
01871
01872 if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
01873 (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
01874
01875
01876 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
01877 conn->bits.ipv6_ip?"[":"",
01878 host,
01879 conn->bits.ipv6_ip?"]":"");
01880 else
01881 conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
01882 conn->bits.ipv6_ip?"[":"",
01883 host,
01884 conn->bits.ipv6_ip?"]":"",
01885 conn->remote_port);
01886
01887 if(!conn->allocptr.host)
01888
01889 return CURLE_OUT_OF_MEMORY;
01890 }
01891
01892 if (conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
01893
01894
01895
01896
01897
01898 if(conn->host.dispname != conn->host.name) {
01899 char *url = data->change.url;
01900 ptr = strstr(url, conn->host.dispname);
01901 if(ptr) {
01902
01903
01904
01905
01906
01907 size_t currlen = strlen(conn->host.dispname);
01908 size_t newlen = strlen(conn->host.name);
01909 size_t urllen = strlen(url);
01910
01911 char *newurl;
01912
01913 newurl = malloc(urllen + newlen - currlen + 1);
01914 if(newurl) {
01915
01916 memcpy(newurl, url, ptr - url);
01917
01918 memcpy(newurl + (ptr - url), conn->host.name, newlen);
01919
01920 memcpy(newurl + newlen + (ptr - url),
01921 ptr + currlen,
01922 urllen - (ptr-url) - currlen + 1);
01923 if(data->change.url_alloc)
01924 free(data->change.url);
01925 data->change.url = newurl;
01926 data->change.url_alloc = TRUE;
01927 }
01928 else
01929 return CURLE_OUT_OF_MEMORY;
01930 }
01931 }
01932 ppath = data->change.url;
01933 }
01934 if(HTTPREQ_POST_FORM == httpreq) {
01935
01936
01937 result = Curl_getFormData(&http->sendit, data->set.httppost,
01938 checkheaders(data, "Content-Type:"),
01939 &http->postsize);
01940 if(CURLE_OK != result) {
01941
01942 failf(data, "failed creating formpost data");
01943 return result;
01944 }
01945 }
01946
01947
01948 http->p_pragma =
01949 (!checkheaders(data, "Pragma:") &&
01950 (conn->bits.httpproxy && !conn->bits.tunnel_proxy) )?
01951 "Pragma: no-cache\r\n":NULL;
01952
01953 if(!checkheaders(data, "Accept:"))
01954 http->p_accept = "Accept: */*\r\n";
01955
01956 if(( (HTTPREQ_POST == httpreq) ||
01957 (HTTPREQ_POST_FORM == httpreq) ||
01958 (HTTPREQ_PUT == httpreq) ) &&
01959 data->reqdata.resume_from) {
01960
01961
01962
01963
01964
01965
01966
01967
01968 if(data->reqdata.resume_from < 0 ) {
01969
01970
01971
01972
01973 data->reqdata.resume_from = 0;
01974 }
01975
01976 if(data->reqdata.resume_from) {
01977
01978 curl_off_t passed=0;
01979
01980
01981
01982
01983 do {
01984 size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed);
01985 size_t actuallyread;
01986
01987 if(readthisamountnow > BUFSIZE)
01988 readthisamountnow = BUFSIZE;
01989
01990 actuallyread =
01991 data->set.fread(data->state.buffer, 1, (size_t)readthisamountnow,
01992 data->set.in);
01993
01994 passed += actuallyread;
01995 if(actuallyread != readthisamountnow) {
01996 failf(data, "Could only read %" FORMAT_OFF_T
01997 " bytes from the input",
01998 passed);
01999 return CURLE_READ_ERROR;
02000 }
02001 } while(passed != data->reqdata.resume_from);
02002
02003
02004 if(data->set.infilesize>0) {
02005 data->set.infilesize -= data->reqdata.resume_from;
02006
02007 if(data->set.infilesize <= 0) {
02008 failf(data, "File already completely uploaded");
02009 return CURLE_PARTIAL_FILE;
02010 }
02011 }
02012
02013 }
02014 }
02015 if(data->reqdata.use_range) {
02016
02017
02018
02019
02020
02021 if((httpreq == HTTPREQ_GET) &&
02022 !checkheaders(data, "Range:")) {
02023
02024 if(conn->allocptr.rangeline)
02025 free(conn->allocptr.rangeline);
02026 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->reqdata.range);
02027 }
02028 else if((httpreq != HTTPREQ_GET) &&
02029 !checkheaders(data, "Content-Range:")) {
02030
02031 if(data->reqdata.resume_from) {
02032
02033 curl_off_t total_expected_size=
02034 data->reqdata.resume_from + data->set.infilesize;
02035 conn->allocptr.rangeline =
02036 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
02037 "/%" FORMAT_OFF_T "\r\n",
02038 data->reqdata.range, total_expected_size-1,
02039 total_expected_size);
02040 }
02041 else {
02042
02043
02044 conn->allocptr.rangeline =
02045 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
02046 data->reqdata.range, data->set.infilesize);
02047 }
02048 }
02049 }
02050
02051 {
02052
02053 const char *httpstring=
02054 data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1";
02055
02056 send_buffer *req_buffer;
02057 curl_off_t postsize;
02058
02059
02060 req_buffer = add_buffer_init();
02061
02062 if(!req_buffer)
02063 return CURLE_OUT_OF_MEMORY;
02064
02065
02066 result =
02067 add_bufferf(req_buffer,
02068 "%s "
02069 "%s HTTP/%s\r\n"
02070 "%s"
02071 "%s"
02072 "%s"
02073 "%s"
02074 "%s"
02075 "%s"
02076 "%s"
02077 "%s"
02078 "%s"
02079 "%s"
02080 "%s",
02081
02082 request,
02083 ppath,
02084 httpstring,
02085 conn->allocptr.proxyuserpwd?
02086 conn->allocptr.proxyuserpwd:"",
02087 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
02088 (data->reqdata.use_range && conn->allocptr.rangeline)?
02089 conn->allocptr.rangeline:"",
02090 (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)?
02091 conn->allocptr.uagent:"",
02092 (conn->allocptr.host?conn->allocptr.host:""),
02093 http->p_pragma?http->p_pragma:"",
02094 http->p_accept?http->p_accept:"",
02095 (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)?
02096 conn->allocptr.accept_encoding:"",
02097 (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" ,
02098 (conn->bits.httpproxy &&
02099 !conn->bits.tunnel_proxy &&
02100 !checkheaders(data, "Proxy-Connection:"))?
02101 "Proxy-Connection: Keep-Alive\r\n":"",
02102 te
02103 );
02104
02105 if(result)
02106 return result;
02107
02108 #if !defined(CURL_DISABLE_COOKIES)
02109 if(data->cookies || addcookies) {
02110 struct Cookie *co=NULL;
02111 int count=0;
02112
02113 if(data->cookies) {
02114 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
02115 co = Curl_cookie_getlist(data->cookies,
02116 conn->allocptr.cookiehost?
02117 conn->allocptr.cookiehost:host, data->reqdata.path,
02118 (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
02119 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
02120 }
02121 if(co) {
02122 struct Cookie *store=co;
02123
02124 while(co) {
02125 if(co->value) {
02126 if(0 == count) {
02127 result = add_bufferf(req_buffer, "Cookie: ");
02128 if(result)
02129 break;
02130 }
02131 result = add_bufferf(req_buffer,
02132 "%s%s=%s", count?"; ":"",
02133 co->name, co->value);
02134 if(result)
02135 break;
02136 count++;
02137 }
02138 co = co->next;
02139 }
02140 Curl_cookie_freelist(store);
02141 }
02142 if(addcookies && (CURLE_OK == result)) {
02143 if(!count)
02144 result = add_bufferf(req_buffer, "Cookie: ");
02145 if(CURLE_OK == result) {
02146 result = add_bufferf(req_buffer, "%s%s",
02147 count?"; ":"",
02148 addcookies);
02149 count++;
02150 }
02151 }
02152 if(count && (CURLE_OK == result))
02153 result = add_buffer(req_buffer, "\r\n", 2);
02154
02155 if(result)
02156 return result;
02157 }
02158 #endif
02159
02160 if(data->set.timecondition) {
02161 struct tm *tm;
02162
02163
02164
02165
02166
02167
02168
02169
02170 #ifdef HAVE_GMTIME_R
02171
02172 struct tm keeptime;
02173 tm = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime);
02174 #else
02175 tm = gmtime(&data->set.timevalue);
02176 #endif
02177
02178
02179 snprintf(buf, BUFSIZE-1,
02180 "%s, %02d %s %4d %02d:%02d:%02d GMT",
02181 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
02182 tm->tm_mday,
02183 Curl_month[tm->tm_mon],
02184 tm->tm_year + 1900,
02185 tm->tm_hour,
02186 tm->tm_min,
02187 tm->tm_sec);
02188
02189 switch(data->set.timecondition) {
02190 case CURL_TIMECOND_IFMODSINCE:
02191 default:
02192 result = add_bufferf(req_buffer,
02193 "If-Modified-Since: %s\r\n", buf);
02194 break;
02195 case CURL_TIMECOND_IFUNMODSINCE:
02196 result = add_bufferf(req_buffer,
02197 "If-Unmodified-Since: %s\r\n", buf);
02198 break;
02199 case CURL_TIMECOND_LASTMOD:
02200 result = add_bufferf(req_buffer,
02201 "Last-Modified: %s\r\n", buf);
02202 break;
02203 }
02204 if(result)
02205 return result;
02206 }
02207
02208 result = add_custom_headers(conn, req_buffer);
02209 if(result)
02210 return result;
02211
02212 http->postdata = NULL;
02213 Curl_pgrsSetUploadSize(data, 0);
02214
02215
02216
02217
02218
02219 switch(httpreq) {
02220
02221 case HTTPREQ_POST_FORM:
02222 if(!http->sendit || conn->bits.authneg) {
02223
02224 result = add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
02225 if(result)
02226 return result;
02227
02228 result = add_buffer_send(req_buffer, conn,
02229 &data->info.request_size, 0, FIRSTSOCKET);
02230 if(result)
02231 failf(data, "Failed sending POST request");
02232 else
02233
02234 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02235 &http->readbytecount,
02236 -1, NULL);
02237 break;
02238 }
02239
02240 if(Curl_FormInit(&http->form, http->sendit)) {
02241 failf(data, "Internal HTTP POST error!");
02242 return CURLE_HTTP_POST_ERROR;
02243 }
02244
02245
02246 conn->fread = (curl_read_callback)Curl_FormReader;
02247 conn->fread_in = &http->form;
02248
02249 http->sending = HTTPSEND_BODY;
02250
02251 if(!conn->bits.upload_chunky) {
02252
02253 result = add_bufferf(req_buffer,
02254 "Content-Length: %" FORMAT_OFF_T "\r\n",
02255 http->postsize);
02256 if(result)
02257 return result;
02258 }
02259
02260 result = expect100(data, req_buffer);
02261 if(result)
02262 return result;
02263
02264 {
02265
02266
02267
02268 char *contentType;
02269 size_t linelength=0;
02270 contentType = Curl_formpostheader((void *)&http->form,
02271 &linelength);
02272 if(!contentType) {
02273 failf(data, "Could not get Content-Type header line!");
02274 return CURLE_HTTP_POST_ERROR;
02275 }
02276
02277 result = add_buffer(req_buffer, contentType, linelength);
02278 if(result)
02279 return result;
02280 }
02281
02282
02283 result = add_buffer(req_buffer, "\r\n", 2);
02284 if(result)
02285 return result;
02286
02287
02288 Curl_pgrsSetUploadSize(data, http->postsize);
02289
02290
02291 result = add_buffer_send(req_buffer, conn,
02292 &data->info.request_size, 0, FIRSTSOCKET);
02293 if(result)
02294 failf(data, "Failed sending POST request");
02295 else
02296
02297 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02298 &http->readbytecount,
02299 FIRSTSOCKET,
02300 &http->writebytecount);
02301
02302 if(result) {
02303 Curl_formclean(&http->sendit);
02304 return result;
02305 }
02306 #ifdef CURL_DOES_CONVERSIONS
02307
02308 result = Curl_formconvert(data, http->sendit);
02309 if(result) {
02310 Curl_formclean(&http->sendit);
02311 return result;
02312 }
02313 #endif
02314 break;
02315
02316 case HTTPREQ_PUT:
02317
02318 if(conn->bits.authneg)
02319 postsize = 0;
02320 else
02321 postsize = data->set.infilesize;
02322
02323 if((postsize != -1) && !conn->bits.upload_chunky) {
02324
02325 result = add_bufferf(req_buffer,
02326 "Content-Length: %" FORMAT_OFF_T "\r\n",
02327 postsize );
02328 if(result)
02329 return result;
02330 }
02331
02332 result = expect100(data, req_buffer);
02333 if(result)
02334 return result;
02335
02336 result = add_buffer(req_buffer, "\r\n", 2);
02337 if(result)
02338 return result;
02339
02340
02341 Curl_pgrsSetUploadSize(data, postsize);
02342
02343
02344 result = add_buffer_send(req_buffer, conn,
02345 &data->info.request_size, 0, FIRSTSOCKET);
02346 if(result)
02347 failf(data, "Failed sending PUT request");
02348 else
02349
02350 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02351 &http->readbytecount,
02352 postsize?FIRSTSOCKET:-1,
02353 postsize?&http->writebytecount:NULL);
02354 if(result)
02355 return result;
02356 break;
02357
02358 case HTTPREQ_POST:
02359
02360
02361 if(conn->bits.authneg)
02362 postsize = 0;
02363 else
02364
02365 postsize = (data->set.postfieldsize != -1)?
02366 data->set.postfieldsize:
02367 (data->set.postfields?(curl_off_t)strlen(data->set.postfields):0);
02368
02369 if(!conn->bits.upload_chunky) {
02370
02371
02372
02373
02374 if(!checkheaders(data, "Content-Length:")) {
02375
02376
02377 result = add_bufferf(req_buffer,
02378 "Content-Length: %" FORMAT_OFF_T"\r\n",
02379 postsize);
02380 if(result)
02381 return result;
02382 }
02383 }
02384
02385 if(!checkheaders(data, "Content-Type:")) {
02386 result = add_bufferf(req_buffer,
02387 "Content-Type: application/x-www-form-urlencoded\r\n");
02388 if(result)
02389 return result;
02390 }
02391
02392 if(data->set.postfields) {
02393
02394
02395
02396 if(postsize > TINY_INITIAL_POST_SIZE) {
02397 result = expect100(data, req_buffer);
02398 if(result)
02399 return result;
02400 }
02401 else
02402 data->state.expect100header = FALSE;
02403
02404 if(!data->state.expect100header &&
02405 (postsize < MAX_INITIAL_POST_SIZE)) {
02406
02407
02408
02409
02410
02411
02412
02413 result = add_buffer(req_buffer, "\r\n", 2);
02414 if(result)
02415 return result;
02416
02417 if(!conn->bits.upload_chunky) {
02418
02419
02420 result = add_buffer(req_buffer, data->set.postfields,
02421 (size_t)postsize);
02422 included_body = postsize;
02423 }
02424 else {
02425
02426 result = add_bufferf(req_buffer, "%x\r\n", (int)postsize);
02427 if(CURLE_OK == result)
02428 result = add_buffer(req_buffer, data->set.postfields,
02429 (size_t)postsize);
02430 if(CURLE_OK == result)
02431 result = add_buffer(req_buffer,
02432 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
02433
02434 included_body = postsize + 7;
02435 }
02436 if(result)
02437 return result;
02438 }
02439 else {
02440
02441 http->postsize = postsize;
02442 http->postdata = data->set.postfields;
02443
02444 http->sending = HTTPSEND_BODY;
02445
02446 conn->fread = (curl_read_callback)readmoredata;
02447 conn->fread_in = (void *)conn;
02448
02449
02450 Curl_pgrsSetUploadSize(data, http->postsize);
02451
02452 result = add_buffer(req_buffer, "\r\n", 2);
02453 if(result)
02454 return result;
02455 }
02456 }
02457 else {
02458 result = add_buffer(req_buffer, "\r\n", 2);
02459 if(result)
02460 return result;
02461
02462 if(data->set.postfieldsize) {
02463
02464 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
02465
02466
02467
02468 http->postdata = (char *)&http->postdata;
02469 }
02470 }
02471
02472 result = add_buffer_send(req_buffer, conn, &data->info.request_size,
02473 (size_t)included_body, FIRSTSOCKET);
02474
02475 if(result)
02476 failf(data, "Failed sending HTTP POST request");
02477 else
02478 result =
02479 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02480 &http->readbytecount,
02481 http->postdata?FIRSTSOCKET:-1,
02482 http->postdata?&http->writebytecount:NULL);
02483 break;
02484
02485 default:
02486 result = add_buffer(req_buffer, "\r\n", 2);
02487 if(result)
02488 return result;
02489
02490
02491 result = add_buffer_send(req_buffer, conn,
02492 &data->info.request_size, 0, FIRSTSOCKET);
02493
02494 if(result)
02495 failf(data, "Failed sending HTTP request");
02496 else
02497
02498 result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02499 &http->readbytecount,
02500 http->postdata?FIRSTSOCKET:-1,
02501 http->postdata?&http->writebytecount:NULL);
02502 }
02503 if(result)
02504 return result;
02505 }
02506
02507 return CURLE_OK;
02508 }
02509 #endif