X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fhttp.c;h=e4b9d8b4b753361f1baa8fa91825c3371473c388;hb=88d478478059f53e6de0d1267c3a1e6b02c4273f;hp=8db86cd84df94de218ad35e87a760f3ac00a51e9;hpb=e9bdad71c8277e20607fa1eaf0027d53a0dc1f37;p=platform%2Fupstream%2Fcurl.git diff --git a/lib/http.c b/lib/http.c index 8db86cd..e4b9d8b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -53,6 +53,7 @@ #include "progress.h" #include "curl_base64.h" #include "cookie.h" +#include "strequal.h" #include "vauth/vauth.h" #include "vtls/vtls.h" #include "http_digest.h" @@ -67,7 +68,7 @@ #include "parsedate.h" /* for the week day and month names */ #include "strtoofft.h" #include "multiif.h" -#include "strcase.h" +#include "rawstr.h" #include "content_encoding.h" #include "http_proxy.h" #include "warnless.h" @@ -76,7 +77,6 @@ #include "pipeline.h" #include "http2.h" #include "connect.h" -#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -182,7 +182,7 @@ char *Curl_checkheaders(const struct connectdata *conn, struct Curl_easy *data = conn->data; for(head = data->set.headers;head; head=head->next) { - if(strncasecompare(head->data, thisheader, thislen)) + if(Curl_raw_nequal(head->data, thisheader, thislen)) return head->data; } @@ -208,7 +208,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn, for(head = (conn->bits.proxy && data->set.sep_headers) ? data->set.proxyheaders : data->set.headers; head; head=head->next) { - if(strncasecompare(head->data, thisheader, thislen)) + if(Curl_raw_nequal(head->data, thisheader, thislen)) return head->data; } @@ -288,8 +288,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) if(proxy) { userp = &conn->allocptr.proxyuserpwd; - user = conn->http_proxy.user; - pwd = conn->http_proxy.passwd; + user = conn->proxyuser; + pwd = conn->proxypasswd; } else { userp = &conn->allocptr.userpwd; @@ -297,8 +297,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) pwd = conn->passwd; } - snprintf(data->state.buffer, CURL_BUFSIZE(data->set.buffer_size), - "%s:%s", user, pwd); + snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); result = Curl_base64_encode(data, data->state.buffer, strlen(data->state.buffer), @@ -546,8 +545,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } } if(http_should_fail(conn)) { - failf(data, "The requested URL returned error: %d", - data->req.httpcode); + failf (data, "The requested URL returned error: %d", + data->req.httpcode); result = CURLE_HTTP_RETURNED_ERROR; } @@ -643,7 +642,7 @@ output_auth_headers(struct connectdata *conn, if(auth) { infof(data, "%s auth using %s with user '%s'\n", proxy ? "Proxy" : "Server", auth, - proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : + proxy ? (conn->proxyuser ? conn->proxyuser : "") : (conn->user ? conn->user : "")); authstatus->multi = (!authstatus->done) ? TRUE : FALSE; } @@ -727,7 +726,7 @@ Curl_http_output_auth(struct connectdata *conn, conn->bits.netrc || !data->state.first_host || data->set.http_disable_hostname_check_before_authentication || - strcasecompare(data->state.first_host, conn->host.name)) { + Curl_raw_equal(data->state.first_host, conn->host.name)) { result = output_auth_headers(conn, authhost, request, path, FALSE); } else @@ -841,11 +840,9 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, auth += strlen("NTLM"); while(*auth && ISSPACE(*auth)) auth++; - if(*auth) { - conn->challenge_header = strdup(auth); - if(!conn->challenge_header) + if(*auth) + if((conn->challenge_header = strdup(auth)) == NULL) return CURLE_OUT_OF_MEMORY; - } } } #endif @@ -1102,9 +1099,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, return result; } - if((conn->handler->flags & PROTOPT_SSL || - conn->http_proxy.proxytype == CURLPROXY_HTTPS) - && conn->httpversion != 20) { + if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that @@ -1261,13 +1256,14 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) if(in->buffer) /* we have a buffer, enlarge the existing one */ - new_rb = Curl_saferealloc(in->buffer, new_size); + new_rb = realloc(in->buffer, new_size); else /* create a new buffer */ new_rb = malloc(new_size); if(!new_rb) { /* If we failed, we cleanup the whole buffer and return error */ + Curl_safefree(in->buffer); free(in); return CURLE_OUT_OF_MEMORY; } @@ -1309,7 +1305,7 @@ Curl_compareheader(const char *headerline, /* line to check */ const char *start; const char *end; - if(!strncasecompare(headerline, header, hlen)) + if(!Curl_raw_nequal(headerline, header, hlen)) return FALSE; /* doesn't start with header */ /* pass the header */ @@ -1335,7 +1331,7 @@ Curl_compareheader(const char *headerline, /* line to check */ /* find the content string in the rest of the line */ for(;len>=clen;len--, start++) { - if(strncasecompare(start, content, clen)) + if(Curl_raw_nequal(start, content, clen)) return TRUE; /* match! */ } @@ -1355,13 +1351,10 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) connkeep(conn, "HTTP default"); /* the CONNECT procedure might not have been completed */ - result = Curl_proxy_connect(conn, FIRSTSOCKET); + result = Curl_proxy_connect(conn); if(result) return result; - if(CONNECT_FIRSTSOCKET_PROXY_SSL()) - return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */ - if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; @@ -1404,16 +1397,50 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) return result; } +#endif +#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_MBEDTLS) +/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only. + It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->handler->flags & PROTOPT_SSL) - return Curl_ssl_getsock(conn, socks, numsocks); + if(conn->handler->flags & PROTOPT_SSL) { + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + else if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + } + + return CURLE_OK; +} +#else +#ifdef USE_SSL +static int https_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; return GETSOCK_BLANK; } #endif /* USE_SSL */ +#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */ /* * Curl_http_done() gets called after a single HTTP request has been @@ -1426,6 +1453,8 @@ CURLcode Curl_http_done(struct connectdata *conn, struct Curl_easy *data = conn->data; struct HTTP *http = data->req.protop; + infof(data, "Curl_http_done: called premature == %d\n", premature); + Curl_unencode_cleanup(conn); #ifdef USE_SPNEGO @@ -1510,20 +1539,6 @@ static bool use_http_1_1plus(const struct Curl_easy *data, (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); } -static const char *get_http_string(const struct Curl_easy *data, - const struct connectdata *conn) -{ -#ifdef USE_NGHTTP2 - if(conn->proto.httpc.h2) - return "2"; -#endif - - if(use_http_1_1plus(data, conn)) - return "1.1"; - - return "1.0"; -} - /* check and possibly add an Expect: header */ static CURLcode expect100(struct Curl_easy *data, struct connectdata *conn, @@ -1633,10 +1648,6 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, Connection: */ checkprefix("Connection", headers->data)) ; - else if((conn->httpversion == 20) && - checkprefix("Transfer-Encoding:", headers->data)) - /* HTTP/2 doesn't support chunked requests */ - ; else { CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data); @@ -1923,42 +1934,47 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } #endif - ptr = Curl_checkheaders(conn, "Transfer-Encoding:"); - if(ptr) { - /* Some kind of TE is requested, check if 'chunked' is chosen */ - data->req.upload_chunky = - Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); - } + if(conn->httpversion == 20) + /* In HTTP2 forbids Transfer-Encoding: chunked */ + ptr = NULL; else { - if((conn->handler->protocol&PROTO_FAMILY_HTTP) && - data->set.upload && - (data->state.infilesize == -1)) { - if(conn->bits.authneg) - /* don't enable chunked during auth neg */ - ; - else if(use_http_1_1plus(data, conn)) { - /* HTTP, upload, unknown file size and not HTTP 1.0 */ - data->req.upload_chunky = TRUE; + ptr = Curl_checkheaders(conn, "Transfer-Encoding:"); + if(ptr) { + /* Some kind of TE is requested, check if 'chunked' is chosen */ + data->req.upload_chunky = + Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); + } + else { + if((conn->handler->protocol&PROTO_FAMILY_HTTP) && + data->set.upload && + (data->state.infilesize == -1)) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ + ; + else if(use_http_1_1plus(data, conn)) { + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + data->req.upload_chunky = TRUE; + } + else { + failf(data, "Chunky upload is not supported by HTTP 1.0"); + return CURLE_UPLOAD_FAILED; + } } else { - failf(data, "Chunky upload is not supported by HTTP 1.0"); - return CURLE_UPLOAD_FAILED; + /* else, no chunky upload */ + data->req.upload_chunky = FALSE; } - } - else { - /* else, no chunky upload */ - data->req.upload_chunky = FALSE; - } - if(data->req.upload_chunky) - te = "Transfer-Encoding: chunked\r\n"; + if(data->req.upload_chunky) + te = "Transfer-Encoding: chunked\r\n"; + } } Curl_safefree(conn->allocptr.host); ptr = Curl_checkheaders(conn, "Host:"); if(ptr && (!data->state.this_is_a_follow || - strcasecompare(data->state.first_host, conn->host.name))) { + Curl_raw_equal(data->state.first_host, conn->host.name))) { #if !defined(CURL_DISABLE_COOKIES) /* If we have a given custom Host: header, we extract the host name in order to possibly use it for cookie reasons later on. We only allow the @@ -2078,7 +2094,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* when doing ftp, append ;type= if not present */ char *type = strstr(ppath, ";type="); if(type && type[6] && type[7] == 0) { - switch(Curl_raw_toupper(type[6])) { + switch (Curl_raw_toupper(type[6])) { case 'A': case 'D': case 'I': @@ -2238,7 +2254,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - httpstring = get_http_string(data, conn); + /* Use 1.1 unless the user specifically asked for 1.0 or the server only + supports 1.0 */ + httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0"; /* initialize a dynamic send-buffer */ req_buffer = Curl_add_buffer_init(); @@ -2312,7 +2330,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated * with the connection and shouldn't be repeated over it either. */ - switch(data->state.authproxy.picked) { + switch (data->state.authproxy.picked) { case CURLAUTH_NEGOTIATE: case CURLAUTH_NTLM: case CURLAUTH_NTLM_WB: @@ -2367,7 +2385,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } co = co->next; /* next cookie please */ } - Curl_cookie_freelist(store); + Curl_cookie_freelist(store, FALSE); /* free the cookie list */ } if(addcookies && !result) { if(!count) @@ -2512,7 +2530,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) postsize = data->state.infilesize; if((postsize != -1) && !data->req.upload_chunky && - (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { + !Curl_checkheaders(conn, "Content-Length:")) { /* only add Content-Length if not uploading chunked */ result = Curl_add_bufferf(req_buffer, "Content-Length: %" CURL_FORMAT_CURL_OFF_T @@ -2564,7 +2582,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) we don't upload data chunked, as RFC2616 forbids us to set both kinds of headers (Transfer-Encoding: chunked and Content-Length) */ if((postsize != -1) && !data->req.upload_chunky && - (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { + !Curl_checkheaders(conn, "Content-Length:")) { /* we allow replacing this header if not during auth negotiation, although it isn't very wise to actually set your own */ result = Curl_add_bufferf(req_buffer, @@ -2743,11 +2761,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - if((conn->httpversion == 20) && data->req.upload_chunky) - /* upload_chunky was set above to set up the request in a chunky fashion, - but is disabled here again to avoid that the chunked encoded version is - actually used when sending the request body over h2 */ - data->req.upload_chunky = FALSE; return result; } @@ -2766,7 +2779,7 @@ checkhttpprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf(data, "Failed to allocate memory for conversion!"); + failf (data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2804,7 +2817,7 @@ checkrtspprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf(data, "Failed to allocate memory for conversion!"); + failf (data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2856,8 +2869,8 @@ static CURLcode header_append(struct Curl_easy *data, /* The reason to have a max limit for this is to avoid the risk of a bad server feeding libcurl with a never-ending header that will cause reallocs infinitely */ - failf(data, "Avoided giant realloc for header (max is %d)!", - CURL_MAX_HTTP_HEADER); + failf (data, "Avoided giant realloc for header (max is %d)!", + CURL_MAX_HTTP_HEADER); return CURLE_OUT_OF_MEMORY; } @@ -2865,7 +2878,7 @@ static CURLcode header_append(struct Curl_easy *data, hbufp_index = k->hbufp - data->state.headerbuff; newbuff = realloc(data->state.headerbuff, newsize); if(!newbuff) { - failf(data, "Failed to alloc memory for big header!"); + failf (data, "Failed to alloc memory for big header!"); return CURLE_OUT_OF_MEMORY; } data->state.headersize=newsize; @@ -3106,8 +3119,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * up and return an error. */ if(http_should_fail(conn)) { - failf(data, "The requested URL returned error: %d", - k->httpcode); + failf (data, "The requested URL returned error: %d", + k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } @@ -3164,21 +3177,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * connection for closure after we've read the entire response. */ if(!k->upload_done) { - if(data->set.http_keep_sending_on_error) { - infof(data, "HTTP error before end of send, keep sending\n"); - if(k->exp100 > EXP100_SEND_DATA) { - k->exp100 = EXP100_SEND_DATA; - k->keepon |= KEEP_SEND; - } - } - else { - infof(data, "HTTP error before end of send, stop sending\n"); - streamclose(conn, "Stop sending data before everything sent"); - k->upload_done = TRUE; - k->keepon &= ~KEEP_SEND; /* don't send */ - if(data->state.expect100header) - k->exp100 = EXP100_FAILED; - } + infof(data, "HTTP error before end of send, stop sending\n"); + streamclose(conn, "Stop sending data before everything sent"); + k->upload_done = TRUE; + k->keepon &= ~KEEP_SEND; /* don't send */ + if(data->state.expect100header) + k->exp100 = EXP100_FAILED; } break;