1 /* Low-level function, decompresses deflate compressed data. Used by gzip_uncompress below. */
3 #include "zlib_interface.h"
12 unsigned char magic[2];
15 unsigned char mtime[4];
21 unsigned char crc32[4];
22 unsigned char size[4];
25 int jg_zlib_uncompress(void * const in_buf, int in_size,
26 void **out_buf_ptr, int *out_size,
32 int out_buf_bytes = 0;
37 /* Prepare the stream structure. */
41 stream.next_in = in_buf;
42 stream.avail_in = in_size;
43 stream.next_out = tmp_buf;
44 stream.avail_out = sizeof tmp_buf;
50 result = inflateInit2(&stream, MAX_WBITS + 32); /* UNTESTED */
52 result = inflateInit2(&stream, -MAX_WBITS);
56 fprintf(stderr, "inflateInit2 failed: %d\n", result);
57 return JG_ZLIB_ERROR_OLDVERSION;
61 /* Should be Z_FINISH? */
62 result = inflate(&stream, Z_NO_FLUSH);
65 if (stream.avail_in == 0)
66 goto DONE; /* zlib bug */
75 snprintf (tmpstring, sizeof(tmpstring), "ERROR: zlib_uncompress: %d %s\n", result, stream.msg);
76 fprintf(stderr, tmpstring);
78 return JG_ZLIB_ERROR_UNCOMPRESS;
80 if (stream.avail_out < sizeof tmp_buf) {
81 /* Add the new uncompressed data to our output buffer. */
82 new_bytes = sizeof tmp_buf - stream.avail_out;
83 out_buf = realloc(out_buf, out_buf_bytes + new_bytes);
84 memcpy(out_buf + out_buf_bytes, tmp_buf, new_bytes);
85 out_buf_bytes += new_bytes;
86 stream.next_out = tmp_buf;
87 stream.avail_out = sizeof tmp_buf;
89 /* For some reason, inflate() didn't write out a single byte. */
93 fprintf(stderr, "ERROR: No output during decompression\n");
94 return JG_ZLIB_ERROR_NODATA;
96 } while (result != Z_STREAM_END);
102 /* Null-terminate the output buffer so it can be handled like a string. */
103 out_buf = realloc(out_buf, out_buf_bytes + 1);
104 out_buf[out_buf_bytes] = 0;
106 /* The returned size does NOT include the additionall null byte! */
107 if (out_size != NULL)
108 *out_size = out_buf_bytes;
110 *out_buf_ptr = out_buf;
115 /* Decompressed gzip,deflate compressed data. This is what the webservers usually send. */
117 int jg_gzip_uncompress(void *in_buf, int in_size,
118 void **out_buf_ptr, int *out_size)
120 char tmpstring[1024];
121 struct gzip_header *header;
123 int offset = sizeof *header;
127 if (out_size != NULL)
130 if ((header->magic[0] != 0x1F) || (header->magic[1] != 0x8B)) {
132 fprintf(stderr, "ERROR: Invalid magic bytes for GZIP data\n");
133 return JG_ZLIB_ERROR_BAD_MAGIC;
136 if (header->method != 8) {
138 fprintf(stderr, "ERROR: Compression method is not deflate\n");
139 return JG_ZLIB_ERROR_BAD_METHOD;
142 if (header->flags != 0 && header->flags != 8) {
144 snprintf (tmpstring, sizeof(tmpstring), "ERROR: Unsupported flags %d", header->flags);
145 fprintf(stderr, "ERROR: %s\n", tmpstring);
147 return JG_ZLIB_ERROR_BAD_FLAGS;
150 if (header->flags & 8) {
151 /* skip the file name */
152 while (offset < in_size) {
153 if (((char *)in_buf)[offset] == 0) {
161 data_start = (char *)in_buf + offset;
163 return jg_zlib_uncompress(data_start, in_size - offset - 8,
164 out_buf_ptr, out_size, 0);