00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifndef CURL_DISABLE_HTTP
00026
00027 #ifdef HAVE_NETINET_IN_H
00028 #include <netinet/in.h>
00029 #endif
00030
00031 #ifdef HAVE_NETDB_H
00032 #include <netdb.h>
00033 #endif
00034 #ifdef HAVE_ARPA_INET_H
00035 #include <arpa/inet.h>
00036 #endif
00037 #ifdef HAVE_NET_IF_H
00038 #include <net/if.h>
00039 #endif
00040 #ifdef HAVE_SYS_IOCTL_H
00041 #include <sys/ioctl.h>
00042 #endif
00043
00044 #ifdef HAVE_SYS_PARAM_H
00045 #include <sys/param.h>
00046 #endif
00047
00048 #include "urldata.h"
00049 #include <curl/curl.h>
00050 #include "transfer.h"
00051 #include "sendf.h"
00052 #include "formdata.h"
00053 #include "progress.h"
00054 #include "curl_base64.h"
00055 #include "cookie.h"
00056 #include "vauth/vauth.h"
00057 #include "vtls/vtls.h"
00058 #include "http_digest.h"
00059 #include "http_ntlm.h"
00060 #include "curl_ntlm_wb.h"
00061 #include "http_negotiate.h"
00062 #include "url.h"
00063 #include "share.h"
00064 #include "hostip.h"
00065 #include "http.h"
00066 #include "select.h"
00067 #include "parsedate.h"
00068 #include "strtoofft.h"
00069 #include "multiif.h"
00070 #include "strcase.h"
00071 #include "content_encoding.h"
00072 #include "http_proxy.h"
00073 #include "warnless.h"
00074 #include "non-ascii.h"
00075 #include "conncache.h"
00076 #include "pipeline.h"
00077 #include "http2.h"
00078 #include "connect.h"
00079 #include "strdup.h"
00080
00081
00082 #include "curl_printf.h"
00083 #include "curl_memory.h"
00084 #include "memdebug.h"
00085
00086
00087
00088
00089
00090 static int http_getsock_do(struct connectdata *conn,
00091 curl_socket_t *socks,
00092 int numsocks);
00093 static int http_should_fail(struct connectdata *conn);
00094
00095 #ifdef USE_SSL
00096 static CURLcode https_connecting(struct connectdata *conn, bool *done);
00097 static int https_getsock(struct connectdata *conn,
00098 curl_socket_t *socks,
00099 int numsocks);
00100 #else
00101 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
00102 #endif
00103
00104
00105
00106
00107 const struct Curl_handler Curl_handler_http = {
00108 "HTTP",
00109 Curl_http_setup_conn,
00110 Curl_http,
00111 Curl_http_done,
00112 ZERO_NULL,
00113 Curl_http_connect,
00114 ZERO_NULL,
00115 ZERO_NULL,
00116 ZERO_NULL,
00117 http_getsock_do,
00118 ZERO_NULL,
00119 ZERO_NULL,
00120 ZERO_NULL,
00121 ZERO_NULL,
00122 PORT_HTTP,
00123 CURLPROTO_HTTP,
00124 PROTOPT_CREDSPERREQUEST
00125 };
00126
00127 #ifdef USE_SSL
00128
00129
00130
00131 const struct Curl_handler Curl_handler_https = {
00132 "HTTPS",
00133 Curl_http_setup_conn,
00134 Curl_http,
00135 Curl_http_done,
00136 ZERO_NULL,
00137 Curl_http_connect,
00138 https_connecting,
00139 ZERO_NULL,
00140 https_getsock,
00141 http_getsock_do,
00142 ZERO_NULL,
00143 ZERO_NULL,
00144 ZERO_NULL,
00145 ZERO_NULL,
00146 PORT_HTTPS,
00147 CURLPROTO_HTTPS,
00148 PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN
00149 };
00150 #endif
00151
00152 CURLcode Curl_http_setup_conn(struct connectdata *conn)
00153 {
00154
00155
00156 struct HTTP *http;
00157 DEBUGASSERT(conn->data->req.protop == NULL);
00158
00159 http = calloc(1, sizeof(struct HTTP));
00160 if(!http)
00161 return CURLE_OUT_OF_MEMORY;
00162
00163 conn->data->req.protop = http;
00164
00165 Curl_http2_setup_conn(conn);
00166 Curl_http2_setup_req(conn->data);
00167
00168 return CURLE_OK;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 char *Curl_checkheaders(const struct connectdata *conn,
00178 const char *thisheader)
00179 {
00180 struct curl_slist *head;
00181 size_t thislen = strlen(thisheader);
00182 struct Curl_easy *data = conn->data;
00183
00184 for(head = data->set.headers;head; head=head->next) {
00185 if(strncasecompare(head->data, thisheader, thislen))
00186 return head->data;
00187 }
00188
00189 return NULL;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 char *Curl_checkProxyheaders(const struct connectdata *conn,
00202 const char *thisheader)
00203 {
00204 struct curl_slist *head;
00205 size_t thislen = strlen(thisheader);
00206 struct Curl_easy *data = conn->data;
00207
00208 for(head = (conn->bits.proxy && data->set.sep_headers) ?
00209 data->set.proxyheaders : data->set.headers;
00210 head; head=head->next) {
00211 if(strncasecompare(head->data, thisheader, thislen))
00212 return head->data;
00213 }
00214
00215 return NULL;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 char *Curl_copy_header_value(const char *header)
00225 {
00226 const char *start;
00227 const char *end;
00228 char *value;
00229 size_t len;
00230
00231 DEBUGASSERT(header);
00232
00233
00234 while(*header && (*header != ':'))
00235 ++header;
00236
00237 if(*header)
00238
00239 ++header;
00240
00241
00242 start = header;
00243 while(*start && ISSPACE(*start))
00244 start++;
00245
00246
00247
00248 end = strchr(start, '\r');
00249 if(!end)
00250 end = strchr(start, '\n');
00251 if(!end)
00252 end = strchr(start, '\0');
00253 if(!end)
00254 return NULL;
00255
00256
00257 while((end > start) && ISSPACE(*end))
00258 end--;
00259
00260
00261 len = end - start + 1;
00262
00263 value = malloc(len + 1);
00264 if(!value)
00265 return NULL;
00266
00267 memcpy(value, start, len);
00268 value[len] = 0;
00269
00270 return value;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
00280 {
00281 size_t size = 0;
00282 char *authorization = NULL;
00283 struct Curl_easy *data = conn->data;
00284 char **userp;
00285 const char *user;
00286 const char *pwd;
00287 CURLcode result;
00288
00289 if(proxy) {
00290 userp = &conn->allocptr.proxyuserpwd;
00291 user = conn->http_proxy.user;
00292 pwd = conn->http_proxy.passwd;
00293 }
00294 else {
00295 userp = &conn->allocptr.userpwd;
00296 user = conn->user;
00297 pwd = conn->passwd;
00298 }
00299
00300 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
00301
00302 result = Curl_base64_encode(data,
00303 data->state.buffer, strlen(data->state.buffer),
00304 &authorization, &size);
00305 if(result)
00306 return result;
00307
00308 if(!authorization)
00309 return CURLE_REMOTE_ACCESS_DENIED;
00310
00311 free(*userp);
00312 *userp = aprintf("%sAuthorization: Basic %s\r\n",
00313 proxy ? "Proxy-" : "",
00314 authorization);
00315 free(authorization);
00316 if(!*userp)
00317 return CURLE_OUT_OF_MEMORY;
00318
00319 return CURLE_OK;
00320 }
00321
00322
00323
00324
00325
00326
00327 static bool pickoneauth(struct auth *pick)
00328 {
00329 bool picked;
00330
00331 unsigned long avail = pick->avail & pick->want;
00332 picked = TRUE;
00333
00334
00335
00336 if(avail & CURLAUTH_NEGOTIATE)
00337 pick->picked = CURLAUTH_NEGOTIATE;
00338 else if(avail & CURLAUTH_DIGEST)
00339 pick->picked = CURLAUTH_DIGEST;
00340 else if(avail & CURLAUTH_NTLM)
00341 pick->picked = CURLAUTH_NTLM;
00342 else if(avail & CURLAUTH_NTLM_WB)
00343 pick->picked = CURLAUTH_NTLM_WB;
00344 else if(avail & CURLAUTH_BASIC)
00345 pick->picked = CURLAUTH_BASIC;
00346 else {
00347 pick->picked = CURLAUTH_PICKNONE;
00348 picked = FALSE;
00349 }
00350 pick->avail = CURLAUTH_NONE;
00351
00352 return picked;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 static CURLcode http_perhapsrewind(struct connectdata *conn)
00379 {
00380 struct Curl_easy *data = conn->data;
00381 struct HTTP *http = data->req.protop;
00382 curl_off_t bytessent;
00383 curl_off_t expectsend = -1;
00384
00385 if(!http)
00386
00387
00388 return CURLE_OK;
00389
00390 switch(data->set.httpreq) {
00391 case HTTPREQ_GET:
00392 case HTTPREQ_HEAD:
00393 return CURLE_OK;
00394 default:
00395 break;
00396 }
00397
00398 bytessent = http->writebytecount;
00399
00400 if(conn->bits.authneg) {
00401
00402
00403 expectsend = 0;
00404 }
00405 else if(!conn->bits.protoconnstart) {
00406
00407 expectsend = 0;
00408 }
00409 else {
00410
00411 switch(data->set.httpreq) {
00412 case HTTPREQ_POST:
00413 if(data->state.infilesize != -1)
00414 expectsend = data->state.infilesize;
00415 else if(data->set.postfields)
00416 expectsend = (curl_off_t)strlen(data->set.postfields);
00417 break;
00418 case HTTPREQ_PUT:
00419 if(data->state.infilesize != -1)
00420 expectsend = data->state.infilesize;
00421 break;
00422 case HTTPREQ_POST_FORM:
00423 expectsend = http->postsize;
00424 break;
00425 default:
00426 break;
00427 }
00428 }
00429
00430 conn->bits.rewindaftersend = FALSE;
00431
00432 if((expectsend == -1) || (expectsend > bytessent)) {
00433 #if defined(USE_NTLM)
00434
00435 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
00436 (data->state.authhost.picked == CURLAUTH_NTLM) ||
00437 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
00438 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
00439 if(((expectsend - bytessent) < 2000) ||
00440 (conn->ntlm.state != NTLMSTATE_NONE) ||
00441 (conn->proxyntlm.state != NTLMSTATE_NONE)) {
00442
00443
00444
00445
00446 if(!conn->bits.authneg) {
00447 conn->bits.rewindaftersend = TRUE;
00448 infof(data, "Rewind stream after send\n");
00449 }
00450
00451 return CURLE_OK;
00452 }
00453
00454 if(conn->bits.close)
00455
00456 return CURLE_OK;
00457
00458 infof(data, "NTLM send, close instead of sending %"
00459 CURL_FORMAT_CURL_OFF_T " bytes\n",
00460 (curl_off_t)(expectsend - bytessent));
00461 }
00462 #endif
00463
00464
00465 streamclose(conn, "Mid-auth HTTP and much data left to send");
00466 data->req.size = 0;
00467
00468
00469
00470 }
00471
00472 if(bytessent)
00473
00474 return Curl_readrewind(conn);
00475
00476 return CURLE_OK;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486 CURLcode Curl_http_auth_act(struct connectdata *conn)
00487 {
00488 struct Curl_easy *data = conn->data;
00489 bool pickhost = FALSE;
00490 bool pickproxy = FALSE;
00491 CURLcode result = CURLE_OK;
00492
00493 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
00494
00495 return CURLE_OK;
00496
00497 if(data->state.authproblem)
00498 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
00499
00500 if(conn->bits.user_passwd &&
00501 ((data->req.httpcode == 401) ||
00502 (conn->bits.authneg && data->req.httpcode < 300))) {
00503 pickhost = pickoneauth(&data->state.authhost);
00504 if(!pickhost)
00505 data->state.authproblem = TRUE;
00506 }
00507 if(conn->bits.proxy_user_passwd &&
00508 ((data->req.httpcode == 407) ||
00509 (conn->bits.authneg && data->req.httpcode < 300))) {
00510 pickproxy = pickoneauth(&data->state.authproxy);
00511 if(!pickproxy)
00512 data->state.authproblem = TRUE;
00513 }
00514
00515 if(pickhost || pickproxy) {
00516
00517
00518
00519 Curl_safefree(data->req.newurl);
00520 data->req.newurl = strdup(data->change.url);
00521 if(!data->req.newurl)
00522 return CURLE_OUT_OF_MEMORY;
00523
00524 if((data->set.httpreq != HTTPREQ_GET) &&
00525 (data->set.httpreq != HTTPREQ_HEAD) &&
00526 !conn->bits.rewindaftersend) {
00527 result = http_perhapsrewind(conn);
00528 if(result)
00529 return result;
00530 }
00531 }
00532 else if((data->req.httpcode < 300) &&
00533 (!data->state.authhost.done) &&
00534 conn->bits.authneg) {
00535
00536
00537
00538
00539 if((data->set.httpreq != HTTPREQ_GET) &&
00540 (data->set.httpreq != HTTPREQ_HEAD)) {
00541 data->req.newurl = strdup(data->change.url);
00542 if(!data->req.newurl)
00543 return CURLE_OUT_OF_MEMORY;
00544 data->state.authhost.done = TRUE;
00545 }
00546 }
00547 if(http_should_fail(conn)) {
00548 failf(data, "The requested URL returned error: %d",
00549 data->req.httpcode);
00550 result = CURLE_HTTP_RETURNED_ERROR;
00551 }
00552
00553 return result;
00554 }
00555
00556
00557
00558
00559
00560 static CURLcode
00561 output_auth_headers(struct connectdata *conn,
00562 struct auth *authstatus,
00563 const char *request,
00564 const char *path,
00565 bool proxy)
00566 {
00567 const char *auth = NULL;
00568 CURLcode result = CURLE_OK;
00569 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
00570 struct Curl_easy *data = conn->data;
00571 #endif
00572 #ifdef USE_SPNEGO
00573 struct negotiatedata *negdata = proxy ?
00574 &data->state.proxyneg : &data->state.negotiate;
00575 #endif
00576
00577 #ifdef CURL_DISABLE_CRYPTO_AUTH
00578 (void)request;
00579 (void)path;
00580 #endif
00581
00582 #ifdef USE_SPNEGO
00583 negdata->state = GSS_AUTHNONE;
00584 if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
00585 negdata->context && !GSS_ERROR(negdata->status)) {
00586 auth = "Negotiate";
00587 result = Curl_output_negotiate(conn, proxy);
00588 if(result)
00589 return result;
00590 authstatus->done = TRUE;
00591 negdata->state = GSS_AUTHSENT;
00592 }
00593 else
00594 #endif
00595 #ifdef USE_NTLM
00596 if(authstatus->picked == CURLAUTH_NTLM) {
00597 auth = "NTLM";
00598 result = Curl_output_ntlm(conn, proxy);
00599 if(result)
00600 return result;
00601 }
00602 else
00603 #endif
00604 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
00605 if(authstatus->picked == CURLAUTH_NTLM_WB) {
00606 auth="NTLM_WB";
00607 result = Curl_output_ntlm_wb(conn, proxy);
00608 if(result)
00609 return result;
00610 }
00611 else
00612 #endif
00613 #ifndef CURL_DISABLE_CRYPTO_AUTH
00614 if(authstatus->picked == CURLAUTH_DIGEST) {
00615 auth = "Digest";
00616 result = Curl_output_digest(conn,
00617 proxy,
00618 (const unsigned char *)request,
00619 (const unsigned char *)path);
00620 if(result)
00621 return result;
00622 }
00623 else
00624 #endif
00625 if(authstatus->picked == CURLAUTH_BASIC) {
00626
00627 if((proxy && conn->bits.proxy_user_passwd &&
00628 !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
00629 (!proxy && conn->bits.user_passwd &&
00630 !Curl_checkheaders(conn, "Authorization:"))) {
00631 auth = "Basic";
00632 result = http_output_basic(conn, proxy);
00633 if(result)
00634 return result;
00635 }
00636
00637
00638
00639 authstatus->done = TRUE;
00640 }
00641
00642 if(auth) {
00643 infof(data, "%s auth using %s with user '%s'\n",
00644 proxy ? "Proxy" : "Server", auth,
00645 proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
00646 (conn->user ? conn->user : ""));
00647 authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
00648 }
00649 else
00650 authstatus->multi = FALSE;
00651
00652 return CURLE_OK;
00653 }
00654
00669 CURLcode
00670 Curl_http_output_auth(struct connectdata *conn,
00671 const char *request,
00672 const char *path,
00673 bool proxytunnel)
00674
00675 {
00676 CURLcode result = CURLE_OK;
00677 struct Curl_easy *data = conn->data;
00678 struct auth *authhost;
00679 struct auth *authproxy;
00680
00681 DEBUGASSERT(data);
00682
00683 authhost = &data->state.authhost;
00684 authproxy = &data->state.authproxy;
00685
00686 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
00687 conn->bits.user_passwd)
00688 ;
00689 else {
00690 authhost->done = TRUE;
00691 authproxy->done = TRUE;
00692 return CURLE_OK;
00693 }
00694
00695 if(authhost->want && !authhost->picked)
00696
00697
00698
00699 authhost->picked = authhost->want;
00700
00701 if(authproxy->want && !authproxy->picked)
00702
00703
00704
00705 authproxy->picked = authproxy->want;
00706
00707 #ifndef CURL_DISABLE_PROXY
00708
00709 if(conn->bits.httpproxy &&
00710 (conn->bits.tunnel_proxy == proxytunnel)) {
00711 result = output_auth_headers(conn, authproxy, request, path, TRUE);
00712 if(result)
00713 return result;
00714 }
00715 else
00716 #else
00717 (void)proxytunnel;
00718 #endif
00719
00720
00721 authproxy->done = TRUE;
00722
00723
00724
00725 if(!data->state.this_is_a_follow ||
00726 conn->bits.netrc ||
00727 !data->state.first_host ||
00728 data->set.http_disable_hostname_check_before_authentication ||
00729 strcasecompare(data->state.first_host, conn->host.name)) {
00730 result = output_auth_headers(conn, authhost, request, path, FALSE);
00731 }
00732 else
00733 authhost->done = TRUE;
00734
00735 return result;
00736 }
00737
00738
00739
00740
00741
00742
00743
00744 CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
00745 const char *auth)
00746 {
00747
00748
00749
00750 struct Curl_easy *data = conn->data;
00751
00752 #ifdef USE_SPNEGO
00753 struct negotiatedata *negdata = proxy?
00754 &data->state.proxyneg:&data->state.negotiate;
00755 #endif
00756 unsigned long *availp;
00757 struct auth *authp;
00758
00759 if(proxy) {
00760 availp = &data->info.proxyauthavail;
00761 authp = &data->state.authproxy;
00762 }
00763 else {
00764 availp = &data->info.httpauthavail;
00765 authp = &data->state.authhost;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 while(*auth) {
00785 #ifdef USE_SPNEGO
00786 if(checkprefix("Negotiate", auth)) {
00787 if((authp->avail & CURLAUTH_NEGOTIATE) ||
00788 Curl_auth_is_spnego_supported()) {
00789 *availp |= CURLAUTH_NEGOTIATE;
00790 authp->avail |= CURLAUTH_NEGOTIATE;
00791
00792 if(authp->picked == CURLAUTH_NEGOTIATE) {
00793 if(negdata->state == GSS_AUTHSENT ||
00794 negdata->state == GSS_AUTHNONE) {
00795 CURLcode result = Curl_input_negotiate(conn, proxy, auth);
00796 if(!result) {
00797 DEBUGASSERT(!data->req.newurl);
00798 data->req.newurl = strdup(data->change.url);
00799 if(!data->req.newurl)
00800 return CURLE_OUT_OF_MEMORY;
00801 data->state.authproblem = FALSE;
00802
00803 negdata->state = GSS_AUTHRECV;
00804 }
00805 else
00806 data->state.authproblem = TRUE;
00807 }
00808 }
00809 }
00810 }
00811 else
00812 #endif
00813 #ifdef USE_NTLM
00814
00815 if(checkprefix("NTLM", auth)) {
00816 if((authp->avail & CURLAUTH_NTLM) ||
00817 (authp->avail & CURLAUTH_NTLM_WB) ||
00818 Curl_auth_is_ntlm_supported()) {
00819 *availp |= CURLAUTH_NTLM;
00820 authp->avail |= CURLAUTH_NTLM;
00821
00822 if(authp->picked == CURLAUTH_NTLM ||
00823 authp->picked == CURLAUTH_NTLM_WB) {
00824
00825 CURLcode result = Curl_input_ntlm(conn, proxy, auth);
00826 if(!result) {
00827 data->state.authproblem = FALSE;
00828 #ifdef NTLM_WB_ENABLED
00829 if(authp->picked == CURLAUTH_NTLM_WB) {
00830 *availp &= ~CURLAUTH_NTLM;
00831 authp->avail &= ~CURLAUTH_NTLM;
00832 *availp |= CURLAUTH_NTLM_WB;
00833 authp->avail |= CURLAUTH_NTLM_WB;
00834
00835
00836
00837 while(*auth && ISSPACE(*auth))
00838 auth++;
00839 if(checkprefix("NTLM", auth)) {
00840 auth += strlen("NTLM");
00841 while(*auth && ISSPACE(*auth))
00842 auth++;
00843 if(*auth) {
00844 conn->challenge_header = strdup(auth);
00845 if(!conn->challenge_header)
00846 return CURLE_OUT_OF_MEMORY;
00847 }
00848 }
00849 }
00850 #endif
00851 }
00852 else {
00853 infof(data, "Authentication problem. Ignoring this.\n");
00854 data->state.authproblem = TRUE;
00855 }
00856 }
00857 }
00858 }
00859 else
00860 #endif
00861 #ifndef CURL_DISABLE_CRYPTO_AUTH
00862 if(checkprefix("Digest", auth)) {
00863 if((authp->avail & CURLAUTH_DIGEST) != 0)
00864 infof(data, "Ignoring duplicate digest auth header.\n");
00865 else if(Curl_auth_is_digest_supported()) {
00866 CURLcode result;
00867
00868 *availp |= CURLAUTH_DIGEST;
00869 authp->avail |= CURLAUTH_DIGEST;
00870
00871
00872
00873
00874
00875 result = Curl_input_digest(conn, proxy, auth);
00876 if(result) {
00877 infof(data, "Authentication problem. Ignoring this.\n");
00878 data->state.authproblem = TRUE;
00879 }
00880 }
00881 }
00882 else
00883 #endif
00884 if(checkprefix("Basic", auth)) {
00885 *availp |= CURLAUTH_BASIC;
00886 authp->avail |= CURLAUTH_BASIC;
00887 if(authp->picked == CURLAUTH_BASIC) {
00888
00889
00890
00891 authp->avail = CURLAUTH_NONE;
00892 infof(data, "Authentication problem. Ignoring this.\n");
00893 data->state.authproblem = TRUE;
00894 }
00895 }
00896
00897
00898 while(*auth && *auth != ',')
00899 auth++;
00900 if(*auth == ',')
00901 auth++;
00902 while(*auth && ISSPACE(*auth))
00903 auth++;
00904 }
00905
00906 return CURLE_OK;
00907 }
00908
00919 static int http_should_fail(struct connectdata *conn)
00920 {
00921 struct Curl_easy *data;
00922 int httpcode;
00923
00924 DEBUGASSERT(conn);
00925 data = conn->data;
00926 DEBUGASSERT(data);
00927
00928 httpcode = data->req.httpcode;
00929
00930
00931
00932
00933
00934 if(!data->set.http_fail_on_error)
00935 return 0;
00936
00937
00938
00939
00940 if(httpcode < 400)
00941 return 0;
00942
00943
00944
00945
00946
00947 if((httpcode != 401) && (httpcode != 407))
00948 return 1;
00949
00950
00951
00952
00953 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 if((httpcode == 401) && !conn->bits.user_passwd)
00974 return TRUE;
00975 if((httpcode == 407) && !conn->bits.proxy_user_passwd)
00976 return TRUE;
00977
00978 return data->state.authproblem;
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 static size_t readmoredata(char *buffer,
00990 size_t size,
00991 size_t nitems,
00992 void *userp)
00993 {
00994 struct connectdata *conn = (struct connectdata *)userp;
00995 struct HTTP *http = conn->data->req.protop;
00996 size_t fullsize = size * nitems;
00997
00998 if(!http->postsize)
00999
01000 return 0;
01001
01002
01003 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
01004
01005 if(http->postsize <= (curl_off_t)fullsize) {
01006 memcpy(buffer, http->postdata, (size_t)http->postsize);
01007 fullsize = (size_t)http->postsize;
01008
01009 if(http->backup.postsize) {
01010
01011 http->postdata = http->backup.postdata;
01012 http->postsize = http->backup.postsize;
01013 conn->data->state.fread_func = http->backup.fread_func;
01014 conn->data->state.in = http->backup.fread_in;
01015
01016 http->sending++;
01017
01018 http->backup.postsize=0;
01019 }
01020 else
01021 http->postsize = 0;
01022
01023 return fullsize;
01024 }
01025
01026 memcpy(buffer, http->postdata, fullsize);
01027 http->postdata += fullsize;
01028 http->postsize -= fullsize;
01029
01030 return fullsize;
01031 }
01032
01033
01034
01035
01036
01037
01038
01039 Curl_send_buffer *Curl_add_buffer_init(void)
01040 {
01041 return calloc(1, sizeof(Curl_send_buffer));
01042 }
01043
01044
01045
01046
01047 void Curl_add_buffer_free(Curl_send_buffer *buff)
01048 {
01049 if(buff)
01050 free(buff->buffer);
01051 free(buff);
01052 }
01053
01054
01055
01056
01057
01058
01059
01060 CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
01061 struct connectdata *conn,
01062
01063
01064
01065 long *bytes_written,
01066
01067
01068 size_t included_body_bytes,
01069 int socketindex)
01070
01071 {
01072 ssize_t amount;
01073 CURLcode result;
01074 char *ptr;
01075 size_t size;
01076 struct HTTP *http = conn->data->req.protop;
01077 size_t sendsize;
01078 curl_socket_t sockfd;
01079 size_t headersize;
01080
01081 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
01082
01083 sockfd = conn->sock[socketindex];
01084
01085
01086
01087
01088 ptr = in->buffer;
01089 size = in->size_used;
01090
01091 headersize = size - included_body_bytes;
01092
01093
01094 DEBUGASSERT(size > included_body_bytes);
01095
01096 result = Curl_convert_to_network(conn->data, ptr, headersize);
01097
01098 if(result) {
01099
01100 Curl_add_buffer_free(in);
01101 return result;
01102 }
01103
01104 if((conn->handler->flags & PROTOPT_SSL ||
01105 conn->http_proxy.proxytype == CURLPROXY_HTTPS)
01106 && conn->httpversion != 20) {
01107
01108
01109
01110
01111
01112
01113 sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
01114
01115
01116
01117
01118
01119
01120
01121 memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
01122 ptr = conn->data->state.uploadbuffer;
01123 }
01124 else
01125 sendsize = size;
01126
01127 result = Curl_write(conn, sockfd, ptr, sendsize, &amount);
01128
01129 if(!result) {
01130
01131
01132
01133
01134
01135
01136 size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
01137 size_t bodylen = amount - headlen;
01138
01139 if(conn->data->set.verbose) {
01140
01141 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
01142 if(bodylen) {
01143
01144
01145 Curl_debug(conn->data, CURLINFO_DATA_OUT,
01146 ptr+headlen, bodylen, conn);
01147 }
01148 }
01149
01150
01151
01152
01153 *bytes_written += (long)amount;
01154
01155 if(http) {
01156
01157
01158 http->writebytecount += bodylen;
01159
01160 if((size_t)amount != size) {
01161
01162
01163
01164
01165 size -= amount;
01166
01167 ptr = in->buffer + amount;
01168
01169
01170 http->backup.fread_func = conn->data->state.fread_func;
01171 http->backup.fread_in = conn->data->state.in;
01172 http->backup.postdata = http->postdata;
01173 http->backup.postsize = http->postsize;
01174
01175
01176 conn->data->state.fread_func = (curl_read_callback)readmoredata;
01177 conn->data->state.in = (void *)conn;
01178 http->postdata = ptr;
01179 http->postsize = (curl_off_t)size;
01180
01181 http->send_buffer = in;
01182 http->sending = HTTPSEND_REQUEST;
01183
01184 return CURLE_OK;
01185 }
01186 http->sending = HTTPSEND_BODY;
01187
01188 }
01189 else {
01190 if((size_t)amount != size)
01191
01192
01193
01194
01195
01196
01197
01198 return CURLE_SEND_ERROR;
01199 else
01200 Curl_pipeline_leave_write(conn);
01201 }
01202 }
01203 Curl_add_buffer_free(in);
01204
01205 return result;
01206 }
01207
01208
01209
01210
01211
01212 CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
01213 {
01214 char *s;
01215 va_list ap;
01216 va_start(ap, fmt);
01217 s = vaprintf(fmt, ap);
01218 va_end(ap);
01219
01220 if(s) {
01221 CURLcode result = Curl_add_buffer(in, s, strlen(s));
01222 free(s);
01223 return result;
01224 }
01225
01226 free(in->buffer);
01227 free(in);
01228 return CURLE_OUT_OF_MEMORY;
01229 }
01230
01231
01232
01233
01234 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
01235 {
01236 char *new_rb;
01237 size_t new_size;
01238
01239 if(~size < in->size_used) {
01240
01241
01242
01243 Curl_safefree(in->buffer);
01244 free(in);
01245 return CURLE_OUT_OF_MEMORY;
01246 }
01247
01248 if(!in->buffer ||
01249 ((in->size_used + size) > (in->size_max - 1))) {
01250
01251
01252
01253
01254
01255 if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
01256 (~(size * 2) < (in->size_used * 2)))
01257 new_size = (size_t)-1;
01258 else
01259 new_size = (in->size_used+size) * 2;
01260
01261 if(in->buffer)
01262
01263 new_rb = Curl_saferealloc(in->buffer, new_size);
01264 else
01265
01266 new_rb = malloc(new_size);
01267
01268 if(!new_rb) {
01269
01270 free(in);
01271 return CURLE_OUT_OF_MEMORY;
01272 }
01273
01274 in->buffer = new_rb;
01275 in->size_max = new_size;
01276 }
01277 memcpy(&in->buffer[in->size_used], inptr, size);
01278
01279 in->size_used += size;
01280
01281 return CURLE_OK;
01282 }
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295 bool
01296 Curl_compareheader(const char *headerline,
01297 const char *header,
01298 const char *content)
01299 {
01300
01301
01302
01303
01304
01305 size_t hlen = strlen(header);
01306 size_t clen;
01307 size_t len;
01308 const char *start;
01309 const char *end;
01310
01311 if(!strncasecompare(headerline, header, hlen))
01312 return FALSE;
01313
01314
01315 start = &headerline[hlen];
01316
01317
01318 while(*start && ISSPACE(*start))
01319 start++;
01320
01321
01322 end = strchr(start, '\r');
01323 if(!end) {
01324
01325 end = strchr(start, '\n');
01326
01327 if(!end)
01328
01329 end = strchr(start, '\0');
01330 }
01331
01332 len = end-start;
01333 clen = strlen(content);
01334
01335
01336 for(;len>=clen;len--, start++) {
01337 if(strncasecompare(start, content, clen))
01338 return TRUE;
01339 }
01340
01341 return FALSE;
01342 }
01343
01344
01345
01346
01347
01348 CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
01349 {
01350 CURLcode result;
01351
01352
01353
01354 connkeep(conn, "HTTP default");
01355
01356
01357 result = Curl_proxy_connect(conn, FIRSTSOCKET);
01358 if(result)
01359 return result;
01360
01361 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
01362 return CURLE_OK;
01363
01364 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
01365
01366 return CURLE_OK;
01367
01368 if(conn->given->flags & PROTOPT_SSL) {
01369
01370 result = https_connecting(conn, done);
01371 if(result)
01372 return result;
01373 }
01374 else
01375 *done = TRUE;
01376
01377 return CURLE_OK;
01378 }
01379
01380
01381
01382
01383 static int http_getsock_do(struct connectdata *conn,
01384 curl_socket_t *socks,
01385 int numsocks)
01386 {
01387
01388 (void)numsocks;
01389 socks[0] = conn->sock[FIRSTSOCKET];
01390 return GETSOCK_WRITESOCK(0);
01391 }
01392
01393 #ifdef USE_SSL
01394 static CURLcode https_connecting(struct connectdata *conn, bool *done)
01395 {
01396 CURLcode result;
01397 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
01398
01399
01400 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
01401 if(result)
01402 connclose(conn, "Failed HTTPS connection");
01403
01404 return result;
01405 }
01406
01407 static int https_getsock(struct connectdata *conn,
01408 curl_socket_t *socks,
01409 int numsocks)
01410 {
01411 if(conn->handler->flags & PROTOPT_SSL)
01412 return Curl_ssl_getsock(conn, socks, numsocks);
01413 return GETSOCK_BLANK;
01414 }
01415 #endif
01416
01417
01418
01419
01420
01421
01422 CURLcode Curl_http_done(struct connectdata *conn,
01423 CURLcode status, bool premature)
01424 {
01425 struct Curl_easy *data = conn->data;
01426 struct HTTP *http = data->req.protop;
01427
01428 infof(data, "Curl_http_done: called premature == %d\n", premature);
01429
01430 Curl_unencode_cleanup(conn);
01431
01432 #ifdef USE_SPNEGO
01433 if(data->state.proxyneg.state == GSS_AUTHSENT ||
01434 data->state.negotiate.state == GSS_AUTHSENT) {
01435
01436
01437
01438
01439 if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
01440 !data->set.connect_only)
01441 streamclose(conn, "Negotiate transfer completed");
01442 Curl_cleanup_negotiate(data);
01443 }
01444 #endif
01445
01446
01447 conn->seek_func = data->set.seek_func;
01448 conn->seek_client = data->set.seek_client;
01449
01450 if(!http)
01451 return CURLE_OK;
01452
01453 if(http->send_buffer) {
01454 Curl_add_buffer_free(http->send_buffer);
01455 http->send_buffer = NULL;
01456 }
01457
01458 Curl_http2_done(conn, premature);
01459
01460 if(HTTPREQ_POST_FORM == data->set.httpreq) {
01461 data->req.bytecount = http->readbytecount + http->writebytecount;
01462
01463 Curl_formclean(&http->sendit);
01464 if(http->form.fp) {
01465
01466 fclose(http->form.fp);
01467 http->form.fp = NULL;
01468 }
01469 }
01470 else if(HTTPREQ_PUT == data->set.httpreq)
01471 data->req.bytecount = http->readbytecount + http->writebytecount;
01472
01473 if(status)
01474 return status;
01475
01476 if(!premature &&
01477
01478 !conn->bits.retry &&
01479 !data->set.connect_only &&
01480 (http->readbytecount +
01481 data->req.headerbytecount -
01482 data->req.deductheadercount) <= 0) {
01483
01484
01485
01486 failf(data, "Empty reply from server");
01487 return CURLE_GOT_NOTHING;
01488 }
01489
01490 return CURLE_OK;
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 static bool use_http_1_1plus(const struct Curl_easy *data,
01503 const struct connectdata *conn)
01504 {
01505 if((data->state.httpversion == 10) || (conn->httpversion == 10))
01506 return FALSE;
01507 if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
01508 (conn->httpversion <= 10))
01509 return FALSE;
01510 return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
01511 (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
01512 }
01513
01514
01515 static CURLcode expect100(struct Curl_easy *data,
01516 struct connectdata *conn,
01517 Curl_send_buffer *req_buffer)
01518 {
01519 CURLcode result = CURLE_OK;
01520 const char *ptr;
01521 data->state.expect100header = FALSE;
01522
01523 if(use_http_1_1plus(data, conn) &&
01524 (conn->httpversion != 20)) {
01525
01526
01527
01528 ptr = Curl_checkheaders(conn, "Expect:");
01529 if(ptr) {
01530 data->state.expect100header =
01531 Curl_compareheader(ptr, "Expect:", "100-continue");
01532 }
01533 else {
01534 result = Curl_add_bufferf(req_buffer,
01535 "Expect: 100-continue\r\n");
01536 if(!result)
01537 data->state.expect100header = TRUE;
01538 }
01539 }
01540
01541 return result;
01542 }
01543
01544 enum proxy_use {
01545 HEADER_SERVER,
01546 HEADER_PROXY,
01547 HEADER_CONNECT
01548 };
01549
01550 CURLcode Curl_add_custom_headers(struct connectdata *conn,
01551 bool is_connect,
01552 Curl_send_buffer *req_buffer)
01553 {
01554 char *ptr;
01555 struct curl_slist *h[2];
01556 struct curl_slist *headers;
01557 int numlists=1;
01558 struct Curl_easy *data = conn->data;
01559 int i;
01560
01561 enum proxy_use proxy;
01562
01563 if(is_connect)
01564 proxy = HEADER_CONNECT;
01565 else
01566 proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
01567 HEADER_PROXY:HEADER_SERVER;
01568
01569 switch(proxy) {
01570 case HEADER_SERVER:
01571 h[0] = data->set.headers;
01572 break;
01573 case HEADER_PROXY:
01574 h[0] = data->set.headers;
01575 if(data->set.sep_headers) {
01576 h[1] = data->set.proxyheaders;
01577 numlists++;
01578 }
01579 break;
01580 case HEADER_CONNECT:
01581 if(data->set.sep_headers)
01582 h[0] = data->set.proxyheaders;
01583 else
01584 h[0] = data->set.headers;
01585 break;
01586 }
01587
01588
01589 for(i=0; i < numlists; i++) {
01590 headers = h[i];
01591
01592 while(headers) {
01593 ptr = strchr(headers->data, ':');
01594 if(ptr) {
01595
01596
01597 ptr++;
01598 while(*ptr && ISSPACE(*ptr))
01599 ptr++;
01600
01601 if(*ptr) {
01602
01603
01604 if(conn->allocptr.host &&
01605
01606
01607 checkprefix("Host:", headers->data))
01608 ;
01609 else if(data->set.httpreq == HTTPREQ_POST_FORM &&
01610
01611 checkprefix("Content-Type:", headers->data))
01612 ;
01613 else if(conn->bits.authneg &&
01614
01615
01616 checkprefix("Content-Length", headers->data))
01617 ;
01618 else if(conn->allocptr.te &&
01619
01620
01621 checkprefix("Connection", headers->data))
01622 ;
01623 else if((conn->httpversion == 20) &&
01624 checkprefix("Transfer-Encoding:", headers->data))
01625
01626 ;
01627 else {
01628 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
01629 headers->data);
01630 if(result)
01631 return result;
01632 }
01633 }
01634 }
01635 else {
01636 ptr = strchr(headers->data, ';');
01637 if(ptr) {
01638
01639 ptr++;
01640 while(*ptr && ISSPACE(*ptr))
01641 ptr++;
01642
01643 if(*ptr) {
01644
01645 }
01646 else {
01647 if(*(--ptr) == ';') {
01648 CURLcode result;
01649
01650
01651 *ptr = ':';
01652 result = Curl_add_bufferf(req_buffer, "%s\r\n",
01653 headers->data);
01654 if(result)
01655 return result;
01656 }
01657 }
01658 }
01659 }
01660 headers = headers->next;
01661 }
01662 }
01663
01664 return CURLE_OK;
01665 }
01666
01667 CURLcode Curl_add_timecondition(struct Curl_easy *data,
01668 Curl_send_buffer *req_buffer)
01669 {
01670 const struct tm *tm;
01671 char *buf = data->state.buffer;
01672 struct tm keeptime;
01673 CURLcode result;
01674
01675 if(data->set.timecondition == CURL_TIMECOND_NONE)
01676
01677 return CURLE_OK;
01678
01679 result = Curl_gmtime(data->set.timevalue, &keeptime);
01680 if(result) {
01681 failf(data, "Invalid TIMEVALUE");
01682 return result;
01683 }
01684 tm = &keeptime;
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694 snprintf(buf, BUFSIZE-1,
01695 "%s, %02d %s %4d %02d:%02d:%02d GMT",
01696 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
01697 tm->tm_mday,
01698 Curl_month[tm->tm_mon],
01699 tm->tm_year + 1900,
01700 tm->tm_hour,
01701 tm->tm_min,
01702 tm->tm_sec);
01703
01704 switch(data->set.timecondition) {
01705 default:
01706 break;
01707 case CURL_TIMECOND_IFMODSINCE:
01708 result = Curl_add_bufferf(req_buffer,
01709 "If-Modified-Since: %s\r\n", buf);
01710 break;
01711 case CURL_TIMECOND_IFUNMODSINCE:
01712 result = Curl_add_bufferf(req_buffer,
01713 "If-Unmodified-Since: %s\r\n", buf);
01714 break;
01715 case CURL_TIMECOND_LASTMOD:
01716 result = Curl_add_bufferf(req_buffer,
01717 "Last-Modified: %s\r\n", buf);
01718 break;
01719 }
01720
01721 return result;
01722 }
01723
01724
01725
01726
01727
01728
01729 CURLcode Curl_http(struct connectdata *conn, bool *done)
01730 {
01731 struct Curl_easy *data = conn->data;
01732 CURLcode result = CURLE_OK;
01733 struct HTTP *http;
01734 const char *ppath = data->state.path;
01735 bool paste_ftp_userpwd = FALSE;
01736 char ftp_typecode[sizeof("/;type=?")] = "";
01737 const char *host = conn->host.name;
01738 const char *te = "";
01739 const char *ptr;
01740 const char *request;
01741 Curl_HttpReq httpreq = data->set.httpreq;
01742 #if !defined(CURL_DISABLE_COOKIES)
01743 char *addcookies = NULL;
01744 #endif
01745 curl_off_t included_body = 0;
01746 const char *httpstring;
01747 Curl_send_buffer *req_buffer;
01748 curl_off_t postsize = 0;
01749 int seekerr = CURL_SEEKFUNC_OK;
01750
01751
01752
01753
01754 *done = TRUE;
01755
01756 if(conn->httpversion < 20) {
01757
01758 switch(conn->negnpn) {
01759 case CURL_HTTP_VERSION_2:
01760 conn->httpversion = 20;
01761
01762 result = Curl_http2_switched(conn, NULL, 0);
01763 if(result)
01764 return result;
01765 break;
01766 case CURL_HTTP_VERSION_1_1:
01767
01768 break;
01769 default:
01770
01771 #ifdef USE_NGHTTP2
01772 if(conn->data->set.httpversion ==
01773 CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
01774 DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
01775 conn->httpversion = 20;
01776
01777 result = Curl_http2_switched(conn, NULL, 0);
01778 if(result)
01779 return result;
01780 }
01781 #endif
01782 break;
01783 }
01784 }
01785 else {
01786
01787 result = Curl_http2_setup(conn);
01788 if(result)
01789 return result;
01790 }
01791
01792 http = data->req.protop;
01793
01794 if(!data->state.this_is_a_follow) {
01795
01796 free(data->state.first_host);
01797
01798 data->state.first_host = strdup(conn->host.name);
01799 if(!data->state.first_host)
01800 return CURLE_OUT_OF_MEMORY;
01801
01802 data->state.first_remote_port = conn->remote_port;
01803 }
01804 http->writebytecount = http->readbytecount = 0;
01805
01806 if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
01807 data->set.upload) {
01808 httpreq = HTTPREQ_PUT;
01809 }
01810
01811
01812 if(data->set.str[STRING_CUSTOMREQUEST])
01813 request = data->set.str[STRING_CUSTOMREQUEST];
01814 else {
01815 if(data->set.opt_no_body)
01816 request = "HEAD";
01817 else {
01818 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
01819 switch(httpreq) {
01820 case HTTPREQ_POST:
01821 case HTTPREQ_POST_FORM:
01822 request = "POST";
01823 break;
01824 case HTTPREQ_PUT:
01825 request = "PUT";
01826 break;
01827 default:
01828 case HTTPREQ_GET:
01829 request = "GET";
01830 break;
01831 case HTTPREQ_HEAD:
01832 request = "HEAD";
01833 break;
01834 }
01835 }
01836 }
01837
01838
01839
01840
01841
01842 if(Curl_checkheaders(conn, "User-Agent:")) {
01843 free(conn->allocptr.uagent);
01844 conn->allocptr.uagent=NULL;
01845 }
01846
01847
01848 result = Curl_http_output_auth(conn, request, ppath, FALSE);
01849 if(result)
01850 return result;
01851
01852 if((data->state.authhost.multi || data->state.authproxy.multi) &&
01853 (httpreq != HTTPREQ_GET) &&
01854 (httpreq != HTTPREQ_HEAD)) {
01855
01856
01857 conn->bits.authneg = TRUE;
01858 }
01859 else
01860 conn->bits.authneg = FALSE;
01861
01862 Curl_safefree(conn->allocptr.ref);
01863 if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
01864 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
01865 if(!conn->allocptr.ref)
01866 return CURLE_OUT_OF_MEMORY;
01867 }
01868 else
01869 conn->allocptr.ref = NULL;
01870
01871 #if !defined(CURL_DISABLE_COOKIES)
01872 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
01873 addcookies = data->set.str[STRING_COOKIE];
01874 #endif
01875
01876 if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
01877 data->set.str[STRING_ENCODING]) {
01878 Curl_safefree(conn->allocptr.accept_encoding);
01879 conn->allocptr.accept_encoding =
01880 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
01881 if(!conn->allocptr.accept_encoding)
01882 return CURLE_OUT_OF_MEMORY;
01883 }
01884 else {
01885 Curl_safefree(conn->allocptr.accept_encoding);
01886 conn->allocptr.accept_encoding = NULL;
01887 }
01888
01889 #ifdef HAVE_LIBZ
01890
01891
01892 if(!Curl_checkheaders(conn, "TE:") &&
01893 data->set.http_transfer_encoding) {
01894
01895
01896
01897
01898
01899 char *cptr = Curl_checkheaders(conn, "Connection:");
01900 #define TE_HEADER "TE: gzip\r\n"
01901
01902 Curl_safefree(conn->allocptr.te);
01903
01904
01905 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
01906 strdup("Connection: TE\r\n" TE_HEADER);
01907
01908 if(!conn->allocptr.te)
01909 return CURLE_OUT_OF_MEMORY;
01910 }
01911 #endif
01912
01913 ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
01914 if(ptr) {
01915
01916 data->req.upload_chunky =
01917 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
01918 }
01919 else {
01920 if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
01921 data->set.upload &&
01922 (data->state.infilesize == -1)) {
01923 if(conn->bits.authneg)
01924
01925 ;
01926 else if(use_http_1_1plus(data, conn)) {
01927
01928 data->req.upload_chunky = TRUE;
01929 }
01930 else {
01931 failf(data, "Chunky upload is not supported by HTTP 1.0");
01932 return CURLE_UPLOAD_FAILED;
01933 }
01934 }
01935 else {
01936
01937 data->req.upload_chunky = FALSE;
01938 }
01939
01940 if(data->req.upload_chunky)
01941 te = "Transfer-Encoding: chunked\r\n";
01942 }
01943
01944 Curl_safefree(conn->allocptr.host);
01945
01946 ptr = Curl_checkheaders(conn, "Host:");
01947 if(ptr && (!data->state.this_is_a_follow ||
01948 strcasecompare(data->state.first_host, conn->host.name))) {
01949 #if !defined(CURL_DISABLE_COOKIES)
01950
01951
01952
01953
01954
01955 char *cookiehost = Curl_copy_header_value(ptr);
01956 if(!cookiehost)
01957 return CURLE_OUT_OF_MEMORY;
01958 if(!*cookiehost)
01959
01960 free(cookiehost);
01961 else {
01962
01963
01964 int startsearch = 0;
01965 if(*cookiehost == '[') {
01966 char *closingbracket;
01967
01968
01969 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
01970 closingbracket = strchr(cookiehost, ']');
01971 if(closingbracket)
01972 *closingbracket = 0;
01973 }
01974 else {
01975 char *colon = strchr(cookiehost + startsearch, ':');
01976 if(colon)
01977 *colon = 0;
01978 }
01979 Curl_safefree(conn->allocptr.cookiehost);
01980 conn->allocptr.cookiehost = cookiehost;
01981 }
01982 #endif
01983
01984 if(strcmp("Host:", ptr)) {
01985 conn->allocptr.host = aprintf("%s\r\n", ptr);
01986 if(!conn->allocptr.host)
01987 return CURLE_OUT_OF_MEMORY;
01988 }
01989 else
01990
01991 conn->allocptr.host = NULL;
01992 }
01993 else {
01994
01995
01996
01997 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
01998 (conn->remote_port == PORT_HTTPS)) ||
01999 ((conn->given->protocol&CURLPROTO_HTTP) &&
02000 (conn->remote_port == PORT_HTTP)) )
02001
02002
02003 conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
02004 conn->bits.ipv6_ip?"[":"",
02005 host,
02006 conn->bits.ipv6_ip?"]":"");
02007 else
02008 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
02009 conn->bits.ipv6_ip?"[":"",
02010 host,
02011 conn->bits.ipv6_ip?"]":"",
02012 conn->remote_port);
02013
02014 if(!conn->allocptr.host)
02015
02016 return CURLE_OUT_OF_MEMORY;
02017 }
02018
02019 #ifndef CURL_DISABLE_PROXY
02020 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
02021
02022
02023
02024
02025
02026 if(conn->host.dispname != conn->host.name) {
02027 char *url = data->change.url;
02028 ptr = strstr(url, conn->host.dispname);
02029 if(ptr) {
02030
02031
02032
02033
02034
02035 size_t currlen = strlen(conn->host.dispname);
02036 size_t newlen = strlen(conn->host.name);
02037 size_t urllen = strlen(url);
02038
02039 char *newurl;
02040
02041 newurl = malloc(urllen + newlen - currlen + 1);
02042 if(newurl) {
02043
02044 memcpy(newurl, url, ptr - url);
02045
02046 memcpy(newurl + (ptr - url), conn->host.name, newlen);
02047
02048 memcpy(newurl + newlen + (ptr - url),
02049 ptr + currlen,
02050 urllen - (ptr-url) - currlen + 1);
02051 if(data->change.url_alloc) {
02052 Curl_safefree(data->change.url);
02053 data->change.url_alloc = FALSE;
02054 }
02055 data->change.url = newurl;
02056 data->change.url_alloc = TRUE;
02057 }
02058 else
02059 return CURLE_OUT_OF_MEMORY;
02060 }
02061 }
02062 ppath = data->change.url;
02063 if(checkprefix("ftp://", ppath)) {
02064 if(data->set.proxy_transfer_mode) {
02065
02066 char *type = strstr(ppath, ";type=");
02067 if(type && type[6] && type[7] == 0) {
02068 switch(Curl_raw_toupper(type[6])) {
02069 case 'A':
02070 case 'D':
02071 case 'I':
02072 break;
02073 default:
02074 type = NULL;
02075 }
02076 }
02077 if(!type) {
02078 char *p = ftp_typecode;
02079
02080
02081 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
02082 *p++ = '/';
02083 }
02084 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
02085 data->set.prefer_ascii ? 'a' : 'i');
02086 }
02087 }
02088 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
02089 paste_ftp_userpwd = TRUE;
02090 }
02091 }
02092 #endif
02093
02094 if(HTTPREQ_POST_FORM == httpreq) {
02095
02096
02097 result = Curl_getformdata(data, &http->sendit, data->set.httppost,
02098 Curl_checkheaders(conn, "Content-Type:"),
02099 &http->postsize);
02100 if(result)
02101 return result;
02102 }
02103
02104 http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
02105
02106 if(( (HTTPREQ_POST == httpreq) ||
02107 (HTTPREQ_POST_FORM == httpreq) ||
02108 (HTTPREQ_PUT == httpreq) ) &&
02109 data->state.resume_from) {
02110
02111
02112
02113
02114
02115
02116
02117
02118 if(data->state.resume_from < 0) {
02119
02120
02121
02122
02123 data->state.resume_from = 0;
02124 }
02125
02126 if(data->state.resume_from && !data->state.this_is_a_follow) {
02127
02128
02129
02130
02131 if(conn->seek_func) {
02132 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
02133 SEEK_SET);
02134 }
02135
02136 if(seekerr != CURL_SEEKFUNC_OK) {
02137 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
02138 failf(data, "Could not seek stream");
02139 return CURLE_READ_ERROR;
02140 }
02141
02142 else {
02143 curl_off_t passed=0;
02144 do {
02145 size_t readthisamountnow =
02146 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
02147 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
02148
02149 size_t actuallyread =
02150 data->state.fread_func(data->state.buffer, 1, readthisamountnow,
02151 data->state.in);
02152
02153 passed += actuallyread;
02154 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
02155
02156
02157 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
02158 " bytes from the input", passed);
02159 return CURLE_READ_ERROR;
02160 }
02161 } while(passed < data->state.resume_from);
02162 }
02163 }
02164
02165
02166 if(data->state.infilesize>0) {
02167 data->state.infilesize -= data->state.resume_from;
02168
02169 if(data->state.infilesize <= 0) {
02170 failf(data, "File already completely uploaded");
02171 return CURLE_PARTIAL_FILE;
02172 }
02173 }
02174
02175 }
02176 }
02177 if(data->state.use_range) {
02178
02179
02180
02181
02182
02183 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
02184 !Curl_checkheaders(conn, "Range:")) {
02185
02186 free(conn->allocptr.rangeline);
02187 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
02188 data->state.range);
02189 }
02190 else if((httpreq != HTTPREQ_GET) &&
02191 !Curl_checkheaders(conn, "Content-Range:")) {
02192
02193
02194 free(conn->allocptr.rangeline);
02195
02196 if(data->set.set_resume_from < 0) {
02197
02198
02199
02200 conn->allocptr.rangeline =
02201 aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
02202 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
02203 data->state.infilesize - 1, data->state.infilesize);
02204
02205 }
02206 else if(data->state.resume_from) {
02207
02208 curl_off_t total_expected_size=
02209 data->state.resume_from + data->state.infilesize;
02210 conn->allocptr.rangeline =
02211 aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
02212 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
02213 data->state.range, total_expected_size-1,
02214 total_expected_size);
02215 }
02216 else {
02217
02218
02219 conn->allocptr.rangeline =
02220 aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
02221 data->state.range, data->state.infilesize);
02222 }
02223 if(!conn->allocptr.rangeline)
02224 return CURLE_OUT_OF_MEMORY;
02225 }
02226 }
02227
02228
02229
02230 httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
02231
02232
02233 req_buffer = Curl_add_buffer_init();
02234
02235 if(!req_buffer)
02236 return CURLE_OUT_OF_MEMORY;
02237
02238
02239
02240 result = Curl_add_bufferf(req_buffer, "%s ", request);
02241 if(result)
02242 return result;
02243
02244
02245 if(paste_ftp_userpwd)
02246 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
02247 conn->user, conn->passwd,
02248 ppath + sizeof("ftp://") - 1);
02249 else
02250 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
02251 if(result)
02252 return result;
02253
02254 result =
02255 Curl_add_bufferf(req_buffer,
02256 "%s"
02257 " HTTP/%s\r\n"
02258 "%s"
02259 "%s"
02260 "%s"
02261 "%s"
02262 "%s"
02263 "%s"
02264 "%s"
02265 "%s"
02266 "%s"
02267 "%s"
02268 "%s",
02269
02270 ftp_typecode,
02271 httpstring,
02272 (conn->allocptr.host?conn->allocptr.host:""),
02273 conn->allocptr.proxyuserpwd?
02274 conn->allocptr.proxyuserpwd:"",
02275 conn->allocptr.userpwd?conn->allocptr.userpwd:"",
02276 (data->state.use_range && conn->allocptr.rangeline)?
02277 conn->allocptr.rangeline:"",
02278 (data->set.str[STRING_USERAGENT] &&
02279 *data->set.str[STRING_USERAGENT] &&
02280 conn->allocptr.uagent)?
02281 conn->allocptr.uagent:"",
02282 http->p_accept?http->p_accept:"",
02283 conn->allocptr.te?conn->allocptr.te:"",
02284 (data->set.str[STRING_ENCODING] &&
02285 *data->set.str[STRING_ENCODING] &&
02286 conn->allocptr.accept_encoding)?
02287 conn->allocptr.accept_encoding:"",
02288 (data->change.referer && conn->allocptr.ref)?
02289 conn->allocptr.ref:"" ,
02290 (conn->bits.httpproxy &&
02291 !conn->bits.tunnel_proxy &&
02292 !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
02293 "Proxy-Connection: Keep-Alive\r\n":"",
02294 te
02295 );
02296
02297
02298 Curl_safefree(conn->allocptr.userpwd);
02299
02300
02301
02302
02303
02304 switch(data->state.authproxy.picked) {
02305 case CURLAUTH_NEGOTIATE:
02306 case CURLAUTH_NTLM:
02307 case CURLAUTH_NTLM_WB:
02308 Curl_safefree(conn->allocptr.proxyuserpwd);
02309 break;
02310 }
02311
02312 if(result)
02313 return result;
02314
02315 if(!(conn->handler->flags&PROTOPT_SSL) &&
02316 conn->httpversion != 20 &&
02317 (data->set.httpversion == CURL_HTTP_VERSION_2)) {
02318
02319
02320 result = Curl_http2_request_upgrade(req_buffer, conn);
02321 if(result)
02322 return result;
02323 }
02324
02325 #if !defined(CURL_DISABLE_COOKIES)
02326 if(data->cookies || addcookies) {
02327 struct Cookie *co=NULL;
02328 int count=0;
02329
02330 if(data->cookies) {
02331 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
02332 co = Curl_cookie_getlist(data->cookies,
02333 conn->allocptr.cookiehost?
02334 conn->allocptr.cookiehost:host,
02335 data->state.path,
02336 (conn->handler->protocol&CURLPROTO_HTTPS)?
02337 TRUE:FALSE);
02338 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
02339 }
02340 if(co) {
02341 struct Cookie *store=co;
02342
02343 while(co) {
02344 if(co->value) {
02345 if(0 == count) {
02346 result = Curl_add_bufferf(req_buffer, "Cookie: ");
02347 if(result)
02348 break;
02349 }
02350 result = Curl_add_bufferf(req_buffer,
02351 "%s%s=%s", count?"; ":"",
02352 co->name, co->value);
02353 if(result)
02354 break;
02355 count++;
02356 }
02357 co = co->next;
02358 }
02359 Curl_cookie_freelist(store);
02360 }
02361 if(addcookies && !result) {
02362 if(!count)
02363 result = Curl_add_bufferf(req_buffer, "Cookie: ");
02364 if(!result) {
02365 result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"",
02366 addcookies);
02367 count++;
02368 }
02369 }
02370 if(count && !result)
02371 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02372
02373 if(result)
02374 return result;
02375 }
02376 #endif
02377
02378 result = Curl_add_timecondition(data, req_buffer);
02379 if(result)
02380 return result;
02381
02382 result = Curl_add_custom_headers(conn, FALSE, req_buffer);
02383 if(result)
02384 return result;
02385
02386 http->postdata = NULL;
02387 Curl_pgrsSetUploadSize(data, -1);
02388
02389
02390
02391
02392
02393 switch(httpreq) {
02394
02395 case HTTPREQ_POST_FORM:
02396 if(!http->sendit || conn->bits.authneg) {
02397
02398 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
02399 if(result)
02400 return result;
02401
02402 result = Curl_add_buffer_send(req_buffer, conn,
02403 &data->info.request_size, 0, FIRSTSOCKET);
02404 if(result)
02405 failf(data, "Failed sending POST request");
02406 else
02407
02408 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
02409 -1, NULL);
02410 break;
02411 }
02412
02413 if(Curl_FormInit(&http->form, http->sendit)) {
02414 failf(data, "Internal HTTP POST error!");
02415 return CURLE_HTTP_POST_ERROR;
02416 }
02417
02418
02419
02420
02421
02422
02423 http->form.fread_func = data->state.fread_func;
02424
02425
02426 data->state.fread_func = (curl_read_callback)Curl_FormReader;
02427 data->state.in = &http->form;
02428
02429 http->sending = HTTPSEND_BODY;
02430
02431 if(!data->req.upload_chunky &&
02432 !Curl_checkheaders(conn, "Content-Length:")) {
02433
02434 result = Curl_add_bufferf(req_buffer,
02435 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
02436 "\r\n", http->postsize);
02437 if(result)
02438 return result;
02439 }
02440
02441 result = expect100(data, conn, req_buffer);
02442 if(result)
02443 return result;
02444
02445 {
02446
02447
02448
02449 char *contentType;
02450 size_t linelength=0;
02451 contentType = Curl_formpostheader((void *)&http->form,
02452 &linelength);
02453 if(!contentType) {
02454 failf(data, "Could not get Content-Type header line!");
02455 return CURLE_HTTP_POST_ERROR;
02456 }
02457
02458 result = Curl_add_buffer(req_buffer, contentType, linelength);
02459 if(result)
02460 return result;
02461 }
02462
02463
02464 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02465 if(result)
02466 return result;
02467
02468
02469 Curl_pgrsSetUploadSize(data, http->postsize);
02470
02471
02472 result = Curl_add_buffer_send(req_buffer, conn,
02473 &data->info.request_size, 0, FIRSTSOCKET);
02474 if(result)
02475 failf(data, "Failed sending POST request");
02476 else
02477
02478 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02479 &http->readbytecount, FIRSTSOCKET,
02480 &http->writebytecount);
02481
02482 if(result) {
02483 Curl_formclean(&http->sendit);
02484 return result;
02485 }
02486
02487
02488 result = Curl_convert_form(data, http->sendit);
02489 if(result) {
02490 Curl_formclean(&http->sendit);
02491 return result;
02492 }
02493
02494 break;
02495
02496 case HTTPREQ_PUT:
02497
02498 if(conn->bits.authneg)
02499 postsize = 0;
02500 else
02501 postsize = data->state.infilesize;
02502
02503 if((postsize != -1) && !data->req.upload_chunky &&
02504 !Curl_checkheaders(conn, "Content-Length:")) {
02505
02506 result = Curl_add_bufferf(req_buffer,
02507 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
02508 "\r\n", postsize);
02509 if(result)
02510 return result;
02511 }
02512
02513 if(postsize != 0) {
02514 result = expect100(data, conn, req_buffer);
02515 if(result)
02516 return result;
02517 }
02518
02519 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02520 if(result)
02521 return result;
02522
02523
02524 Curl_pgrsSetUploadSize(data, postsize);
02525
02526
02527 result = Curl_add_buffer_send(req_buffer, conn,
02528 &data->info.request_size, 0, FIRSTSOCKET);
02529 if(result)
02530 failf(data, "Failed sending PUT request");
02531 else
02532
02533 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02534 &http->readbytecount, postsize?FIRSTSOCKET:-1,
02535 postsize?&http->writebytecount:NULL);
02536 if(result)
02537 return result;
02538 break;
02539
02540 case HTTPREQ_POST:
02541
02542
02543 if(conn->bits.authneg)
02544 postsize = 0;
02545 else {
02546
02547 postsize = (data->state.infilesize != -1)?
02548 data->state.infilesize:
02549 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
02550 }
02551
02552
02553
02554
02555 if((postsize != -1) && !data->req.upload_chunky &&
02556 !Curl_checkheaders(conn, "Content-Length:")) {
02557
02558
02559 result = Curl_add_bufferf(req_buffer,
02560 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
02561 "\r\n", postsize);
02562 if(result)
02563 return result;
02564 }
02565
02566 if(!Curl_checkheaders(conn, "Content-Type:")) {
02567 result = Curl_add_bufferf(req_buffer,
02568 "Content-Type: application/"
02569 "x-www-form-urlencoded\r\n");
02570 if(result)
02571 return result;
02572 }
02573
02574
02575
02576
02577
02578 ptr = Curl_checkheaders(conn, "Expect:");
02579 if(ptr) {
02580 data->state.expect100header =
02581 Curl_compareheader(ptr, "Expect:", "100-continue");
02582 }
02583 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
02584 result = expect100(data, conn, req_buffer);
02585 if(result)
02586 return result;
02587 }
02588 else
02589 data->state.expect100header = FALSE;
02590
02591 if(data->set.postfields) {
02592
02593
02594
02595 if(conn->httpversion != 20 &&
02596 !data->state.expect100header &&
02597 (postsize < MAX_INITIAL_POST_SIZE)) {
02598
02599
02600
02601
02602
02603
02604
02605 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02606 if(result)
02607 return result;
02608
02609 if(!data->req.upload_chunky) {
02610
02611
02612 result = Curl_add_buffer(req_buffer, data->set.postfields,
02613 (size_t)postsize);
02614 included_body = postsize;
02615 }
02616 else {
02617 if(postsize) {
02618
02619 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
02620 if(!result) {
02621 result = Curl_add_buffer(req_buffer, data->set.postfields,
02622 (size_t)postsize);
02623 if(!result)
02624 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02625 included_body = postsize + 2;
02626 }
02627 }
02628 if(!result)
02629 result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
02630
02631 included_body += 5;
02632 }
02633 if(result)
02634 return result;
02635
02636 Curl_pgrsSetUploadSize(data, postsize);
02637 }
02638 else {
02639
02640 http->postsize = postsize;
02641 http->postdata = data->set.postfields;
02642
02643 http->sending = HTTPSEND_BODY;
02644
02645 data->state.fread_func = (curl_read_callback)readmoredata;
02646 data->state.in = (void *)conn;
02647
02648
02649 Curl_pgrsSetUploadSize(data, http->postsize);
02650
02651 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02652 if(result)
02653 return result;
02654 }
02655 }
02656 else {
02657 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02658 if(result)
02659 return result;
02660
02661 if(data->req.upload_chunky && conn->bits.authneg) {
02662
02663
02664 result = Curl_add_buffer(req_buffer,
02665 "\x30\x0d\x0a\x0d\x0a", 5);
02666
02667 if(result)
02668 return result;
02669 }
02670
02671 else if(data->state.infilesize) {
02672
02673 Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
02674
02675
02676
02677
02678 if(!conn->bits.authneg) {
02679 http->postdata = (char *)&http->postdata;
02680 http->postsize = postsize;
02681 }
02682 }
02683 }
02684
02685 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
02686 (size_t)included_body, FIRSTSOCKET);
02687
02688 if(result)
02689 failf(data, "Failed sending HTTP POST request");
02690 else
02691 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
02692 &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
02693 http->postdata?&http->writebytecount:NULL);
02694 break;
02695
02696 default:
02697 result = Curl_add_buffer(req_buffer, "\r\n", 2);
02698 if(result)
02699 return result;
02700
02701
02702 result = Curl_add_buffer_send(req_buffer, conn,
02703 &data->info.request_size, 0, FIRSTSOCKET);
02704
02705 if(result)
02706 failf(data, "Failed sending HTTP request");
02707 else
02708
02709 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
02710 http->postdata?FIRSTSOCKET:-1,
02711 http->postdata?&http->writebytecount:NULL);
02712 }
02713 if(result)
02714 return result;
02715
02716 if(http->writebytecount) {
02717
02718
02719 Curl_pgrsSetUploadCounter(data, http->writebytecount);
02720 if(Curl_pgrsUpdate(conn))
02721 result = CURLE_ABORTED_BY_CALLBACK;
02722
02723 if(http->writebytecount >= postsize) {
02724
02725
02726 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
02727 " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
02728 http->writebytecount, postsize);
02729 data->req.upload_done = TRUE;
02730 data->req.keepon &= ~KEEP_SEND;
02731 data->req.exp100 = EXP100_SEND_DATA;
02732 }
02733 }
02734
02735 if((conn->httpversion == 20) && data->req.upload_chunky)
02736
02737
02738
02739 data->req.upload_chunky = FALSE;
02740 return result;
02741 }
02742
02743
02744
02745
02746
02747
02748 static bool
02749 checkhttpprefix(struct Curl_easy *data,
02750 const char *s)
02751 {
02752 struct curl_slist *head = data->set.http200aliases;
02753 bool rc = FALSE;
02754 #ifdef CURL_DOES_CONVERSIONS
02755
02756 char *scratch = strdup(s);
02757 if(NULL == scratch) {
02758 failf(data, "Failed to allocate memory for conversion!");
02759 return FALSE;
02760 }
02761 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
02762
02763 free(scratch);
02764 return FALSE;
02765 }
02766 s = scratch;
02767 #endif
02768
02769 while(head) {
02770 if(checkprefix(head->data, s)) {
02771 rc = TRUE;
02772 break;
02773 }
02774 head = head->next;
02775 }
02776
02777 if(!rc && (checkprefix("HTTP/", s)))
02778 rc = TRUE;
02779
02780 #ifdef CURL_DOES_CONVERSIONS
02781 free(scratch);
02782 #endif
02783 return rc;
02784 }
02785
02786 #ifndef CURL_DISABLE_RTSP
02787 static bool
02788 checkrtspprefix(struct Curl_easy *data,
02789 const char *s)
02790 {
02791
02792 #ifdef CURL_DOES_CONVERSIONS
02793
02794 char *scratch = strdup(s);
02795 if(NULL == scratch) {
02796 failf(data, "Failed to allocate memory for conversion!");
02797 return FALSE;
02798 }
02799 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
02800
02801 free(scratch);
02802 return FALSE;
02803 }
02804 s = scratch;
02805 #else
02806 (void)data;
02807 #endif
02808 if(checkprefix("RTSP/", s))
02809 return TRUE;
02810 else
02811 return FALSE;
02812 }
02813 #endif
02814
02815 static bool
02816 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
02817 const char *s)
02818 {
02819 #ifndef CURL_DISABLE_RTSP
02820 if(conn->handler->protocol & CURLPROTO_RTSP)
02821 return checkrtspprefix(data, s);
02822 #else
02823 (void)conn;
02824 #endif
02825
02826 return checkhttpprefix(data, s);
02827 }
02828
02829
02830
02831
02832
02833
02834 static CURLcode header_append(struct Curl_easy *data,
02835 struct SingleRequest *k,
02836 size_t length)
02837 {
02838 if(k->hbuflen + length >= data->state.headersize) {
02839
02840 char *newbuff;
02841 size_t hbufp_index;
02842 size_t newsize;
02843
02844 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
02845
02846
02847
02848 failf(data, "Avoided giant realloc for header (max is %d)!",
02849 CURL_MAX_HTTP_HEADER);
02850 return CURLE_OUT_OF_MEMORY;
02851 }
02852
02853 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
02854 hbufp_index = k->hbufp - data->state.headerbuff;
02855 newbuff = realloc(data->state.headerbuff, newsize);
02856 if(!newbuff) {
02857 failf(data, "Failed to alloc memory for big header!");
02858 return CURLE_OUT_OF_MEMORY;
02859 }
02860 data->state.headersize=newsize;
02861 data->state.headerbuff = newbuff;
02862 k->hbufp = data->state.headerbuff + hbufp_index;
02863 }
02864 memcpy(k->hbufp, k->str_start, length);
02865 k->hbufp += length;
02866 k->hbuflen += length;
02867 *k->hbufp = 0;
02868
02869 return CURLE_OK;
02870 }
02871
02872 static void print_http_error(struct Curl_easy *data)
02873 {
02874 struct SingleRequest *k = &data->req;
02875 char *beg = k->p;
02876
02877
02878 if(!strncmp(beg, "HTTP", 4)) {
02879
02880
02881 beg = strchr(beg, ' ');
02882 if(beg && *++beg) {
02883
02884
02885 char end_char = '\r';
02886 char *end = strchr(beg, end_char);
02887 if(!end) {
02888
02889 end_char = '\n';
02890 end = strchr(beg, end_char);
02891 }
02892
02893 if(end) {
02894
02895 *end = '\0';
02896 failf(data, "The requested URL returned error: %s", beg);
02897
02898
02899 *end = end_char;
02900 return;
02901 }
02902 }
02903 }
02904
02905
02906 failf(data, "The requested URL returned error: %d", k->httpcode);
02907 }
02908
02909
02910
02911
02912 CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
02913 struct connectdata *conn,
02914 ssize_t *nread,
02915 bool *stop_reading)
02916 {
02917 CURLcode result;
02918 struct SingleRequest *k = &data->req;
02919
02920
02921 do {
02922 size_t rest_length;
02923 size_t full_length;
02924 int writetype;
02925
02926
02927 k->str_start = k->str;
02928
02929
02930 k->end_ptr = memchr(k->str_start, 0x0a, *nread);
02931
02932 if(!k->end_ptr) {
02933
02934
02935 result = header_append(data, k, *nread);
02936 if(result)
02937 return result;
02938
02939 if(!k->headerline && (k->hbuflen>5)) {
02940
02941 if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
02942
02943 k->header = FALSE;
02944 k->badheader = HEADER_ALLBAD;
02945 break;
02946 }
02947 }
02948
02949 break;
02950 }
02951
02952
02953 rest_length = (k->end_ptr - k->str)+1;
02954 *nread -= (ssize_t)rest_length;
02955
02956 k->str = k->end_ptr + 1;
02957
02958 full_length = k->str - k->str_start;
02959
02960 result = header_append(data, k, full_length);
02961 if(result)
02962 return result;
02963
02964 k->end_ptr = k->hbufp;
02965 k->p = data->state.headerbuff;
02966
02967
02968
02969
02970
02971 if(!k->headerline) {
02972
02973 if((k->hbuflen>5) &&
02974 !checkprotoprefix(data, conn, data->state.headerbuff)) {
02975
02976 k->header = FALSE;
02977 if(*nread)
02978
02979 k->badheader = HEADER_PARTHEADER;
02980 else {
02981
02982 k->badheader = HEADER_ALLBAD;
02983 *nread = (ssize_t)rest_length;
02984 }
02985 break;
02986 }
02987 }
02988
02989
02990
02991 if((0x0a == *k->p) || (0x0d == *k->p)) {
02992 size_t headerlen;
02993
02994
02995 #ifdef CURL_DOES_CONVERSIONS
02996 if(0x0d == *k->p) {
02997 *k->p = '\r';
02998 k->p++;
02999 }
03000 if(0x0a == *k->p) {
03001 *k->p = '\n';
03002 k->p++;
03003 }
03004 #else
03005 if('\r' == *k->p)
03006 k->p++;
03007 if('\n' == *k->p)
03008 k->p++;
03009 #endif
03010
03011 if(100 <= k->httpcode && 199 >= k->httpcode) {
03012
03013 switch(k->httpcode) {
03014 case 100:
03015
03016
03017
03018
03019
03020
03021
03022 k->header = TRUE;
03023 k->headerline = 0;
03024
03025
03026 if(k->exp100 > EXP100_SEND_DATA) {
03027 k->exp100 = EXP100_SEND_DATA;
03028 k->keepon |= KEEP_SEND;
03029 }
03030 break;
03031 case 101:
03032
03033 if(k->upgr101 == UPGR101_REQUESTED) {
03034
03035 infof(data, "Received 101\n");
03036 k->upgr101 = UPGR101_RECEIVED;
03037
03038
03039 k->header = TRUE;
03040 k->headerline = 0;
03041
03042
03043
03044 result = Curl_http2_switched(conn, k->str, *nread);
03045 if(result)
03046 return result;
03047 *nread = 0;
03048 }
03049 else {
03050
03051 k->header = FALSE;
03052 }
03053 break;
03054 default:
03055
03056
03057 k->header = TRUE;
03058 k->headerline = 0;
03059 break;
03060 }
03061 }
03062 else {
03063 k->header = FALSE;
03064
03065 if((k->size == -1) && !k->chunk && !conn->bits.close &&
03066 (conn->httpversion == 11) &&
03067 !(conn->handler->protocol & CURLPROTO_RTSP) &&
03068 data->set.httpreq != HTTPREQ_HEAD) {
03069
03070
03071
03072
03073
03074 infof(data, "no chunk, no close, no size. Assume close to "
03075 "signal end\n");
03076 streamclose(conn, "HTTP: No end-of-message indicator");
03077 }
03078 }
03079
03080
03081
03082 #if defined(USE_NTLM)
03083 if(conn->bits.close &&
03084 (((data->req.httpcode == 401) &&
03085 (conn->ntlm.state == NTLMSTATE_TYPE2)) ||
03086 ((data->req.httpcode == 407) &&
03087 (conn->proxyntlm.state == NTLMSTATE_TYPE2)))) {
03088 infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
03089 data->state.authproblem = TRUE;
03090 }
03091 #endif
03092
03093
03094
03095
03096
03097 if(http_should_fail(conn)) {
03098 failf(data, "The requested URL returned error: %d",
03099 k->httpcode);
03100 return CURLE_HTTP_RETURNED_ERROR;
03101 }
03102
03103
03104
03105 writetype = CLIENTWRITE_HEADER;
03106 if(data->set.include_header)
03107 writetype |= CLIENTWRITE_BODY;
03108
03109 headerlen = k->p - data->state.headerbuff;
03110
03111 result = Curl_client_write(conn, writetype,
03112 data->state.headerbuff,
03113 headerlen);
03114 if(result)
03115 return result;
03116
03117 data->info.header_size += (long)headerlen;
03118 data->req.headerbytecount += (long)headerlen;
03119
03120 data->req.deductheadercount =
03121 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
03122
03123
03124
03125
03126 result = Curl_http_auth_act(conn);
03127
03128 if(result)
03129 return result;
03130
03131 if(k->httpcode >= 300) {
03132 if((!conn->bits.authneg) && !conn->bits.close &&
03133 !conn->bits.rewindaftersend) {
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147 switch(data->set.httpreq) {
03148 case HTTPREQ_PUT:
03149 case HTTPREQ_POST:
03150 case HTTPREQ_POST_FORM:
03151
03152
03153
03154
03155 if(!k->upload_done) {
03156 if(data->set.http_keep_sending_on_error) {
03157 infof(data, "HTTP error before end of send, keep sending\n");
03158 if(k->exp100 > EXP100_SEND_DATA) {
03159 k->exp100 = EXP100_SEND_DATA;
03160 k->keepon |= KEEP_SEND;
03161 }
03162 }
03163 else {
03164 infof(data, "HTTP error before end of send, stop sending\n");
03165 streamclose(conn, "Stop sending data before everything sent");
03166 k->upload_done = TRUE;
03167 k->keepon &= ~KEEP_SEND;
03168 if(data->state.expect100header)
03169 k->exp100 = EXP100_FAILED;
03170 }
03171 }
03172 break;
03173
03174 default:
03175 break;
03176 }
03177 }
03178
03179 if(conn->bits.rewindaftersend) {
03180
03181
03182 infof(data, "Keep sending data to get tossed away!\n");
03183 k->keepon |= KEEP_SEND;
03184 }
03185 }
03186
03187 if(!k->header) {
03188
03189
03190
03191
03192
03193
03194 if(data->set.opt_no_body)
03195 *stop_reading = TRUE;
03196 #ifndef CURL_DISABLE_RTSP
03197 else if((conn->handler->protocol & CURLPROTO_RTSP) &&
03198 (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
03199 (k->size <= -1))
03200
03201
03202
03203
03204 *stop_reading = TRUE;
03205 #endif
03206 else {
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220 if(k->chunk)
03221 k->maxdownload = k->size = -1;
03222 }
03223 if(-1 != k->size) {
03224
03225
03226
03227
03228 Curl_pgrsSetDownloadSize(data, k->size);
03229 k->maxdownload = k->size;
03230 }
03231
03232
03233
03234 if(0 == k->maxdownload)
03235 *stop_reading = TRUE;
03236
03237 if(*stop_reading) {
03238
03239 k->keepon &= ~KEEP_RECV;
03240 }
03241
03242 if(data->set.verbose)
03243 Curl_debug(data, CURLINFO_HEADER_IN,
03244 k->str_start, headerlen, conn);
03245 break;
03246 }
03247
03248
03249
03250 k->hbufp = data->state.headerbuff;
03251 k->hbuflen = 0;
03252 continue;
03253 }
03254
03255
03256
03257
03258
03259 if(!k->headerline++) {
03260
03261
03262 int httpversion_major;
03263 int rtspversion_major;
03264 int nc = 0;
03265 #ifdef CURL_DOES_CONVERSIONS
03266 #define HEADER1 scratch
03267 #define SCRATCHSIZE 21
03268 CURLcode res;
03269 char scratch[SCRATCHSIZE+1];
03270
03271
03272
03273
03274
03275 strncpy(&scratch[0], k->p, SCRATCHSIZE);
03276 scratch[SCRATCHSIZE] = 0;
03277 res = Curl_convert_from_network(data,
03278 &scratch[0],
03279 SCRATCHSIZE);
03280 if(res)
03281
03282 return res;
03283 #else
03284 #define HEADER1 k->p
03285 #endif
03286
03287 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
03288
03289
03290
03291
03292
03293
03294
03295 nc = sscanf(HEADER1,
03296 " HTTP/%d.%d %d",
03297 &httpversion_major,
03298 &conn->httpversion,
03299 &k->httpcode);
03300
03301 if(nc == 1 && httpversion_major == 2 &&
03302 1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) {
03303 conn->httpversion = 0;
03304 nc = 3;
03305 }
03306
03307 if(nc==3) {
03308 conn->httpversion += 10 * httpversion_major;
03309
03310 if(k->upgr101 == UPGR101_RECEIVED) {
03311
03312 if(conn->httpversion != 20)
03313 infof(data, "Lying server, not serving HTTP/2\n");
03314 }
03315 }
03316 else {
03317
03318
03319
03320 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
03321 conn->httpversion = 10;
03322
03323
03324
03325
03326 if(!nc) {
03327 if(checkhttpprefix(data, k->p)) {
03328 nc = 1;
03329 k->httpcode = 200;
03330 conn->httpversion = 10;
03331 }
03332 }
03333 }
03334 }
03335 else if(conn->handler->protocol & CURLPROTO_RTSP) {
03336 nc = sscanf(HEADER1,
03337 " RTSP/%d.%d %3d",
03338 &rtspversion_major,
03339 &conn->rtspversion,
03340 &k->httpcode);
03341 if(nc==3) {
03342 conn->rtspversion += 10 * rtspversion_major;
03343 conn->httpversion = 11;
03344 }
03345 else {
03346
03347 nc = 0;
03348 }
03349 }
03350
03351 if(nc) {
03352 data->info.httpcode = k->httpcode;
03353
03354 data->info.httpversion = conn->httpversion;
03355 if(!data->state.httpversion ||
03356 data->state.httpversion > conn->httpversion)
03357
03358 data->state.httpversion = conn->httpversion;
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368 if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
03369 ((k->httpcode != 401) || !conn->bits.user_passwd) &&
03370 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
03371
03372 if(data->state.resume_from &&
03373 (data->set.httpreq==HTTPREQ_GET) &&
03374 (k->httpcode == 416)) {
03375
03376
03377 }
03378 else {
03379
03380 print_http_error(data);
03381 return CURLE_HTTP_RETURNED_ERROR;
03382 }
03383 }
03384
03385 if(conn->httpversion == 10) {
03386
03387
03388
03389 infof(data, "HTTP 1.0, assume close after body\n");
03390 connclose(conn, "HTTP/1.0 close after body");
03391 }
03392 else if(conn->httpversion == 20 ||
03393 (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
03394 DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
03395
03396
03397
03398 conn->bundle->multiuse = BUNDLE_MULTIPLEX;
03399 }
03400 else if(conn->httpversion >= 11 &&
03401 !conn->bits.close) {
03402
03403
03404 DEBUGF(infof(data,
03405 "HTTP 1.1 or later with persistent connection, "
03406 "pipelining supported\n"));
03407
03408 if(conn->bundle) {
03409 if(!Curl_pipeline_site_blacklisted(data, conn))
03410 conn->bundle->multiuse = BUNDLE_PIPELINING;
03411 }
03412 }
03413
03414 switch(k->httpcode) {
03415 case 204:
03416
03417
03418
03419
03420
03421
03422 case 304:
03423
03424
03425
03426
03427 if(data->set.timecondition)
03428 data->info.timecond = TRUE;
03429 k->size=0;
03430 k->maxdownload=0;
03431 k->ignorecl = TRUE;
03432 break;
03433 default:
03434
03435 break;
03436 }
03437 }
03438 else {
03439 k->header = FALSE;
03440 break;
03441 }
03442 }
03443
03444 result = Curl_convert_from_network(data, k->p, strlen(k->p));
03445
03446 if(result)
03447 return result;
03448
03449
03450 if(!k->ignorecl && !data->set.ignorecl &&
03451 checkprefix("Content-Length:", k->p)) {
03452 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
03453 if(data->set.max_filesize &&
03454 contentlength > data->set.max_filesize) {
03455 failf(data, "Maximum file size exceeded");
03456 return CURLE_FILESIZE_EXCEEDED;
03457 }
03458 if(contentlength >= 0) {
03459 k->size = contentlength;
03460 k->maxdownload = k->size;
03461
03462
03463
03464 Curl_pgrsSetDownloadSize(data, k->size);
03465 }
03466 else {
03467
03468
03469
03470 streamclose(conn, "negative content-length");
03471 infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
03472 ", closing after transfer\n", contentlength);
03473 }
03474 }
03475
03476 else if(checkprefix("Content-Type:", k->p)) {
03477 char *contenttype = Curl_copy_header_value(k->p);
03478 if(!contenttype)
03479 return CURLE_OUT_OF_MEMORY;
03480 if(!*contenttype)
03481
03482 free(contenttype);
03483 else {
03484 Curl_safefree(data->info.contenttype);
03485 data->info.contenttype = contenttype;
03486 }
03487 }
03488 else if(checkprefix("Server:", k->p)) {
03489 if(conn->httpversion < 20) {
03490
03491 char *server_name = Curl_copy_header_value(k->p);
03492
03493
03494 if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) {
03495 if(Curl_pipeline_server_blacklisted(data, server_name))
03496 conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
03497 }
03498 free(server_name);
03499 }
03500 }
03501 else if((conn->httpversion == 10) &&
03502 conn->bits.httpproxy &&
03503 Curl_compareheader(k->p,
03504 "Proxy-Connection:", "keep-alive")) {
03505
03506
03507
03508
03509
03510
03511 connkeep(conn, "Proxy-Connection keep-alive");
03512 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
03513 }
03514 else if((conn->httpversion == 11) &&
03515 conn->bits.httpproxy &&
03516 Curl_compareheader(k->p,
03517 "Proxy-Connection:", "close")) {
03518
03519
03520
03521
03522 connclose(conn, "Proxy-Connection: asked to close after done");
03523 infof(data, "HTTP/1.1 proxy connection set close!\n");
03524 }
03525 else if((conn->httpversion == 10) &&
03526 Curl_compareheader(k->p, "Connection:", "keep-alive")) {
03527
03528
03529
03530
03531
03532
03533 connkeep(conn, "Connection keep-alive");
03534 infof(data, "HTTP/1.0 connection set to keep alive!\n");
03535 }
03536 else if(Curl_compareheader(k->p, "Connection:", "close")) {
03537
03538
03539
03540
03541
03542
03543 streamclose(conn, "Connection: close used");
03544 }
03545 else if(checkprefix("Transfer-Encoding:", k->p)) {
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557 char *start;
03558
03559
03560 start = k->p + 18;
03561
03562 for(;;) {
03563
03564 while(*start && (ISSPACE(*start) || (*start == ',')))
03565 start++;
03566
03567 if(checkprefix("chunked", start)) {
03568 k->chunk = TRUE;
03569
03570
03571 Curl_httpchunk_init(conn);
03572
03573 start += 7;
03574 }
03575
03576 if(k->auto_decoding)
03577
03578 break;
03579
03580 if(checkprefix("identity", start)) {
03581 k->auto_decoding = IDENTITY;
03582 start += 8;
03583 }
03584 else if(checkprefix("deflate", start)) {
03585 k->auto_decoding = DEFLATE;
03586 start += 7;
03587 }
03588 else if(checkprefix("gzip", start)) {
03589 k->auto_decoding = GZIP;
03590 start += 4;
03591 }
03592 else if(checkprefix("x-gzip", start)) {
03593 k->auto_decoding = GZIP;
03594 start += 6;
03595 }
03596 else
03597
03598 break;
03599
03600 }
03601
03602 }
03603 else if(checkprefix("Content-Encoding:", k->p) &&
03604 data->set.str[STRING_ENCODING]) {
03605
03606
03607
03608
03609
03610
03611
03612 char *start;
03613
03614
03615 start = k->p + 17;
03616 while(*start && ISSPACE(*start))
03617 start++;
03618
03619
03620 if(checkprefix("identity", start))
03621 k->auto_decoding = IDENTITY;
03622 else if(checkprefix("deflate", start))
03623 k->auto_decoding = DEFLATE;
03624 else if(checkprefix("gzip", start)
03625 || checkprefix("x-gzip", start))
03626 k->auto_decoding = GZIP;
03627 }
03628 else if(checkprefix("Content-Range:", k->p)) {
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640 char *ptr = k->p + 14;
03641
03642
03643 while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
03644 ptr++;
03645
03646
03647 if(ISDIGIT(*ptr)) {
03648 k->offset = curlx_strtoofft(ptr, NULL, 10);
03649
03650 if(data->state.resume_from == k->offset)
03651
03652 k->content_range = TRUE;
03653 }
03654 else
03655 data->state.resume_from = 0;
03656 }
03657 #if !defined(CURL_DISABLE_COOKIES)
03658 else if(data->cookies &&
03659 checkprefix("Set-Cookie:", k->p)) {
03660 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
03661 CURL_LOCK_ACCESS_SINGLE);
03662 Curl_cookie_add(data,
03663 data->cookies, TRUE, k->p+11,
03664
03665
03666 conn->allocptr.cookiehost?
03667 conn->allocptr.cookiehost:conn->host.name,
03668 data->state.path);
03669 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
03670 }
03671 #endif
03672 else if(checkprefix("Last-Modified:", k->p) &&
03673 (data->set.timecondition || data->set.get_filetime) ) {
03674 time_t secs=time(NULL);
03675 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
03676 &secs);
03677 if(data->set.get_filetime)
03678 data->info.filetime = (long)k->timeofdoc;
03679 }
03680 else if((checkprefix("WWW-Authenticate:", k->p) &&
03681 (401 == k->httpcode)) ||
03682 (checkprefix("Proxy-authenticate:", k->p) &&
03683 (407 == k->httpcode))) {
03684
03685 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
03686 char *auth = Curl_copy_header_value(k->p);
03687 if(!auth)
03688 return CURLE_OUT_OF_MEMORY;
03689
03690 result = Curl_http_input_auth(conn, proxy, auth);
03691
03692 free(auth);
03693
03694 if(result)
03695 return result;
03696 }
03697 else if((k->httpcode >= 300 && k->httpcode < 400) &&
03698 checkprefix("Location:", k->p) &&
03699 !data->req.location) {
03700
03701 char *location = Curl_copy_header_value(k->p);
03702 if(!location)
03703 return CURLE_OUT_OF_MEMORY;
03704 if(!*location)
03705
03706 free(location);
03707 else {
03708 data->req.location = location;
03709
03710 if(data->set.http_follow_location) {
03711 DEBUGASSERT(!data->req.newurl);
03712 data->req.newurl = strdup(data->req.location);
03713 if(!data->req.newurl)
03714 return CURLE_OUT_OF_MEMORY;
03715
03716
03717
03718 result = http_perhapsrewind(conn);
03719 if(result)
03720 return result;
03721 }
03722 }
03723 }
03724 else if(conn->handler->protocol & CURLPROTO_RTSP) {
03725 result = Curl_rtsp_parseheader(conn, k->p);
03726 if(result)
03727 return result;
03728 }
03729
03730
03731
03732
03733
03734 writetype = CLIENTWRITE_HEADER;
03735 if(data->set.include_header)
03736 writetype |= CLIENTWRITE_BODY;
03737
03738 if(data->set.verbose)
03739 Curl_debug(data, CURLINFO_HEADER_IN,
03740 k->p, (size_t)k->hbuflen, conn);
03741
03742 result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
03743 if(result)
03744 return result;
03745
03746 data->info.header_size += (long)k->hbuflen;
03747 data->req.headerbytecount += (long)k->hbuflen;
03748
03749
03750 k->hbufp = data->state.headerbuff;
03751 k->hbuflen = 0;
03752 }
03753 while(*k->str);
03754
03755
03756
03757
03758
03759 return CURLE_OK;
03760 }
03761
03762 #endif