cc68a136 |
1 | #include "unzip.h"\r |
2 | \r |
3 | #include <stdlib.h>\r |
4 | #include <string.h>\r |
5 | #include <ctype.h>\r |
6 | #include <assert.h>\r |
7 | \r |
8 | #ifdef __SYMBIAN32__\r |
9 | #include <ezlib.h>\r |
10 | #else\r |
11 | #include "zlib/zlib.h"\r |
12 | #endif\r |
13 | \r |
14 | /* public globals */\r |
15 | //int gUnzipQuiet = 0; /* flag controls error messages */\r |
16 | \r |
17 | #define ERROR_CORRUPT "The zipfile seems to be corrupt, please check it"\r |
18 | #define ERROR_FILESYSTEM "Your filesystem seems to be corrupt, please check it"\r |
19 | #define ERROR_UNSUPPORTED "The format of this zipfile is not supported, please recompress it"\r |
20 | \r |
21 | #define INFLATE_INPUT_BUFFER_MAX 16384\r |
22 | #ifndef MIN\r |
23 | #define MIN(x,y) ((x)<(y)?(x):(y))\r |
24 | #endif\r |
25 | \r |
26 | \r |
27 | // notaz\r |
83bd0b76 |
28 | #if 1 //def __DEBUG_PRINT\r |
29 | #define logerror printf\r |
30 | #define errormsg(str1,def,fname) printf("%s: " #def ": " str1 "\n", fname);\r |
cc68a136 |
31 | #else\r |
32 | #define logerror(x...)\r |
33 | #define errormsg(x...)\r |
34 | #endif\r |
35 | \r |
36 | /* Print a error message */\r |
37 | //void errormsg(const char* extmsg, const char* usermsg, const char* zipname) {\r |
38 | /* Output to the user with no internal detail */\r |
39 | // if (!gUnzipQuiet)\r |
40 | // printf("Error in zipfile %s\n%s\n", zipname, usermsg);\r |
41 | /* Output to log file with all informations */\r |
42 | // logerror("Error in zipfile %s: %s\n", zipname, extmsg);\r |
43 | // printf("Error in zipfile %s: %s\n", zipname, extmsg);\r |
44 | //}\r |
45 | \r |
46 | /* -------------------------------------------------------------------------\r |
47 | Unzip support\r |
48 | ------------------------------------------------------------------------- */\r |
49 | \r |
50 | /* Use these to avoid structure padding and byte-ordering problems */\r |
51 | static UINT16 read_word (char *buf) {\r |
52 | unsigned char *ubuf = (unsigned char *) buf;\r |
53 | \r |
54 | return ((UINT16)ubuf[1] << 8) | (UINT16)ubuf[0];\r |
55 | }\r |
56 | \r |
57 | /* Use these to avoid structure padding and byte-ordering problems */\r |
58 | static UINT32 read_dword (char *buf) {\r |
59 | unsigned char *ubuf = (unsigned char *) buf;\r |
60 | \r |
61 | return ((UINT32)ubuf[3] << 24) | ((UINT32)ubuf[2] << 16) | ((UINT32)ubuf[1] << 8) | (UINT32)ubuf[0];\r |
62 | }\r |
63 | \r |
64 | /* Locate end-of-central-dir sig in buffer and return offset\r |
65 | out:\r |
66 | *offset offset of cent dir start in buffer\r |
67 | return:\r |
68 | ==0 not found\r |
69 | !=0 found, *offset valid\r |
70 | */\r |
71 | static int ecd_find_sig (char *buffer, int buflen, int *offset)\r |
72 | {\r |
73 | static char ecdsig[] = { 'P', 'K', 0x05, 0x06 };\r |
74 | int i;\r |
75 | for (i=buflen-22; i>=0; i--) {\r |
76 | if (memcmp(buffer+i, ecdsig, 4) == 0) {\r |
77 | *offset = i;\r |
78 | return 1;\r |
79 | }\r |
80 | }\r |
81 | return 0;\r |
82 | }\r |
83 | \r |
84 | /* Read ecd data in zip structure\r |
85 | in:\r |
86 | zip->fp, zip->length zip file\r |
87 | out:\r |
88 | zip->ecd, zip->ecd_length ecd data\r |
89 | */\r |
90 | static int ecd_read(ZIP* zip) {\r |
91 | char* buf;\r |
92 | int buf_length = 1024; /* initial buffer length */\r |
93 | \r |
94 | while (1) {\r |
95 | int offset;\r |
96 | \r |
97 | if (buf_length > zip->length)\r |
98 | buf_length = zip->length;\r |
99 | \r |
100 | if (fseek(zip->fp, zip->length - buf_length, SEEK_SET) != 0) {\r |
101 | return -1;\r |
102 | }\r |
103 | \r |
104 | /* allocate buffer */\r |
105 | buf = (char*)malloc( buf_length );\r |
106 | if (!buf) {\r |
107 | return -1;\r |
108 | }\r |
109 | \r |
110 | if (fread( buf, buf_length, 1, zip->fp ) != 1) {\r |
111 | free(buf);\r |
112 | return -1;\r |
113 | }\r |
114 | \r |
115 | if (ecd_find_sig(buf, buf_length, &offset)) {\r |
116 | zip->ecd_length = buf_length - offset;\r |
117 | \r |
118 | zip->ecd = (char*)malloc( zip->ecd_length );\r |
119 | if (!zip->ecd) {\r |
120 | free(buf);\r |
121 | return -1;\r |
122 | }\r |
123 | \r |
124 | memcpy(zip->ecd, buf + offset, zip->ecd_length);\r |
125 | \r |
126 | free(buf);\r |
127 | return 0;\r |
128 | }\r |
129 | \r |
130 | free(buf);\r |
131 | \r |
132 | if (buf_length < zip->length) {\r |
133 | /* double buffer */\r |
134 | buf_length = 2*buf_length;\r |
135 | \r |
136 | logerror("Retry reading of zip ecd for %d bytes\n",buf_length);\r |
137 | \r |
138 | } else {\r |
139 | return -1;\r |
140 | }\r |
141 | }\r |
142 | }\r |
143 | \r |
144 | /* offsets in end of central directory structure */\r |
145 | #define ZIPESIG 0x00\r |
146 | #define ZIPEDSK 0x04\r |
147 | #define ZIPECEN 0x06\r |
148 | #define ZIPENUM 0x08\r |
149 | #define ZIPECENN 0x0a\r |
150 | #define ZIPECSZ 0x0c\r |
151 | #define ZIPEOFST 0x10\r |
152 | #define ZIPECOML 0x14\r |
153 | #define ZIPECOM 0x16\r |
154 | \r |
155 | /* offsets in central directory entry structure */\r |
156 | #define ZIPCENSIG 0x0\r |
157 | #define ZIPCVER 0x4\r |
158 | #define ZIPCOS 0x5\r |
159 | #define ZIPCVXT 0x6\r |
160 | #define ZIPCEXOS 0x7\r |
161 | #define ZIPCFLG 0x8\r |
162 | #define ZIPCMTHD 0xa\r |
163 | #define ZIPCTIM 0xc\r |
164 | #define ZIPCDAT 0xe\r |
165 | #define ZIPCCRC 0x10\r |
166 | #define ZIPCSIZ 0x14\r |
167 | #define ZIPCUNC 0x18\r |
168 | #define ZIPCFNL 0x1c\r |
169 | #define ZIPCXTL 0x1e\r |
170 | #define ZIPCCML 0x20\r |
171 | #define ZIPDSK 0x22\r |
172 | #define ZIPINT 0x24\r |
173 | #define ZIPEXT 0x26\r |
174 | #define ZIPOFST 0x2a\r |
175 | #define ZIPCFN 0x2e\r |
176 | \r |
177 | /* offsets in local file header structure */\r |
178 | #define ZIPLOCSIG 0x00\r |
179 | #define ZIPVER 0x04\r |
180 | #define ZIPGENFLG 0x06\r |
181 | #define ZIPMTHD 0x08\r |
182 | #define ZIPTIME 0x0a\r |
183 | #define ZIPDATE 0x0c\r |
184 | #define ZIPCRC 0x0e\r |
185 | #define ZIPSIZE 0x12\r |
186 | #define ZIPUNCMP 0x16\r |
187 | #define ZIPFNLN 0x1a\r |
188 | #define ZIPXTRALN 0x1c\r |
189 | #define ZIPNAME 0x1e\r |
190 | \r |
191 | /* Opens a zip stream for reading\r |
192 | return:\r |
193 | !=0 success, zip stream\r |
194 | ==0 error\r |
195 | */\r |
196 | ZIP* openzip(const char* zipfile) {\r |
197 | /* allocate */\r |
198 | ZIP* zip = (ZIP*)malloc( sizeof(ZIP) );\r |
199 | if (!zip) {\r |
200 | return 0;\r |
201 | }\r |
202 | \r |
203 | /* open */\r |
204 | zip->fp = fopen(zipfile, "rb");\r |
205 | if (!zip->fp) {\r |
206 | errormsg ("Opening for reading", ERROR_FILESYSTEM, zipfile);\r |
207 | free(zip);\r |
208 | return 0;\r |
209 | }\r |
210 | \r |
211 | /* go to end */\r |
212 | if (fseek(zip->fp, 0L, SEEK_END) != 0) {\r |
213 | errormsg ("Seeking to end", ERROR_FILESYSTEM, zipfile);\r |
214 | fclose(zip->fp);\r |
215 | free(zip);\r |
216 | return 0;\r |
217 | }\r |
218 | \r |
219 | /* get length */\r |
220 | zip->length = ftell(zip->fp);\r |
221 | if (zip->length < 0) {\r |
222 | errormsg ("Get file size", ERROR_FILESYSTEM, zipfile);\r |
223 | fclose(zip->fp);\r |
224 | free(zip);\r |
225 | return 0;\r |
226 | }\r |
227 | if (zip->length == 0) {\r |
228 | errormsg ("Empty file", ERROR_CORRUPT, zipfile);\r |
229 | fclose(zip->fp);\r |
230 | free(zip);\r |
231 | return 0;\r |
232 | }\r |
233 | \r |
234 | /* read ecd data */\r |
235 | if (ecd_read(zip)!=0) {\r |
236 | errormsg ("Reading ECD (end of central directory)", ERROR_CORRUPT, zipfile);\r |
237 | fclose(zip->fp);\r |
238 | free(zip);\r |
239 | return 0;\r |
240 | }\r |
241 | \r |
242 | /* compile ecd info */\r |
243 | zip->end_of_cent_dir_sig = read_dword (zip->ecd+ZIPESIG);\r |
244 | zip->number_of_this_disk = read_word (zip->ecd+ZIPEDSK);\r |
245 | zip->number_of_disk_start_cent_dir = read_word (zip->ecd+ZIPECEN);\r |
246 | zip->total_entries_cent_dir_this_disk = read_word (zip->ecd+ZIPENUM);\r |
247 | zip->total_entries_cent_dir = read_word (zip->ecd+ZIPECENN);\r |
248 | zip->size_of_cent_dir = read_dword (zip->ecd+ZIPECSZ);\r |
249 | zip->offset_to_start_of_cent_dir = read_dword (zip->ecd+ZIPEOFST);\r |
250 | zip->zipfile_comment_length = read_word (zip->ecd+ZIPECOML);\r |
251 | zip->zipfile_comment = zip->ecd+ZIPECOM;\r |
252 | \r |
253 | /* verify that we can work with this zipfile (no disk spanning allowed) */\r |
254 | if ((zip->number_of_this_disk != zip->number_of_disk_start_cent_dir) ||\r |
255 | (zip->total_entries_cent_dir_this_disk != zip->total_entries_cent_dir) ||\r |
256 | (zip->total_entries_cent_dir < 1)) {\r |
257 | errormsg("Cannot span disks", ERROR_UNSUPPORTED, zipfile);\r |
258 | free(zip->ecd);\r |
259 | fclose(zip->fp);\r |
260 | free(zip);\r |
261 | return 0;\r |
262 | }\r |
263 | \r |
264 | if (fseek(zip->fp, zip->offset_to_start_of_cent_dir, SEEK_SET)!=0) {\r |
265 | errormsg ("Seeking to central directory", ERROR_CORRUPT, zipfile);\r |
266 | free(zip->ecd);\r |
267 | fclose(zip->fp);\r |
268 | free(zip);\r |
269 | return 0;\r |
270 | }\r |
271 | \r |
272 | /* read from start of central directory */\r |
273 | zip->cd = (char*)malloc( zip->size_of_cent_dir );\r |
274 | if (!zip->cd) {\r |
275 | free(zip->ecd);\r |
276 | fclose(zip->fp);\r |
277 | free(zip);\r |
278 | return 0;\r |
279 | }\r |
280 | \r |
281 | if (fread(zip->cd, zip->size_of_cent_dir, 1, zip->fp)!=1) {\r |
282 | errormsg ("Reading central directory", ERROR_CORRUPT, zipfile);\r |
283 | free(zip->cd);\r |
284 | free(zip->ecd);\r |
285 | fclose(zip->fp);\r |
286 | free(zip);\r |
287 | return 0;\r |
288 | }\r |
289 | \r |
290 | /* reset ent */\r |
291 | zip->ent.name = 0;\r |
292 | \r |
293 | /* rewind */\r |
294 | zip->cd_pos = 0;\r |
295 | \r |
296 | /* file name */\r |
297 | zip->zip = (char*)malloc(strlen(zipfile)+1);\r |
298 | if (!zip->zip) {\r |
299 | free(zip->cd);\r |
300 | free(zip->ecd);\r |
301 | fclose(zip->fp);\r |
302 | free(zip);\r |
303 | return 0;\r |
304 | }\r |
305 | strcpy(zip->zip, zipfile);\r |
306 | \r |
307 | return zip;\r |
308 | }\r |
309 | \r |
310 | /* Reads the current entry from a zip stream\r |
311 | in:\r |
312 | zip opened zip\r |
313 | return:\r |
314 | !=0 success\r |
315 | ==0 error\r |
316 | */\r |
317 | struct zipent* readzip(ZIP* zip) {\r |
318 | \r |
319 | /* end of directory */\r |
320 | if (zip->cd_pos >= zip->size_of_cent_dir)\r |
321 | return 0;\r |
322 | \r |
323 | /* compile zipent info */\r |
324 | zip->ent.cent_file_header_sig = read_dword (zip->cd+zip->cd_pos+ZIPCENSIG);\r |
325 | zip->ent.version_made_by = *(zip->cd+zip->cd_pos+ZIPCVER);\r |
326 | zip->ent.host_os = *(zip->cd+zip->cd_pos+ZIPCOS);\r |
327 | zip->ent.version_needed_to_extract = *(zip->cd+zip->cd_pos+ZIPCVXT);\r |
328 | zip->ent.os_needed_to_extract = *(zip->cd+zip->cd_pos+ZIPCEXOS);\r |
329 | zip->ent.general_purpose_bit_flag = read_word (zip->cd+zip->cd_pos+ZIPCFLG);\r |
330 | zip->ent.compression_method = read_word (zip->cd+zip->cd_pos+ZIPCMTHD);\r |
331 | zip->ent.last_mod_file_time = read_word (zip->cd+zip->cd_pos+ZIPCTIM);\r |
332 | zip->ent.last_mod_file_date = read_word (zip->cd+zip->cd_pos+ZIPCDAT);\r |
333 | zip->ent.crc32 = read_dword (zip->cd+zip->cd_pos+ZIPCCRC);\r |
334 | zip->ent.compressed_size = read_dword (zip->cd+zip->cd_pos+ZIPCSIZ);\r |
335 | zip->ent.uncompressed_size = read_dword (zip->cd+zip->cd_pos+ZIPCUNC);\r |
336 | zip->ent.filename_length = read_word (zip->cd+zip->cd_pos+ZIPCFNL);\r |
337 | zip->ent.extra_field_length = read_word (zip->cd+zip->cd_pos+ZIPCXTL);\r |
338 | zip->ent.file_comment_length = read_word (zip->cd+zip->cd_pos+ZIPCCML);\r |
339 | zip->ent.disk_number_start = read_word (zip->cd+zip->cd_pos+ZIPDSK);\r |
340 | zip->ent.internal_file_attrib = read_word (zip->cd+zip->cd_pos+ZIPINT);\r |
341 | zip->ent.external_file_attrib = read_dword (zip->cd+zip->cd_pos+ZIPEXT);\r |
342 | zip->ent.offset_lcl_hdr_frm_frst_disk = read_dword (zip->cd+zip->cd_pos+ZIPOFST);\r |
343 | \r |
344 | /* check to see if filename length is illegally long (past the size of this directory\r |
345 | entry) */\r |
346 | if (zip->cd_pos + ZIPCFN + zip->ent.filename_length > zip->size_of_cent_dir)\r |
347 | {\r |
348 | errormsg("Invalid filename length in directory", ERROR_CORRUPT,zip->zip);\r |
349 | return 0;\r |
350 | }\r |
351 | \r |
352 | /* copy filename */\r |
353 | free(zip->ent.name);\r |
354 | zip->ent.name = (char*)malloc(zip->ent.filename_length + 1);\r |
355 | memcpy(zip->ent.name, zip->cd+zip->cd_pos+ZIPCFN, zip->ent.filename_length);\r |
356 | zip->ent.name[zip->ent.filename_length] = 0;\r |
357 | \r |
358 | /* skip to next entry in central dir */\r |
359 | zip->cd_pos += ZIPCFN + zip->ent.filename_length + zip->ent.extra_field_length + zip->ent.file_comment_length;\r |
360 | \r |
361 | return &zip->ent;\r |
362 | }\r |
363 | \r |
364 | /* Closes a zip stream */\r |
365 | void closezip(ZIP* zip) {\r |
366 | /* release all */\r |
367 | free(zip->ent.name);\r |
368 | free(zip->cd);\r |
369 | free(zip->ecd);\r |
370 | /* only if not suspended */\r |
371 | if (zip->fp)\r |
372 | fclose(zip->fp);\r |
373 | free(zip->zip);\r |
374 | free(zip);\r |
375 | }\r |
376 | \r |
377 | /* Suspend access to a zip file (release file handler)\r |
378 | in:\r |
379 | zip opened zip\r |
380 | note:\r |
381 | A suspended zip is automatically reopened at first call of\r |
382 | readuncompressd() or readcompressed() functions\r |
383 | */\r |
384 | void suspendzip(ZIP* zip) {\r |
385 | if (zip->fp) {\r |
386 | fclose(zip->fp);\r |
387 | zip->fp = 0;\r |
388 | }\r |
389 | }\r |
390 | \r |
391 | /* Revive a suspended zip file (reopen file handler)\r |
392 | in:\r |
393 | zip suspended zip\r |
394 | return:\r |
395 | zip success\r |
396 | ==0 error (zip must be closed with closezip)\r |
397 | */\r |
398 | static ZIP* revivezip(ZIP* zip) {\r |
399 | if (!zip->fp) {\r |
400 | zip->fp = fopen(zip->zip, "rb");\r |
401 | if (!zip->fp) {\r |
402 | return 0;\r |
403 | }\r |
404 | }\r |
405 | return zip;\r |
406 | \r |
407 | }\r |
408 | \r |
409 | /* Reset a zip stream to the first entry\r |
410 | in:\r |
411 | zip opened zip\r |
412 | note:\r |
413 | ZIP file must be opened and not suspended\r |
414 | */\r |
415 | void rewindzip(ZIP* zip) {\r |
416 | zip->cd_pos = 0;\r |
417 | }\r |
418 | \r |
419 | /* Seek zip->fp to compressed data\r |
420 | return:\r |
421 | ==0 success\r |
422 | <0 error\r |
423 | */\r |
424 | int seekcompresszip(ZIP* zip, struct zipent* ent) {\r |
425 | char buf[ZIPNAME];\r |
426 | long offset;\r |
427 | \r |
428 | if (!zip->fp) {\r |
429 | if (!revivezip(zip))\r |
430 | return -1;\r |
431 | }\r |
432 | \r |
433 | if (fseek(zip->fp, ent->offset_lcl_hdr_frm_frst_disk, SEEK_SET)!=0) {\r |
434 | errormsg ("Seeking to header", ERROR_CORRUPT, zip->zip);\r |
435 | return -1;\r |
436 | }\r |
437 | \r |
438 | if (fread(buf, ZIPNAME, 1, zip->fp)!=1) {\r |
439 | errormsg ("Reading header", ERROR_CORRUPT, zip->zip);\r |
440 | return -1;\r |
441 | }\r |
442 | \r |
443 | {\r |
444 | UINT16 filename_length = read_word (buf+ZIPFNLN);\r |
445 | UINT16 extra_field_length = read_word (buf+ZIPXTRALN);\r |
446 | \r |
447 | /* calculate offset to data and fseek() there */\r |
448 | offset = ent->offset_lcl_hdr_frm_frst_disk + ZIPNAME + filename_length + extra_field_length;\r |
449 | \r |
450 | if (fseek(zip->fp, offset, SEEK_SET) != 0) {\r |
451 | errormsg ("Seeking to compressed data", ERROR_CORRUPT, zip->zip);\r |
452 | return -1;\r |
453 | }\r |
454 | \r |
455 | }\r |
456 | \r |
457 | return 0;\r |
458 | }\r |
459 | \r |
460 | /* Inflate a file\r |
461 | in:\r |
462 | in_file stream to inflate\r |
463 | in_size size of the compressed data to read\r |
464 | out_size size of decompressed data\r |
465 | out:\r |
466 | out_data buffer for decompressed data\r |
467 | return:\r |
468 | ==0 ok\r |
469 | \r |
470 | 990525 rewritten for use with zlib MLR\r |
471 | */\r |
472 | static int inflate_file(FILE* in_file, unsigned in_size, unsigned char* out_data, unsigned out_size)\r |
473 | {\r |
474 | int err;\r |
475 | unsigned char* in_buffer;\r |
476 | z_stream d_stream; /* decompression stream */\r |
477 | \r |
478 | d_stream.zalloc = 0;\r |
479 | d_stream.zfree = 0;\r |
480 | d_stream.opaque = 0;\r |
481 | \r |
482 | d_stream.next_in = 0;\r |
483 | d_stream.avail_in = 0;\r |
484 | d_stream.next_out = out_data;\r |
485 | d_stream.avail_out = out_size;\r |
486 | \r |
487 | err = inflateInit2(&d_stream, -MAX_WBITS);\r |
488 | /* windowBits is passed < 0 to tell that there is no zlib header.\r |
489 | * Note that in this case inflate *requires* an extra "dummy" byte\r |
490 | * after the compressed stream in order to complete decompression and\r |
491 | * return Z_STREAM_END.\r |
492 | */\r |
493 | if (err != Z_OK)\r |
494 | {\r |
495 | logerror("inflateInit error: %d\n", err);\r |
496 | return -1;\r |
497 | }\r |
498 | \r |
499 | in_buffer = (unsigned char*)malloc(INFLATE_INPUT_BUFFER_MAX+1);\r |
500 | if (!in_buffer)\r |
501 | return -1;\r |
502 | \r |
503 | for (;;)\r |
504 | {\r |
505 | if (in_size <= 0)\r |
506 | {\r |
507 | logerror("inflate error: compressed size too small\n");\r |
508 | free (in_buffer);\r |
509 | return -1;\r |
510 | }\r |
511 | d_stream.next_in = in_buffer;\r |
512 | d_stream.avail_in = fread (in_buffer, 1, MIN(in_size, INFLATE_INPUT_BUFFER_MAX), in_file);\r |
513 | in_size -= d_stream.avail_in;\r |
514 | if (in_size == 0)\r |
515 | d_stream.avail_in++; /* add dummy byte at end of compressed data */\r |
516 | \r |
517 | err = inflate(&d_stream, Z_NO_FLUSH);\r |
518 | if (err == Z_STREAM_END)\r |
519 | break;\r |
520 | if (err != Z_OK)\r |
521 | {\r |
522 | logerror("inflate error: %d\n", err);\r |
523 | free (in_buffer);\r |
524 | return -1;\r |
525 | }\r |
526 | }\r |
527 | \r |
528 | err = inflateEnd(&d_stream);\r |
529 | if (err != Z_OK)\r |
530 | {\r |
531 | logerror("inflateEnd error: %d\n", err);\r |
532 | free (in_buffer);\r |
533 | return -1;\r |
534 | }\r |
535 | \r |
536 | free (in_buffer);\r |
537 | \r |
538 | if ((d_stream.avail_out > 0) || (in_size > 0))\r |
539 | {\r |
540 | logerror("zip size mismatch. %i\n", in_size);\r |
541 | return -1;\r |
542 | }\r |
543 | \r |
544 | return 0;\r |
545 | }\r |
546 | \r |
547 | /* Read compressed data\r |
548 | out:\r |
549 | data compressed data read\r |
550 | return:\r |
551 | ==0 success\r |
552 | <0 error\r |
553 | */\r |
554 | int readcompresszip(ZIP* zip, struct zipent* ent, char* data) {\r |
555 | int err = seekcompresszip(zip,ent);\r |
556 | if (err!=0)\r |
557 | return err;\r |
558 | \r |
559 | if (fread(data, ent->compressed_size, 1, zip->fp)!=1) {\r |
560 | errormsg ("Reading compressed data", ERROR_CORRUPT, zip->zip);\r |
561 | return -1;\r |
562 | }\r |
563 | \r |
564 | return 0;\r |
565 | }\r |
566 | \r |
567 | /* Read UNcompressed data\r |
568 | out:\r |
569 | data UNcompressed data\r |
570 | return:\r |
571 | ==0 success\r |
572 | <0 error\r |
573 | */\r |
574 | int readuncompresszip(ZIP* zip, struct zipent* ent, char* data) {\r |
575 | if (ent->compression_method == 0x0000) {\r |
576 | /* file is not compressed, simply stored */\r |
577 | \r |
578 | /* check if size are equal */\r |
579 | if (ent->compressed_size != ent->uncompressed_size) {\r |
580 | errormsg("Wrong uncompressed size in store compression", ERROR_CORRUPT,zip->zip);\r |
581 | return -3;\r |
582 | }\r |
583 | \r |
584 | return readcompresszip(zip,ent,data);\r |
585 | } else if (ent->compression_method == 0x0008) {\r |
586 | /* file is compressed using "Deflate" method */\r |
587 | if (ent->version_needed_to_extract > 0x14) {\r |
588 | errormsg("Version too new", ERROR_UNSUPPORTED,zip->zip);\r |
589 | return -2;\r |
590 | }\r |
591 | \r |
592 | if (ent->os_needed_to_extract != 0x00) {\r |
593 | errormsg("OS not supported", ERROR_UNSUPPORTED,zip->zip);\r |
594 | return -2;\r |
595 | }\r |
596 | \r |
597 | if (ent->disk_number_start != zip->number_of_this_disk) {\r |
598 | errormsg("Cannot span disks", ERROR_UNSUPPORTED,zip->zip);\r |
599 | return -2;\r |
600 | }\r |
601 | \r |
602 | /* read compressed data */\r |
603 | if (seekcompresszip(zip,ent)!=0) {\r |
604 | return -1;\r |
605 | }\r |
606 | \r |
607 | /* configure inflate */\r |
608 | if (inflate_file( zip->fp, ent->compressed_size, (unsigned char*)data, ent->uncompressed_size))\r |
609 | {\r |
610 | errormsg("Inflating compressed data", ERROR_CORRUPT, zip->zip);\r |
611 | return -3;\r |
612 | }\r |
613 | \r |
614 | return 0;\r |
615 | } else {\r |
616 | errormsg("Compression method unsupported", ERROR_UNSUPPORTED, zip->zip);\r |
617 | return -2;\r |
618 | }\r |
619 | }\r |