xref: /PHP-5.5/ext/zip/lib/zip_source_deflate.c (revision 335a11b1)
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 ZIP_EXTERN(struct zip_source *)
zip_source_deflate(struct zip * za,struct zip_source * src,zip_uint16_t cm,int flags)64 zip_source_deflate(struct zip *za, struct zip_source *src,
65 		   zip_uint16_t cm, int flags)
66 {
67     struct deflate *ctx;
68     struct zip_source *s2;
69 
70     if (src == NULL || cm != ZIP_CM_DEFLATE) {
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 = len;
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,
140 				       sizeof(ctx->buffer))) < 0) {
141 		    zip_source_error(src, ctx->e, ctx->e+1);
142 		    end = 1;
143 		    break;
144 		}
145 		else if (n == 0) {
146 		    ctx->eof = 1;
147 		    ctx->size = ctx->zstr.total_in;
148 		    /* XXX: check against stat of src? */
149 		}
150 		else {
151 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
152 		    ctx->zstr.avail_in = n;
153 		}
154 		continue;
155 	    }
156 	    /* fallthrough */
157 	case Z_NEED_DICT:
158 	case Z_DATA_ERROR:
159 	case Z_STREAM_ERROR:
160 	case Z_MEM_ERROR:
161 	    ctx->e[0] = ZIP_ER_ZLIB;
162 	    ctx->e[1] = ret;
163 
164 	    end = 1;
165 	    break;
166 	}
167     }
168 
169     if (ctx->zstr.avail_out < len)
170 	return len - ctx->zstr.avail_out;
171 
172     return (ctx->e[0] == 0) ? 0 : -1;
173 }
174 
175 
176 
177 static zip_int64_t
decompress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)178 decompress_read(struct zip_source *src, struct deflate *ctx,
179 		void *data, zip_uint64_t len)
180 {
181     int end, ret;
182     zip_int64_t n;
183 
184     if (ctx->e[0] != 0)
185 	return -1;
186 
187     if (len == 0)
188 	return 0;
189 
190     ctx->zstr.next_out = (Bytef *)data;
191     ctx->zstr.avail_out = len;
192 
193     end = 0;
194     while (!end && ctx->zstr.avail_out) {
195 	ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
196 
197 	switch (ret) {
198 	case Z_OK:
199 	    break;
200 
201 	case Z_STREAM_END:
202 	    ctx->eof = 1;
203 	    end = 1;
204 	    break;
205 
206 	case Z_BUF_ERROR:
207 	    if (ctx->zstr.avail_in == 0) {
208 		if (ctx->eof) {
209 		    end = 1;
210 		    break;
211 		}
212 
213 		if ((n=zip_source_read(src, ctx->buffer,
214 			    sizeof(ctx->buffer))) < 0) {
215 		    zip_source_error(src, ctx->e, ctx->e+1);
216 		    end = 1;
217 		    break;
218 		}
219 		else if (n == 0)
220 		    ctx->eof = 1;
221 		else {
222 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
223 		    ctx->zstr.avail_in = n;
224 		}
225 		continue;
226 	    }
227 	    /* fallthrough */
228 	case Z_NEED_DICT:
229 	case Z_DATA_ERROR:
230 	case Z_STREAM_ERROR:
231 	case Z_MEM_ERROR:
232 	    ctx->e[0] = ZIP_ER_ZLIB;
233 	    ctx->e[1] = ret;
234 	    end = 1;
235 	    break;
236 	}
237     }
238 
239     if (ctx->zstr.avail_out < len)
240 	return len - ctx->zstr.avail_out;
241 
242     return (ctx->e[0] == 0) ? 0 : -1;
243 }
244 
245 
246 
247 static zip_int64_t
deflate_compress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)248 deflate_compress(struct zip_source *src, void *ud, void *data,
249 		 zip_uint64_t len, enum zip_source_cmd cmd)
250 {
251     struct deflate *ctx;
252     int ret;
253 
254     ctx = (struct deflate *)ud;
255 
256     switch (cmd) {
257     case ZIP_SOURCE_OPEN:
258 	ctx->zstr.zalloc = Z_NULL;
259 	ctx->zstr.zfree = Z_NULL;
260 	ctx->zstr.opaque = NULL;
261 	ctx->zstr.avail_in = 0;
262 	ctx->zstr.next_in = NULL;
263 	ctx->zstr.avail_out = 0;
264 	ctx->zstr.next_out = NULL;
265 
266 	/* negative value to tell zlib not to write a header */
267 	if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED,
268 			      -MAX_WBITS, ctx->mem_level,
269 			      Z_DEFAULT_STRATEGY)) != Z_OK) {
270 	    ctx->e[0] = ZIP_ER_ZLIB;
271 	    ctx->e[1] = ret;
272 	    return -1;
273 	}
274 
275 	return 0;
276 
277     case ZIP_SOURCE_READ:
278 	return compress_read(src, ctx, data, len);
279 
280     case ZIP_SOURCE_CLOSE:
281 	deflateEnd(&ctx->zstr);
282 	return 0;
283 
284     case ZIP_SOURCE_STAT:
285     	{
286 	    struct zip_stat *st;
287 
288 	    st = (struct zip_stat *)data;
289 
290 	    st->comp_method = ZIP_CM_DEFLATE;
291 	    st->valid |= ZIP_STAT_COMP_METHOD;
292 	    if (ctx->eof) {
293 		st->comp_size = ctx->size;
294 		st->valid |= ZIP_STAT_COMP_SIZE;
295 	    }
296 	    else
297 		st->valid &= ~ZIP_STAT_COMP_SIZE;
298 	}
299 	return 0;
300 
301     case ZIP_SOURCE_ERROR:
302 	memcpy(data, ctx->e, sizeof(int)*2);
303 	return sizeof(int)*2;
304 
305     case ZIP_SOURCE_FREE:
306 	deflate_free(ctx);
307 	return 0;
308 
309     default:
310 	ctx->e[0] = ZIP_ER_INVAL;
311 	ctx->e[1] = 0;
312 	return -1;
313     }
314 }
315 
316 
317 
318 static zip_int64_t
deflate_decompress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)319 deflate_decompress(struct zip_source *src, void *ud, void *data,
320 		   zip_uint64_t len, enum zip_source_cmd cmd)
321 {
322     struct deflate *ctx;
323     zip_int64_t n;
324     int ret;
325 
326     ctx = (struct deflate *)ud;
327 
328     switch (cmd) {
329     case ZIP_SOURCE_OPEN:
330 	if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
331 	    return ZIP_SOURCE_ERR_LOWER;
332 
333 	ctx->zstr.zalloc = Z_NULL;
334 	ctx->zstr.zfree = Z_NULL;
335 	ctx->zstr.opaque = NULL;
336 	ctx->zstr.next_in = (Bytef *)ctx->buffer;
337 	ctx->zstr.avail_in = n;
338 
339 	/* negative value to tell zlib that there is no header */
340 	if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
341 	    ctx->e[0] = ZIP_ER_ZLIB;
342 	    ctx->e[1] = ret;
343 
344 	    return -1;
345 	}
346 	return 0;
347 
348     case ZIP_SOURCE_READ:
349 	return decompress_read(src, ctx, data, len);
350 
351     case ZIP_SOURCE_CLOSE:
352 	inflateEnd(&ctx->zstr);
353 	return 0;
354 
355     case ZIP_SOURCE_STAT:
356 	{
357 	    struct zip_stat *st;
358 
359 	    st = (struct zip_stat *)data;
360 
361 	    st->comp_method = ZIP_CM_STORE;
362 	    if (st->comp_size > 0 && st->size > 0)
363 		st->comp_size = st->size;
364 	}
365 	return 0;
366 
367     case ZIP_SOURCE_ERROR:
368 	if (len < sizeof(int)*2)
369 	    return -1;
370 
371 	memcpy(data, ctx->e, sizeof(int)*2);
372 	return sizeof(int)*2;
373 
374     case ZIP_SOURCE_FREE:
375 	/* XXX: inflateEnd if close was not called */
376 	free(ctx);
377 	return 0;
378 
379     default:
380 	ctx->e[0] = ZIP_ER_INVAL;
381 	ctx->e[1] = 0;
382 	return -1;
383     }
384 
385 }
386 
387 
388 
389 static void
deflate_free(struct deflate * ctx)390 deflate_free(struct deflate *ctx)
391 {
392     /* XXX: deflateEnd if close was not called */
393     free(ctx);
394 }
395