xref: /PHP-5.6/ext/zip/lib/zip_source_deflate.c (revision 0a950a05)
1 /*
2   zip_source_deflate.c -- deflate (de)compressoin routines
3   Copyright (C) 2009 Dieter Baron and Thomas Klausner
4 
5   This file is part of libzip, a library to manipulate ZIP archives.
6   The authors can be contacted at <libzip@nih.at>
7 
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions
10   are met:
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in
15      the documentation and/or other materials provided with the
16      distribution.
17   3. The names of the authors may not be used to endorse or promote
18      products derived from this software without specific prior
19      written permission.
20 
21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 
35 
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "zipint.h"
40 
41 struct deflate {
42     int e[2];
43 
44     int eof;
45     int mem_level;
46     zip_uint64_t size;
47     char buffer[BUFSIZE];
48     z_stream zstr;
49 };
50 
51 static zip_int64_t compress_read(struct zip_source *, struct deflate *,
52 				 void *, zip_uint64_t);
53 static zip_int64_t decompress_read(struct zip_source *, struct deflate *,
54 				   void *, zip_uint64_t);
55 static zip_int64_t deflate_compress(struct zip_source *, void *, void *,
56 				    zip_uint64_t, enum zip_source_cmd);
57 static zip_int64_t deflate_decompress(struct zip_source *, void *, void *,
58 				      zip_uint64_t, enum zip_source_cmd);
59 static void deflate_free(struct deflate *);
60 
61 
62 
63 struct zip_source *
zip_source_deflate(struct zip * za,struct zip_source * src,zip_int32_t cm,int flags)64 zip_source_deflate(struct zip *za, struct zip_source *src,
65 		   zip_int32_t cm, int flags)
66 {
67     struct deflate *ctx;
68     struct zip_source *s2;
69 
70     if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
71 	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
72 	return NULL;
73     }
74 
75     if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
76 	_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
77 	return NULL;
78     }
79 
80     ctx->e[0] = ctx->e[1] = 0;
81     ctx->eof = 0;
82     if (flags & ZIP_CODEC_ENCODE) {
83 	if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
84 	    ctx->mem_level = TORRENT_MEM_LEVEL;
85 	else
86 	    ctx->mem_level = MAX_MEM_LEVEL;
87     }
88 
89     if ((s2=zip_source_layered(za, src,
90 			       ((flags & ZIP_CODEC_ENCODE)
91 				? deflate_compress : deflate_decompress),
92 			       ctx)) == NULL) {
93 	deflate_free(ctx);
94 	return NULL;
95     }
96 
97     return s2;
98 }
99 
100 
101 
102 static zip_int64_t
compress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)103 compress_read(struct zip_source *src, struct deflate *ctx,
104 	      void *data, zip_uint64_t len)
105 {
106     int end, ret;
107     zip_int64_t n;
108 
109     if (ctx->e[0] != 0)
110 	return -1;
111 
112     if (len == 0)
113 	return 0;
114 
115     ctx->zstr.next_out = (Bytef *)data;
116     ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */
117 
118     end = 0;
119     while (!end) {
120 	ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
121 
122 	switch (ret) {
123 	case Z_OK:
124 	case Z_STREAM_END:
125 	    /* all ok */
126 
127 	    if (ctx->zstr.avail_out == 0
128 		|| (ctx->eof && ctx->zstr.avail_in == 0))
129 		end = 1;
130 	    break;
131 
132 	case Z_BUF_ERROR:
133 	    if (ctx->zstr.avail_in == 0) {
134 		if (ctx->eof) {
135 		    end = 1;
136 		    break;
137 		}
138 
139 		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
140 		    zip_source_error(src, ctx->e, ctx->e+1);
141 		    end = 1;
142 		    break;
143 		}
144 		else if (n == 0) {
145 		    ctx->eof = 1;
146 		    ctx->size = ctx->zstr.total_in;
147 		    /* TODO: check against stat of src? */
148 		}
149 		else {
150 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
151 		    ctx->zstr.avail_in = (uInt)n;
152 		}
153 		continue;
154 	    }
155 	    /* fallthrough */
156 	case Z_NEED_DICT:
157 	case Z_DATA_ERROR:
158 	case Z_STREAM_ERROR:
159 	case Z_MEM_ERROR:
160 	    ctx->e[0] = ZIP_ER_ZLIB;
161 	    ctx->e[1] = ret;
162 
163 	    end = 1;
164 	    break;
165 	}
166     }
167 
168     if (ctx->zstr.avail_out < len)
169 	return (zip_int64_t)(len - ctx->zstr.avail_out);
170 
171     return (ctx->e[0] == 0) ? 0 : -1;
172 }
173 
174 
175 
176 static zip_int64_t
decompress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)177 decompress_read(struct zip_source *src, struct deflate *ctx,
178 		void *data, zip_uint64_t len)
179 {
180     int end, ret;
181     zip_int64_t n;
182 
183     if (ctx->e[0] != 0)
184 	return -1;
185 
186     if (len == 0)
187 	return 0;
188 
189     ctx->zstr.next_out = (Bytef *)data;
190     ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */
191 
192     end = 0;
193     while (!end && ctx->zstr.avail_out) {
194 	ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
195 
196 	switch (ret) {
197 	case Z_OK:
198 	    break;
199 
200 	case Z_STREAM_END:
201 	    ctx->eof = 1;
202 	    end = 1;
203 	    break;
204 
205 	case Z_BUF_ERROR:
206 	    if (ctx->zstr.avail_in == 0) {
207 		if (ctx->eof) {
208 		    end = 1;
209 		    break;
210 		}
211 
212 		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
213 		    zip_source_error(src, ctx->e, ctx->e+1);
214 		    end = 1;
215 		    break;
216 		}
217 		else if (n == 0)
218 		    ctx->eof = 1;
219 		else {
220 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
221 		    ctx->zstr.avail_in = (uInt)n;
222 		}
223 		continue;
224 	    }
225 	    /* fallthrough */
226 	case Z_NEED_DICT:
227 	case Z_DATA_ERROR:
228 	case Z_STREAM_ERROR:
229 	case Z_MEM_ERROR:
230 	    ctx->e[0] = ZIP_ER_ZLIB;
231 	    ctx->e[1] = ret;
232 	    end = 1;
233 	    break;
234 	}
235     }
236 
237     if (ctx->zstr.avail_out < len)
238 	return (zip_int64_t)(len - ctx->zstr.avail_out);
239 
240     return (ctx->e[0] == 0) ? 0 : -1;
241 }
242 
243 
244 
245 static zip_int64_t
deflate_compress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)246 deflate_compress(struct zip_source *src, void *ud, void *data,
247 		 zip_uint64_t len, enum zip_source_cmd cmd)
248 {
249     struct deflate *ctx;
250     int ret;
251 
252     ctx = (struct deflate *)ud;
253 
254     switch (cmd) {
255     case ZIP_SOURCE_OPEN:
256 	ctx->zstr.zalloc = Z_NULL;
257 	ctx->zstr.zfree = Z_NULL;
258 	ctx->zstr.opaque = NULL;
259 	ctx->zstr.avail_in = 0;
260 	ctx->zstr.next_in = NULL;
261 	ctx->zstr.avail_out = 0;
262 	ctx->zstr.next_out = NULL;
263 
264 	/* negative value to tell zlib not to write a header */
265 	if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED,
266 			      -MAX_WBITS, ctx->mem_level,
267 			      Z_DEFAULT_STRATEGY)) != Z_OK) {
268 	    ctx->e[0] = ZIP_ER_ZLIB;
269 	    ctx->e[1] = ret;
270 	    return -1;
271 	}
272 
273 	return 0;
274 
275     case ZIP_SOURCE_READ:
276 	return compress_read(src, ctx, data, len);
277 
278     case ZIP_SOURCE_CLOSE:
279 	deflateEnd(&ctx->zstr);
280 	return 0;
281 
282     case ZIP_SOURCE_STAT:
283     	{
284 	    struct zip_stat *st;
285 
286 	    st = (struct zip_stat *)data;
287 
288 	    st->comp_method = ZIP_CM_DEFLATE;
289 	    st->valid |= ZIP_STAT_COMP_METHOD;
290 	    if (ctx->eof) {
291 		st->comp_size = ctx->size;
292 		st->valid |= ZIP_STAT_COMP_SIZE;
293 	    }
294 	    else
295 		st->valid &= ~ZIP_STAT_COMP_SIZE;
296 	}
297 	return 0;
298 
299     case ZIP_SOURCE_ERROR:
300 	memcpy(data, ctx->e, sizeof(int)*2);
301 	return sizeof(int)*2;
302 
303     case ZIP_SOURCE_FREE:
304 	deflate_free(ctx);
305 	return 0;
306 
307     default:
308 	ctx->e[0] = ZIP_ER_INVAL;
309 	ctx->e[1] = 0;
310 	return -1;
311     }
312 }
313 
314 
315 
316 static zip_int64_t
deflate_decompress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)317 deflate_decompress(struct zip_source *src, void *ud, void *data,
318 		   zip_uint64_t len, enum zip_source_cmd cmd)
319 {
320     struct deflate *ctx;
321     zip_int64_t n;
322     int ret;
323 
324     ctx = (struct deflate *)ud;
325 
326     switch (cmd) {
327     case ZIP_SOURCE_OPEN:
328 	if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
329 	    return ZIP_SOURCE_ERR_LOWER;
330 
331 	ctx->zstr.zalloc = Z_NULL;
332 	ctx->zstr.zfree = Z_NULL;
333 	ctx->zstr.opaque = NULL;
334 	ctx->zstr.next_in = (Bytef *)ctx->buffer;
335 	ctx->zstr.avail_in = (uInt)n /* TODO: check for overflow */;
336 
337 	/* negative value to tell zlib that there is no header */
338 	if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
339 	    ctx->e[0] = ZIP_ER_ZLIB;
340 	    ctx->e[1] = ret;
341 
342 	    return -1;
343 	}
344 	return 0;
345 
346     case ZIP_SOURCE_READ:
347 	return decompress_read(src, ctx, data, len);
348 
349     case ZIP_SOURCE_CLOSE:
350 	inflateEnd(&ctx->zstr);
351 	return 0;
352 
353     case ZIP_SOURCE_STAT:
354 	{
355 	    struct zip_stat *st;
356 
357 	    st = (struct zip_stat *)data;
358 
359 	    st->comp_method = ZIP_CM_STORE;
360 	    if (st->comp_size > 0 && st->size > 0)
361 		st->comp_size = st->size;
362 	}
363 	return 0;
364 
365     case ZIP_SOURCE_ERROR:
366 	if (len < sizeof(int)*2)
367 	    return -1;
368 
369 	memcpy(data, ctx->e, sizeof(int)*2);
370 	return sizeof(int)*2;
371 
372     case ZIP_SOURCE_FREE:
373 	/* TODO: inflateEnd if close was not called */
374 	free(ctx);
375 	return 0;
376 
377     default:
378 	ctx->e[0] = ZIP_ER_INVAL;
379 	ctx->e[1] = 0;
380 	return -1;
381     }
382 
383 }
384 
385 
386 
387 static void
deflate_free(struct deflate * ctx)388 deflate_free(struct deflate *ctx)
389 {
390     /* TODO: deflateEnd if close was not called */
391     free(ctx);
392 }
393