diff options
Diffstat (limited to 'lib/http_chunks.c')
-rw-r--r-- | lib/http_chunks.c | 171 |
1 files changed, 73 insertions, 98 deletions
diff --git a/lib/http_chunks.c b/lib/http_chunks.c index 0d41979a..80c0f954 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -19,28 +19,22 @@ * KIND, either express or implied. * ***************************************************************************/ -#include "setup.h" + +#include "curl_setup.h" #ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> -#include <ctype.h> #include "urldata.h" /* it includes http_chunks.h */ #include "sendf.h" /* for the client write stuff */ #include "content_encoding.h" #include "http.h" -#include "curl_memory.h" -#include "easyif.h" /* for Curl_convert_to_network prototype */ +#include "non-ascii.h" /* for Curl_convert_to_network prototype */ +#include "strtoofft.h" +#include "warnless.h" -#define _MPRINTF_REPLACE /* use our functions only */ -#include <curl/mprintf.h> - -/* The last #include file should be: */ +/* The last #include files should be: */ +#include "curl_memory.h" #include "memdebug.h" /* @@ -84,16 +78,16 @@ We avoid the use of isxdigit to accommodate non-ASCII hosts. */ static bool Curl_isxdigit(char digit) { - return (bool)( (digit >= 0x30 && digit <= 0x39) /* 0-9 */ - || (digit >= 0x41 && digit <= 0x46) /* A-F */ - || (digit >= 0x61 && digit <= 0x66) ); /* a-f */ + return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */ + || (digit >= 0x41 && digit <= 0x46) /* A-F */ + || (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE; } void Curl_httpchunk_init(struct connectdata *conn) { struct Curl_chunker *chunk = &conn->chunk; - chunk->hexindex=0; /* start at 0 */ - chunk->dataleft=0; /* no data left yet! */ + chunk->hexindex=0; /* start at 0 */ + chunk->dataleft=0; /* no data left yet! */ chunk->state = CHUNK_HEX; /* we get hex first! */ } @@ -118,7 +112,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, struct Curl_chunker *ch = &conn->chunk; struct SingleRequest *k = &data->req; size_t piece; - size_t length = (size_t)datalen; + curl_off_t length = (curl_off_t)datalen; size_t *wrote = (size_t *)wrotep; *wrote = 0; /* nothing's written yet */ @@ -146,74 +140,62 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, } } else { - if(0 == ch->hexindex) { + char *endptr; + if(0 == ch->hexindex) /* This is illegal data, we received junk where we expected a hexadecimal digit. */ return CHUNKE_ILLEGAL_HEX; - } + /* length and datap are unmodified */ ch->hexbuffer[ch->hexindex]=0; -#ifdef CURL_DOES_CONVERSIONS + /* convert to host encoding before calling strtoul */ - result = Curl_convert_from_network(conn->data, - ch->hexbuffer, + result = Curl_convert_from_network(conn->data, ch->hexbuffer, ch->hexindex); - if(result != CURLE_OK) { + if(result) { /* Curl_convert_from_network calls failf if unsuccessful */ /* Treat it as a bad hex character */ - return(CHUNKE_ILLEGAL_HEX); + return CHUNKE_ILLEGAL_HEX; } -#endif /* CURL_DOES_CONVERSIONS */ - ch->datasize=strtoul(ch->hexbuffer, NULL, 16); - ch->state = CHUNK_POSTHEX; - } - break; - case CHUNK_POSTHEX: - /* In this state, we're waiting for CRLF to arrive. We support - this to allow so called chunk-extensions to show up here - before the CRLF comes. */ - if(*datap == 0x0d) - ch->state = CHUNK_CR; - length--; - datap++; + ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16); + if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE)) + /* overflow is an error */ + return CHUNKE_ILLEGAL_HEX; + ch->state = CHUNK_LF; /* now wait for the CRLF */ + } break; - case CHUNK_CR: - /* waiting for the LF */ + case CHUNK_LF: + /* waiting for the LF after a chunk size */ if(*datap == 0x0a) { /* we're now expecting data to come, unless size was zero! */ if(0 == ch->datasize) { ch->state = CHUNK_TRAILER; /* now check for trailers */ conn->trlPos=0; } - else { + else ch->state = CHUNK_DATA; - } } - else - /* previously we got a fake CR, go back to CR waiting! */ - ch->state = CHUNK_CR; + datap++; length--; break; case CHUNK_DATA: - /* we get pure and fine data - - We expect another 'datasize' of data. We have 'length' right now, - it can be more or less than 'datasize'. Get the smallest piece. + /* We expect 'datasize' of data. We have 'length' right now, it can be + more or less than 'datasize'. Get the smallest piece. */ - piece = (ch->datasize >= length)?length:ch->datasize; + piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); /* Write the data portion available */ #ifdef HAVE_LIBZ switch (conn->data->set.http_ce_skip? - IDENTITY : data->req.content_encoding) { + IDENTITY : data->req.auto_decoding) { case IDENTITY: #endif if(!k->ignorebody) { - if( !data->set.http_te_skip ) + if(!data->set.http_te_skip) result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); else @@ -257,37 +239,22 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, if(0 == ch->datasize) /* end of data this round, we now expect a trailing CRLF */ - ch->state = CHUNK_POSTCR; - break; - - case CHUNK_POSTCR: - if(*datap == 0x0d) { ch->state = CHUNK_POSTLF; - datap++; - length--; - } - else - return CHUNKE_BAD_CHUNK; - break; case CHUNK_POSTLF: if(*datap == 0x0a) { - /* - * The last one before we go back to hex state and start all - * over. - */ - Curl_httpchunk_init(conn); - datap++; - length--; + /* The last one before we go back to hex state and start all over. */ + Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */ } - else + else if(*datap != 0x0d) return CHUNKE_BAD_CHUNK; - + datap++; + length--; break; case CHUNK_TRAILER: - if(*datap == 0x0d) { + if((*datap == 0x0d) || (*datap == 0x0a)) { /* this is the end of a trailer, but if the trailer was zero bytes there was no trailer and we move on */ @@ -297,17 +264,14 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, conn->trailer[conn->trlPos++]=0x0a; conn->trailer[conn->trlPos]=0; -#ifdef CURL_DOES_CONVERSIONS /* Convert to host encoding before calling Curl_client_write */ - result = Curl_convert_from_network(conn->data, - conn->trailer, + result = Curl_convert_from_network(conn->data, conn->trailer, conn->trlPos); - if(result != CURLE_OK) + if(result) /* Curl_convert_from_network calls failf if unsuccessful */ /* Treat it as a bad chunk */ return CHUNKE_BAD_CHUNK; -#endif /* CURL_DOES_CONVERSIONS */ if(!data->set.http_te_skip) { result = Curl_client_write(conn, CLIENTWRITE_HEADER, conn->trailer, conn->trlPos); @@ -316,6 +280,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, } conn->trlPos=0; ch->state = CHUNK_TRAILER_CR; + if(*datap == 0x0a) + /* already on the LF */ + break; } else { /* no trailer, we're on the final CRLF pair */ @@ -342,7 +309,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, return CHUNKE_OUT_OF_MEMORY; conn->trailer = ptr; } - fprintf(stderr, "MOO: %c\n", *datap); conn->trailer[conn->trlPos++]=*datap; } datap++; @@ -362,27 +328,18 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, case CHUNK_TRAILER_POSTCR: /* We enter this state when a CR should arrive so we expect to have to first pass a CR before we wait for LF */ - if(*datap != 0x0d) { + if((*datap != 0x0d) && (*datap != 0x0a)) { /* not a CR then it must be another header in the trailer */ ch->state = CHUNK_TRAILER; break; } - datap++; - length--; - /* now wait for the final LF */ - ch->state = CHUNK_STOP; - break; - - case CHUNK_STOPCR: - /* Read the final CRLF that ends all chunk bodies */ - if(*datap == 0x0d) { - ch->state = CHUNK_STOP; + /* skip if CR */ datap++; length--; } - else - return CHUNKE_BAD_CHUNK; + /* now wait for the final LF */ + ch->state = CHUNK_STOP; break; case CHUNK_STOP: @@ -391,17 +348,35 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, /* Record the length of any data left in the end of the buffer even if there's no more chunks to read */ + ch->dataleft = curlx_sotouz(length); - ch->dataleft = length; return CHUNKE_STOP; /* return stop */ } else return CHUNKE_BAD_CHUNK; - - default: - return CHUNKE_STATE_ERROR; } } return CHUNKE_OK; } + +const char *Curl_chunked_strerror(CHUNKcode code) +{ + switch (code) { + default: + return "OK"; + case CHUNKE_TOO_LONG_HEX: + return "Too long hexadecimal number"; + case CHUNKE_ILLEGAL_HEX: + return "Illegal or missing hexadecimal sequence"; + case CHUNKE_BAD_CHUNK: + return "Malformed encoding found"; + case CHUNKE_WRITE_ERROR: + return "Write error"; + case CHUNKE_BAD_ENCODING: + return "Bad content-encoding found"; + case CHUNKE_OUT_OF_MEMORY: + return "Out of memory"; + } +} + #endif /* CURL_DISABLE_HTTP */ |