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