diff options
Diffstat (limited to 'Utilities/cmcurl/lib/content_encoding.c')
-rw-r--r-- | Utilities/cmcurl/lib/content_encoding.c | 183 |
1 files changed, 97 insertions, 86 deletions
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c index 97f8341..c68e6e5 100644 --- a/Utilities/cmcurl/lib/content_encoding.c +++ b/Utilities/cmcurl/lib/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2011, 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 @@ -18,21 +18,17 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ -#include "setup.h" +#include "curl_setup.h" #ifdef HAVE_LIBZ -#include <stdlib.h> -#include <string.h> - #include "urldata.h" #include <curl/curl.h> #include "sendf.h" #include "content_encoding.h" -#include "memory.h" +#include "curl_memory.h" #include "memdebug.h" @@ -40,7 +36,7 @@ (doing so will reduce code size slightly). */ #define OLD_ZLIB_SUPPORT 1 -#define DSIZ 0x10000 /* buffer size for decompressed data */ +#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ #define GZIP_MAGIC_0 0x1f #define GZIP_MAGIC_1 0x8b @@ -53,19 +49,26 @@ #define COMMENT 0x10 /* bit 4 set: file comment present */ #define RESERVED 0xE0 /* bits 5..7: reserved */ -enum zlibState { - ZLIB_UNINIT, /* uninitialized */ - ZLIB_INIT, /* initialized */ - ZLIB_GZIP_HEADER, /* reading gzip header */ - ZLIB_GZIP_INFLATING, /* inflating gzip stream */ - ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ -}; +static voidpf +zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) +{ + (void) opaque; + /* not a typo, keep it calloc() */ + return (voidpf) calloc(items, size); +} + +static void +zfree_cb(voidpf opaque, voidpf ptr) +{ + (void) opaque; + free(ptr); +} static CURLcode process_zlib_error(struct connectdata *conn, z_stream *z) { struct SessionHandle *data = conn->data; - if (z->msg) + if(z->msg) failf (data, "Error while processing content unencoding: %s", z->msg); else @@ -76,7 +79,7 @@ process_zlib_error(struct connectdata *conn, z_stream *z) } static CURLcode -exit_zlib(z_stream *z, bool *zlib_init, CURLcode result) +exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result) { inflateEnd(z); *zlib_init = ZLIB_UNINIT; @@ -85,7 +88,7 @@ exit_zlib(z_stream *z, bool *zlib_init, CURLcode result) static CURLcode inflate_stream(struct connectdata *conn, - struct Curl_transfer_keeper *k) + struct SingleRequest *k) { int allow_restart = 1; z_stream *z = &k->z; /* zlib state structure */ @@ -97,53 +100,56 @@ inflate_stream(struct connectdata *conn, /* Dynamically allocate a buffer for decompression because it's uncommonly large to hold on the stack */ - decomp = (char*)malloc(DSIZ); - if (decomp == NULL) { + decomp = malloc(DSIZ); + if(decomp == NULL) { return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } /* because the buffer size is fixed, iteratively decompress and transfer to the client via client_write. */ - for (;;) { + for(;;) { /* (re)set buffer for decompressed output for every iteration */ z->next_out = (Bytef *)decomp; z->avail_out = DSIZ; status = inflate(z, Z_SYNC_FLUSH); - if (status == Z_OK || status == Z_STREAM_END) { + if(status == Z_OK || status == Z_STREAM_END) { allow_restart = 0; - if(DSIZ - z->avail_out) { + if((DSIZ - z->avail_out) && (!k->ignorebody)) { result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp, DSIZ - z->avail_out); /* if !CURLE_OK, clean up, return */ - if (result) { + if(result) { free(decomp); return exit_zlib(z, &k->zlib_init, result); } } /* Done? clean up, return */ - if (status == Z_STREAM_END) { + if(status == Z_STREAM_END) { free(decomp); - if (inflateEnd(z) == Z_OK) + if(inflateEnd(z) == Z_OK) return exit_zlib(z, &k->zlib_init, result); else return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); } /* Done with these bytes, exit */ - if (status == Z_OK && z->avail_in == 0) { + + /* status is always Z_OK at this point! */ + if(z->avail_in == 0) { free(decomp); return result; } } - else if (allow_restart && status == Z_DATA_ERROR) { + else if(allow_restart && status == Z_DATA_ERROR) { /* some servers seem to not generate zlib headers, so this is an attempt to fix and continue anyway */ - inflateReset(z); - if (inflateInit2(z, -MAX_WBITS) != Z_OK) { - return process_zlib_error(conn, z); + (void) inflateEnd(z); /* don't care about the return code */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + free(decomp); + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); } z->next_in = orig_in; z->avail_in = nread; @@ -160,19 +166,18 @@ inflate_stream(struct connectdata *conn, CURLcode Curl_unencode_deflate_write(struct connectdata *conn, - struct Curl_transfer_keeper *k, + struct SingleRequest *k, ssize_t nread) { z_stream *z = &k->z; /* zlib state structure */ /* Initialize zlib? */ - if (k->zlib_init == ZLIB_UNINIT) { - z->zalloc = (alloc_func)Z_NULL; - z->zfree = (free_func)Z_NULL; - z->opaque = 0; - z->next_in = NULL; - z->avail_in = 0; - if (inflateInit(z) != Z_OK) + if(k->zlib_init == ZLIB_UNINIT) { + memset(z, 0, sizeof(z_stream)); + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; + + if(inflateInit(z) != Z_OK) return process_zlib_error(conn, z); k->zlib_init = ZLIB_INIT; } @@ -197,16 +202,16 @@ static enum { const ssize_t totallen = len; /* The shortest header is 10 bytes */ - if (len < 10) + if(len < 10) return GZIP_UNDERFLOW; - if ((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) + if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) return GZIP_BAD; method = data[2]; flags = data[3]; - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + if(method != Z_DEFLATED || (flags & RESERVED) != 0) { /* Can't handle this compression method or unknown flag */ return GZIP_BAD; } @@ -215,28 +220,28 @@ static enum { len -= 10; data += 10; - if (flags & EXTRA_FIELD) { + if(flags & EXTRA_FIELD) { ssize_t extra_len; - if (len < 2) + if(len < 2) return GZIP_UNDERFLOW; extra_len = (data[1] << 8) | data[0]; - if (len < (extra_len+2)) + if(len < (extra_len+2)) return GZIP_UNDERFLOW; len -= (extra_len + 2); data += (extra_len + 2); } - if (flags & ORIG_NAME) { + if(flags & ORIG_NAME) { /* Skip over NUL-terminated file name */ - while (len && *data) { + while(len && *data) { --len; ++data; } - if (!len || *data) + if(!len || *data) return GZIP_UNDERFLOW; /* Skip over the NUL */ @@ -244,26 +249,24 @@ static enum { ++data; } - if (flags & COMMENT) { + if(flags & COMMENT) { /* Skip over NUL-terminated comment */ - while (len && *data) { + while(len && *data) { --len; ++data; } - if (!len || *data) + if(!len || *data) return GZIP_UNDERFLOW; /* Skip over the NUL */ --len; - ++data; } - if (flags & HEAD_CRC) { - if (len < 2) + if(flags & HEAD_CRC) { + if(len < 2) return GZIP_UNDERFLOW; len -= 2; - data += 2; } *headerlen = totallen - len; @@ -273,41 +276,39 @@ static enum { CURLcode Curl_unencode_gzip_write(struct connectdata *conn, - struct Curl_transfer_keeper *k, + struct SingleRequest *k, ssize_t nread) { z_stream *z = &k->z; /* zlib state structure */ /* Initialize zlib? */ - if (k->zlib_init == ZLIB_UNINIT) { - z->zalloc = (alloc_func)Z_NULL; - z->zfree = (free_func)Z_NULL; - z->opaque = 0; - z->next_in = NULL; - z->avail_in = 0; - - if (strcmp(zlibVersion(), "1.2.0.4") >= 0) { - /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ - if (inflateInit2(z, MAX_WBITS+32) != Z_OK) { - return process_zlib_error(conn, z); - } - k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ - - } else { - /* we must parse the gzip header ourselves */ - if (inflateInit2(z, -MAX_WBITS) != Z_OK) { - return process_zlib_error(conn, z); - } - k->zlib_init = ZLIB_INIT; /* Initial call state */ + if(k->zlib_init == ZLIB_UNINIT) { + memset(z, 0, sizeof(z_stream)); + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; + + if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { + /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ + if(inflateInit2(z, MAX_WBITS+32) != Z_OK) { + return process_zlib_error(conn, z); + } + k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ + } + else { + /* we must parse the gzip header ourselves */ + if(inflateInit2(z, -MAX_WBITS) != Z_OK) { + return process_zlib_error(conn, z); + } + k->zlib_init = ZLIB_INIT; /* Initial call state */ } } - if (k->zlib_init == ZLIB_INIT_GZIP) { - /* Let zlib handle the gzip decompression entirely */ - z->next_in = (Bytef *)k->str; - z->avail_in = (uInt)nread; - /* Now uncompress the data */ - return inflate_stream(conn, k); + if(k->zlib_init == ZLIB_INIT_GZIP) { + /* Let zlib handle the gzip decompression entirely */ + z->next_in = (Bytef *)k->str; + z->avail_in = (uInt)nread; + /* Now uncompress the data */ + return inflate_stream(conn, k); } #ifndef OLD_ZLIB_SUPPORT @@ -350,7 +351,7 @@ Curl_unencode_gzip_write(struct connectdata *conn, */ z->avail_in = (uInt)nread; z->next_in = malloc(z->avail_in); - if (z->next_in == NULL) { + if(z->next_in == NULL) { return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, k->str, z->avail_in); @@ -372,9 +373,9 @@ Curl_unencode_gzip_write(struct connectdata *conn, ssize_t hlen; unsigned char *oldblock = z->next_in; - z->avail_in += nread; + z->avail_in += (uInt)nread; z->next_in = realloc(z->next_in, z->avail_in); - if (z->next_in == NULL) { + if(z->next_in == NULL) { free(oldblock); return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } @@ -412,7 +413,7 @@ Curl_unencode_gzip_write(struct connectdata *conn, break; } - if (z->avail_in == 0) { + if(z->avail_in == 0) { /* We don't have any data to inflate; wait until next time */ return CURLE_OK; } @@ -421,4 +422,14 @@ Curl_unencode_gzip_write(struct connectdata *conn, return inflate_stream(conn, k); #endif } + +void Curl_unencode_cleanup(struct connectdata *conn) +{ + struct SessionHandle *data = conn->data; + struct SingleRequest *k = &data->req; + z_stream *z = &k->z; + if(k->zlib_init != ZLIB_UNINIT) + (void) exit_zlib(z, &k->zlib_init, CURLE_OK); +} + #endif /* HAVE_LIBZ */ |