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.
39 * Uncompresses a zlib compressed packet inside a message of tvb at offset with
40 * length comprlen. Returns an uncompressed tvbuffer if uncompression
41 * succeeded or NULL if uncompression failed.
43 #define TVB_Z_MIN_BUFSIZ 32768
44 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
45 /* #define TVB_Z_DEBUG 1 */
49 tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
54 guint8 *uncompr = NULL;
55 tvbuff_t *uncompr_tvb = NULL;
59 gint wbits = MAX_WBITS;
63 guint inflate_passes = 0;
64 guint bytes_in = tvb_captured_length_remaining(tvb, offset);
71 compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
77 * Assume that the uncompressed data is at least twice as big as
78 * the compressed size.
80 bufsiz = tvb_captured_length_remaining(tvb, offset) * 2;
81 bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
84 printf("bufsiz: %u bytes\n", bufsiz);
89 strm = g_new0(z_stream, 1);
91 strm->avail_in = comprlen;
93 strmbuf = (Bytef *)g_malloc0(bufsiz);
94 strm->next_out = strmbuf;
95 strm->avail_out = bufsiz;
97 err = inflateInit2(strm, wbits);
108 memset(strmbuf, '\0', bufsiz);
109 strm->next_out = strmbuf;
110 strm->avail_out = bufsiz;
112 err = inflate(strm, Z_SYNC_FLUSH);
114 if (err == Z_OK || err == Z_STREAM_END) {
115 guint bytes_pass = bufsiz - strm->avail_out;
121 if (uncompr == NULL) {
123 * This is ugly workaround for bug #6480
124 * (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6480)
126 * g_memdup(..., 0) returns NULL (g_malloc(0) also)
127 * when uncompr is NULL logic below doesn't create tvb
128 * which is later interpreted as decompression failed.
130 uncompr = (guint8 *)((bytes_pass || err != Z_STREAM_END) ?
131 g_memdup(strmbuf, bytes_pass) :
134 guint8 *new_data = (guint8 *)g_malloc0(bytes_out + bytes_pass);
136 memcpy(new_data, uncompr, bytes_out);
137 memcpy(new_data + bytes_out, strmbuf, bytes_pass);
143 bytes_out += bytes_pass;
145 if (err == Z_STREAM_END) {
151 } else if (err == Z_BUF_ERROR) {
153 * It's possible that not enough frames were captured
154 * to decompress this fully, so return what we've done
161 if (uncompr != NULL) {
168 } else if (err == Z_DATA_ERROR && inits_done == 1
169 && uncompr == NULL && comprlen >= 2 &&
170 (*compr == 0x1f) && (*(compr + 1) == 0x8b)) {
172 * inflate() is supposed to handle both gzip and deflate
173 * streams automatically, but in reality it doesn't
174 * seem to handle either (at least not within the
175 * context of an HTTP response.) We have to try
176 * several tweaks, depending on the type of data and
177 * version of the library installed.
181 * Gzip file format. Skip past the header, since the
182 * fix to make it work (setting windowBits to 31)
183 * doesn't work with all versions of the library.
185 Bytef *c = compr + 2;
188 /* we read two bytes already (0x1f, 0x8b) and
189 need at least Z_DEFLATED, 1 byte flags, 4
190 bytes MTIME, 1 byte XFL, 1 byte OS */
191 if (comprlen < 10 || *c != Z_DEFLATED) {
203 /* Skip past the MTIME (4 bytes),
204 XFL, and OS fields (1 byte each). */
207 if (flags & (1 << 2)) {
208 /* An Extra field is present. It
209 consists of 2 bytes xsize and xsize
211 Read byte-by-byte (least significant
212 byte first) to make sure we abort
213 cleanly when the xsize is truncated
214 after the first byte. */
217 if (c-compr < comprlen) {
221 if (c-compr < comprlen) {
229 if (flags & (1 << 3)) {
230 /* A null terminated filename */
232 while ((c - compr) < comprlen && *c != '\0') {
239 if (flags & (1 << 4)) {
240 /* A null terminated comment */
242 while ((c - compr) < comprlen && *c != '\0') {
250 if (c - compr > comprlen) {
257 /* Drop gzip header */
258 comprlen -= (int) (c - compr);
262 strm->next_in = next;
263 strm->avail_in = comprlen;
266 inflateInit2(strm, wbits);
268 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
272 * Re-init the stream with a negative
273 * MAX_WBITS. This is necessary due to
274 * some servers (Apache) not sending
275 * the deflate header with the
276 * content-encoded response.
282 strm->next_in = next;
283 strm->avail_in = comprlen;
286 memset(strmbuf, '\0', bufsiz);
287 strm->next_out = strmbuf;
288 strm->avail_out = bufsiz;
290 err = inflateInit2(strm, wbits);
307 if (uncompr == NULL) {
317 printf("inflate() total passes: %u\n", inflate_passes);
318 printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
321 if (uncompr != NULL) {
322 uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out, bytes_out);
323 tvb_set_free_cb(uncompr_tvb, g_free);
330 tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
337 tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
339 tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
341 tvb_set_child_real_data_tvbuff (parent, new_tvb);
346 * Editor modelines - http://www.wireshark.org/tools/modelines.html
351 * indent-tabs-mode: t
354 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
355 * :indentSize=8:tabSize=8:noTabs=false: