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


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:04