3 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 * Uncompresses a zlib compressed packet inside a message of tvb at offset with
39 * length comprlen. Returns an uncompressed tvbuffer if uncompression
40 * succeeded or NULL if uncompression failed.
42 #define TVB_Z_MIN_BUFSIZ 32768
43 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
44 /* #define TVB_Z_DEBUG 1 */
48 tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
53 guint8 *uncompr = NULL;
54 tvbuff_t *uncompr_tvb = NULL;
58 gint wbits = MAX_WBITS;
62 guint inflate_passes = 0;
63 guint bytes_in = tvb_captured_length_remaining(tvb, offset);
70 compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
76 * Assume that the uncompressed data is at least twice as big as
77 * the compressed size.
79 bufsiz = tvb_captured_length_remaining(tvb, offset) * 2;
80 bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
83 printf("bufsiz: %u bytes\n", bufsiz);
88 strm = g_new0(z_stream, 1);
90 strm->avail_in = comprlen;
92 strmbuf = (Bytef *)g_malloc0(bufsiz);
93 strm->next_out = strmbuf;
94 strm->avail_out = bufsiz;
96 err = inflateInit2(strm, wbits);
107 memset(strmbuf, '\0', bufsiz);
108 strm->next_out = strmbuf;
109 strm->avail_out = bufsiz;
111 err = inflate(strm, Z_SYNC_FLUSH);
113 if (err == Z_OK || err == Z_STREAM_END) {
114 guint bytes_pass = bufsiz - strm->avail_out;
120 if (uncompr == NULL) {
122 * This is ugly workaround for bug #6480
123 * (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6480)
125 * g_memdup(..., 0) returns NULL (g_malloc(0) also)
126 * when uncompr is NULL logic below doesn't create tvb
127 * which is later interpreted as decompression failed.
129 uncompr = (guint8 *)((bytes_pass || err != Z_STREAM_END) ?
130 g_memdup(strmbuf, bytes_pass) :
133 guint8 *new_data = (guint8 *)g_malloc0(bytes_out + bytes_pass);
135 memcpy(new_data, uncompr, bytes_out);
136 memcpy(new_data + bytes_out, strmbuf, bytes_pass);
142 bytes_out += bytes_pass;
144 if (err == Z_STREAM_END) {
150 } else if (err == Z_BUF_ERROR) {
152 * It's possible that not enough frames were captured
153 * to decompress this fully, so return what we've done
160 if (uncompr != NULL) {
167 } else if (err == Z_DATA_ERROR && inits_done == 1
168 && uncompr == NULL && comprlen >= 2 &&
169 (*compr == 0x1f) && (*(compr + 1) == 0x8b)) {
171 * inflate() is supposed to handle both gzip and deflate
172 * streams automatically, but in reality it doesn't
173 * seem to handle either (at least not within the
174 * context of an HTTP response.) We have to try
175 * several tweaks, depending on the type of data and
176 * version of the library installed.
180 * Gzip file format. Skip past the header, since the
181 * fix to make it work (setting windowBits to 31)
182 * doesn't work with all versions of the library.
184 Bytef *c = compr + 2;
187 /* we read two bytes already (0x1f, 0x8b) and
188 need at least Z_DEFLATED, 1 byte flags, 4
189 bytes MTIME, 1 byte XFL, 1 byte OS */
190 if (comprlen < 10 || *c != Z_DEFLATED) {
202 /* Skip past the MTIME (4 bytes),
203 XFL, and OS fields (1 byte each). */
206 if (flags & (1 << 2)) {
207 /* An Extra field is present. It
208 consists of 2 bytes xsize and xsize
210 Read byte-by-byte (least significant
211 byte first) to make sure we abort
212 cleanly when the xsize is truncated
213 after the first byte. */
216 if (c-compr < comprlen) {
220 if (c-compr < comprlen) {
228 if (flags & (1 << 3)) {
229 /* A null terminated filename */
231 while ((c - compr) < comprlen && *c != '\0') {
238 if (flags & (1 << 4)) {
239 /* A null terminated comment */
241 while ((c - compr) < comprlen && *c != '\0') {
251 strm->next_in = next;
252 if (c - compr > comprlen) {
259 comprlen -= (int) (c - compr);
262 inflateInit2(strm, wbits);
264 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
268 * Re-init the stream with a negative
269 * MAX_WBITS. This is necessary due to
270 * some servers (Apache) not sending
271 * the deflate header with the
272 * content-encoded response.
278 strm->next_in = next;
279 strm->avail_in = comprlen;
282 memset(strmbuf, '\0', bufsiz);
283 strm->next_out = strmbuf;
284 strm->avail_out = bufsiz;
286 err = inflateInit2(strm, wbits);
303 if (uncompr == NULL) {
313 printf("inflate() total passes: %u\n", inflate_passes);
314 printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
317 if (uncompr != NULL) {
318 uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out, bytes_out);
319 tvb_set_free_cb(uncompr_tvb, g_free);
326 tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
333 tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
335 tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
337 tvb_set_child_real_data_tvbuff (parent, new_tvb);
342 * Editor modelines - http://www.wireshark.org/tools/modelines.html
347 * indent-tabs-mode: t
350 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
351 * :indentSize=8:tabSize=8:noTabs=false: