diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/transfer.c | 106 | 
1 files changed, 86 insertions, 20 deletions
| diff --git a/lib/transfer.c b/lib/transfer.c index 0056792e7..6403384bf 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -130,12 +130,19 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)    struct SessionHandle *data = conn->data;    size_t buffersize = (size_t)bytes;    int nread; +  int sending_http_headers = FALSE;    if(data->req.upload_chunky) {      /* if chunked Transfer-Encoding */      buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */      data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */    } +  if((data->state.proto.http) +  && (data->state.proto.http->sending == HTTPSEND_REQUEST)) { +     /* We're sending the HTTP request headers, not the data. +        Remember that so we don't re-translate them into garbage. */ +     sending_http_headers = TRUE; +  }    /* this function returns a size_t, so we typecast to int to prevent warnings       with picky compilers */ @@ -166,10 +173,40 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)    }    if(!data->req.forbidchunk && data->req.upload_chunky) { -    /* if chunked Transfer-Encoding */ +    /* if chunked Transfer-Encoding  +     *    build chunk: +     * +     *        <HEX SIZE> CRLF +     *        <DATA> CRLF +     */ +    /* On non-ASCII platforms the <DATA> may or may not be +       translated based on set.prefer_ascii while the protocol +       portion must always be translated to the network encoding. +       To further complicate matters, line end conversion might be +       done later on, so we need to prevent CRLFs from becoming +       CRCRLFs if that's the case.  To do this we use bare LFs +       here, knowing they'll become CRLFs later on. +     */ +      char hexbuffer[11]; -    int hexlen = snprintf(hexbuffer, sizeof(hexbuffer), -                          "%x\r\n", nread); +    const char *endofline_native; +    const char *endofline_network; +    int hexlen; +#ifdef CURL_DO_LINEEND_CONV +    if((data->set.crlf) || (data->set.prefer_ascii)) { +#else +    if(data->set.crlf) { +#endif /* CURL_DO_LINEEND_CONV */ +      /* \n will become \r\n later on */ +      endofline_native  = "\n"; +      endofline_network = "\x0a"; +    } else { +      endofline_native  = "\r\n"; +      endofline_network = "\x0d\x0a"; +    } +    hexlen = snprintf(hexbuffer, sizeof(hexbuffer), +                      "%x%s", nread, endofline_native); +      /* move buffer pointer */      data->req.upload_fromhere -= hexlen;      nread += hexlen; @@ -177,29 +214,48 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)      /* copy the prefix to the buffer, leaving out the NUL */      memcpy(data->req.upload_fromhere, hexbuffer, hexlen); -    /* always append CRLF to the data */ -    memcpy(data->req.upload_fromhere + nread, "\r\n", 2); +    /* always append ASCII CRLF to the data */   +    memcpy(data->req.upload_fromhere + nread,  +           endofline_network,  +           strlen(endofline_network)); + +#ifdef CURL_DOES_CONVERSIONS +    CURLcode res; +    int length; +    if(data->set.prefer_ascii) { +      /* translate the protocol and data */ +      length = nread; +    } else { +      /* just translate the protocol portion */ +      length = strlen(hexbuffer); +    } +    res = Curl_convert_to_network(data, data->req.upload_fromhere, length); +    /* Curl_convert_to_network calls failf if unsuccessful */ +    if(res != CURLE_OK) { +      return(res); +    } +#endif /* CURL_DOES_CONVERSIONS */      if((nread - hexlen) == 0) {        /* mark this as done once this chunk is transfered */        data->req.upload_done = TRUE;      } -    nread+=2; /* for the added CRLF */ -  } - -  *nreadp = nread; - +    nread+=strlen(endofline_native); /* for the added end of line */  #ifdef CURL_DOES_CONVERSIONS -  if(data->set.prefer_ascii) { -    CURLcode res; -    res = Curl_convert_to_network(data, data->req.upload_fromhere, nread); -    /* Curl_convert_to_network calls failf if unsuccessful */ -    if(res != CURLE_OK) { -      return(res); +  } else { +    if((data->set.prefer_ascii) && (!sending_http_headers)) { +      CURLcode res; +      res = Curl_convert_to_network(data, data->req.upload_fromhere, nread); +      /* Curl_convert_to_network calls failf if unsuccessful */ +      if(res != CURLE_OK) { +        return(res); +      }      } -  }  #endif /* CURL_DOES_CONVERSIONS */ +  } + +  *nreadp = nread;    return CURLE_OK;  } @@ -1404,6 +1460,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,    ssize_t bytes_written;    CURLcode result;    ssize_t nread; /* number of bytes read */ +  int sending_http_headers = FALSE;    if((k->bytecount == 0) && (k->writebytecount == 0))      Curl_pgrsTime(data, TIMER_STARTTRANSFER); @@ -1439,6 +1496,15 @@ static CURLcode readwrite_upload(struct SessionHandle *data,            break;          } +        if(data->state.proto.http) { +          if(data->state.proto.http->sending == HTTPSEND_REQUEST) { +            /* We're sending the HTTP request headers, not the data. +               Remember that so we don't change the line endings. */ +               sending_http_headers = TRUE; +          } else { +            sending_http_headers = FALSE; +          } +        }          result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);          if(result)            return result; @@ -1470,11 +1536,11 @@ static CURLcode readwrite_upload(struct SessionHandle *data,        /* convert LF to CRLF if so asked */  #ifdef CURL_DO_LINEEND_CONV        /* always convert if we're FTPing in ASCII mode */ -      if((data->set.crlf) || (data->set.prefer_ascii)) +        if(((data->set.crlf) || (data->set.prefer_ascii))  #else -        if(data->set.crlf) +        if((data->set.crlf)  #endif /* CURL_DO_LINEEND_CONV */ -        { +        && (!sending_http_headers)) {            if(data->state.scratch == NULL)              data->state.scratch = malloc(2*BUFSIZE);            if(data->state.scratch == NULL) { | 
