1 /* deflate/gzip encoding backend */
19 #include "encoding/deflate.h"
20 #include "encoding/encoding.h"
21 #include "util/memory.h"
23 /* How many bytes of compressed data to read before decompressing. */
24 #define ELINKS_DEFLATE_BUFFER_LENGTH 5000
26 struct deflate_enc_data
{
27 z_stream deflate_stream
;
29 /* The file descriptor from which we read. */
32 unsigned int last_read
:1;
33 unsigned int after_first_read
:1;
35 /* A buffer for data that has been read from the file but not
36 * yet decompressed. z_stream.next_in and z_stream.avail_in
37 * refer to this buffer. */
38 unsigned char buf
[ELINKS_DEFLATE_BUFFER_LENGTH
];
42 deflate_open(int window_size
, struct stream_encoded
*stream
, int fd
)
44 /* A zero-initialized z_stream. The compiler ensures that all
45 * pointer members in it are null. (Can't do this with memset
46 * because C99 does not require all-bits-zero to be a null
48 static const z_stream null_z_stream
= {0};
51 struct deflate_enc_data
*data
= mem_alloc(sizeof(*data
));
58 /* Initialize all members of *data, except data->buf[], which
59 * will be initialized on demand by deflate_read. */
60 copy_struct(&data
->deflate_stream
, &null_z_stream
);
63 data
->after_first_read
= 0;
65 err
= inflateInit2(&data
->deflate_stream
, window_size
);
77 deflate_raw_open(struct stream_encoded
*stream
, int fd
)
79 /* raw DEFLATE with neither zlib nor gzip header */
80 return deflate_open(-MAX_WBITS
, stream
, fd
);
85 deflate_gzip_open(struct stream_encoded
*stream
, int fd
)
87 /* detect gzip header, else assume zlib header */
88 return deflate_open(MAX_WBITS
+ 32, stream
, fd
);
92 deflate_read(struct stream_encoded
*stream
, unsigned char *buf
, int len
)
94 struct deflate_enc_data
*data
= (struct deflate_enc_data
*) stream
->data
;
102 if (data
->last_read
) return 0;
104 data
->deflate_stream
.avail_out
= len
;
105 data
->deflate_stream
.next_out
= buf
;
108 if (data
->deflate_stream
.avail_in
== 0) {
109 l
= safe_read(data
->fdread
, data
->buf
,
110 ELINKS_DEFLATE_BUFFER_LENGTH
);
116 return -1; /* I/O error */
118 /* EOF. It is error: we wait for more bytes */
122 data
->deflate_stream
.next_in
= data
->buf
;
123 data
->deflate_stream
.avail_in
= l
;
126 err
= inflate(&data
->deflate_stream
, Z_SYNC_FLUSH
);
127 if (err
== Z_DATA_ERROR
&& !data
->after_first_read
) {
128 data
->after_first_read
= 1;
129 inflateEnd(&data
->deflate_stream
);
130 data
->deflate_stream
.avail_out
= len
;
131 data
->deflate_stream
.next_out
= buf
;
132 data
->deflate_stream
.next_in
= data
->buf
;
133 data
->deflate_stream
.avail_in
= l
;
134 err
= inflateInit2(&data
->deflate_stream
, -MAX_WBITS
);
135 if (err
== Z_OK
) goto restart
;
137 data
->after_first_read
= 1;
138 if (err
== Z_STREAM_END
) {
141 } else if (err
!= Z_OK
) {
144 } while (data
->deflate_stream
.avail_out
> 0);
146 assert(len
- data
->deflate_stream
.avail_out
== data
->deflate_stream
.next_out
- buf
);
147 return len
- data
->deflate_stream
.avail_out
;
150 static unsigned char *
151 deflate_decode_buffer(int window_size
, unsigned char *data
, int len
, int *new_len
)
154 unsigned char *buffer
= NULL
;
157 *new_len
= 0; /* default, left there if an error occurs */
159 if (!len
) return NULL
;
160 memset(&stream
, 0, sizeof(z_stream
));
161 stream
.next_in
= data
;
162 stream
.avail_in
= len
;
164 if (inflateInit2(&stream
, window_size
) != Z_OK
)
168 unsigned char *new_buffer
;
169 size_t size
= stream
.total_out
+ MAX_STR_LEN
;
171 new_buffer
= mem_realloc(buffer
, size
);
178 stream
.next_out
= buffer
+ stream
.total_out
;
179 stream
.avail_out
= MAX_STR_LEN
;
181 error
= inflate(&stream
, Z_SYNC_FLUSH
);
182 if (error
== Z_STREAM_END
) {
186 } while (error
== Z_OK
&& stream
.avail_in
> 0);
191 *new_len
= stream
.total_out
;
194 if (buffer
) mem_free(buffer
);
199 static unsigned char *
200 deflate_raw_decode_buffer(unsigned char *data
, int len
, int *new_len
)
202 /* raw DEFLATE with neither zlib nor gzip header */
203 return deflate_decode_buffer(-MAX_WBITS
, data
, len
, new_len
);
206 static unsigned char *
207 deflate_gzip_decode_buffer(unsigned char *data
, int len
, int *new_len
)
209 /* detect gzip header, else assume zlib header */
210 return deflate_decode_buffer(MAX_WBITS
+ 32, data
, len
, new_len
);
214 deflate_close(struct stream_encoded
*stream
)
216 struct deflate_enc_data
*data
= (struct deflate_enc_data
*) stream
->data
;
219 inflateEnd(&data
->deflate_stream
);
226 static const unsigned char *const deflate_extensions
[] = { NULL
};
228 const struct decoding_backend deflate_decoding_backend
= {
233 deflate_raw_decode_buffer
,
237 static const unsigned char *const gzip_extensions
[] = { ".gz", ".tgz", NULL
};
239 const struct decoding_backend gzip_decoding_backend
= {
244 deflate_gzip_decode_buffer
,