63
77
check_header (GsfInputGZip *input)
65
static guint8 const signature [2] = {0x1f, 0x8b};
71
if (gsf_input_seek (input->source, (gsf_off_t) 0, G_SEEK_SET) ||
72
NULL == (data = gsf_input_read (input->source, 2 + 1 + 1 + 6, NULL)) ||
73
0 != memcmp (data, signature, sizeof (signature)))
76
/* verify flags and compression type */
78
if (data [2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
81
/* Get the uncompressed size */
82
if (gsf_input_seek (input->source, (gsf_off_t) -4, G_SEEK_END) ||
83
NULL == (data = gsf_input_read (input->source, 4, NULL)))
85
/* FIXME, but how? The size read here is modulo 2^32. */
86
gsf_input_set_size (GSF_INPUT (input),
87
(gsf_off_t) GSF_LE_GET_GUINT32 (data));
89
if (gsf_input_seek (input->source, (gsf_off_t) 2 + 1 + 1 + 6,
93
if (flags & GZIP_EXTRA_FIELD) {
94
if (NULL == (data = gsf_input_read (input->source, 2, NULL)))
96
len = data [0] | (data [1] << 8);
97
if (NULL == gsf_input_read (input->source, len, NULL))
100
if (flags & GZIP_ORIGINAL_NAME) {
101
/* Skip over the filename (which is in ISO 8859-1 encoding). */
103
if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
105
} while (*data != 0);
108
if (flags & GZIP_HAS_COMMENT) {
109
/* Skip over the comment (which is in ISO 8859-1 encoding). */
111
if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
113
} while (*data != 0);
116
if (flags & GZIP_HEADER_CRC &&
117
NULL == (data = gsf_input_read (input->source, 2, NULL)))
120
input->header_size = input->source->cur_offset;
122
if (gsf_input_remaining (input->source) < 9)
80
input->header_size = 0;
81
input->trailer_size = 0;
83
static guint8 const signature[2] = {0x1f, 0x8b};
88
if (NULL == (data = gsf_input_read (input->source, 2 + 1 + 1 + 6, NULL)) ||
89
0 != memcmp (data, signature, sizeof (signature)))
92
/* verify flags and compression type */
94
if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
97
/* If we have the size, don't bother seeking to the end. */
98
if (input->uncompressed_size < 0) {
99
/* Get the uncompressed size */
100
if (gsf_input_seek (input->source, (gsf_off_t) -4, G_SEEK_END) ||
101
NULL == (data = gsf_input_read (input->source, 4, NULL)))
103
/* FIXME, but how? The size read here is modulo 2^32. */
104
input->uncompressed_size = GSF_LE_GET_GUINT32 (data);
106
if (input->uncompressed_size / 1000 > gsf_input_size (input->source)) {
107
g_warning ("Suspiciously well compressed file with better than 1000:1 ratio.\n"
108
"It is probably truncated or corrupt");
112
if (gsf_input_seek (input->source, 2 + 1 + 1 + 6, G_SEEK_SET))
115
if (flags & GZIP_EXTRA_FIELD) {
116
if (NULL == (data = gsf_input_read (input->source, 2, NULL)))
118
len = GSF_LE_GET_GUINT16 (data);
119
if (NULL == gsf_input_read (input->source, len, NULL))
122
if (flags & GZIP_ORIGINAL_NAME) {
123
/* Skip over the filename (which is in ISO 8859-1 encoding). */
125
if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
127
} while (*data != 0);
130
if (flags & GZIP_HAS_COMMENT) {
131
/* Skip over the comment (which is in ISO 8859-1 encoding). */
133
if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
135
} while (*data != 0);
138
if (flags & GZIP_HEADER_CRC &&
139
NULL == (data = gsf_input_read (input->source, 2, NULL)))
142
input->header_size = input->source->cur_offset;
143
/* the last 8 bytes are the crc and size. */
144
input->trailer_size = 8;
147
gsf_input_set_size (GSF_INPUT (input), input->uncompressed_size);
149
if (gsf_input_remaining (input->source) < input->trailer_size)
123
150
return TRUE; /* No room for payload */
129
156
init_zip (GsfInputGZip *gzip, GError **err)
131
158
gsf_off_t cur_pos;
133
160
if (Z_OK != inflateInit2 (&(gzip->stream), -MAX_WBITS)) {
135
*err = g_error_new (gsf_input_error (), 0,
162
*err = g_error_new (gsf_input_error_id (), 0,
136
163
"Unable to initialize zlib");
140
167
cur_pos = gsf_input_tell (gzip->source);
168
if (gsf_input_seek (gzip->source, 0, G_SEEK_SET)) {
170
*err = g_error_new (gsf_input_error_id (), 0,
171
"Failed to rewind source");
142
175
if (check_header (gzip) != FALSE) {
144
*err = g_error_new (gsf_input_error (), 0,
177
*err = g_error_new (gsf_input_error_id (), 0,
145
178
"Invalid gzip header");
146
179
if (gsf_input_seek (gzip->source, cur_pos, G_SEEK_SET)) {
147
180
g_warning ("attempt to restore position failed ??");
162
195
* Returns a new file or NULL.
165
198
gsf_input_gzip_new (GsfInput *source, GError **err)
167
200
GsfInputGZip *gzip;
169
202
g_return_val_if_fail (GSF_IS_INPUT (source), NULL);
171
gzip = g_object_new (GSF_INPUT_GZIP_TYPE, NULL);
172
g_object_ref (G_OBJECT (source));
173
gzip->source = source;
174
gzip->seek_skipped = 0;
176
if (init_zip (gzip, err) != FALSE) {
177
g_object_unref (G_OBJECT (gzip));
204
gzip = g_object_new (GSF_INPUT_GZIP_TYPE,
209
*err = g_error_copy (gzip->err);
210
g_object_unref (gzip);
214
return GSF_INPUT (gzip);
185
218
gsf_input_gzip_finalize (GObject *obj)
187
GObjectClass *parent_class;
188
220
GsfInputGZip *gzip = (GsfInputGZip *)obj;
190
222
if (gzip->source != NULL) {
197
229
if (gzip->stream.state != NULL)
198
230
inflateEnd (&(gzip->stream));
200
parent_class = g_type_class_peek (GSF_INPUT_TYPE);
201
if (parent_class && parent_class->finalize)
202
parent_class->finalize (obj);
232
g_clear_error (&gzip->err);
234
parent_class->finalize (obj);
205
237
static GsfInput *
206
238
gsf_input_gzip_dup (GsfInput *src_input, GError **err)
208
240
GsfInputGZip const *src = (GsfInputGZip *)src_input;
209
GsfInputGZip *dst = g_object_new (GSF_INPUT_GZIP_TYPE, NULL);
211
dst->source = gsf_input_dup(src->source, NULL);
213
if (init_zip (dst, err) != FALSE) {
214
g_object_unref (G_OBJECT (dst));
242
GsfInput *src_source_copy;
245
src_source_copy = gsf_input_dup (src->source, err);
249
src_source_copy = NULL;
251
dst = g_object_new (GSF_INPUT_GZIP_TYPE,
252
"source", src_source_copy,
256
g_object_unref (src_source_copy);
259
g_clear_error (&dst->err);
260
dst->err = g_error_copy (src->err);
261
} else if (dst->err) {
263
*err = g_error_copy (dst->err);
264
g_object_unref (dst);
238
287
while (gzip->stream.avail_out != 0) {
240
289
if (gzip->stream.avail_in == 0) {
241
/* the last 8 bytes are the crc and size, but we need 1
242
* byte to flush the decompresion.
244
290
gsf_off_t remain = gsf_input_remaining (gzip->source);
248
n = MIN (remain - 7, Z_BUFSIZE);
291
if (remain <= gzip->trailer_size) {
292
if (remain < gzip->trailer_size || gzip->stop_byte_added) {
293
g_clear_error (&gzip->err);
294
gzip->err = g_error_new
295
(gsf_input_error_id (), 0,
299
/* zlib requires an extra byte. */
300
gzip->stream.avail_in = 1;
301
gzip->gzipped_data = "";
302
gzip->stop_byte_added = TRUE;
304
size_t n = MIN (remain - gzip->trailer_size,
250
if (NULL == (gzip->gzipped_data = gsf_input_read (gzip->source, n, NULL)))
252
gzip->stream.avail_in = n;
308
gsf_input_read (gzip->source, n, NULL);
309
if (!gzip->gzipped_data) {
310
g_clear_error (&gzip->err);
311
gzip->err = g_error_new
312
(gsf_input_error_id (), 0,
313
"Failed to read from source");
316
gzip->stream.avail_in = n;
253
318
gzip->stream.next_in = (Byte *)gzip->gzipped_data;
255
320
zerr = inflate (&(gzip->stream), Z_NO_FLUSH);
323
391
gzip->crc = crc32 (0L, Z_NULL, 0);
324
392
gzip->buf = NULL;
325
393
gzip->buf_size = 0;
394
gzip->seek_skipped = 0;
398
gsf_input_gzip_get_property (GObject *object,
403
GsfInputGZip *gzip = (GsfInputGZip *)object;
405
switch (property_id) {
407
g_value_set_boolean (value, gzip->raw);
410
g_value_set_object (value, gzip->source);
412
case PROP_UNCOMPRESSED_SIZE:
413
g_value_set_int64 (value, gzip->uncompressed_size);
416
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
422
gsf_input_gzip_set_source (GsfInputGZip *gzip, GsfInput *source)
425
g_object_ref (GSF_INPUT (source));
427
g_object_unref (gzip->source);
428
gzip->source = source;
432
gsf_input_gzip_set_property (GObject *object,
437
GsfInputGZip *gzip = (GsfInputGZip *)object;
439
switch (property_id) {
441
gzip->raw = g_value_get_boolean (value);
444
gsf_input_gzip_set_source (gzip, g_value_get_object (value));
446
case PROP_UNCOMPRESSED_SIZE:
447
gzip->uncompressed_size = g_value_get_int64 (value);
450
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
456
gsf_input_gzip_constructor (GType type,
457
guint n_construct_properties,
458
GObjectConstructParam *construct_params)
462
gzip = (GsfInputGZip *)(parent_class->constructor (type,
463
n_construct_properties,
467
g_clear_error (&gzip->err);
468
gzip->err = g_error_new (gsf_input_error_id (), 0,
470
} else if (gzip->raw && gzip->uncompressed_size < 0) {
471
g_clear_error (&gzip->err);
472
gzip->err = g_error_new (gsf_input_error_id (), 0,
473
"Uncompressed size not set");
474
} else if (init_zip (gzip, &gzip->err) != FALSE) {
478
return (GObject *)gzip;
331
484
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
333
gobject_class->finalize = gsf_input_gzip_finalize;
334
input_class->Dup = gsf_input_gzip_dup;
335
input_class->Read = gsf_input_gzip_read;
336
input_class->Seek = gsf_input_gzip_seek;
486
gobject_class->constructor = gsf_input_gzip_constructor;
487
gobject_class->finalize = gsf_input_gzip_finalize;
488
gobject_class->set_property = gsf_input_gzip_set_property;
489
gobject_class->get_property = gsf_input_gzip_get_property;
490
input_class->Dup = gsf_input_gzip_dup;
491
input_class->Read = gsf_input_gzip_read;
492
input_class->Seek = gsf_input_gzip_seek;
494
g_object_class_install_property
497
g_param_spec_boolean ("raw", "Raw",
498
"Whether to read compressed data with no header and no trailer.",
502
G_PARAM_CONSTRUCT_ONLY));
503
g_object_class_install_property
506
g_param_spec_object ("source", "Source",
507
"Where the compressed data comes from.",
511
G_PARAM_CONSTRUCT_ONLY));
513
* GsfInputGzip:uncompressed_size:
515
* The size that the data will have after uncompression.
516
* The is mandatory for raw streams and if the uncompressed size is
519
g_object_class_install_property
521
PROP_UNCOMPRESSED_SIZE,
522
g_param_spec_int64 ("uncompressed-size", "Size after decompression",
523
"The source's uncompressed size",
527
G_PARAM_CONSTRUCT_ONLY));
529
parent_class = g_type_class_peek_parent (gobject_class);
339
532
GSF_CLASS (GsfInputGZip, gsf_input_gzip,
340
533
gsf_input_gzip_class_init, gsf_input_gzip_init, GSF_INPUT_TYPE)