1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23#include "setup.h" 24 25#ifndef CURL_DISABLE_HTTP 26 27#ifdef HAVE_SYS_SOCKET_H 28#include <sys/socket.h> 29#endif 30#ifdef HAVE_NETINET_IN_H 31#include <netinet/in.h> 32#endif 33 34#ifdef HAVE_UNISTD_H 35#include <unistd.h> 36#endif 37#ifdef HAVE_NETDB_H 38#include <netdb.h> 39#endif 40#ifdef HAVE_ARPA_INET_H 41#include <arpa/inet.h> 42#endif 43#ifdef HAVE_NET_IF_H 44#include <net/if.h> 45#endif 46#ifdef HAVE_SYS_IOCTL_H 47#include <sys/ioctl.h> 48#endif 49 50#ifdef HAVE_SYS_PARAM_H 51#include <sys/param.h> 52#endif 53 54#include "urldata.h" 55#include <curl/curl.h> 56#include "transfer.h" 57#include "sendf.h" 58#include "formdata.h" 59#include "progress.h" 60#include "curl_base64.h" 61#include "cookie.h" 62#include "strequal.h" 63#include "sslgen.h" 64#include "http_digest.h" 65#include "curl_ntlm.h" 66#include "curl_ntlm_wb.h" 67#include "http_negotiate.h" 68#include "url.h" 69#include "share.h" 70#include "hostip.h" 71#include "http.h" 72#include "curl_memory.h" 73#include "select.h" 74#include "parsedate.h" /* for the week day and month names */ 75#include "strtoofft.h" 76#include "multiif.h" 77#include "rawstr.h" 78#include "content_encoding.h" 79#include "http_proxy.h" 80#include "warnless.h" 81#include "non-ascii.h" 82 83#define _MPRINTF_REPLACE /* use our functions only */ 84#include <curl/mprintf.h> 85 86/* The last #include file should be: */ 87#include "memdebug.h" 88 89/* 90 * Forward declarations. 91 */ 92 93static int http_getsock_do(struct connectdata *conn, 94 curl_socket_t *socks, 95 int numsocks); 96static int http_should_fail(struct connectdata *conn); 97 98#ifdef USE_SSL 99static CURLcode https_connecting(struct connectdata *conn, bool *done); 100static int https_getsock(struct connectdata *conn, 101 curl_socket_t *socks, 102 int numsocks); 103#else 104#define https_connecting(x,y) CURLE_COULDNT_CONNECT 105#endif 106 107/* 108 * HTTP handler interface. 109 */ 110const struct Curl_handler Curl_handler_http = { 111 "HTTP", /* scheme */ 112 ZERO_NULL, /* setup_connection */ 113 Curl_http, /* do_it */ 114 Curl_http_done, /* done */ 115 ZERO_NULL, /* do_more */ 116 Curl_http_connect, /* connect_it */ 117 ZERO_NULL, /* connecting */ 118 ZERO_NULL, /* doing */ 119 ZERO_NULL, /* proto_getsock */ 120 http_getsock_do, /* doing_getsock */ 121 ZERO_NULL, /* domore_getsock */ 122 ZERO_NULL, /* perform_getsock */ 123 ZERO_NULL, /* disconnect */ 124 ZERO_NULL, /* readwrite */ 125 PORT_HTTP, /* defport */ 126 CURLPROTO_HTTP, /* protocol */ 127 PROTOPT_NONE /* flags */ 128}; 129 130#ifdef USE_SSL 131/* 132 * HTTPS handler interface. 133 */ 134const struct Curl_handler Curl_handler_https = { 135 "HTTPS", /* scheme */ 136 ZERO_NULL, /* setup_connection */ 137 Curl_http, /* do_it */ 138 Curl_http_done, /* done */ 139 ZERO_NULL, /* do_more */ 140 Curl_http_connect, /* connect_it */ 141 https_connecting, /* connecting */ 142 ZERO_NULL, /* doing */ 143 https_getsock, /* proto_getsock */ 144 http_getsock_do, /* doing_getsock */ 145 ZERO_NULL, /* domore_getsock */ 146 ZERO_NULL, /* perform_getsock */ 147 ZERO_NULL, /* disconnect */ 148 ZERO_NULL, /* readwrite */ 149 PORT_HTTPS, /* defport */ 150 CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ 151 PROTOPT_SSL /* flags */ 152}; 153#endif 154 155 156/* 157 * checkheaders() checks the linked list of custom HTTP headers for a 158 * particular header (prefix). 159 * 160 * Returns a pointer to the first matching header or NULL if none matched. 161 */ 162char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader) 163{ 164 struct curl_slist *head; 165 size_t thislen = strlen(thisheader); 166 167 for(head = data->set.headers; head; head=head->next) { 168 if(Curl_raw_nequal(head->data, thisheader, thislen)) 169 return head->data; 170 } 171 return NULL; 172} 173 174/* 175 * Strip off leading and trailing whitespace from the value in the 176 * given HTTP header line and return a strdupped copy. Returns NULL in 177 * case of allocation failure. Returns an empty string if the header value 178 * consists entirely of whitespace. 179 */ 180static char *copy_header_value(const char *h) 181{ 182 const char *start; 183 const char *end; 184 char *value; 185 size_t len; 186 187 DEBUGASSERT(h); 188 189 /* Find the end of the header name */ 190 while(*h && (*h != ':')) 191 ++h; 192 193 if(*h) 194 /* Skip over colon */ 195 ++h; 196 197 /* Find the first non-space letter */ 198 start = h; 199 while(*start && ISSPACE(*start)) 200 start++; 201 202 /* data is in the host encoding so 203 use '\r' and '\n' instead of 0x0d and 0x0a */ 204 end = strchr(start, '\r'); 205 if(!end) 206 end = strchr(start, '\n'); 207 if(!end) 208 end = strchr(start, '\0'); 209 if(!end) 210 return NULL; 211 212 /* skip all trailing space letters */ 213 while((end > start) && ISSPACE(*end)) 214 end--; 215 216 /* get length of the type */ 217 len = end-start+1; 218 219 value = malloc(len + 1); 220 if(!value) 221 return NULL; 222 223 memcpy(value, start, len); 224 value[len] = 0; /* zero terminate */ 225 226 return value; 227} 228 229/* 230 * http_output_basic() sets up an Authorization: header (or the proxy version) 231 * for HTTP Basic authentication. 232 * 233 * Returns CURLcode. 234 */ 235static CURLcode http_output_basic(struct connectdata *conn, bool proxy) 236{ 237 size_t size = 0; 238 char *authorization = NULL; 239 struct SessionHandle *data = conn->data; 240 char **userp; 241 const char *user; 242 const char *pwd; 243 CURLcode error; 244 245 if(proxy) { 246 userp = &conn->allocptr.proxyuserpwd; 247 user = conn->proxyuser; 248 pwd = conn->proxypasswd; 249 } 250 else { 251 userp = &conn->allocptr.userpwd; 252 user = conn->user; 253 pwd = conn->passwd; 254 } 255 256 snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); 257 258 error = Curl_base64_encode(data, 259 data->state.buffer, strlen(data->state.buffer), 260 &authorization, &size); 261 if(error) 262 return error; 263 264 if(!authorization) 265 return CURLE_REMOTE_ACCESS_DENIED; 266 267 Curl_safefree(*userp); 268 *userp = aprintf("%sAuthorization: Basic %s\r\n", 269 proxy?"Proxy-":"", 270 authorization); 271 free(authorization); 272 if(!*userp) 273 return CURLE_OUT_OF_MEMORY; 274 275 return CURLE_OK; 276} 277 278/* pickoneauth() selects the most favourable authentication method from the 279 * ones available and the ones we want. 280 * 281 * return TRUE if one was picked 282 */ 283static bool pickoneauth(struct auth *pick) 284{ 285 bool picked; 286 /* only deal with authentication we want */ 287 long avail = pick->avail & pick->want; 288 picked = TRUE; 289 290 /* The order of these checks is highly relevant, as this will be the order 291 of preference in case of the existence of multiple accepted types. */ 292 if(avail & CURLAUTH_GSSNEGOTIATE) 293 pick->picked = CURLAUTH_GSSNEGOTIATE; 294 else if(avail & CURLAUTH_DIGEST) 295 pick->picked = CURLAUTH_DIGEST; 296 else if(avail & CURLAUTH_NTLM) 297 pick->picked = CURLAUTH_NTLM; 298 else if(avail & CURLAUTH_NTLM_WB) 299 pick->picked = CURLAUTH_NTLM_WB; 300 else if(avail & CURLAUTH_BASIC) 301 pick->picked = CURLAUTH_BASIC; 302 else { 303 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ 304 picked = FALSE; 305 } 306 pick->avail = CURLAUTH_NONE; /* clear it here */ 307 308 return picked; 309} 310 311/* 312 * Curl_http_perhapsrewind() 313 * 314 * If we are doing POST or PUT { 315 * If we have more data to send { 316 * If we are doing NTLM { 317 * Keep sending since we must not disconnect 318 * } 319 * else { 320 * If there is more than just a little data left to send, close 321 * the current connection by force. 322 * } 323 * } 324 * If we have sent any data { 325 * If we don't have track of all the data { 326 * call app to tell it to rewind 327 * } 328 * else { 329 * rewind internally so that the operation can restart fine 330 * } 331 * } 332 * } 333 */ 334static CURLcode http_perhapsrewind(struct connectdata *conn) 335{ 336 struct SessionHandle *data = conn->data; 337 struct HTTP *http = data->state.proto.http; 338 curl_off_t bytessent; 339 curl_off_t expectsend = -1; /* default is unknown */ 340 341 if(!http) 342 /* If this is still NULL, we have not reach very far and we can safely 343 skip this rewinding stuff */ 344 return CURLE_OK; 345 346 switch(data->set.httpreq) { 347 case HTTPREQ_GET: 348 case HTTPREQ_HEAD: 349 return CURLE_OK; 350 default: 351 break; 352 } 353 354 bytessent = http->writebytecount; 355 356 if(conn->bits.authneg) 357 /* This is a state where we are known to be negotiating and we don't send 358 any data then. */ 359 expectsend = 0; 360 else { 361 /* figure out how much data we are expected to send */ 362 switch(data->set.httpreq) { 363 case HTTPREQ_POST: 364 if(data->set.postfieldsize != -1) 365 expectsend = data->set.postfieldsize; 366 else if(data->set.postfields) 367 expectsend = (curl_off_t)strlen(data->set.postfields); 368 break; 369 case HTTPREQ_PUT: 370 if(data->set.infilesize != -1) 371 expectsend = data->set.infilesize; 372 break; 373 case HTTPREQ_POST_FORM: 374 expectsend = http->postsize; 375 break; 376 default: 377 break; 378 } 379 } 380 381 conn->bits.rewindaftersend = FALSE; /* default */ 382 383 if((expectsend == -1) || (expectsend > bytessent)) { 384 /* There is still data left to send */ 385 if((data->state.authproxy.picked == CURLAUTH_NTLM) || 386 (data->state.authhost.picked == CURLAUTH_NTLM) || 387 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || 388 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { 389 if(((expectsend - bytessent) < 2000) || 390 (conn->ntlm.state != NTLMSTATE_NONE)) { 391 /* The NTLM-negotiation has started *OR* there is just a little (<2K) 392 data left to send, keep on sending. */ 393 394 /* rewind data when completely done sending! */ 395 if(!conn->bits.authneg) { 396 conn->bits.rewindaftersend = TRUE; 397 infof(data, "Rewind stream after send\n"); 398 } 399 400 return CURLE_OK; 401 } 402 if(conn->bits.close) 403 /* this is already marked to get closed */ 404 return CURLE_OK; 405 406 infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T 407 " bytes\n", (curl_off_t)(expectsend - bytessent)); 408 } 409 410 /* This is not NTLM or NTLM with many bytes left to send: close 411 */ 412 conn->bits.close = TRUE; 413 data->req.size = 0; /* don't download any more than 0 bytes */ 414 415 /* There still is data left to send, but this connection is marked for 416 closure so we can safely do the rewind right now */ 417 } 418 419 if(bytessent) 420 /* we rewind now at once since if we already sent something */ 421 return Curl_readrewind(conn); 422 423 return CURLE_OK; 424} 425 426/* 427 * Curl_http_auth_act() gets called when all HTTP headers have been received 428 * and it checks what authentication methods that are available and decides 429 * which one (if any) to use. It will set 'newurl' if an auth method was 430 * picked. 431 */ 432 433CURLcode Curl_http_auth_act(struct connectdata *conn) 434{ 435 struct SessionHandle *data = conn->data; 436 bool pickhost = FALSE; 437 bool pickproxy = FALSE; 438 CURLcode code = CURLE_OK; 439 440 if(100 <= data->req.httpcode && 199 >= data->req.httpcode) 441 /* this is a transient response code, ignore */ 442 return CURLE_OK; 443 444 if(data->state.authproblem) 445 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; 446 447 if(conn->bits.user_passwd && 448 ((data->req.httpcode == 401) || 449 (conn->bits.authneg && data->req.httpcode < 300))) { 450 pickhost = pickoneauth(&data->state.authhost); 451 if(!pickhost) 452 data->state.authproblem = TRUE; 453 } 454 if(conn->bits.proxy_user_passwd && 455 ((data->req.httpcode == 407) || 456 (conn->bits.authneg && data->req.httpcode < 300))) { 457 pickproxy = pickoneauth(&data->state.authproxy); 458 if(!pickproxy) 459 data->state.authproblem = TRUE; 460 } 461 462 if(pickhost || pickproxy) { 463 /* In case this is GSS auth, the newurl field is already allocated so 464 we must make sure to free it before allocating a new one. As figured 465 out in bug #2284386 */ 466 Curl_safefree(data->req.newurl); 467 data->req.newurl = strdup(data->change.url); /* clone URL */ 468 if(!data->req.newurl) 469 return CURLE_OUT_OF_MEMORY; 470 471 if((data->set.httpreq != HTTPREQ_GET) && 472 (data->set.httpreq != HTTPREQ_HEAD) && 473 !conn->bits.rewindaftersend) { 474 code = http_perhapsrewind(conn); 475 if(code) 476 return code; 477 } 478 } 479 480 else if((data->req.httpcode < 300) && 481 (!data->state.authhost.done) && 482 conn->bits.authneg) { 483 /* no (known) authentication available, 484 authentication is not "done" yet and 485 no authentication seems to be required and 486 we didn't try HEAD or GET */ 487 if((data->set.httpreq != HTTPREQ_GET) && 488 (data->set.httpreq != HTTPREQ_HEAD)) { 489 data->req.newurl = strdup(data->change.url); /* clone URL */ 490 if(!data->req.newurl) 491 return CURLE_OUT_OF_MEMORY; 492 data->state.authhost.done = TRUE; 493 } 494 } 495 if(http_should_fail(conn)) { 496 failf (data, "The requested URL returned error: %d", 497 data->req.httpcode); 498 code = CURLE_HTTP_RETURNED_ERROR; 499 } 500 501 return code; 502} 503 504 505/* 506 * Output the correct authentication header depending on the auth type 507 * and whether or not it is to a proxy. 508 */ 509static CURLcode 510output_auth_headers(struct connectdata *conn, 511 struct auth *authstatus, 512 const char *request, 513 const char *path, 514 bool proxy) 515{ 516 struct SessionHandle *data = conn->data; 517 const char *auth=NULL; 518 CURLcode result = CURLE_OK; 519#ifdef USE_HTTP_NEGOTIATE 520 struct negotiatedata *negdata = proxy? 521 &data->state.proxyneg:&data->state.negotiate; 522#endif 523 524#ifdef CURL_DISABLE_CRYPTO_AUTH 525 (void)request; 526 (void)path; 527#endif 528 529#ifdef USE_HTTP_NEGOTIATE 530 negdata->state = GSS_AUTHNONE; 531 if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && 532 negdata->context && !GSS_ERROR(negdata->status)) { 533 auth="GSS-Negotiate"; 534 result = Curl_output_negotiate(conn, proxy); 535 if(result) 536 return result; 537 authstatus->done = TRUE; 538 negdata->state = GSS_AUTHSENT; 539 } 540 else 541#endif 542#ifdef USE_NTLM 543 if(authstatus->picked == CURLAUTH_NTLM) { 544 auth="NTLM"; 545 result = Curl_output_ntlm(conn, proxy); 546 if(result) 547 return result; 548 } 549 else 550#endif 551#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) 552 if(authstatus->picked == CURLAUTH_NTLM_WB) { 553 auth="NTLM_WB"; 554 result = Curl_output_ntlm_wb(conn, proxy); 555 if(result) 556 return result; 557 } 558 else 559#endif 560#ifndef CURL_DISABLE_CRYPTO_AUTH 561 if(authstatus->picked == CURLAUTH_DIGEST) { 562 auth="Digest"; 563 result = Curl_output_digest(conn, 564 proxy, 565 (const unsigned char *)request, 566 (const unsigned char *)path); 567 if(result) 568 return result; 569 } 570 else 571#endif 572 if(authstatus->picked == CURLAUTH_BASIC) { 573 /* Basic */ 574 if((proxy && conn->bits.proxy_user_passwd && 575 !Curl_checkheaders(data, "Proxy-authorization:")) || 576 (!proxy && conn->bits.user_passwd && 577 !Curl_checkheaders(data, "Authorization:"))) { 578 auth="Basic"; 579 result = http_output_basic(conn, proxy); 580 if(result) 581 return result; 582 } 583 /* NOTE: this function should set 'done' TRUE, as the other auth 584 functions work that way */ 585 authstatus->done = TRUE; 586 } 587 588 if(auth) { 589 infof(data, "%s auth using %s with user '%s'\n", 590 proxy?"Proxy":"Server", auth, 591 proxy?(conn->proxyuser?conn->proxyuser:""): 592 (conn->user?conn->user:"")); 593 authstatus->multi = (!authstatus->done) ? TRUE : FALSE; 594 } 595 else 596 authstatus->multi = FALSE; 597 598 return CURLE_OK; 599} 600 601/** 602 * Curl_http_output_auth() setups the authentication headers for the 603 * host/proxy and the correct authentication 604 * method. conn->data->state.authdone is set to TRUE when authentication is 605 * done. 606 * 607 * @param conn all information about the current connection 608 * @param request pointer to the request keyword 609 * @param path pointer to the requested path 610 * @param proxytunnel boolean if this is the request setting up a "proxy 611 * tunnel" 612 * 613 * @returns CURLcode 614 */ 615CURLcode 616Curl_http_output_auth(struct connectdata *conn, 617 const char *request, 618 const char *path, 619 bool proxytunnel) /* TRUE if this is the request setting 620 up the proxy tunnel */ 621{ 622 CURLcode result = CURLE_OK; 623 struct SessionHandle *data = conn->data; 624 struct auth *authhost; 625 struct auth *authproxy; 626 627 DEBUGASSERT(data); 628 629 authhost = &data->state.authhost; 630 authproxy = &data->state.authproxy; 631 632 if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || 633 conn->bits.user_passwd) 634 /* continue please */ ; 635 else { 636 authhost->done = TRUE; 637 authproxy->done = TRUE; 638 return CURLE_OK; /* no authentication with no user or password */ 639 } 640 641 if(authhost->want && !authhost->picked) 642 /* The app has selected one or more methods, but none has been picked 643 so far by a server round-trip. Then we set the picked one to the 644 want one, and if this is one single bit it'll be used instantly. */ 645 authhost->picked = authhost->want; 646 647 if(authproxy->want && !authproxy->picked) 648 /* The app has selected one or more methods, but none has been picked so 649 far by a proxy round-trip. Then we set the picked one to the want one, 650 and if this is one single bit it'll be used instantly. */ 651 authproxy->picked = authproxy->want; 652 653#ifndef CURL_DISABLE_PROXY 654 /* Send proxy authentication header if needed */ 655 if(conn->bits.httpproxy && 656 (conn->bits.tunnel_proxy == proxytunnel)) { 657 result = output_auth_headers(conn, authproxy, request, path, TRUE); 658 if(result) 659 return result; 660 } 661 else 662#else 663 (void)proxytunnel; 664#endif /* CURL_DISABLE_PROXY */ 665 /* we have no proxy so let's pretend we're done authenticating 666 with it */ 667 authproxy->done = TRUE; 668 669 /* To prevent the user+password to get sent to other than the original 670 host due to a location-follow, we do some weirdo checks here */ 671 if(!data->state.this_is_a_follow || 672 conn->bits.netrc || 673 !data->state.first_host || 674 data->set.http_disable_hostname_check_before_authentication || 675 Curl_raw_equal(data->state.first_host, conn->host.name)) { 676 result = output_auth_headers(conn, authhost, request, path, FALSE); 677 } 678 else 679 authhost->done = TRUE; 680 681 return result; 682} 683 684 685/* 686 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: 687 * headers. They are dealt with both in the transfer.c main loop and in the 688 * proxy CONNECT loop. 689 */ 690 691CURLcode Curl_http_input_auth(struct connectdata *conn, 692 int httpcode, 693 const char *header) /* the first non-space */ 694{ 695 /* 696 * This resource requires authentication 697 */ 698 struct SessionHandle *data = conn->data; 699 700 long *availp; 701 const char *start; 702 struct auth *authp; 703 704 if(httpcode == 407) { 705 start = header+strlen("Proxy-authenticate:"); 706 availp = &data->info.proxyauthavail; 707 authp = &data->state.authproxy; 708 } 709 else { 710 start = header+strlen("WWW-Authenticate:"); 711 availp = &data->info.httpauthavail; 712 authp = &data->state.authhost; 713 } 714 715 /* pass all white spaces */ 716 while(*start && ISSPACE(*start)) 717 start++; 718 719 /* 720 * Here we check if we want the specific single authentication (using ==) and 721 * if we do, we initiate usage of it. 722 * 723 * If the provided authentication is wanted as one out of several accepted 724 * types (using &), we OR this authentication type to the authavail 725 * variable. 726 * 727 * Note: 728 * 729 * ->picked is first set to the 'want' value (one or more bits) before the 730 * request is sent, and then it is again set _after_ all response 401/407 731 * headers have been received but then only to a single preferred method 732 * (bit). 733 * 734 */ 735 736 while(*start) { 737#ifdef USE_HTTP_NEGOTIATE 738 if(checkprefix("GSS-Negotiate", start) || 739 checkprefix("Negotiate", start)) { 740 int neg; 741 *availp |= CURLAUTH_GSSNEGOTIATE; 742 authp->avail |= CURLAUTH_GSSNEGOTIATE; 743 744 if(authp->picked == CURLAUTH_GSSNEGOTIATE) { 745 if(data->state.negotiate.state == GSS_AUTHSENT) { 746 /* if we sent GSS authentication in the outgoing request and we get 747 this back, we're in trouble */ 748 infof(data, "Authentication problem. Ignoring this.\n"); 749 data->state.authproblem = TRUE; 750 } 751 else { 752 neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); 753 if(neg == 0) { 754 DEBUGASSERT(!data->req.newurl); 755 data->req.newurl = strdup(data->change.url); 756 if(!data->req.newurl) 757 return CURLE_OUT_OF_MEMORY; 758 data->state.authproblem = FALSE; 759 /* we received GSS auth info and we dealt with it fine */ 760 data->state.negotiate.state = GSS_AUTHRECV; 761 } 762 else 763 data->state.authproblem = TRUE; 764 } 765 } 766 } 767 else 768#endif 769#ifdef USE_NTLM 770 /* NTLM support requires the SSL crypto libs */ 771 if(checkprefix("NTLM", start)) { 772 *availp |= CURLAUTH_NTLM; 773 authp->avail |= CURLAUTH_NTLM; 774 if(authp->picked == CURLAUTH_NTLM || 775 authp->picked == CURLAUTH_NTLM_WB) { 776 /* NTLM authentication is picked and activated */ 777 CURLcode ntlm = 778 Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); 779 if(CURLE_OK == ntlm) { 780 data->state.authproblem = FALSE; 781#ifdef NTLM_WB_ENABLED 782 if(authp->picked == CURLAUTH_NTLM_WB) { 783 *availp &= ~CURLAUTH_NTLM; 784 authp->avail &= ~CURLAUTH_NTLM; 785 *availp |= CURLAUTH_NTLM_WB; 786 authp->avail |= CURLAUTH_NTLM_WB; 787 788 /* Get the challenge-message which will be passed to 789 * ntlm_auth for generating the type 3 message later */ 790 while(*start && ISSPACE(*start)) 791 start++; 792 if(checkprefix("NTLM", start)) { 793 start += strlen("NTLM"); 794 while(*start && ISSPACE(*start)) 795 start++; 796 if(*start) 797 if((conn->challenge_header = strdup(start)) == NULL) 798 return CURLE_OUT_OF_MEMORY; 799 } 800 } 801#endif 802 } 803 else { 804 infof(data, "Authentication problem. Ignoring this.\n"); 805 data->state.authproblem = TRUE; 806 } 807 } 808 } 809 else 810#endif 811#ifndef CURL_DISABLE_CRYPTO_AUTH 812 if(checkprefix("Digest", start)) { 813 if((authp->avail & CURLAUTH_DIGEST) != 0) { 814 infof(data, "Ignoring duplicate digest auth header.\n"); 815 } 816 else { 817 CURLdigest dig; 818 *availp |= CURLAUTH_DIGEST; 819 authp->avail |= CURLAUTH_DIGEST; 820 821 /* We call this function on input Digest headers even if Digest 822 * authentication isn't activated yet, as we need to store the 823 * incoming data from this header in case we are gonna use 824 * Digest. */ 825 dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); 826 827 if(CURLDIGEST_FINE != dig) { 828 infof(data, "Authentication problem. Ignoring this.\n"); 829 data->state.authproblem = TRUE; 830 } 831 } 832 } 833 else 834#endif 835 if(checkprefix("Basic", start)) { 836 *availp |= CURLAUTH_BASIC; 837 authp->avail |= CURLAUTH_BASIC; 838 if(authp->picked == CURLAUTH_BASIC) { 839 /* We asked for Basic authentication but got a 40X back 840 anyway, which basically means our name+password isn't 841 valid. */ 842 authp->avail = CURLAUTH_NONE; 843 infof(data, "Authentication problem. Ignoring this.\n"); 844 data->state.authproblem = TRUE; 845 } 846 } 847 848 /* there may be multiple methods on one line, so keep reading */ 849 while(*start && *start != ',') /* read up to the next comma */ 850 start++; 851 if(*start == ',') /* if we're on a comma, skip it */ 852 start++; 853 while(*start && ISSPACE(*start)) 854 start++; 855 } 856 return CURLE_OK; 857} 858 859/** 860 * http_should_fail() determines whether an HTTP response has gotten us 861 * into an error state or not. 862 * 863 * @param conn all information about the current connection 864 * 865 * @retval 0 communications should continue 866 * 867 * @retval 1 communications should not continue 868 */ 869static int http_should_fail(struct connectdata *conn) 870{ 871 struct SessionHandle *data; 872 int httpcode; 873 874 DEBUGASSERT(conn); 875 data = conn->data; 876 DEBUGASSERT(data); 877 878 httpcode = data->req.httpcode; 879 880 /* 881 ** If we haven't been asked to fail on error, 882 ** don't fail. 883 */ 884 if(!data->set.http_fail_on_error) 885 return 0; 886 887 /* 888 ** Any code < 400 is never terminal. 889 */ 890 if(httpcode < 400) 891 return 0; 892 893 if(data->state.resume_from && 894 (data->set.httpreq==HTTPREQ_GET) && 895 (httpcode == 416)) { 896 /* "Requested Range Not Satisfiable", just proceed and 897 pretend this is no error */ 898 return 0; 899 } 900 901 /* 902 ** Any code >= 400 that's not 401 or 407 is always 903 ** a terminal error 904 */ 905 if((httpcode != 401) && 906 (httpcode != 407)) 907 return 1; 908 909 /* 910 ** All we have left to deal with is 401 and 407 911 */ 912 DEBUGASSERT((httpcode == 401) || (httpcode == 407)); 913 914 /* 915 ** Examine the current authentication state to see if this 916 ** is an error. The idea is for this function to get 917 ** called after processing all the headers in a response 918 ** message. So, if we've been to asked to authenticate a 919 ** particular stage, and we've done it, we're OK. But, if 920 ** we're already completely authenticated, it's not OK to 921 ** get another 401 or 407. 922 ** 923 ** It is possible for authentication to go stale such that 924 ** the client needs to reauthenticate. Once that info is 925 ** available, use it here. 926 */ 927 928 /* 929 ** Either we're not authenticating, or we're supposed to 930 ** be authenticating something else. This is an error. 931 */ 932 if((httpcode == 401) && !conn->bits.user_passwd) 933 return TRUE; 934 if((httpcode == 407) && !conn->bits.proxy_user_passwd) 935 return TRUE; 936 937 return data->state.authproblem; 938} 939 940/* 941 * readmoredata() is a "fread() emulation" to provide POST and/or request 942 * data. It is used when a huge POST is to be made and the entire chunk wasn't 943 * sent in the first send(). This function will then be called from the 944 * transfer.c loop when more data is to be sent to the peer. 945 * 946 * Returns the amount of bytes it filled the buffer with. 947 */ 948static size_t readmoredata(char *buffer, 949 size_t size, 950 size_t nitems, 951 void *userp) 952{ 953 struct connectdata *conn = (struct connectdata *)userp; 954 struct HTTP *http = conn->data->state.proto.http; 955 size_t fullsize = size * nitems; 956 957 if(0 == http->postsize) 958 /* nothing to return */ 959 return 0; 960 961 /* make sure that a HTTP request is never sent away chunked! */ 962 conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; 963 964 if(http->postsize <= (curl_off_t)fullsize) { 965 memcpy(buffer, http->postdata, (size_t)http->postsize); 966 fullsize = (size_t)http->postsize; 967 968 if(http->backup.postsize) { 969 /* move backup data into focus and continue on that */ 970 http->postdata = http->backup.postdata; 971 http->postsize = http->backup.postsize; 972 conn->fread_func = http->backup.fread_func; 973 conn->fread_in = http->backup.fread_in; 974 975 http->sending++; /* move one step up */ 976 977 http->backup.postsize=0; 978 } 979 else 980 http->postsize = 0; 981 982 return fullsize; 983 } 984 985 memcpy(buffer, http->postdata, fullsize); 986 http->postdata += fullsize; 987 http->postsize -= fullsize; 988 989 return fullsize; 990} 991 992/* ------------------------------------------------------------------------- */ 993/* add_buffer functions */ 994 995/* 996 * Curl_add_buffer_init() sets up and returns a fine buffer struct 997 */ 998Curl_send_buffer *Curl_add_buffer_init(void) 999{ 1000 return calloc(1, sizeof(Curl_send_buffer)); 1001} 1002 1003/* 1004 * Curl_add_buffer_send() sends a header buffer and frees all associated 1005 * memory. Body data may be appended to the header data if desired. 1006 * 1007 * Returns CURLcode 1008 */ 1009CURLcode Curl_add_buffer_send(Curl_send_buffer *in, 1010 struct connectdata *conn, 1011 1012 /* add the number of sent bytes to this 1013 counter */ 1014 long *bytes_written, 1015 1016 /* how much of the buffer contains body data */ 1017 size_t included_body_bytes, 1018 int socketindex) 1019 1020{ 1021 ssize_t amount; 1022 CURLcode res; 1023 char *ptr; 1024 size_t size; 1025 struct HTTP *http = conn->data->state.proto.http; 1026 size_t sendsize; 1027 curl_socket_t sockfd; 1028 size_t headersize; 1029 1030 DEBUGASSERT(socketindex <= SECONDARYSOCKET); 1031 1032 sockfd = conn->sock[socketindex]; 1033 1034 /* The looping below is required since we use non-blocking sockets, but due 1035 to the circumstances we will just loop and try again and again etc */ 1036 1037 ptr = in->buffer; 1038 size = in->size_used; 1039 1040 headersize = size - included_body_bytes; /* the initial part that isn't body 1041 is header */ 1042 1043 DEBUGASSERT(size > included_body_bytes); 1044 1045 res = Curl_convert_to_network(conn->data, ptr, headersize); 1046 /* Curl_convert_to_network calls failf if unsuccessful */ 1047 if(res) { 1048 /* conversion failed, free memory and return to the caller */ 1049 if(in->buffer) 1050 free(in->buffer); 1051 free(in); 1052 return res; 1053 } 1054 1055 if(conn->handler->flags & PROTOPT_SSL) { 1056 /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk 1057 when we speak HTTPS, as if only a fraction of it is sent now, this data 1058 needs to fit into the normal read-callback buffer later on and that 1059 buffer is using this size. 1060 */ 1061 1062 sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size; 1063 1064 /* OpenSSL is very picky and we must send the SAME buffer pointer to the 1065 library when we attempt to re-send this buffer. Sending the same data 1066 is not enough, we must use the exact same address. For this reason, we 1067 must copy the data to the uploadbuffer first, since that is the buffer 1068 we will be using if this send is retried later. 1069 */ 1070 memcpy(conn->data->state.uploadbuffer, ptr, sendsize); 1071 ptr = conn->data->state.uploadbuffer; 1072 } 1073 else 1074 sendsize = size; 1075 1076 res = Curl_write(conn, sockfd, ptr, sendsize, &amount); 1077 1078 if(CURLE_OK == res) { 1079 /* 1080 * Note that we may not send the entire chunk at once, and we have a set 1081 * number of data bytes at the end of the big buffer (out of which we may 1082 * only send away a part). 1083 */ 1084 /* how much of the header that was sent */ 1085 size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount; 1086 size_t bodylen = amount - headlen; 1087 1088 if(conn->data->set.verbose) { 1089 /* this data _may_ contain binary stuff */ 1090 Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); 1091 if((size_t)amount > headlen) { 1092 /* there was body data sent beyond the initial header part, pass that 1093 on to the debug callback too */ 1094 Curl_debug(conn->data, CURLINFO_DATA_OUT, 1095 ptr+headlen, bodylen, conn); 1096 } 1097 } 1098 if(bodylen) 1099 /* since we sent a piece of the body here, up the byte counter for it 1100 accordingly */ 1101 http->writebytecount += bodylen; 1102 1103 /* 'amount' can never be a very large value here so typecasting it so a 1104 signed 31 bit value should not cause problems even if ssize_t is 1105 64bit */ 1106 *bytes_written += (long)amount; 1107 1108 if(http) { 1109 if((size_t)amount != size) { 1110 /* The whole request could not be sent in one system call. We must 1111 queue it up and send it later when we get the chance. We must not 1112 loop here and wait until it might work again. */ 1113 1114 size -= amount; 1115 1116 ptr = in->buffer + amount; 1117 1118 /* backup the currently set pointers */ 1119 http->backup.fread_func = conn->fread_func; 1120 http->backup.fread_in = conn->fread_in; 1121 http->backup.postdata = http->postdata; 1122 http->backup.postsize = http->postsize; 1123 1124 /* set the new pointers for the request-sending */ 1125 conn->fread_func = (curl_read_callback)readmoredata; 1126 conn->fread_in = (void *)conn; 1127 http->postdata = ptr; 1128 http->postsize = (curl_off_t)size; 1129 1130 http->send_buffer = in; 1131 http->sending = HTTPSEND_REQUEST; 1132 1133 return CURLE_OK; 1134 } 1135 http->sending = HTTPSEND_BODY; 1136 /* the full buffer was sent, clean up and return */ 1137 } 1138 else { 1139 if((size_t)amount != size) 1140 /* We have no continue-send mechanism now, fail. This can only happen 1141 when this function is used from the CONNECT sending function. We 1142 currently (stupidly) assume that the whole request is always sent 1143 away in the first single chunk. 1144 1145 This needs FIXing. 1146 */ 1147 return CURLE_SEND_ERROR; 1148 else 1149 conn->writechannel_inuse = FALSE; 1150 } 1151 } 1152 if(in->buffer) 1153 free(in->buffer); 1154 free(in); 1155 1156 return res; 1157} 1158 1159 1160/* 1161 * add_bufferf() add the formatted input to the buffer. 1162 */ 1163CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) 1164{ 1165 char *s; 1166 va_list ap; 1167 va_start(ap, fmt); 1168 s = vaprintf(fmt, ap); /* this allocs a new string to append */ 1169 va_end(ap); 1170 1171 if(s) { 1172 CURLcode result = Curl_add_buffer(in, s, strlen(s)); 1173 free(s); 1174 return result; 1175 } 1176 /* If we failed, we cleanup the whole buffer and return error */ 1177 if(in->buffer) 1178 free(in->buffer); 1179 free(in); 1180 return CURLE_OUT_OF_MEMORY; 1181} 1182 1183/* 1184 * add_buffer() appends a memory chunk to the existing buffer 1185 */ 1186CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) 1187{ 1188 char *new_rb; 1189 size_t new_size; 1190 1191 if(~size < in->size_used) { 1192 /* If resulting used size of send buffer would wrap size_t, cleanup 1193 the whole buffer and return error. Otherwise the required buffer 1194 size will fit into a single allocatable memory chunk */ 1195 Curl_safefree(in->buffer); 1196 free(in); 1197 return CURLE_OUT_OF_MEMORY; 1198 } 1199 1200 if(!in->buffer || 1201 ((in->size_used + size) > (in->size_max - 1))) { 1202 1203 /* If current buffer size isn't enough to hold the result, use a 1204 buffer size that doubles the required size. If this new size 1205 would wrap size_t, then just use the largest possible one */ 1206 1207 if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) || 1208 (~(size*2) < (in->size_used*2))) 1209 new_size = (size_t)-1; 1210 else 1211 new_size = (in->size_used+size)*2; 1212 1213 if(in->buffer) 1214 /* we have a buffer, enlarge the existing one */ 1215 new_rb = realloc(in->buffer, new_size); 1216 else 1217 /* create a new buffer */ 1218 new_rb = malloc(new_size); 1219 1220 if(!new_rb) { 1221 /* If we failed, we cleanup the whole buffer and return error */ 1222 Curl_safefree(in->buffer); 1223 free(in); 1224 return CURLE_OUT_OF_MEMORY; 1225 } 1226 1227 in->buffer = new_rb; 1228 in->size_max = new_size; 1229 } 1230 memcpy(&in->buffer[in->size_used], inptr, size); 1231 1232 in->size_used += size; 1233 1234 return CURLE_OK; 1235} 1236 1237/* end of the add_buffer functions */ 1238/* ------------------------------------------------------------------------- */ 1239 1240 1241 1242/* 1243 * Curl_compareheader() 1244 * 1245 * Returns TRUE if 'headerline' contains the 'header' with given 'content'. 1246 * Pass headers WITH the colon. 1247 */ 1248bool 1249Curl_compareheader(const char *headerline, /* line to check */ 1250 const char *header, /* header keyword _with_ colon */ 1251 const char *content) /* content string to find */ 1252{ 1253 /* RFC2616, section 4.2 says: "Each header field consists of a name followed 1254 * by a colon (":") and the field value. Field names are case-insensitive. 1255 * The field value MAY be preceded by any amount of LWS, though a single SP 1256 * is preferred." */ 1257 1258 size_t hlen = strlen(header); 1259 size_t clen; 1260 size_t len; 1261 const char *start; 1262 const char *end; 1263 1264 if(!Curl_raw_nequal(headerline, header, hlen)) 1265 return FALSE; /* doesn't start with header */ 1266 1267 /* pass the header */ 1268 start = &headerline[hlen]; 1269 1270 /* pass all white spaces */ 1271 while(*start && ISSPACE(*start)) 1272 start++; 1273 1274 /* find the end of the header line */ 1275 end = strchr(start, '\r'); /* lines end with CRLF */ 1276 if(!end) { 1277 /* in case there's a non-standard compliant line here */ 1278 end = strchr(start, '\n'); 1279 1280 if(!end) 1281 /* hm, there's no line ending here, use the zero byte! */ 1282 end = strchr(start, '\0'); 1283 } 1284 1285 len = end-start; /* length of the content part of the input line */ 1286 clen = strlen(content); /* length of the word to find */ 1287 1288 /* find the content string in the rest of the line */ 1289 for(;len>=clen;len--, start++) { 1290 if(Curl_raw_nequal(start, content, clen)) 1291 return TRUE; /* match! */ 1292 } 1293 1294 return FALSE; /* no match */ 1295} 1296 1297/* 1298 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from 1299 * the generic Curl_connect(). 1300 */ 1301CURLcode Curl_http_connect(struct connectdata *conn, bool *done) 1302{ 1303 struct SessionHandle *data; 1304 CURLcode result; 1305 1306 data=conn->data; 1307 1308 /* We default to persistent connections. We set this already in this connect 1309 function to make the re-use checks properly be able to check this bit. */ 1310 conn->bits.close = FALSE; 1311 1312#ifndef CURL_DISABLE_PROXY 1313 /* If we are not using a proxy and we want a secure connection, perform SSL 1314 * initialization & connection now. If using a proxy with https, then we 1315 * must tell the proxy to CONNECT to the host we want to talk to. Only 1316 * after the connect has occurred, can we start talking SSL 1317 */ 1318 if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { 1319 1320 /* either SSL over proxy, or explicitly asked for */ 1321 result = Curl_proxyCONNECT(conn, FIRSTSOCKET, 1322 conn->host.name, 1323 conn->remote_port); 1324 if(CURLE_OK != result) 1325 return result; 1326 } 1327 1328 if(conn->bits.tunnel_connecting) { 1329 /* nothing else to do except wait right now - we're not done here. */ 1330 return CURLE_OK; 1331 } 1332#endif /* CURL_DISABLE_PROXY */ 1333 1334 if(conn->given->flags & PROTOPT_SSL) { 1335 /* perform SSL initialization */ 1336 if(data->state.used_interface == Curl_if_multi) { 1337 result = https_connecting(conn, done); 1338 if(result) 1339 return result; 1340 } 1341 else { 1342 /* BLOCKING */ 1343 result = Curl_ssl_connect(conn, FIRSTSOCKET); 1344 if(result) 1345 return result; 1346 *done = TRUE; 1347 } 1348 } 1349 else { 1350 *done = TRUE; 1351 } 1352 1353 return CURLE_OK; 1354} 1355 1356/* this returns the socket to wait for in the DO and DOING state for the multi 1357 interface and then we're always _sending_ a request and thus we wait for 1358 the single socket to become writable only */ 1359static int http_getsock_do(struct connectdata *conn, 1360 curl_socket_t *socks, 1361 int numsocks) 1362{ 1363 /* write mode */ 1364 (void)numsocks; /* unused, we trust it to be at least 1 */ 1365 socks[0] = conn->sock[FIRSTSOCKET]; 1366 return GETSOCK_WRITESOCK(0); 1367} 1368 1369#ifdef USE_SSL 1370static CURLcode https_connecting(struct connectdata *conn, bool *done) 1371{ 1372 CURLcode result; 1373 DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL)); 1374 1375 /* perform SSL initialization for this socket */ 1376 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); 1377 if(result) 1378 conn->bits.close = TRUE; /* a failed connection is marked for closure 1379 to prevent (bad) re-use or similar */ 1380 return result; 1381} 1382#endif 1383 1384#if defined(USE_SSLEAY) || defined(USE_GNUTLS) 1385/* This function is for OpenSSL and GnuTLS only. It should be made to query 1386 the generic SSL layer instead. */ 1387static int https_getsock(struct connectdata *conn, 1388 curl_socket_t *socks, 1389 int numsocks) 1390{ 1391 if(conn->handler->flags & PROTOPT_SSL) { 1392 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; 1393 1394 if(!numsocks) 1395 return GETSOCK_BLANK; 1396 1397 if(connssl->connecting_state == ssl_connect_2_writing) { 1398 /* write mode */ 1399 socks[0] = conn->sock[FIRSTSOCKET]; 1400 return GETSOCK_WRITESOCK(0); 1401 } 1402 else if(connssl->connecting_state == ssl_connect_2_reading) { 1403 /* read mode */ 1404 socks[0] = conn->sock[FIRSTSOCKET]; 1405 return GETSOCK_READSOCK(0); 1406 } 1407 } 1408 return CURLE_OK; 1409} 1410#else 1411#if defined(USE_NSS) || defined(USE_QSOSSL) || \ 1412 defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL) 1413static int https_getsock(struct connectdata *conn, 1414 curl_socket_t *socks, 1415 int numsocks) 1416{ 1417 (void)conn; 1418 (void)socks; 1419 (void)numsocks; 1420 return GETSOCK_BLANK; 1421} 1422#endif /* USE_AXTLS || USE_POLARSSL || USE_QSOSSL || USE_NSS */ 1423#endif /* USE_SSLEAY || USE_GNUTLS */ 1424 1425/* 1426 * Curl_http_done() gets called from Curl_done() after a single HTTP request 1427 * has been performed. 1428 */ 1429 1430CURLcode Curl_http_done(struct connectdata *conn, 1431 CURLcode status, bool premature) 1432{ 1433 struct SessionHandle *data = conn->data; 1434 struct HTTP *http =data->state.proto.http; 1435 1436 Curl_unencode_cleanup(conn); 1437 1438 /* set the proper values (possibly modified on POST) */ 1439 conn->fread_func = data->set.fread_func; /* restore */ 1440 conn->fread_in = data->set.in; /* restore */ 1441 conn->seek_func = data->set.seek_func; /* restore */ 1442 conn->seek_client = data->set.seek_client; /* restore */ 1443 1444 if(http == NULL) 1445 return CURLE_OK; 1446 1447 if(http->send_buffer) { 1448 Curl_send_buffer *buff = http->send_buffer; 1449 1450 free(buff->buffer); 1451 free(buff); 1452 http->send_buffer = NULL; /* clear the pointer */ 1453 } 1454 1455 if(HTTPREQ_POST_FORM == data->set.httpreq) { 1456 data->req.bytecount = http->readbytecount + http->writebytecount; 1457 1458 Curl_formclean(&http->sendit); /* Now free that whole lot */ 1459 if(http->form.fp) { 1460 /* a file being uploaded was left opened, close it! */ 1461 fclose(http->form.fp); 1462 http->form.fp = NULL; 1463 } 1464 } 1465 else if(HTTPREQ_PUT == data->set.httpreq) 1466 data->req.bytecount = http->readbytecount + http->writebytecount; 1467 1468 if(status != CURLE_OK) 1469 return (status); 1470 1471 if(!premature && /* this check is pointless when DONE is called before the 1472 entire operation is complete */ 1473 !conn->bits.retry && 1474 ((http->readbytecount + 1475 data->req.headerbytecount - 1476 data->req.deductheadercount)) <= 0) { 1477 /* If this connection isn't simply closed to be retried, AND nothing was 1478 read from the HTTP server (that counts), this can't be right so we 1479 return an error here */ 1480 failf(data, "Empty reply from server"); 1481 return CURLE_GOT_NOTHING; 1482 } 1483 1484 return CURLE_OK; 1485} 1486 1487 1488/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it 1489 are if the user specifically requested HTTP 1.0, if the server we are 1490 connected to only supports 1.0, or if any server previously contacted to 1491 handle this request only supports 1.0. */ 1492static bool use_http_1_1(const struct SessionHandle *data, 1493 const struct connectdata *conn) 1494{ 1495 return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) || 1496 ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && 1497 ((conn->httpversion == 11) || 1498 ((conn->httpversion != 10) && 1499 (data->state.httpversion != 10))))) ? TRUE : FALSE; 1500} 1501 1502/* check and possibly add an Expect: header */ 1503static CURLcode expect100(struct SessionHandle *data, 1504 struct connectdata *conn, 1505 Curl_send_buffer *req_buffer) 1506{ 1507 CURLcode result = CURLE_OK; 1508 const char *ptr; 1509 data->state.expect100header = FALSE; /* default to false unless it is set 1510 to TRUE below */ 1511 if(use_http_1_1(data, conn)) { 1512 /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: 1513 100-continue to the headers which actually speeds up post operations 1514 (as there is one packet coming back from the web server) */ 1515 ptr = Curl_checkheaders(data, "Expect:"); 1516 if(ptr) { 1517 data->state.expect100header = 1518 Curl_compareheader(ptr, "Expect:", "100-continue"); 1519 } 1520 else { 1521 result = Curl_add_bufferf(req_buffer, 1522 "Expect: 100-continue\r\n"); 1523 if(result == CURLE_OK) 1524 data->state.expect100header = TRUE; 1525 } 1526 } 1527 return result; 1528} 1529 1530CURLcode Curl_add_custom_headers(struct connectdata *conn, 1531 Curl_send_buffer *req_buffer) 1532{ 1533 char *ptr; 1534 struct curl_slist *headers=conn->data->set.headers; 1535 1536 while(headers) { 1537 ptr = strchr(headers->data, ':'); 1538 if(ptr) { 1539 /* we require a colon for this to be a true header */ 1540 1541 ptr++; /* pass the colon */ 1542 while(*ptr && ISSPACE(*ptr)) 1543 ptr++; 1544 1545 if(*ptr) { 1546 /* only send this if the contents was non-blank */ 1547 1548 if(conn->allocptr.host && 1549 /* a Host: header was sent already, don't pass on any custom Host: 1550 header as that will produce *two* in the same request! */ 1551 checkprefix("Host:", headers->data)) 1552 ; 1553 else if(conn->data->set.httpreq == HTTPREQ_POST_FORM && 1554 /* this header (extended by formdata.c) is sent later */ 1555 checkprefix("Content-Type:", headers->data)) 1556 ; 1557 else if(conn->bits.authneg && 1558 /* while doing auth neg, don't allow the custom length since 1559 we will force length zero then */ 1560 checkprefix("Content-Length", headers->data)) 1561 ; 1562 else if(conn->allocptr.te && 1563 /* when asking for Transfer-Encoding, don't pass on a custom 1564 Connection: */ 1565 checkprefix("Connection", headers->data)) 1566 ; 1567 else { 1568 CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", 1569 headers->data); 1570 if(result) 1571 return result; 1572 } 1573 } 1574 } 1575 else { 1576 ptr = strchr(headers->data, ';'); 1577 if(ptr) { 1578 1579 ptr++; /* pass the semicolon */ 1580 while(*ptr && ISSPACE(*ptr)) 1581 ptr++; 1582 1583 if(*ptr) { 1584 /* this may be used for something else in the future */ 1585 } 1586 else { 1587 if(*(--ptr) == ';') { 1588 CURLcode result; 1589 1590 /* send no-value custom header if terminated by semicolon */ 1591 *ptr = ':'; 1592 result = Curl_add_bufferf(req_buffer, "%s\r\n", 1593 headers->data); 1594 if(result) 1595 return result; 1596 } 1597 } 1598 } 1599 } 1600 headers = headers->next; 1601 } 1602 return CURLE_OK; 1603} 1604 1605CURLcode Curl_add_timecondition(struct SessionHandle *data, 1606 Curl_send_buffer *req_buffer) 1607{ 1608 const struct tm *tm; 1609 char *buf = data->state.buffer; 1610 CURLcode result = CURLE_OK; 1611 struct tm keeptime; 1612 1613 result = Curl_gmtime(data->set.timevalue, &keeptime); 1614 if(result) { 1615 failf(data, "Invalid TIMEVALUE\n"); 1616 return result; 1617 } 1618 tm = &keeptime; 1619 1620 /* The If-Modified-Since header family should have their times set in 1621 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be 1622 * represented in Greenwich Mean Time (GMT), without exception. For the 1623 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal 1624 * Time)." (see page 20 of RFC2616). 1625 */ 1626 1627 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ 1628 snprintf(buf, BUFSIZE-1, 1629 "%s, %02d %s %4d %02d:%02d:%02d GMT", 1630 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], 1631 tm->tm_mday, 1632 Curl_month[tm->tm_mon], 1633 tm->tm_year + 1900, 1634 tm->tm_hour, 1635 tm->tm_min, 1636 tm->tm_sec); 1637 1638 switch(data->set.timecondition) { 1639 case CURL_TIMECOND_IFMODSINCE: 1640 default: 1641 result = Curl_add_bufferf(req_buffer, 1642 "If-Modified-Since: %s\r\n", buf); 1643 break; 1644 case CURL_TIMECOND_IFUNMODSINCE: 1645 result = Curl_add_bufferf(req_buffer, 1646 "If-Unmodified-Since: %s\r\n", buf); 1647 break; 1648 case CURL_TIMECOND_LASTMOD: 1649 result = Curl_add_bufferf(req_buffer, 1650 "Last-Modified: %s\r\n", buf); 1651 break; 1652 } 1653 1654 return result; 1655} 1656 1657/* 1658 * Curl_http() gets called from the generic Curl_do() function when a HTTP 1659 * request is to be performed. This creates and sends a properly constructed 1660 * HTTP request. 1661 */ 1662CURLcode Curl_http(struct connectdata *conn, bool *done) 1663{ 1664 struct SessionHandle *data=conn->data; 1665 CURLcode result=CURLE_OK; 1666 struct HTTP *http; 1667 const char *ppath = data->state.path; 1668 bool paste_ftp_userpwd = FALSE; 1669 char ftp_typecode[sizeof("/;type=?")] = ""; 1670 const char *host = conn->host.name; 1671 const char *te = ""; /* transfer-encoding */ 1672 const char *ptr; 1673 const char *request; 1674 Curl_HttpReq httpreq = data->set.httpreq; 1675 char *addcookies = NULL; 1676 curl_off_t included_body = 0; 1677 const char *httpstring; 1678 Curl_send_buffer *req_buffer; 1679 curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */ 1680 int seekerr = CURL_SEEKFUNC_OK; 1681 1682 /* Always consider the DO phase done after this function call, even if there 1683 may be parts of the request that is not yet sent, since we can deal with 1684 the rest of the request in the PERFORM phase. */ 1685 *done = TRUE; 1686 1687 /* If there already is a protocol-specific struct allocated for this 1688 sessionhandle, deal with it */ 1689 Curl_reset_reqproto(conn); 1690 1691 if(!data->state.proto.http) { 1692 /* Only allocate this struct if we don't already have it! */ 1693 1694 http = calloc(1, sizeof(struct HTTP)); 1695 if(!http) 1696 return CURLE_OUT_OF_MEMORY; 1697 data->state.proto.http = http; 1698 } 1699 else 1700 http = data->state.proto.http; 1701 1702 if(!data->state.this_is_a_follow) { 1703 /* this is not a followed location, get the original host name */ 1704 if(data->state.first_host) 1705 /* Free to avoid leaking memory on multiple requests*/ 1706 free(data->state.first_host); 1707 1708 data->state.first_host = strdup(conn->host.name); 1709 if(!data->state.first_host) 1710 return CURLE_OUT_OF_MEMORY; 1711 } 1712 http->writebytecount = http->readbytecount = 0; 1713 1714 if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && 1715 data->set.upload) { 1716 httpreq = HTTPREQ_PUT; 1717 } 1718 1719 /* Now set the 'request' pointer to the proper request string */ 1720 if(data->set.str[STRING_CUSTOMREQUEST]) 1721 request = data->set.str[STRING_CUSTOMREQUEST]; 1722 else { 1723 if(data->set.opt_no_body) 1724 request = "HEAD"; 1725 else { 1726 DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); 1727 switch(httpreq) { 1728 case HTTPREQ_POST: 1729 case HTTPREQ_POST_FORM: 1730 request = "POST"; 1731 break; 1732 case HTTPREQ_PUT: 1733 request = "PUT"; 1734 break; 1735 default: /* this should never happen */ 1736 case HTTPREQ_GET: 1737 request = "GET"; 1738 break; 1739 case HTTPREQ_HEAD: 1740 request = "HEAD"; 1741 break; 1742 } 1743 } 1744 } 1745 1746 /* The User-Agent string might have been allocated in url.c already, because 1747 it might have been used in the proxy connect, but if we have got a header 1748 with the user-agent string specified, we erase the previously made string 1749 here. */ 1750 if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { 1751 free(conn->allocptr.uagent); 1752 conn->allocptr.uagent=NULL; 1753 } 1754 1755 /* setup the authentication headers */ 1756 result = Curl_http_output_auth(conn, request, ppath, FALSE); 1757 if(result) 1758 return result; 1759 1760 if((data->state.authhost.multi || data->state.authproxy.multi) && 1761 (httpreq != HTTPREQ_GET) && 1762 (httpreq != HTTPREQ_HEAD)) { 1763 /* Auth is required and we are not authenticated yet. Make a PUT or POST 1764 with content-length zero as a "probe". */ 1765 conn->bits.authneg = TRUE; 1766 } 1767 else 1768 conn->bits.authneg = FALSE; 1769 1770 Curl_safefree(conn->allocptr.ref); 1771 if(data->change.referer && !Curl_checkheaders(data, "Referer:")) 1772 conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); 1773 else 1774 conn->allocptr.ref = NULL; 1775 1776 if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:")) 1777 addcookies = data->set.str[STRING_COOKIE]; 1778 1779 if(!Curl_checkheaders(data, "Accept-Encoding:") && 1780 data->set.str[STRING_ENCODING]) { 1781 Curl_safefree(conn->allocptr.accept_encoding); 1782 conn->allocptr.accept_encoding = 1783 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); 1784 if(!conn->allocptr.accept_encoding) 1785 return CURLE_OUT_OF_MEMORY; 1786 } 1787 1788#ifdef HAVE_LIBZ 1789 /* we only consider transfer-encoding magic if libz support is built-in */ 1790 1791 if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) { 1792 /* When we are to insert a TE: header in the request, we must also insert 1793 TE in a Connection: header, so we need to merge the custom provided 1794 Connection: header and prevent the original to get sent. Note that if 1795 the user has inserted his/hers own TE: header we don't do this magic 1796 but then assume that the user will handle it all! */ 1797 char *cptr = Curl_checkheaders(data, "Connection:"); 1798#define TE_HEADER "TE: gzip\r\n" 1799 1800 Curl_safefree(conn->allocptr.te); 1801 1802 /* Create the (updated) Connection: header */ 1803 conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr): 1804 strdup("Connection: TE\r\n" TE_HEADER); 1805 1806 if(!conn->allocptr.te) 1807 return CURLE_OUT_OF_MEMORY; 1808 } 1809#endif 1810 1811 ptr = Curl_checkheaders(data, "Transfer-Encoding:"); 1812 if(ptr) { 1813 /* Some kind of TE is requested, check if 'chunked' is chosen */ 1814 data->req.upload_chunky = 1815 Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); 1816 } 1817 else { 1818 if((conn->handler->protocol&CURLPROTO_HTTP) && 1819 data->set.upload && 1820 (data->set.infilesize == -1)) { 1821 if(conn->bits.authneg) 1822 /* don't enable chunked during auth neg */ 1823 ; 1824 else if(use_http_1_1(data, conn)) { 1825 /* HTTP, upload, unknown file size and not HTTP 1.0 */ 1826 data->req.upload_chunky = TRUE; 1827 } 1828 else { 1829 failf(data, "Chunky upload is not supported by HTTP 1.0"); 1830 return CURLE_UPLOAD_FAILED; 1831 } 1832 } 1833 else { 1834 /* else, no chunky upload */ 1835 data->req.upload_chunky = FALSE; 1836 } 1837 1838 if(data->req.upload_chunky) 1839 te = "Transfer-Encoding: chunked\r\n"; 1840 } 1841 1842 Curl_safefree(conn->allocptr.host); 1843 1844 ptr = Curl_checkheaders(data, "Host:"); 1845 if(ptr && (!data->state.this_is_a_follow || 1846 Curl_raw_equal(data->state.first_host, conn->host.name))) { 1847#if !defined(CURL_DISABLE_COOKIES) 1848 /* If we have a given custom Host: header, we extract the host name in 1849 order to possibly use it for cookie reasons later on. We only allow the 1850 custom Host: header if this is NOT a redirect, as setting Host: in the 1851 redirected request is being out on thin ice. Except if the host name 1852 is the same as the first one! */ 1853 char *cookiehost = copy_header_value(ptr); 1854 if(!cookiehost) 1855 return CURLE_OUT_OF_MEMORY; 1856 if(!*cookiehost) 1857 /* ignore empty data */ 1858 free(cookiehost); 1859 else { 1860 char *colon = strchr(cookiehost, ':'); 1861 if(colon) 1862 *colon = 0; /* The host must not include an embedded port number */ 1863 Curl_safefree(conn->allocptr.cookiehost); 1864 conn->allocptr.cookiehost = cookiehost; 1865 } 1866#endif 1867 1868 conn->allocptr.host = NULL; 1869 } 1870 else { 1871 /* When building Host: headers, we must put the host name within 1872 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ 1873 1874 if(((conn->given->protocol&CURLPROTO_HTTPS) && 1875 (conn->remote_port == PORT_HTTPS)) || 1876 ((conn->given->protocol&CURLPROTO_HTTP) && 1877 (conn->remote_port == PORT_HTTP)) ) 1878 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include 1879 the port number in the host string */ 1880 conn->allocptr.host = aprintf("Host: %s%s%s\r\n", 1881 conn->bits.ipv6_ip?"[":"", 1882 host, 1883 conn->bits.ipv6_ip?"]":""); 1884 else 1885 conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n", 1886 conn->bits.ipv6_ip?"[":"", 1887 host, 1888 conn->bits.ipv6_ip?"]":"", 1889 conn->remote_port); 1890 1891 if(!conn->allocptr.host) 1892 /* without Host: we can't make a nice request */ 1893 return CURLE_OUT_OF_MEMORY; 1894 } 1895 1896#ifndef CURL_DISABLE_PROXY 1897 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { 1898 /* Using a proxy but does not tunnel through it */ 1899 1900 /* The path sent to the proxy is in fact the entire URL. But if the remote 1901 host is a IDN-name, we must make sure that the request we produce only 1902 uses the encoded host name! */ 1903 if(conn->host.dispname != conn->host.name) { 1904 char *url = data->change.url; 1905 ptr = strstr(url, conn->host.dispname); 1906 if(ptr) { 1907 /* This is where the display name starts in the URL, now replace this 1908 part with the encoded name. TODO: This method of replacing the host 1909 name is rather crude as I believe there's a slight risk that the 1910 user has entered a user name or password that contain the host name 1911 string. */ 1912 size_t currlen = strlen(conn->host.dispname); 1913 size_t newlen = strlen(conn->host.name); 1914 size_t urllen = strlen(url); 1915 1916 char *newurl; 1917 1918 newurl = malloc(urllen + newlen - currlen + 1); 1919 if(newurl) { 1920 /* copy the part before the host name */ 1921 memcpy(newurl, url, ptr - url); 1922 /* append the new host name instead of the old */ 1923 memcpy(newurl + (ptr - url), conn->host.name, newlen); 1924 /* append the piece after the host name */ 1925 memcpy(newurl + newlen + (ptr - url), 1926 ptr + currlen, /* copy the trailing zero byte too */ 1927 urllen - (ptr-url) - currlen + 1); 1928 if(data->change.url_alloc) { 1929 Curl_safefree(data->change.url); 1930 data->change.url_alloc = FALSE; 1931 } 1932 data->change.url = newurl; 1933 data->change.url_alloc = TRUE; 1934 } 1935 else 1936 return CURLE_OUT_OF_MEMORY; 1937 } 1938 } 1939 ppath = data->change.url; 1940 if(checkprefix("ftp://", ppath)) { 1941 if(data->set.proxy_transfer_mode) { 1942 /* when doing ftp, append ;type=<a|i> if not present */ 1943 char *type = strstr(ppath, ";type="); 1944 if(type && type[6] && type[7] == 0) { 1945 switch (Curl_raw_toupper(type[6])) { 1946 case 'A': 1947 case 'D': 1948 case 'I': 1949 break; 1950 default: 1951 type = NULL; 1952 } 1953 } 1954 if(!type) { 1955 char *p = ftp_typecode; 1956 /* avoid sending invalid URLs like ftp://example.com;type=i if the 1957 * user specified ftp://example.com without the slash */ 1958 if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') { 1959 *p++ = '/'; 1960 } 1961 snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", 1962 data->set.prefer_ascii ? 'a' : 'i'); 1963 } 1964 } 1965 if(conn->bits.user_passwd && !conn->bits.userpwd_in_url) 1966 paste_ftp_userpwd = TRUE; 1967 } 1968 } 1969#endif /* CURL_DISABLE_PROXY */ 1970 1971 if(HTTPREQ_POST_FORM == httpreq) { 1972 /* we must build the whole post sequence first, so that we have a size of 1973 the whole transfer before we start to send it */ 1974 result = Curl_getformdata(data, &http->sendit, data->set.httppost, 1975 Curl_checkheaders(data, "Content-Type:"), 1976 &http->postsize); 1977 if(result) 1978 return result; 1979 } 1980 1981 http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; 1982 1983 if(( (HTTPREQ_POST == httpreq) || 1984 (HTTPREQ_POST_FORM == httpreq) || 1985 (HTTPREQ_PUT == httpreq) ) && 1986 data->state.resume_from) { 1987 /********************************************************************** 1988 * Resuming upload in HTTP means that we PUT or POST and that we have 1989 * got a resume_from value set. The resume value has already created 1990 * a Range: header that will be passed along. We need to "fast forward" 1991 * the file the given number of bytes and decrease the assume upload 1992 * file size before we continue this venture in the dark lands of HTTP. 1993 *********************************************************************/ 1994 1995 if(data->state.resume_from < 0 ) { 1996 /* 1997 * This is meant to get the size of the present remote-file by itself. 1998 * We don't support this now. Bail out! 1999 */ 2000 data->state.resume_from = 0; 2001 } 2002 2003 if(data->state.resume_from && !data->state.this_is_a_follow) { 2004 /* do we still game? */ 2005 2006 /* Now, let's read off the proper amount of bytes from the 2007 input. */ 2008 if(conn->seek_func) { 2009 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, 2010 SEEK_SET); 2011 } 2012 2013 if(seekerr != CURL_SEEKFUNC_OK) { 2014 if(seekerr != CURL_SEEKFUNC_CANTSEEK) { 2015 failf(data, "Could not seek stream"); 2016 return CURLE_READ_ERROR; 2017 } 2018 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ 2019 else { 2020 curl_off_t passed=0; 2021 do { 2022 size_t readthisamountnow = 2023 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? 2024 BUFSIZE : curlx_sotouz(data->state.resume_from - passed); 2025 2026 size_t actuallyread = 2027 data->set.fread_func(data->state.buffer, 1, readthisamountnow, 2028 data->set.in); 2029 2030 passed += actuallyread; 2031 if((actuallyread == 0) || (actuallyread > readthisamountnow)) { 2032 /* this checks for greater-than only to make sure that the 2033 CURL_READFUNC_ABORT return code still aborts */ 2034 failf(data, "Could only read %" FORMAT_OFF_T 2035 " bytes from the input", 2036 passed); 2037 return CURLE_READ_ERROR; 2038 } 2039 } while(passed < data->state.resume_from); 2040 } 2041 } 2042 2043 /* now, decrease the size of the read */ 2044 if(data->set.infilesize>0) { 2045 data->set.infilesize -= data->state.resume_from; 2046 2047 if(data->set.infilesize <= 0) { 2048 failf(data, "File already completely uploaded"); 2049 return CURLE_PARTIAL_FILE; 2050 } 2051 } 2052 /* we've passed, proceed as normal */ 2053 } 2054 } 2055 if(data->state.use_range) { 2056 /* 2057 * A range is selected. We use different headers whether we're downloading 2058 * or uploading and we always let customized headers override our internal 2059 * ones if any such are specified. 2060 */ 2061 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && 2062 !Curl_checkheaders(data, "Range:")) { 2063 /* if a line like this was already allocated, free the previous one */ 2064 if(conn->allocptr.rangeline) 2065 free(conn->allocptr.rangeline); 2066 conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", 2067 data->state.range); 2068 } 2069 else if((httpreq != HTTPREQ_GET) && 2070 !Curl_checkheaders(data, "Content-Range:")) { 2071 2072 /* if a line like this was already allocated, free the previous one */ 2073 if(conn->allocptr.rangeline) 2074 free(conn->allocptr.rangeline); 2075 2076 if(data->set.set_resume_from < 0) { 2077 /* Upload resume was asked for, but we don't know the size of the 2078 remote part so we tell the server (and act accordingly) that we 2079 upload the whole file (again) */ 2080 conn->allocptr.rangeline = 2081 aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T 2082 "/%" FORMAT_OFF_T "\r\n", 2083 data->set.infilesize - 1, data->set.infilesize); 2084 2085 } 2086 else if(data->state.resume_from) { 2087 /* This is because "resume" was selected */ 2088 curl_off_t total_expected_size= 2089 data->state.resume_from + data->set.infilesize; 2090 conn->allocptr.rangeline = 2091 aprintf("Content-Range: bytes %s%" FORMAT_OFF_T 2092 "/%" FORMAT_OFF_T "\r\n", 2093 data->state.range, total_expected_size-1, 2094 total_expected_size); 2095 } 2096 else { 2097 /* Range was selected and then we just pass the incoming range and 2098 append total size */ 2099 conn->allocptr.rangeline = 2100 aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", 2101 data->state.range, data->set.infilesize); 2102 } 2103 if(!conn->allocptr.rangeline) 2104 return CURLE_OUT_OF_MEMORY; 2105 } 2106 } 2107 2108 /* Use 1.1 unless the user specifically asked for 1.0 or the server only 2109 supports 1.0 */ 2110 httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; 2111 2112 /* initialize a dynamic send-buffer */ 2113 req_buffer = Curl_add_buffer_init(); 2114 2115 if(!req_buffer) 2116 return CURLE_OUT_OF_MEMORY; 2117 2118 /* add the main request stuff */ 2119 /* GET/HEAD/POST/PUT */ 2120 result = Curl_add_bufferf(req_buffer, "%s ", request); 2121 if(result) 2122 return result; 2123 2124 /* url */ 2125 if(paste_ftp_userpwd) 2126 result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", 2127 conn->user, conn->passwd, 2128 ppath + sizeof("ftp://") - 1); 2129 else 2130 result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); 2131 if(result) 2132 return result; 2133 2134 result = 2135 Curl_add_bufferf(req_buffer, 2136 "%s" /* ftp typecode (;type=x) */ 2137 " HTTP/%s\r\n" /* HTTP version */ 2138 "%s" /* proxyuserpwd */ 2139 "%s" /* userpwd */ 2140 "%s" /* range */ 2141 "%s" /* user agent */ 2142 "%s" /* host */ 2143 "%s" /* accept */ 2144 "%s" /* TE: */ 2145 "%s" /* accept-encoding */ 2146 "%s" /* referer */ 2147 "%s" /* Proxy-Connection */ 2148 "%s",/* transfer-encoding */ 2149 2150 ftp_typecode, 2151 httpstring, 2152 conn->allocptr.proxyuserpwd? 2153 conn->allocptr.proxyuserpwd:"", 2154 conn->allocptr.userpwd?conn->allocptr.userpwd:"", 2155 (data->state.use_range && conn->allocptr.rangeline)? 2156 conn->allocptr.rangeline:"", 2157 (data->set.str[STRING_USERAGENT] && 2158 *data->set.str[STRING_USERAGENT] && 2159 conn->allocptr.uagent)? 2160 conn->allocptr.uagent:"", 2161 (conn->allocptr.host?conn->allocptr.host:""), 2162 http->p_accept?http->p_accept:"", 2163 conn->allocptr.te?conn->allocptr.te:"", 2164 (data->set.str[STRING_ENCODING] && 2165 *data->set.str[STRING_ENCODING] && 2166 conn->allocptr.accept_encoding)? 2167 conn->allocptr.accept_encoding:"", 2168 (data->change.referer && conn->allocptr.ref)? 2169 conn->allocptr.ref:"" /* Referer: <data> */, 2170 (conn->bits.httpproxy && 2171 !conn->bits.tunnel_proxy && 2172 !Curl_checkheaders(data, "Proxy-Connection:"))? 2173 "Proxy-Connection: Keep-Alive\r\n":"", 2174 te 2175 ); 2176 2177 /* 2178 * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM 2179 * with basic and digest, it will be freed anyway by the next request 2180 */ 2181 2182 Curl_safefree (conn->allocptr.userpwd); 2183 conn->allocptr.userpwd = NULL; 2184 2185 if(result) 2186 return result; 2187 2188#if !defined(CURL_DISABLE_COOKIES) 2189 if(data->cookies || addcookies) { 2190 struct Cookie *co=NULL; /* no cookies from start */ 2191 int count=0; 2192 2193 if(data->cookies) { 2194 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); 2195 co = Curl_cookie_getlist(data->cookies, 2196 conn->allocptr.cookiehost? 2197 conn->allocptr.cookiehost:host, 2198 data->state.path, 2199 (conn->handler->protocol&CURLPROTO_HTTPS)? 2200 TRUE:FALSE); 2201 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 2202 } 2203 if(co) { 2204 struct Cookie *store=co; 2205 /* now loop through all cookies that matched */ 2206 while(co) { 2207 if(co->value) { 2208 if(0 == count) { 2209 result = Curl_add_bufferf(req_buffer, "Cookie: "); 2210 if(result) 2211 break; 2212 } 2213 result = Curl_add_bufferf(req_buffer, 2214 "%s%s=%s", count?"; ":"", 2215 co->name, co->value); 2216 if(result) 2217 break; 2218 count++; 2219 } 2220 co = co->next; /* next cookie please */ 2221 } 2222 Curl_cookie_freelist(store, FALSE); /* free the cookie list */ 2223 } 2224 if(addcookies && (CURLE_OK == result)) { 2225 if(!count) 2226 result = Curl_add_bufferf(req_buffer, "Cookie: "); 2227 if(CURLE_OK == result) { 2228 result = Curl_add_bufferf(req_buffer, "%s%s", 2229 count?"; ":"", 2230 addcookies); 2231 count++; 2232 } 2233 } 2234 if(count && (CURLE_OK == result)) 2235 result = Curl_add_buffer(req_buffer, "\r\n", 2); 2236 2237 if(result) 2238 return result; 2239 } 2240#endif 2241 2242 if(data->set.timecondition) { 2243 result = Curl_add_timecondition(data, req_buffer); 2244 if(result) 2245 return result; 2246 } 2247 2248 result = Curl_add_custom_headers(conn, req_buffer); 2249 if(result) 2250 return result; 2251 2252 http->postdata = NULL; /* nothing to post at this point */ 2253 Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ 2254 2255 /* If 'authdone' is FALSE, we must not set the write socket index to the 2256 Curl_transfer() call below, as we're not ready to actually upload any 2257 data yet. */ 2258 2259 switch(httpreq) { 2260 2261 case HTTPREQ_POST_FORM: 2262 if(!http->sendit || conn->bits.authneg) { 2263 /* nothing to post! */ 2264 result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); 2265 if(result) 2266 return result; 2267 2268 result = Curl_add_buffer_send(req_buffer, conn, 2269 &data->info.request_size, 0, FIRSTSOCKET); 2270 if(result) 2271 failf(data, "Failed sending POST request"); 2272 else 2273 /* setup variables for the upcoming transfer */ 2274 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, 2275 -1, NULL); 2276 break; 2277 } 2278 2279 if(Curl_FormInit(&http->form, http->sendit)) { 2280 failf(data, "Internal HTTP POST error!"); 2281 return CURLE_HTTP_POST_ERROR; 2282 } 2283 2284 /* Get the currently set callback function pointer and store that in the 2285 form struct since we might want the actual user-provided callback later 2286 on. The conn->fread_func pointer itself will be changed for the 2287 multipart case to the function that returns a multipart formatted 2288 stream. */ 2289 http->form.fread_func = conn->fread_func; 2290 2291 /* Set the read function to read from the generated form data */ 2292 conn->fread_func = (curl_read_callback)Curl_FormReader; 2293 conn->fread_in = &http->form; 2294 2295 http->sending = HTTPSEND_BODY; 2296 2297 if(!data->req.upload_chunky && 2298 !Curl_checkheaders(data, "Content-Length:")) { 2299 /* only add Content-Length if not uploading chunked */ 2300 result = Curl_add_bufferf(req_buffer, 2301 "Content-Length: %" FORMAT_OFF_T "\r\n", 2302 http->postsize); 2303 if(result) 2304 return result; 2305 } 2306 2307 result = expect100(data, conn, req_buffer); 2308 if(result) 2309 return result; 2310 2311 { 2312 2313 /* Get Content-Type: line from Curl_formpostheader. 2314 */ 2315 char *contentType; 2316 size_t linelength=0; 2317 contentType = Curl_formpostheader((void *)&http->form, 2318 &linelength); 2319 if(!contentType) { 2320 failf(data, "Could not get Content-Type header line!"); 2321 return CURLE_HTTP_POST_ERROR; 2322 } 2323 2324 result = Curl_add_buffer(req_buffer, contentType, linelength); 2325 if(result) 2326 return result; 2327 } 2328 2329 /* make the request end in a true CRLF */ 2330 result = Curl_add_buffer(req_buffer, "\r\n", 2); 2331 if(result) 2332 return result; 2333 2334 /* set upload size to the progress meter */ 2335 Curl_pgrsSetUploadSize(data, http->postsize); 2336 2337 /* fire away the whole request to the server */ 2338 result = Curl_add_buffer_send(req_buffer, conn, 2339 &data->info.request_size, 0, FIRSTSOCKET); 2340 if(result) 2341 failf(data, "Failed sending POST request"); 2342 else 2343 /* setup variables for the upcoming transfer */ 2344 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, 2345 &http->readbytecount, FIRSTSOCKET, 2346 &http->writebytecount); 2347 2348 if(result) { 2349 Curl_formclean(&http->sendit); /* free that whole lot */ 2350 return result; 2351 } 2352 2353 /* convert the form data */ 2354 result = Curl_convert_form(data, http->sendit); 2355 if(result) { 2356 Curl_formclean(&http->sendit); /* free that whole lot */ 2357 return result; 2358 } 2359 2360 break; 2361 2362 case HTTPREQ_PUT: /* Let's PUT the data to the server! */ 2363 2364 if(conn->bits.authneg) 2365 postsize = 0; 2366 else 2367 postsize = data->set.infilesize; 2368 2369 if((postsize != -1) && !data->req.upload_chunky && 2370 !Curl_checkheaders(data, "Content-Length:")) { 2371 /* only add Content-Length if not uploading chunked */ 2372 result = Curl_add_bufferf(req_buffer, 2373 "Content-Length: %" FORMAT_OFF_T "\r\n", 2374 postsize ); 2375 if(result) 2376 return result; 2377 } 2378 2379 result = expect100(data, conn, req_buffer); 2380 if(result) 2381 return result; 2382 2383 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */ 2384 if(result) 2385 return result; 2386 2387 /* set the upload size to the progress meter */ 2388 Curl_pgrsSetUploadSize(data, postsize); 2389 2390 /* this sends the buffer and frees all the buffer resources */ 2391 result = Curl_add_buffer_send(req_buffer, conn, 2392 &data->info.request_size, 0, FIRSTSOCKET); 2393 if(result) 2394 failf(data, "Failed sending PUT request"); 2395 else 2396 /* prepare for transfer */ 2397 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, 2398 &http->readbytecount, postsize?FIRSTSOCKET:-1, 2399 postsize?&http->writebytecount:NULL); 2400 if(result) 2401 return result; 2402 break; 2403 2404 case HTTPREQ_POST: 2405 /* this is the simple POST, using x-www-form-urlencoded style */ 2406 2407 if(conn->bits.authneg) 2408 postsize = 0; 2409 else { 2410 /* figure out the size of the postfields */ 2411 postsize = (data->set.postfieldsize != -1)? 2412 data->set.postfieldsize: 2413 (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); 2414 } 2415 if(!data->req.upload_chunky) { 2416 /* We only set Content-Length and allow a custom Content-Length if 2417 we don't upload data chunked, as RFC2616 forbids us to set both 2418 kinds of headers (Transfer-Encoding: chunked and Content-Length) */ 2419 2420 if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) { 2421 /* we allow replacing this header if not during auth negotiation, 2422 although it isn't very wise to actually set your own */ 2423 result = Curl_add_bufferf(req_buffer, 2424 "Content-Length: %" FORMAT_OFF_T"\r\n", 2425 postsize); 2426 if(result) 2427 return result; 2428 } 2429 } 2430 2431 if(!Curl_checkheaders(data, "Content-Type:")) { 2432 result = Curl_add_bufferf(req_buffer, 2433 "Content-Type: application/" 2434 "x-www-form-urlencoded\r\n"); 2435 if(result) 2436 return result; 2437 } 2438 2439 /* For really small posts we don't use Expect: headers at all, and for 2440 the somewhat bigger ones we allow the app to disable it. Just make 2441 sure that the expect100header is always set to the preferred value 2442 here. */ 2443 ptr = Curl_checkheaders(data, "Expect:"); 2444 if(ptr) { 2445 data->state.expect100header = 2446 Curl_compareheader(ptr, "Expect:", "100-continue"); 2447 } 2448 else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) { 2449 result = expect100(data, conn, req_buffer); 2450 if(result) 2451 return result; 2452 } 2453 else 2454 data->state.expect100header = FALSE; 2455 2456 if(data->set.postfields) { 2457 2458 if(!data->state.expect100header && 2459 (postsize < MAX_INITIAL_POST_SIZE)) { 2460 /* if we don't use expect: 100 AND 2461 postsize is less than MAX_INITIAL_POST_SIZE 2462 2463 then append the post data to the HTTP request header. This limit 2464 is no magic limit but only set to prevent really huge POSTs to 2465 get the data duplicated with malloc() and family. */ 2466 2467 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ 2468 if(result) 2469 return result; 2470 2471 if(!data->req.upload_chunky) { 2472 /* We're not sending it 'chunked', append it to the request 2473 already now to reduce the number if send() calls */ 2474 result = Curl_add_buffer(req_buffer, data->set.postfields, 2475 (size_t)postsize); 2476 included_body = postsize; 2477 } 2478 else { 2479 /* Append the POST data chunky-style */ 2480 result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); 2481 if(CURLE_OK == result) 2482 result = Curl_add_buffer(req_buffer, data->set.postfields, 2483 (size_t)postsize); 2484 if(CURLE_OK == result) 2485 result = Curl_add_buffer(req_buffer, 2486 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); 2487 /* CR LF 0 CR LF CR LF */ 2488 included_body = postsize + 7; 2489 } 2490 if(result) 2491 return result; 2492 /* Make sure the progress information is accurate */ 2493 Curl_pgrsSetUploadSize(data, postsize); 2494 } 2495 else { 2496 /* A huge POST coming up, do data separate from the request */ 2497 http->postsize = postsize; 2498 http->postdata = data->set.postfields; 2499 2500 http->sending = HTTPSEND_BODY; 2501 2502 conn->fread_func = (curl_read_callback)readmoredata; 2503 conn->fread_in = (void *)conn; 2504 2505 /* set the upload size to the progress meter */ 2506 Curl_pgrsSetUploadSize(data, http->postsize); 2507 2508 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ 2509 if(result) 2510 return result; 2511 } 2512 } 2513 else { 2514 result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ 2515 if(result) 2516 return result; 2517 2518 if(data->req.upload_chunky && conn->bits.authneg) { 2519 /* Chunky upload is selected and we're negotiating auth still, send 2520 end-of-data only */ 2521 result = Curl_add_buffer(req_buffer, 2522 "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); 2523 /* CR LF 0 CR LF CR LF */ 2524 if(result) 2525 return result; 2526 } 2527 2528 else if(data->set.postfieldsize) { 2529 /* set the upload size to the progress meter */ 2530 Curl_pgrsSetUploadSize(data, postsize?postsize:-1); 2531 2532 /* set the pointer to mark that we will send the post body using the 2533 read callback, but only if we're not in authenticate 2534 negotiation */ 2535 if(!conn->bits.authneg) { 2536 http->postdata = (char *)&http->postdata; 2537 http->postsize = postsize; 2538 } 2539 } 2540 } 2541 /* issue the request */ 2542 result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 2543 (size_t)included_body, FIRSTSOCKET); 2544 2545 if(result) 2546 failf(data, "Failed sending HTTP POST request"); 2547 else 2548 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, 2549 &http->readbytecount, http->postdata?FIRSTSOCKET:-1, 2550 http->postdata?&http->writebytecount:NULL); 2551 break; 2552 2553 default: 2554 result = Curl_add_buffer(req_buffer, "\r\n", 2); 2555 if(result) 2556 return result; 2557 2558 /* issue the request */ 2559 result = Curl_add_buffer_send(req_buffer, conn, 2560 &data->info.request_size, 0, FIRSTSOCKET); 2561 2562 if(result) 2563 failf(data, "Failed sending HTTP request"); 2564 else 2565 /* HTTP GET/HEAD download: */ 2566 Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, 2567 http->postdata?FIRSTSOCKET:-1, 2568 http->postdata?&http->writebytecount:NULL); 2569 } 2570 if(result) 2571 return result; 2572 2573 if(http->writebytecount) { 2574 /* if a request-body has been sent off, we make sure this progress is noted 2575 properly */ 2576 Curl_pgrsSetUploadCounter(data, http->writebytecount); 2577 if(Curl_pgrsUpdate(conn)) 2578 result = CURLE_ABORTED_BY_CALLBACK; 2579 2580 if(http->writebytecount >= postsize) { 2581 /* already sent the entire request body, mark the "upload" as 2582 complete */ 2583 infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of " 2584 "%" FORMAT_OFF_T " bytes\n", 2585 http->writebytecount, postsize); 2586 data->req.upload_done = TRUE; 2587 data->req.keepon &= ~KEEP_SEND; /* we're done writing */ 2588 data->req.exp100 = EXP100_SEND_DATA; /* already sent */ 2589 } 2590 } 2591 2592 return result; 2593} 2594 2595/* 2596 * checkhttpprefix() 2597 * 2598 * Returns TRUE if member of the list matches prefix of string 2599 */ 2600static bool 2601checkhttpprefix(struct SessionHandle *data, 2602 const char *s) 2603{ 2604 struct curl_slist *head = data->set.http200aliases; 2605 bool rc = FALSE; 2606#ifdef CURL_DOES_CONVERSIONS 2607 /* convert from the network encoding using a scratch area */ 2608 char *scratch = strdup(s); 2609 if(NULL == scratch) { 2610 failf (data, "Failed to allocate memory for conversion!"); 2611 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ 2612 } 2613 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { 2614 /* Curl_convert_from_network calls failf if unsuccessful */ 2615 free(scratch); 2616 return FALSE; /* can't return CURLE_foobar so return FALSE */ 2617 } 2618 s = scratch; 2619#endif /* CURL_DOES_CONVERSIONS */ 2620 2621 while(head) { 2622 if(checkprefix(head->data, s)) { 2623 rc = TRUE; 2624 break; 2625 } 2626 head = head->next; 2627 } 2628 2629 if(!rc && (checkprefix("HTTP/", s))) 2630 rc = TRUE; 2631 2632#ifdef CURL_DOES_CONVERSIONS 2633 free(scratch); 2634#endif /* CURL_DOES_CONVERSIONS */ 2635 return rc; 2636} 2637 2638#ifndef CURL_DISABLE_RTSP 2639static bool 2640checkrtspprefix(struct SessionHandle *data, 2641 const char *s) 2642{ 2643 2644#ifdef CURL_DOES_CONVERSIONS 2645 /* convert from the network encoding using a scratch area */ 2646 char *scratch = strdup(s); 2647 if(NULL == scratch) { 2648 failf (data, "Failed to allocate memory for conversion!"); 2649 return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ 2650 } 2651 if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { 2652 /* Curl_convert_from_network calls failf if unsuccessful */ 2653 free(scratch); 2654 return FALSE; /* can't return CURLE_foobar so return FALSE */ 2655 } 2656 s = scratch; 2657#else 2658 (void)data; /* unused */ 2659#endif /* CURL_DOES_CONVERSIONS */ 2660 if(checkprefix("RTSP/", s)) 2661 return TRUE; 2662 else 2663 return FALSE; 2664} 2665#endif /* CURL_DISABLE_RTSP */ 2666 2667static bool 2668checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, 2669 const char *s) 2670{ 2671#ifndef CURL_DISABLE_RTSP 2672 if(conn->handler->protocol & CURLPROTO_RTSP) 2673 return checkrtspprefix(data, s); 2674#else 2675 (void)conn; 2676#endif /* CURL_DISABLE_RTSP */ 2677 2678 return checkhttpprefix(data, s); 2679} 2680 2681/* 2682 * header_append() copies a chunk of data to the end of the already received 2683 * header. We make sure that the full string fit in the allocated header 2684 * buffer, or else we enlarge it. 2685 */ 2686static CURLcode header_append(struct SessionHandle *data, 2687 struct SingleRequest *k, 2688 size_t length) 2689{ 2690 if(k->hbuflen + length >= data->state.headersize) { 2691 /* We enlarge the header buffer as it is too small */ 2692 char *newbuff; 2693 size_t hbufp_index; 2694 size_t newsize; 2695 2696 if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) { 2697 /* The reason to have a max limit for this is to avoid the risk of a bad 2698 server feeding libcurl with a never-ending header that will cause 2699 reallocs infinitely */ 2700 failf (data, "Avoided giant realloc for header (max is %d)!", 2701 CURL_MAX_HTTP_HEADER); 2702 return CURLE_OUT_OF_MEMORY; 2703 } 2704 2705 newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2); 2706 hbufp_index = k->hbufp - data->state.headerbuff; 2707 newbuff = realloc(data->state.headerbuff, newsize); 2708 if(!newbuff) { 2709 failf (data, "Failed to alloc memory for big header!"); 2710 return CURLE_OUT_OF_MEMORY; 2711 } 2712 data->state.headersize=newsize; 2713 data->state.headerbuff = newbuff; 2714 k->hbufp = data->state.headerbuff + hbufp_index; 2715 } 2716 memcpy(k->hbufp, k->str_start, length); 2717 k->hbufp += length; 2718 k->hbuflen += length; 2719 *k->hbufp = 0; 2720 2721 return CURLE_OK; 2722} 2723 2724 2725/* 2726 * Read any HTTP header lines from the server and pass them to the client app. 2727 */ 2728CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, 2729 struct connectdata *conn, 2730 ssize_t *nread, 2731 bool *stop_reading) 2732{ 2733 CURLcode result; 2734 struct SingleRequest *k = &data->req; 2735 2736 /* header line within buffer loop */ 2737 do { 2738 size_t rest_length; 2739 size_t full_length; 2740 int writetype; 2741 2742 /* str_start is start of line within buf */ 2743 k->str_start = k->str; 2744 2745 /* data is in network encoding so use 0x0a instead of '\n' */ 2746 k->end_ptr = memchr(k->str_start, 0x0a, *nread); 2747 2748 if(!k->end_ptr) { 2749 /* Not a complete header line within buffer, append the data to 2750 the end of the headerbuff. */ 2751 result = header_append(data, k, *nread); 2752 if(result) 2753 return result; 2754 2755 if(!k->headerline && (k->hbuflen>5)) { 2756 /* make a first check that this looks like a protocol header */ 2757 if(!checkprotoprefix(data, conn, data->state.headerbuff)) { 2758 /* this is not the beginning of a protocol first header line */ 2759 k->header = FALSE; 2760 k->badheader = HEADER_ALLBAD; 2761 break; 2762 } 2763 } 2764 2765 break; /* read more and try again */ 2766 } 2767 2768 /* decrease the size of the remaining (supposed) header line */ 2769 rest_length = (k->end_ptr - k->str)+1; 2770 *nread -= (ssize_t)rest_length; 2771 2772 k->str = k->end_ptr + 1; /* move past new line */ 2773 2774 full_length = k->str - k->str_start; 2775 2776 result = header_append(data, k, full_length); 2777 if(result) 2778 return result; 2779 2780 k->end_ptr = k->hbufp; 2781 k->p = data->state.headerbuff; 2782 2783 /**** 2784 * We now have a FULL header line that p points to 2785 *****/ 2786 2787 if(!k->headerline) { 2788 /* the first read header */ 2789 if((k->hbuflen>5) && 2790 !checkprotoprefix(data, conn, data->state.headerbuff)) { 2791 /* this is not the beginning of a protocol first header line */ 2792 k->header = FALSE; 2793 if(*nread) 2794 /* since there's more, this is a partial bad header */ 2795 k->badheader = HEADER_PARTHEADER; 2796 else { 2797 /* this was all we read so it's all a bad header */ 2798 k->badheader = HEADER_ALLBAD; 2799 *nread = (ssize_t)rest_length; 2800 } 2801 break; 2802 } 2803 } 2804 2805 /* headers are in network encoding so 2806 use 0x0a and 0x0d instead of '\n' and '\r' */ 2807 if((0x0a == *k->p) || (0x0d == *k->p)) { 2808 size_t headerlen; 2809 /* Zero-length header line means end of headers! */ 2810 2811#ifdef CURL_DOES_CONVERSIONS 2812 if(0x0d == *k->p) { 2813 *k->p = '\r'; /* replace with CR in host encoding */ 2814 k->p++; /* pass the CR byte */ 2815 } 2816 if(0x0a == *k->p) { 2817 *k->p = '\n'; /* replace with LF in host encoding */ 2818 k->p++; /* pass the LF byte */ 2819 } 2820#else 2821 if('\r' == *k->p) 2822 k->p++; /* pass the \r byte */ 2823 if('\n' == *k->p) 2824 k->p++; /* pass the \n byte */ 2825#endif /* CURL_DOES_CONVERSIONS */ 2826 2827 if(100 <= k->httpcode && 199 >= k->httpcode) { 2828 /* 2829 * We have made a HTTP PUT or POST and this is 1.1-lingo 2830 * that tells us that the server is OK with this and ready 2831 * to receive the data. 2832 * However, we'll get more headers now so we must get 2833 * back into the header-parsing state! 2834 */ 2835 k->header = TRUE; 2836 k->headerline = 0; /* restart the header line counter */ 2837 2838 /* if we did wait for this do enable write now! */ 2839 if(k->exp100) { 2840 k->exp100 = EXP100_SEND_DATA; 2841 k->keepon |= KEEP_SEND; 2842 } 2843 } 2844 else { 2845 k->header = FALSE; /* no more header to parse! */ 2846 2847 if((k->size == -1) && !k->chunk && !conn->bits.close && 2848 (conn->httpversion >= 11) && 2849 !(conn->handler->protocol & CURLPROTO_RTSP)) { 2850 /* On HTTP 1.1, when connection is not to get closed, but no 2851 Content-Length nor Content-Encoding chunked have been 2852 received, according to RFC2616 section 4.4 point 5, we 2853 assume that the server will close the connection to 2854 signal the end of the document. */ 2855 infof(data, "no chunk, no close, no size. Assume close to " 2856 "signal end\n"); 2857 conn->bits.close = TRUE; 2858 } 2859 } 2860 2861 /* 2862 * When all the headers have been parsed, see if we should give 2863 * up and return an error. 2864 */ 2865 if(http_should_fail(conn)) { 2866 failf (data, "The requested URL returned error: %d", 2867 k->httpcode); 2868 return CURLE_HTTP_RETURNED_ERROR; 2869 } 2870 2871 /* now, only output this if the header AND body are requested: 2872 */ 2873 writetype = CLIENTWRITE_HEADER; 2874 if(data->set.include_header) 2875 writetype |= CLIENTWRITE_BODY; 2876 2877 headerlen = k->p - data->state.headerbuff; 2878 2879 result = Curl_client_write(conn, writetype, 2880 data->state.headerbuff, 2881 headerlen); 2882 if(result) 2883 return result; 2884 2885 data->info.header_size += (long)headerlen; 2886 data->req.headerbytecount += (long)headerlen; 2887 2888 data->req.deductheadercount = 2889 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; 2890 2891 if(!*stop_reading) { 2892 /* Curl_http_auth_act() checks what authentication methods 2893 * that are available and decides which one (if any) to 2894 * use. It will set 'newurl' if an auth method was picked. */ 2895 result = Curl_http_auth_act(conn); 2896 2897 if(result) 2898 return result; 2899 2900 if(k->httpcode >= 300) { 2901 if((!conn->bits.authneg) && !conn->bits.close && 2902 !conn->bits.rewindaftersend) { 2903 /* 2904 * General treatment of errors when about to send data. Including : 2905 * "417 Expectation Failed", while waiting for 100-continue. 2906 * 2907 * The check for close above is done simply because of something 2908 * else has already deemed the connection to get closed then 2909 * something else should've considered the big picture and we 2910 * avoid this check. 2911 * 2912 * rewindaftersend indicates that something has told libcurl to 2913 * continue sending even if it gets discarded 2914 */ 2915 2916 switch(data->set.httpreq) { 2917 case HTTPREQ_PUT: 2918 case HTTPREQ_POST: 2919 case HTTPREQ_POST_FORM: 2920 /* We got an error response. If this happened before the whole 2921 * request body has been sent we stop sending and mark the 2922 * connection for closure after we've read the entire response. 2923 */ 2924 if(!k->upload_done) { 2925 infof(data, "HTTP error before end of send, stop sending\n"); 2926 conn->bits.close = TRUE; /* close after this */ 2927 k->upload_done = TRUE; 2928 k->keepon &= ~KEEP_SEND; /* don't send */ 2929 if(data->state.expect100header) 2930 k->exp100 = EXP100_FAILED; 2931 } 2932 break; 2933 2934 default: /* default label present to avoid compiler warnings */ 2935 break; 2936 } 2937 } 2938 } 2939 2940 if(conn->bits.rewindaftersend) { 2941 /* We rewind after a complete send, so thus we continue 2942 sending now */ 2943 infof(data, "Keep sending data to get tossed away!\n"); 2944 k->keepon |= KEEP_SEND; 2945 } 2946 } 2947 2948 if(!k->header) { 2949 /* 2950 * really end-of-headers. 2951 * 2952 * If we requested a "no body", this is a good time to get 2953 * out and return home. 2954 */ 2955 if(data->set.opt_no_body) 2956 *stop_reading = TRUE; 2957 else { 2958 /* If we know the expected size of this document, we set the 2959 maximum download size to the size of the expected 2960 document or else, we won't know when to stop reading! 2961 2962 Note that we set the download maximum even if we read a 2963 "Connection: close" header, to make sure that 2964 "Content-Length: 0" still prevents us from attempting to 2965 read the (missing) response-body. 2966 */ 2967 /* According to RFC2616 section 4.4, we MUST ignore 2968 Content-Length: headers if we are now receiving data 2969 using chunked Transfer-Encoding. 2970 */ 2971 if(k->chunk) 2972 k->maxdownload = k->size = -1; 2973 } 2974 if(-1 != k->size) { 2975 /* We do this operation even if no_body is true, since this 2976 data might be retrieved later with curl_easy_getinfo() 2977 and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ 2978 2979 Curl_pgrsSetDownloadSize(data, k->size); 2980 k->maxdownload = k->size; 2981 } 2982 2983 /* If max download size is *zero* (nothing) we already 2984 have nothing and can safely return ok now! */ 2985 if(0 == k->maxdownload) 2986 *stop_reading = TRUE; 2987 2988 if(*stop_reading) { 2989 /* we make sure that this socket isn't read more now */ 2990 k->keepon &= ~KEEP_RECV; 2991 } 2992 2993 if(data->set.verbose) 2994 Curl_debug(data, CURLINFO_HEADER_IN, 2995 k->str_start, headerlen, conn); 2996 break; /* exit header line loop */ 2997 } 2998 2999 /* We continue reading headers, so reset the line-based 3000 header parsing variables hbufp && hbuflen */ 3001 k->hbufp = data->state.headerbuff; 3002 k->hbuflen = 0; 3003 continue; 3004 } 3005 3006 /* 3007 * Checks for special headers coming up. 3008 */ 3009 3010 if(!k->headerline++) { 3011 /* This is the first header, it MUST be the error code line 3012 or else we consider this to be the body right away! */ 3013 int httpversion_major; 3014 int rtspversion_major; 3015 int nc = 0; 3016#ifdef CURL_DOES_CONVERSIONS 3017#define HEADER1 scratch 3018#define SCRATCHSIZE 21 3019 CURLcode res; 3020 char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */ 3021 /* We can't really convert this yet because we 3022 don't know if it's the 1st header line or the body. 3023 So we do a partial conversion into a scratch area, 3024 leaving the data at k->p as-is. 3025 */ 3026 strncpy(&scratch[0], k->p, SCRATCHSIZE); 3027 scratch[SCRATCHSIZE] = 0; /* null terminate */ 3028 res = Curl_convert_from_network(data, 3029 &scratch[0], 3030 SCRATCHSIZE); 3031 if(res) 3032 /* Curl_convert_from_network calls failf if unsuccessful */ 3033 return res; 3034#else 3035#define HEADER1 k->p /* no conversion needed, just use k->p */ 3036#endif /* CURL_DOES_CONVERSIONS */ 3037 3038 if(conn->handler->protocol & CURLPROTO_HTTP) { 3039 nc = sscanf(HEADER1, 3040 " HTTP/%d.%d %3d", 3041 &httpversion_major, 3042 &conn->httpversion, 3043 &k->httpcode); 3044 if(nc==3) { 3045 conn->httpversion += 10 * httpversion_major; 3046 } 3047 else { 3048 /* this is the real world, not a Nirvana 3049 NCSA 1.5.x returns this crap when asked for HTTP/1.1 3050 */ 3051 nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); 3052 conn->httpversion = 10; 3053 3054 /* If user has set option HTTP200ALIASES, 3055 compare header line against list of aliases 3056 */ 3057 if(!nc) { 3058 if(checkhttpprefix(data, k->p)) { 3059 nc = 1; 3060 k->httpcode = 200; 3061 conn->httpversion = 10; 3062 } 3063 } 3064 } 3065 } 3066 else if(conn->handler->protocol & CURLPROTO_RTSP) { 3067 nc = sscanf(HEADER1, 3068 " RTSP/%d.%d %3d", 3069 &rtspversion_major, 3070 &conn->rtspversion, 3071 &k->httpcode); 3072 if(nc==3) { 3073 conn->rtspversion += 10 * rtspversion_major; 3074 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ 3075 } 3076 else { 3077 /* TODO: do we care about the other cases here? */ 3078 nc = 0; 3079 } 3080 } 3081 3082 if(nc) { 3083 data->info.httpcode = k->httpcode; 3084 3085 data->info.httpversion = conn->httpversion; 3086 if(!data->state.httpversion || 3087 data->state.httpversion > conn->httpversion) 3088 /* store the lowest server version we encounter */ 3089 data->state.httpversion = conn->httpversion; 3090 3091 /* 3092 * This code executes as part of processing the header. As a 3093 * result, it's not totally clear how to interpret the 3094 * response code yet as that depends on what other headers may 3095 * be present. 401 and 407 may be errors, but may be OK 3096 * depending on how authentication is working. Other codes 3097 * are definitely errors, so give up here. 3098 */ 3099 if(data->set.http_fail_on_error && (k->httpcode >= 400) && 3100 ((k->httpcode != 401) || !conn->bits.user_passwd) && 3101 ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { 3102 3103 if(data->state.resume_from && 3104 (data->set.httpreq==HTTPREQ_GET) && 3105 (k->httpcode == 416)) { 3106 /* "Requested Range Not Satisfiable", just proceed and 3107 pretend this is no error */ 3108 } 3109 else { 3110 /* serious error, go home! */ 3111 failf (data, "The requested URL returned error: %d", 3112 k->httpcode); 3113 return CURLE_HTTP_RETURNED_ERROR; 3114 } 3115 } 3116 3117 if(conn->httpversion == 10) { 3118 /* Default action for HTTP/1.0 must be to close, unless 3119 we get one of those fancy headers that tell us the 3120 server keeps it open for us! */ 3121 infof(data, "HTTP 1.0, assume close after body\n"); 3122 conn->bits.close = TRUE; 3123 } 3124 else if(conn->httpversion >= 11 && 3125 !conn->bits.close) { 3126 /* If HTTP version is >= 1.1 and connection is persistent 3127 server supports pipelining. */ 3128 DEBUGF(infof(data, 3129 "HTTP 1.1 or later with persistent connection, " 3130 "pipelining supported\n")); 3131 conn->server_supports_pipelining = TRUE; 3132 } 3133 3134 switch(k->httpcode) { 3135 case 204: 3136 /* (quote from RFC2616, section 10.2.5): The server has 3137 * fulfilled the request but does not need to return an 3138 * entity-body ... The 204 response MUST NOT include a 3139 * message-body, and thus is always terminated by the first 3140 * empty line after the header fields. */ 3141 /* FALLTHROUGH */ 3142 case 304: 3143 /* (quote from RFC2616, section 10.3.5): The 304 response 3144 * MUST NOT contain a message-body, and thus is always 3145 * terminated by the first empty line after the header 3146 * fields. */ 3147 if(data->set.timecondition) 3148 data->info.timecond = TRUE; 3149 k->size=0; 3150 k->maxdownload=0; 3151 k->ignorecl = TRUE; /* ignore Content-Length headers */ 3152 break; 3153 default: 3154 /* nothing */ 3155 break; 3156 } 3157 } 3158 else { 3159 k->header = FALSE; /* this is not a header line */ 3160 break; 3161 } 3162 } 3163 3164 result = Curl_convert_from_network(data, k->p, strlen(k->p)); 3165 /* Curl_convert_from_network calls failf if unsuccessful */ 3166 if(result) 3167 return result; 3168 3169 /* Check for Content-Length: header lines to get size */ 3170 if(!k->ignorecl && !data->set.ignorecl && 3171 checkprefix("Content-Length:", k->p)) { 3172 curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10); 3173 if(data->set.max_filesize && 3174 contentlength > data->set.max_filesize) { 3175 failf(data, "Maximum file size exceeded"); 3176 return CURLE_FILESIZE_EXCEEDED; 3177 } 3178 if(contentlength >= 0) { 3179 k->size = contentlength; 3180 k->maxdownload = k->size; 3181 /* we set the progress download size already at this point 3182 just to make it easier for apps/callbacks to extract this 3183 info as soon as possible */ 3184 Curl_pgrsSetDownloadSize(data, k->size); 3185 } 3186 else { 3187 /* Negative Content-Length is really odd, and we know it 3188 happens for example when older Apache servers send large 3189 files */ 3190 conn->bits.close = TRUE; 3191 infof(data, "Negative content-length: %" FORMAT_OFF_T 3192 ", closing after transfer\n", contentlength); 3193 } 3194 } 3195 /* check for Content-Type: header lines to get the MIME-type */ 3196 else if(checkprefix("Content-Type:", k->p)) { 3197 char *contenttype = copy_header_value(k->p); 3198 if(!contenttype) 3199 return CURLE_OUT_OF_MEMORY; 3200 if(!*contenttype) 3201 /* ignore empty data */ 3202 free(contenttype); 3203 else { 3204 Curl_safefree(data->info.contenttype); 3205 data->info.contenttype = contenttype; 3206 } 3207 } 3208 else if((conn->httpversion == 10) && 3209 conn->bits.httpproxy && 3210 Curl_compareheader(k->p, 3211 "Proxy-Connection:", "keep-alive")) { 3212 /* 3213 * When a HTTP/1.0 reply comes when using a proxy, the 3214 * 'Proxy-Connection: keep-alive' line tells us the 3215 * connection will be kept alive for our pleasure. 3216 * Default action for 1.0 is to close. 3217 */ 3218 conn->bits.close = FALSE; /* don't close when done */ 3219 infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); 3220 } 3221 else if((conn->httpversion == 11) && 3222 conn->bits.httpproxy && 3223 Curl_compareheader(k->p, 3224 "Proxy-Connection:", "close")) { 3225 /* 3226 * We get a HTTP/1.1 response from a proxy and it says it'll 3227 * close down after this transfer. 3228 */ 3229 conn->bits.close = TRUE; /* close when done */ 3230 infof(data, "HTTP/1.1 proxy connection set close!\n"); 3231 } 3232 else if((conn->httpversion == 10) && 3233 Curl_compareheader(k->p, "Connection:", "keep-alive")) { 3234 /* 3235 * A HTTP/1.0 reply with the 'Connection: keep-alive' line 3236 * tells us the connection will be kept alive for our 3237 * pleasure. Default action for 1.0 is to close. 3238 * 3239 * [RFC2068, section 19.7.1] */ 3240 conn->bits.close = FALSE; /* don't close when done */ 3241 infof(data, "HTTP/1.0 connection set to keep alive!\n"); 3242 } 3243 else if(Curl_compareheader(k->p, "Connection:", "close")) { 3244 /* 3245 * [RFC 2616, section 8.1.2.1] 3246 * "Connection: close" is HTTP/1.1 language and means that 3247 * the connection will close when this request has been 3248 * served. 3249 */ 3250 conn->bits.close = TRUE; /* close when done */ 3251 } 3252 else if(checkprefix("Transfer-Encoding:", k->p)) { 3253 /* One or more encodings. We check for chunked and/or a compression 3254 algorithm. */ 3255 /* 3256 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding 3257 * means that the server will send a series of "chunks". Each 3258 * chunk starts with line with info (including size of the 3259 * coming block) (terminated with CRLF), then a block of data 3260 * with the previously mentioned size. There can be any amount 3261 * of chunks, and a chunk-data set to zero signals the 3262 * end-of-chunks. */ 3263 3264 char *start; 3265 3266 /* Find the first non-space letter */ 3267 start = k->p + 18; 3268 3269 for(;;) { 3270 /* skip whitespaces and commas */ 3271 while(*start && (ISSPACE(*start) || (*start == ','))) 3272 start++; 3273 3274 if(checkprefix("chunked", start)) { 3275 k->chunk = TRUE; /* chunks coming our way */ 3276 3277 /* init our chunky engine */ 3278 Curl_httpchunk_init(conn); 3279 3280 start += 7; 3281 } 3282 3283 if(k->auto_decoding) 3284 /* TODO: we only support the first mentioned compression for now */ 3285 break; 3286 3287 if(checkprefix("identity", start)) { 3288 k->auto_decoding = IDENTITY; 3289 start += 8; 3290 } 3291 else if(checkprefix("deflate", start)) { 3292 k->auto_decoding = DEFLATE; 3293 start += 7; 3294 } 3295 else if(checkprefix("gzip", start)) { 3296 k->auto_decoding = GZIP; 3297 start += 4; 3298 } 3299 else if(checkprefix("x-gzip", start)) { 3300 k->auto_decoding = GZIP; 3301 start += 6; 3302 } 3303 else if(checkprefix("compress", start)) { 3304 k->auto_decoding = COMPRESS; 3305 start += 8; 3306 } 3307 else if(checkprefix("x-compress", start)) { 3308 k->auto_decoding = COMPRESS; 3309 start += 10; 3310 } 3311 else 3312 /* unknown! */ 3313 break; 3314 3315 } 3316 3317 } 3318 else if(checkprefix("Content-Encoding:", k->p) && 3319 data->set.str[STRING_ENCODING]) { 3320 /* 3321 * Process Content-Encoding. Look for the values: identity, 3322 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and 3323 * x-compress are the same as gzip and compress. (Sec 3.5 RFC 3324 * 2616). zlib cannot handle compress. However, errors are 3325 * handled further down when the response body is processed 3326 */ 3327 char *start; 3328 3329 /* Find the first non-space letter */ 3330 start = k->p + 17; 3331 while(*start && ISSPACE(*start)) 3332 start++; 3333 3334 /* Record the content-encoding for later use */ 3335 if(checkprefix("identity", start)) 3336 k->auto_decoding = IDENTITY; 3337 else if(checkprefix("deflate", start)) 3338 k->auto_decoding = DEFLATE; 3339 else if(checkprefix("gzip", start) 3340 || checkprefix("x-gzip", start)) 3341 k->auto_decoding = GZIP; 3342 else if(checkprefix("compress", start) 3343 || checkprefix("x-compress", start)) 3344 k->auto_decoding = COMPRESS; 3345 } 3346 else if(checkprefix("Content-Range:", k->p)) { 3347 /* Content-Range: bytes [num]- 3348 Content-Range: bytes: [num]- 3349 Content-Range: [num]- 3350 3351 The second format was added since Sun's webserver 3352 JavaWebServer/1.1.1 obviously sends the header this way! 3353 The third added since some servers use that! 3354 */ 3355 3356 char *ptr = k->p + 14; 3357 3358 /* Move forward until first digit */ 3359 while(*ptr && !ISDIGIT(*ptr)) 3360 ptr++; 3361 3362 k->offset = curlx_strtoofft(ptr, NULL, 10); 3363 3364 if(data->state.resume_from == k->offset) 3365 /* we asked for a resume and we got it */ 3366 k->content_range = TRUE; 3367 } 3368#if !defined(CURL_DISABLE_COOKIES) 3369 else if(data->cookies && 3370 checkprefix("Set-Cookie:", k->p)) { 3371 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, 3372 CURL_LOCK_ACCESS_SINGLE); 3373 Curl_cookie_add(data, 3374 data->cookies, TRUE, k->p+11, 3375 /* If there is a custom-set Host: name, use it 3376 here, or else use real peer host name. */ 3377 conn->allocptr.cookiehost? 3378 conn->allocptr.cookiehost:conn->host.name, 3379 data->state.path); 3380 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 3381 } 3382#endif 3383 else if(checkprefix("Last-Modified:", k->p) && 3384 (data->set.timecondition || data->set.get_filetime) ) { 3385 time_t secs=time(NULL); 3386 k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), 3387 &secs); 3388 if(data->set.get_filetime) 3389 data->info.filetime = (long)k->timeofdoc; 3390 } 3391 else if((checkprefix("WWW-Authenticate:", k->p) && 3392 (401 == k->httpcode)) || 3393 (checkprefix("Proxy-authenticate:", k->p) && 3394 (407 == k->httpcode))) { 3395 result = Curl_http_input_auth(conn, k->httpcode, k->p); 3396 if(result) 3397 return result; 3398 } 3399 else if((k->httpcode >= 300 && k->httpcode < 400) && 3400 checkprefix("Location:", k->p) && 3401 !data->req.location) { 3402 /* this is the URL that the server advises us to use instead */ 3403 char *location = copy_header_value(k->p); 3404 if(!location) 3405 return CURLE_OUT_OF_MEMORY; 3406 if(!*location) 3407 /* ignore empty data */ 3408 free(location); 3409 else { 3410 data->req.location = location; 3411 3412 if(data->set.http_follow_location) { 3413 DEBUGASSERT(!data->req.newurl); 3414 data->req.newurl = strdup(data->req.location); /* clone */ 3415 if(!data->req.newurl) 3416 return CURLE_OUT_OF_MEMORY; 3417 3418 /* some cases of POST and PUT etc needs to rewind the data 3419 stream at this point */ 3420 result = http_perhapsrewind(conn); 3421 if(result) 3422 return result; 3423 } 3424 } 3425 } 3426 else if(conn->handler->protocol & CURLPROTO_RTSP) { 3427 result = Curl_rtsp_parseheader(conn, k->p); 3428 if(result) 3429 return result; 3430 } 3431 3432 /* 3433 * End of header-checks. Write them to the client. 3434 */ 3435 3436 writetype = CLIENTWRITE_HEADER; 3437 if(data->set.include_header) 3438 writetype |= CLIENTWRITE_BODY; 3439 3440 if(data->set.verbose) 3441 Curl_debug(data, CURLINFO_HEADER_IN, 3442 k->p, (size_t)k->hbuflen, conn); 3443 3444 result = Curl_client_write(conn, writetype, k->p, k->hbuflen); 3445 if(result) 3446 return result; 3447 3448 data->info.header_size += (long)k->hbuflen; 3449 data->req.headerbytecount += (long)k->hbuflen; 3450 3451 /* reset hbufp pointer && hbuflen */ 3452 k->hbufp = data->state.headerbuff; 3453 k->hbuflen = 0; 3454 } 3455 while(!*stop_reading && *k->str); /* header line within buffer */ 3456 3457 /* We might have reached the end of the header part here, but 3458 there might be a non-header part left in the end of the read 3459 buffer. */ 3460 3461 return CURLE_OK; 3462} 3463 3464#endif /* CURL_DISABLE_HTTP */ 3465