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 #ifdef HAVE_LIBZ
00026
00027 #include "urldata.h"
00028 #include <curl/curl.h>
00029 #include "sendf.h"
00030 #include "content_encoding.h"
00031 #include "strdup.h"
00032 #include "curl_memory.h"
00033 #include "memdebug.h"
00034
00035
00036
00037 #define OLD_ZLIB_SUPPORT 1
00038
00039 #define DSIZ CURL_MAX_WRITE_SIZE
00040
00041 #define GZIP_MAGIC_0 0x1f
00042 #define GZIP_MAGIC_1 0x8b
00043
00044
00045 #define ASCII_FLAG 0x01
00046 #define HEAD_CRC 0x02
00047 #define EXTRA_FIELD 0x04
00048 #define ORIG_NAME 0x08
00049 #define COMMENT 0x10
00050 #define RESERVED 0xE0
00051
00052 static voidpf
00053 zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
00054 {
00055 (void) opaque;
00056
00057 return (voidpf) calloc(items, size);
00058 }
00059
00060 static void
00061 zfree_cb(voidpf opaque, voidpf ptr)
00062 {
00063 (void) opaque;
00064 free(ptr);
00065 }
00066
00067 static CURLcode
00068 process_zlib_error(struct connectdata *conn, z_stream *z)
00069 {
00070 struct Curl_easy *data = conn->data;
00071 if(z->msg)
00072 failf(data, "Error while processing content unencoding: %s",
00073 z->msg);
00074 else
00075 failf(data, "Error while processing content unencoding: "
00076 "Unknown failure within decompression software.");
00077
00078 return CURLE_BAD_CONTENT_ENCODING;
00079 }
00080
00081 static CURLcode
00082 exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result)
00083 {
00084 inflateEnd(z);
00085 *zlib_init = ZLIB_UNINIT;
00086 return result;
00087 }
00088
00089 static CURLcode
00090 inflate_stream(struct connectdata *conn,
00091 struct SingleRequest *k)
00092 {
00093 int allow_restart = 1;
00094 z_stream *z = &k->z;
00095 uInt nread = z->avail_in;
00096 Bytef *orig_in = z->next_in;
00097 int status;
00098 CURLcode result = CURLE_OK;
00099 char *decomp;
00100
00101
00102
00103 decomp = malloc(DSIZ);
00104 if(decomp == NULL) {
00105 return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
00106 }
00107
00108
00109
00110 for(;;) {
00111
00112 z->next_out = (Bytef *)decomp;
00113 z->avail_out = DSIZ;
00114
00115 status = inflate(z, Z_SYNC_FLUSH);
00116 if(status == Z_OK || status == Z_STREAM_END) {
00117 allow_restart = 0;
00118 if((DSIZ - z->avail_out) && (!k->ignorebody)) {
00119 result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
00120 DSIZ - z->avail_out);
00121
00122 if(result) {
00123 free(decomp);
00124 return exit_zlib(z, &k->zlib_init, result);
00125 }
00126 }
00127
00128
00129 if(status == Z_STREAM_END) {
00130 free(decomp);
00131 if(inflateEnd(z) == Z_OK)
00132 return exit_zlib(z, &k->zlib_init, result);
00133 else
00134 return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
00135 }
00136
00137
00138
00139
00140 if(z->avail_in == 0) {
00141 free(decomp);
00142 return result;
00143 }
00144 }
00145 else if(allow_restart && status == Z_DATA_ERROR) {
00146
00147
00148
00149 (void) inflateEnd(z);
00150 if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
00151 free(decomp);
00152 return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
00153 }
00154 z->next_in = orig_in;
00155 z->avail_in = nread;
00156 allow_restart = 0;
00157 continue;
00158 }
00159 else {
00160 free(decomp);
00161 return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
00162 }
00163 }
00164
00165 }
00166
00167 CURLcode
00168 Curl_unencode_deflate_write(struct connectdata *conn,
00169 struct SingleRequest *k,
00170 ssize_t nread)
00171 {
00172 z_stream *z = &k->z;
00173
00174
00175 if(k->zlib_init == ZLIB_UNINIT) {
00176 memset(z, 0, sizeof(z_stream));
00177 z->zalloc = (alloc_func)zalloc_cb;
00178 z->zfree = (free_func)zfree_cb;
00179
00180 if(inflateInit(z) != Z_OK)
00181 return process_zlib_error(conn, z);
00182 k->zlib_init = ZLIB_INIT;
00183 }
00184
00185
00186 z->next_in = (Bytef *)k->str;
00187 z->avail_in = (uInt)nread;
00188
00189
00190 return inflate_stream(conn, k);
00191 }
00192
00193 #ifdef OLD_ZLIB_SUPPORT
00194
00195 static enum {
00196 GZIP_OK,
00197 GZIP_BAD,
00198 GZIP_UNDERFLOW
00199 } check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
00200 {
00201 int method, flags;
00202 const ssize_t totallen = len;
00203
00204
00205 if(len < 10)
00206 return GZIP_UNDERFLOW;
00207
00208 if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
00209 return GZIP_BAD;
00210
00211 method = data[2];
00212 flags = data[3];
00213
00214 if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
00215
00216 return GZIP_BAD;
00217 }
00218
00219
00220 len -= 10;
00221 data += 10;
00222
00223 if(flags & EXTRA_FIELD) {
00224 ssize_t extra_len;
00225
00226 if(len < 2)
00227 return GZIP_UNDERFLOW;
00228
00229 extra_len = (data[1] << 8) | data[0];
00230
00231 if(len < (extra_len+2))
00232 return GZIP_UNDERFLOW;
00233
00234 len -= (extra_len + 2);
00235 data += (extra_len + 2);
00236 }
00237
00238 if(flags & ORIG_NAME) {
00239
00240 while(len && *data) {
00241 --len;
00242 ++data;
00243 }
00244 if(!len || *data)
00245 return GZIP_UNDERFLOW;
00246
00247
00248 --len;
00249 ++data;
00250 }
00251
00252 if(flags & COMMENT) {
00253
00254 while(len && *data) {
00255 --len;
00256 ++data;
00257 }
00258 if(!len || *data)
00259 return GZIP_UNDERFLOW;
00260
00261
00262 --len;
00263 }
00264
00265 if(flags & HEAD_CRC) {
00266 if(len < 2)
00267 return GZIP_UNDERFLOW;
00268
00269 len -= 2;
00270 }
00271
00272 *headerlen = totallen - len;
00273 return GZIP_OK;
00274 }
00275 #endif
00276
00277 CURLcode
00278 Curl_unencode_gzip_write(struct connectdata *conn,
00279 struct SingleRequest *k,
00280 ssize_t nread)
00281 {
00282 z_stream *z = &k->z;
00283
00284
00285 if(k->zlib_init == ZLIB_UNINIT) {
00286 memset(z, 0, sizeof(z_stream));
00287 z->zalloc = (alloc_func)zalloc_cb;
00288 z->zfree = (free_func)zfree_cb;
00289
00290 if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
00291
00292 if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
00293 return process_zlib_error(conn, z);
00294 }
00295 k->zlib_init = ZLIB_INIT_GZIP;
00296 }
00297 else {
00298
00299 if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
00300 return process_zlib_error(conn, z);
00301 }
00302 k->zlib_init = ZLIB_INIT;
00303 }
00304 }
00305
00306 if(k->zlib_init == ZLIB_INIT_GZIP) {
00307
00308 z->next_in = (Bytef *)k->str;
00309 z->avail_in = (uInt)nread;
00310
00311 return inflate_stream(conn, k);
00312 }
00313
00314 #ifndef OLD_ZLIB_SUPPORT
00315
00316
00317 return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
00318
00319 #else
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 switch(k->zlib_init) {
00331
00332 case ZLIB_INIT:
00333 {
00334
00335 ssize_t hlen;
00336
00337 switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
00338 case GZIP_OK:
00339 z->next_in = (Bytef *)k->str + hlen;
00340 z->avail_in = (uInt)(nread - hlen);
00341 k->zlib_init = ZLIB_GZIP_INFLATING;
00342 break;
00343
00344 case GZIP_UNDERFLOW:
00345
00346
00347
00348
00349
00350
00351
00352 z->avail_in = (uInt)nread;
00353 z->next_in = malloc(z->avail_in);
00354 if(z->next_in == NULL) {
00355 return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
00356 }
00357 memcpy(z->next_in, k->str, z->avail_in);
00358 k->zlib_init = ZLIB_GZIP_HEADER;
00359
00360 return CURLE_OK;
00361
00362 case GZIP_BAD:
00363 default:
00364 return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
00365 }
00366
00367 }
00368 break;
00369
00370 case ZLIB_GZIP_HEADER:
00371 {
00372
00373 ssize_t hlen;
00374 z->avail_in += (uInt)nread;
00375 z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
00376 if(z->next_in == NULL) {
00377 return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
00378 }
00379
00380 memcpy(z->next_in + z->avail_in - nread, k->str, nread);
00381
00382 switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
00383 case GZIP_OK:
00384
00385 free(z->next_in);
00386
00387 z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
00388 z->avail_in = (uInt)(z->avail_in - hlen);
00389 k->zlib_init = ZLIB_GZIP_INFLATING;
00390 break;
00391
00392 case GZIP_UNDERFLOW:
00393
00394 return CURLE_OK;
00395
00396 case GZIP_BAD:
00397 default:
00398 free(z->next_in);
00399 return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
00400 }
00401
00402 }
00403 break;
00404
00405 case ZLIB_GZIP_INFLATING:
00406 default:
00407
00408 z->next_in = (Bytef *)k->str;
00409 z->avail_in = (uInt)nread;
00410 break;
00411 }
00412
00413 if(z->avail_in == 0) {
00414
00415 return CURLE_OK;
00416 }
00417
00418
00419 return inflate_stream(conn, k);
00420 #endif
00421 }
00422
00423 void Curl_unencode_cleanup(struct connectdata *conn)
00424 {
00425 struct Curl_easy *data = conn->data;
00426 struct SingleRequest *k = &data->req;
00427 z_stream *z = &k->z;
00428 if(k->zlib_init != ZLIB_UNINIT)
00429 (void) exit_zlib(z, &k->zlib_init, CURLE_OK);
00430 }
00431
00432 #endif