Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifndef CURL_DISABLE_HTTP
00026
00027 #include "urldata.h"
00028 #include "sendf.h"
00029
00030 #include "content_encoding.h"
00031 #include "http.h"
00032 #include "non-ascii.h"
00033 #include "strtoofft.h"
00034 #include "warnless.h"
00035
00036
00037 #include "curl_memory.h"
00038 #include "memdebug.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static bool Curl_isxdigit(char digit)
00080 {
00081 return ( (digit >= 0x30 && digit <= 0x39)
00082 || (digit >= 0x41 && digit <= 0x46)
00083 || (digit >= 0x61 && digit <= 0x66) ) ? TRUE : FALSE;
00084 }
00085
00086 void Curl_httpchunk_init(struct connectdata *conn)
00087 {
00088 struct Curl_chunker *chunk = &conn->chunk;
00089 chunk->hexindex=0;
00090 chunk->dataleft=0;
00091 chunk->state = CHUNK_HEX;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
00106 char *datap,
00107 ssize_t datalen,
00108 ssize_t *wrotep)
00109 {
00110 CURLcode result=CURLE_OK;
00111 struct Curl_easy *data = conn->data;
00112 struct Curl_chunker *ch = &conn->chunk;
00113 struct SingleRequest *k = &data->req;
00114 size_t piece;
00115 curl_off_t length = (curl_off_t)datalen;
00116 size_t *wrote = (size_t *)wrotep;
00117
00118 *wrote = 0;
00119
00120
00121
00122 if(data->set.http_te_skip && !k->ignorebody) {
00123 result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
00124 if(result)
00125 return CHUNKE_WRITE_ERROR;
00126 }
00127
00128 while(length) {
00129 switch(ch->state) {
00130 case CHUNK_HEX:
00131 if(Curl_isxdigit(*datap)) {
00132 if(ch->hexindex < MAXNUM_SIZE) {
00133 ch->hexbuffer[ch->hexindex] = *datap;
00134 datap++;
00135 length--;
00136 ch->hexindex++;
00137 }
00138 else {
00139 return CHUNKE_TOO_LONG_HEX;
00140 }
00141 }
00142 else {
00143 char *endptr;
00144 if(0 == ch->hexindex)
00145
00146
00147 return CHUNKE_ILLEGAL_HEX;
00148
00149
00150 ch->hexbuffer[ch->hexindex]=0;
00151
00152
00153 result = Curl_convert_from_network(conn->data, ch->hexbuffer,
00154 ch->hexindex);
00155 if(result) {
00156
00157
00158 return CHUNKE_ILLEGAL_HEX;
00159 }
00160
00161 ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16);
00162 if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE))
00163
00164 return CHUNKE_ILLEGAL_HEX;
00165 ch->state = CHUNK_LF;
00166 }
00167 break;
00168
00169 case CHUNK_LF:
00170
00171 if(*datap == 0x0a) {
00172
00173 if(0 == ch->datasize) {
00174 ch->state = CHUNK_TRAILER;
00175 conn->trlPos=0;
00176 }
00177 else
00178 ch->state = CHUNK_DATA;
00179 }
00180
00181 datap++;
00182 length--;
00183 break;
00184
00185 case CHUNK_DATA:
00186
00187
00188
00189 piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
00190
00191
00192 #ifdef HAVE_LIBZ
00193 switch(conn->data->set.http_ce_skip?
00194 IDENTITY : data->req.auto_decoding) {
00195 case IDENTITY:
00196 #endif
00197 if(!k->ignorebody) {
00198 if(!data->set.http_te_skip)
00199 result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
00200 piece);
00201 else
00202 result = CURLE_OK;
00203 }
00204 #ifdef HAVE_LIBZ
00205 break;
00206
00207 case DEFLATE:
00208
00209 data->req.str = datap;
00210 result = Curl_unencode_deflate_write(conn, &data->req,
00211 (ssize_t)piece);
00212 break;
00213
00214 case GZIP:
00215
00216 data->req.str = datap;
00217 result = Curl_unencode_gzip_write(conn, &data->req,
00218 (ssize_t)piece);
00219 break;
00220
00221 default:
00222 failf(conn->data,
00223 "Unrecognized content encoding type. "
00224 "libcurl understands `identity', `deflate' and `gzip' "
00225 "content encodings.");
00226 return CHUNKE_BAD_ENCODING;
00227 }
00228 #endif
00229
00230 if(result)
00231 return CHUNKE_WRITE_ERROR;
00232
00233 *wrote += piece;
00234
00235 ch->datasize -= piece;
00236 datap += piece;
00237 length -= piece;
00238
00239 if(0 == ch->datasize)
00240
00241 ch->state = CHUNK_POSTLF;
00242 break;
00243
00244 case CHUNK_POSTLF:
00245 if(*datap == 0x0a) {
00246
00247 Curl_httpchunk_init(conn);
00248 }
00249 else if(*datap != 0x0d)
00250 return CHUNKE_BAD_CHUNK;
00251 datap++;
00252 length--;
00253 break;
00254
00255 case CHUNK_TRAILER:
00256 if((*datap == 0x0d) || (*datap == 0x0a)) {
00257
00258
00259
00260 if(conn->trlPos) {
00261
00262 conn->trailer[conn->trlPos++]=0x0d;
00263 conn->trailer[conn->trlPos++]=0x0a;
00264 conn->trailer[conn->trlPos]=0;
00265
00266
00267 result = Curl_convert_from_network(conn->data, conn->trailer,
00268 conn->trlPos);
00269 if(result)
00270
00271
00272 return CHUNKE_BAD_CHUNK;
00273
00274 if(!data->set.http_te_skip) {
00275 result = Curl_client_write(conn, CLIENTWRITE_HEADER,
00276 conn->trailer, conn->trlPos);
00277 if(result)
00278 return CHUNKE_WRITE_ERROR;
00279 }
00280 conn->trlPos=0;
00281 ch->state = CHUNK_TRAILER_CR;
00282 if(*datap == 0x0a)
00283
00284 break;
00285 }
00286 else {
00287
00288 ch->state = CHUNK_TRAILER_POSTCR;
00289 break;
00290 }
00291 }
00292 else {
00293
00294
00295 if(conn->trlPos >= conn->trlMax) {
00296
00297
00298 char *ptr;
00299 if(conn->trlMax) {
00300 conn->trlMax *= 2;
00301 ptr = realloc(conn->trailer, conn->trlMax + 3);
00302 }
00303 else {
00304 conn->trlMax=128;
00305 ptr = malloc(conn->trlMax + 3);
00306 }
00307 if(!ptr)
00308 return CHUNKE_OUT_OF_MEMORY;
00309 conn->trailer = ptr;
00310 }
00311 conn->trailer[conn->trlPos++]=*datap;
00312 }
00313 datap++;
00314 length--;
00315 break;
00316
00317 case CHUNK_TRAILER_CR:
00318 if(*datap == 0x0a) {
00319 ch->state = CHUNK_TRAILER_POSTCR;
00320 datap++;
00321 length--;
00322 }
00323 else
00324 return CHUNKE_BAD_CHUNK;
00325 break;
00326
00327 case CHUNK_TRAILER_POSTCR:
00328
00329
00330 if((*datap != 0x0d) && (*datap != 0x0a)) {
00331
00332 ch->state = CHUNK_TRAILER;
00333 break;
00334 }
00335 if(*datap == 0x0d) {
00336
00337 datap++;
00338 length--;
00339 }
00340
00341 ch->state = CHUNK_STOP;
00342 break;
00343
00344 case CHUNK_STOP:
00345 if(*datap == 0x0a) {
00346 length--;
00347
00348
00349
00350 ch->dataleft = curlx_sotouz(length);
00351
00352 return CHUNKE_STOP;
00353 }
00354 else
00355 return CHUNKE_BAD_CHUNK;
00356 }
00357 }
00358 return CHUNKE_OK;
00359 }
00360
00361 const char *Curl_chunked_strerror(CHUNKcode code)
00362 {
00363 switch(code) {
00364 default:
00365 return "OK";
00366 case CHUNKE_TOO_LONG_HEX:
00367 return "Too long hexadecimal number";
00368 case CHUNKE_ILLEGAL_HEX:
00369 return "Illegal or missing hexadecimal sequence";
00370 case CHUNKE_BAD_CHUNK:
00371 return "Malformed encoding found";
00372 case CHUNKE_WRITE_ERROR:
00373 return "Write error";
00374 case CHUNKE_BAD_ENCODING:
00375 return "Bad content-encoding found";
00376 case CHUNKE_OUT_OF_MEMORY:
00377 return "Out of memory";
00378 }
00379 }
00380
00381 #endif