"Fossies" - the Fresh Open Source Software Archive 
Member "libextractor-1.11/src/common/unzip.c" (30 Jan 2021, 44242 Bytes) of package /linux/privat/libextractor-1.11.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "unzip.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.10_vs_1.11.
1 /*
2 This file is part of libextractor.
3 Copyright (C) 2004, 2008, 2012 Vidyut Samanta and Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20 /**
21 * @file common/unzip.c
22 * @brief API to access ZIP archives
23 * @author Christian Grothoff
24 *
25 * This code is based in part on
26 * unzip 1.00 Copyright 1998-2003 Gilles Vollant
27 * http://www.winimage.com/zLibDll"
28 *
29 *
30 * The filenames for each file in a zipfile are stored in two locations.
31 * There is one at the start of each entry, just before the compressed data,
32 * and another at the end in a 'central directory structure'.
33 *
34 * In order to catch self-extracting executables, we scan backwards from the end
35 * of the file looking for the central directory structure. The previous version
36 * of this went forewards through the local headers, but that only works for plain
37 * vanilla zip's and I don't feel like writing a special case for each of the dozen
38 * self-extracting executable stubs.
39 *
40 * This assumes that the zip file is considered to be non-corrupt/non-truncated.
41 * If it is truncated then it's not considered to be a zip and skipped.
42 *
43 * ZIP format description from appnote.iz and appnote.txt (more or less):
44 *
45 * (this is why you always need to put in the last floppy if you span disks)
46 *
47 * 0- 3 end of central dir signature 4 bytes (0x06054b50) P K ^E ^F
48 * 4- 5 number of this disk 2 bytes
49 * 6- 7 number of the disk with the
50 * start of the central directory 2 bytes
51 * 8- 9 total number of entries in
52 * the central dir on this disk 2 bytes
53 * 10-11 total number of entries in
54 * the central dir 2 bytes
55 * 12-15 size of the central directory 4 bytes
56 * 16-19 offset of start of central
57 * directory with respect to
58 * the starting disk number 4 bytes
59 * 20-21 zipfile comment length 2 bytes
60 * 22-?? zipfile comment (variable size) max length 65536 bytes
61 */
62 #include "platform.h"
63 #include <ctype.h>
64 #include "extractor.h"
65 #include "unzip.h"
66
67 #define CASESENSITIVITY (0)
68 #define MAXFILENAME (256)
69
70 #ifndef UNZ_BUFSIZE
71 #define UNZ_BUFSIZE (16384)
72 #endif
73
74 #ifndef UNZ_MAXFILENAMEINZIP
75 #define UNZ_MAXFILENAMEINZIP (256)
76 #endif
77
78 #define SIZECENTRALDIRITEM (0x2e)
79 #define SIZEZIPLOCALHEADER (0x1e)
80
81
82 /**
83 * IO callbacks for access to the ZIP data.
84 */
85 struct FileFuncDefs
86 {
87 /**
88 * Callback for reading 'size' bytes from the ZIP archive into buf.
89 */
90 uLong (*zread_file) (voidpf opaque, void*buf, uLong size);
91
92 /**
93 * Callback to obtain the current read offset in the ZIP archive.
94 */
95 long (*ztell_file) (voidpf opaque);
96
97 /**
98 * Callback for seeking to a different position in the ZIP archive.
99 */
100 long (*zseek_file) (voidpf opaque, uLong offset, int origin);
101
102 /**
103 * Opaque argument to pass to all IO functions.
104 */
105 voidpf opaque;
106 };
107
108
109 /**
110 * Macro to read using filefunc API.
111 *
112 * @param filefunc filefunc struct
113 * @param buf where to write data
114 * @param size number of bytes to read
115 * @return number of bytes copied to buf
116 */
117 #define ZREAD(filefunc,buf,size) ((*((filefunc).zread_file))((filefunc).opaque, \
118 buf, size))
119
120 /**
121 * Macro to obtain current offset in file using filefunc API.
122 *
123 * @param filefunc filefunc struct
124 * @return current offset in file
125 */
126 #define ZTELL(filefunc) ((*((filefunc).ztell_file))((filefunc).opaque))
127
128 /**
129 * Macro to seek using filefunc API.
130 *
131 * @param filefunc filefunc struct
132 * @param pos position to seek
133 * @param mode seek mode
134 * @return 0 on success
135 */
136 #define ZSEEK(filefunc,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque, \
137 pos, mode))
138
139
140 /**
141 * Global data about the ZIPfile
142 * These data comes from the end of central dir
143 */
144 struct GlobalInfo
145 {
146
147 /**
148 * total number of entries in
149 * the central dir on this disk
150 */
151 uLong number_entry;
152
153 /**
154 * size of the global comment of the zipfile
155 */
156 uLong size_comment;
157
158 /**
159 * offset of the global comment in the zipfile
160 */
161 uLong offset_comment;
162 };
163
164
165 /**
166 * internal info about a file in zipfile
167 */
168 struct UnzipFileInfoInternal
169 {
170
171 /**
172 * relative offset of local header 4 bytes
173 */
174 uLong offset_curfile;
175
176 };
177
178
179 /**
180 * Information about a file in zipfile, when reading and
181 * decompressing it
182 */
183 struct FileInZipReadInfo
184 {
185 /**
186 * internal buffer for compressed data
187 */
188 char *read_buffer;
189
190 /**
191 * zLib stream structure for inflate
192 */
193 z_stream stream;
194
195 /**
196 * position in byte on the zipfile, for fseek
197 */
198 uLong pos_in_zipfile;
199
200 /**
201 * flag set if stream structure is initialised
202 */
203 uLong stream_initialised;
204
205 /**
206 * offset of the local extra field
207 */
208 uLong offset_local_extrafield;
209
210 /**
211 * size of the local extra field
212 */
213 uInt size_local_extrafield;
214
215 /**
216 * position in the local extra field in read
217 */
218 uLong pos_local_extrafield;
219
220 /**
221 * crc32 of all data uncompressed so far
222 */
223 uLong crc32;
224
225 /**
226 * crc32 we must obtain after decompress all
227 */
228 uLong crc32_wait;
229
230 /**
231 * number of bytes to be decompressed
232 */
233 uLong rest_read_compressed;
234
235 /**
236 * number of bytes to be obtained after decomp
237 */
238 uLong rest_read_uncompressed;
239
240 /**
241 * IO functions.
242 */
243 struct FileFuncDefs z_filefunc;
244
245 /**
246 * compression method (0==store)
247 */
248 uLong compression_method;
249
250 /**
251 * byte before the zipfile, (>0 for sfx)
252 */
253 uLong byte_before_the_zipfile;
254 };
255
256
257 /**
258 * Handle for a ZIP archive.
259 * contains internal information about the zipfile
260 */
261 struct EXTRACTOR_UnzipFile
262 {
263 /**
264 * io structore of the zipfile
265 */
266 struct FileFuncDefs z_filefunc;
267
268 /**
269 * public global information
270 */
271 struct GlobalInfo gi;
272
273 /**
274 * byte before the zipfile, (>0 for sfx)
275 */
276 uLong byte_before_the_zipfile;
277
278 /**
279 * number of the current file in the zipfile
280 */
281 uLong num_file;
282
283 /**
284 * pos of the current file in the central dir
285 */
286 uLong pos_in_central_dir;
287
288 /**
289 * flag about the usability of the current file
290 */
291 uLong current_file_ok;
292
293 /**
294 * position of the beginning of the central dir
295 */
296 uLong central_pos;
297
298 /**
299 * size of the central directory
300 */
301 uLong size_central_dir;
302
303 /**
304 * offset of start of central directory with respect to the starting
305 * disk number
306 */
307 uLong offset_central_dir;
308
309 /**
310 * public info about the current file in zip
311 */
312 struct EXTRACTOR_UnzipFileInfo cur_file_info;
313
314 /**
315 * private info about it
316 */
317 struct UnzipFileInfoInternal cur_file_info_internal;
318
319 /**
320 * structure about the current file if we are decompressing it
321 */
322 struct FileInZipReadInfo *pfile_in_zip_read;
323
324 /**
325 * Is the file encrypted?
326 */
327 int encrypted;
328 };
329
330
331 /**
332 * Read a byte from a gz_stream; update next_in and avail_in. Return EOF
333 * for end of file.
334 * IN assertion: the stream s has been successfully opened for reading.
335 *
336 * @param ffd functions for performing IO operations
337 * @param pi where to store the byte that was read
338 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF
339 */
340 static int
341 read_byte_from_ffd (const struct FileFuncDefs *ffd,
342 int *pi)
343 {
344 unsigned char c;
345
346 if (1 != ZREAD (*ffd, &c, 1))
347 return EXTRACTOR_UNZIP_EOF;
348 *pi = (int) c;
349 return EXTRACTOR_UNZIP_OK;
350 }
351
352
353 /**
354 * Read a short (2 bytes) from a gz_stream; update next_in and avail_in. Return EOF
355 * for end of file.
356 * IN assertion: the stream s has been successfully opened for reading.
357 *
358 * @param ffd functions for performing IO operations
359 * @param pi where to store the short that was read
360 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF
361 */
362 static int
363 read_short_from_ffd (const struct FileFuncDefs *ffd,
364 uLong *pX)
365 {
366 uLong x;
367 int i;
368 int err;
369
370 *pX = 0;
371 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
372 return err;
373 x = (uLong) i;
374 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
375 return err;
376 x += ((uLong) i) << 8;
377 *pX = x;
378 return err;
379 }
380
381
382 /**
383 * Read a 'long' (4 bytes) from a gz_stream; update next_in and avail_in. Return EOF
384 * for end of file.
385 * IN assertion: the stream s has been successfully opened for reading.
386 *
387 * @param ffd functions for performing IO operations
388 * @param pi where to store the long that was read
389 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF
390 */
391 static int
392 read_long_from_ffd (const struct FileFuncDefs *ffd,
393 uLong *pX)
394 {
395 uLong x;
396 int i;
397 int err;
398
399 *pX = 0;
400 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
401 return err;
402 x = (uLong) i;
403 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
404 return err;
405 x += ((uLong) i) << 8;
406 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
407 return err;
408 x += ((uLong) i) << 16;
409 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i)))
410 return err;
411 x += ((uLong) i) << 24;
412 *pX = x;
413 return err;
414 }
415
416
417 #ifndef CASESENSITIVITYDEFAULT_NO
418 #if ! defined(unix) && ! defined(CASESENSITIVITYDEFAULT_YES)
419 #define CASESENSITIVITYDEFAULT_NO
420 #endif
421 #endif
422
423 #ifdef CASESENSITIVITYDEFAULT_NO
424 #define CASESENSITIVITYDEFAULTVALUE 2
425 #else
426 #define CASESENSITIVITYDEFAULTVALUE 1
427 #endif
428
429
430 /**
431 * Compare two filenames (fileName1, fileName2).
432 *
433 * @param filename1 name of first file
434 * @param filename2 name of second file
435 * @param iCaseSensitivity, use 1 for case sensitivity (like strcmp);
436 * 2 for no case sensitivity (like strcmpi or strcasecmp); or
437 * 0 for default of your operating system (like 1 on Unix, 2 on Windows)
438 * @return 0 if names are equal
439 */
440 static int
441 EXTRACTOR_common_unzip_string_file_name_compare (const char*fileName1,
442 const char*fileName2,
443 int iCaseSensitivity)
444 {
445 if (0 == iCaseSensitivity)
446 iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
447 if (1 == iCaseSensitivity)
448 return strcmp (fileName1, fileName2);
449 return strcasecmp (fileName1, fileName2);
450 }
451
452
453 #ifndef BUFREADCOMMENT
454 #define BUFREADCOMMENT (0x400)
455 #endif
456
457
458 /**
459 * Locate the central directory in the ZIP file.
460 *
461 * @param ffd IO functions
462 * @return offset of central directory, 0 on error
463 */
464 static uLong
465 locate_central_directory (const struct FileFuncDefs *ffd)
466 {
467 unsigned char buf[BUFREADCOMMENT + 4];
468 uLong uSizeFile;
469 uLong uBackRead;
470 uLong uMaxBack = 0xffff; /* maximum size of global comment */
471
472 if (0 != ZSEEK (*ffd, 0, SEEK_END))
473 return 0;
474 uSizeFile = ZTELL (*ffd);
475 if (uMaxBack > uSizeFile)
476 uMaxBack = uSizeFile;
477 uBackRead = 4;
478 while (uBackRead < uMaxBack)
479 {
480 uLong uReadSize;
481 uLong uReadPos;
482 int i;
483
484 if (uBackRead + BUFREADCOMMENT > uMaxBack)
485 uBackRead = uMaxBack;
486 else
487 uBackRead += BUFREADCOMMENT;
488 uReadPos = uSizeFile - uBackRead;
489 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
490 ? (BUFREADCOMMENT + 4)
491 : (uSizeFile - uReadPos);
492 if (0 != ZSEEK (*ffd, uReadPos, SEEK_SET))
493 break;
494 if (ZREAD (*ffd, buf, uReadSize) != uReadSize)
495 break;
496 i = (int) uReadSize - 3;
497 while (i-- > 0)
498 if ( (0x50 == (*(buf + i))) &&
499 (0x4b == (*(buf + i + 1))) &&
500 (0x05 == (*(buf + i + 2))) &&
501 (0x06 == (*(buf + i + 3))) )
502 return uReadPos + i;
503 }
504 return 0;
505 }
506
507
508 /**
509 * Translate date/time from Dos format to `struct
510 * EXTRACTOR_UnzipDateTimeInfo` (readable more easilty)
511 *
512 * @param ulDosDate time in DOS format (input)
513 * @param ptm where to write time in readable format
514 */
515 static void
516 dos_date_to_tmu_date (uLong ulDosDate,
517 struct EXTRACTOR_UnzipDateTimeInfo*ptm)
518 {
519 uLong uDate;
520
521 uDate = (uLong) (ulDosDate >> 16);
522 ptm->tm_mday = (uInt) (uDate & 0x1f);
523 ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1);
524 ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980);
525 ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800);
526 ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20);
527 ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f));
528 }
529
530
531 /**
532 * Write info about the ZipFile in the *pglobal_info structure.
533 * No preparation of the structure is needed.
534 *
535 * @param file zipfile to manipulate
536 * @param pfile_info file information to initialize
537 * @param pfile_info_internal internal file information to initialize
538 * @param szFileName where to write the name of the current file
539 * @param fileNameBufferSize number of bytes available in @a szFileName
540 * @param extraField where to write extra data
541 * @param extraFieldBufferSize number of bytes available in extraField
542 * @param szComment where to write the comment on the current file
543 * @param commentBufferSize number of bytes available in @a szComment
544 * @return #EXTRACTOR_UNZIP_OK if there is no problem.
545 */
546 static int
547 get_current_file_info (struct EXTRACTOR_UnzipFile *file,
548 struct EXTRACTOR_UnzipFileInfo *pfile_info,
549 struct UnzipFileInfoInternal *pfile_info_internal,
550 char *szFileName,
551 uLong fileNameBufferSize,
552 void *extraField,
553 uLong extraFieldBufferSize,
554 char *szComment,
555 uLong commentBufferSize)
556 {
557 struct EXTRACTOR_UnzipFileInfo file_info;
558 struct UnzipFileInfoInternal file_info_internal;
559 uLong uMagic;
560 long lSeek = 0;
561
562 if (NULL == file)
563 return EXTRACTOR_UNZIP_PARAMERROR;
564 if (0 != ZSEEK (file->z_filefunc,
565 file->pos_in_central_dir + file->byte_before_the_zipfile,
566 SEEK_SET))
567 return EXTRACTOR_UNZIP_ERRNO;
568
569 /* we check the magic */
570 if (EXTRACTOR_UNZIP_OK !=
571 read_long_from_ffd (&file->z_filefunc, &uMagic))
572 return EXTRACTOR_UNZIP_ERRNO;
573 if (0x02014b50 != uMagic)
574 return EXTRACTOR_UNZIP_BADZIPFILE;
575
576 if ( (EXTRACTOR_UNZIP_OK !=
577 read_short_from_ffd (&file->z_filefunc, &file_info.version)) ||
578 (EXTRACTOR_UNZIP_OK !=
579 read_short_from_ffd (&file->z_filefunc, &file_info.version_needed)) ||
580 (EXTRACTOR_UNZIP_OK !=
581 read_short_from_ffd (&file->z_filefunc, &file_info.flag)) ||
582 (EXTRACTOR_UNZIP_OK !=
583 read_short_from_ffd (&file->z_filefunc,
584 &file_info.compression_method)) ||
585 (EXTRACTOR_UNZIP_OK !=
586 read_long_from_ffd (&file->z_filefunc, &file_info.dosDate)) )
587 return EXTRACTOR_UNZIP_ERRNO;
588 dos_date_to_tmu_date (file_info.dosDate,
589 &file_info.tmu_date);
590 if ( (EXTRACTOR_UNZIP_OK !=
591 read_long_from_ffd (&file->z_filefunc, &file_info.crc)) ||
592 (EXTRACTOR_UNZIP_OK !=
593 read_long_from_ffd (&file->z_filefunc, &file_info.compressed_size)) ||
594 (EXTRACTOR_UNZIP_OK !=
595 read_long_from_ffd (&file->z_filefunc, &file_info.uncompressed_size)) ||
596 (EXTRACTOR_UNZIP_OK !=
597 read_short_from_ffd (&file->z_filefunc, &file_info.size_filename)) ||
598 (EXTRACTOR_UNZIP_OK !=
599 read_short_from_ffd (&file->z_filefunc, &file_info.size_file_extra)) ||
600 (EXTRACTOR_UNZIP_OK !=
601 read_short_from_ffd (&file->z_filefunc,
602 &file_info.size_file_comment)) ||
603 (EXTRACTOR_UNZIP_OK !=
604 read_short_from_ffd (&file->z_filefunc, &file_info.disk_num_start)) ||
605 (EXTRACTOR_UNZIP_OK !=
606 read_short_from_ffd (&file->z_filefunc, &file_info.internal_fa)) ||
607 (EXTRACTOR_UNZIP_OK !=
608 read_long_from_ffd (&file->z_filefunc, &file_info.external_fa)) ||
609 (EXTRACTOR_UNZIP_OK !=
610 read_long_from_ffd (&file->z_filefunc,
611 &file_info_internal.offset_curfile)) )
612 return EXTRACTOR_UNZIP_ERRNO;
613
614 lSeek += file_info.size_filename;
615 if (NULL != szFileName)
616 {
617 uLong uSizeRead;
618
619 if (file_info.size_filename < fileNameBufferSize)
620 {
621 *(szFileName + file_info.size_filename) = '\0';
622 uSizeRead = file_info.size_filename;
623 }
624 else
625 uSizeRead = fileNameBufferSize;
626
627 if ( (file_info.size_filename > 0) &&
628 (fileNameBufferSize > 0) )
629 if (ZREAD (file->z_filefunc, szFileName, uSizeRead) != uSizeRead)
630 return EXTRACTOR_UNZIP_ERRNO;
631 lSeek -= uSizeRead;
632 }
633
634 if (NULL != extraField)
635 {
636 uLong uSizeRead;
637
638 if (file_info.size_file_extra<extraFieldBufferSize)
639 uSizeRead = file_info.size_file_extra;
640 else
641 uSizeRead = extraFieldBufferSize;
642
643 if (0 != lSeek)
644 {
645 if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR))
646 lSeek = 0;
647 else
648 return EXTRACTOR_UNZIP_ERRNO;
649 }
650 if ( (file_info.size_file_extra > 0) &&
651 (extraFieldBufferSize > 0) &&
652 (ZREAD (file->z_filefunc,
653 extraField,
654 uSizeRead) != uSizeRead) )
655 return EXTRACTOR_UNZIP_ERRNO;
656 lSeek += file_info.size_file_extra - uSizeRead;
657 }
658 else
659 lSeek += file_info.size_file_extra;
660
661 if (NULL != szComment)
662 {
663 uLong uSizeRead;
664
665 if (file_info.size_file_comment < commentBufferSize)
666 {
667 *(szComment + file_info.size_file_comment) = '\0';
668 uSizeRead = file_info.size_file_comment;
669 }
670 else
671 {
672 *(szComment + commentBufferSize - 1) = '\0';
673 uSizeRead = commentBufferSize - 1;
674 }
675
676 if (0 != lSeek)
677 {
678 if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR))
679 lSeek = 0;
680 else
681 return EXTRACTOR_UNZIP_ERRNO;
682 }
683 if ( (file_info.size_file_comment > 0) &&
684 (commentBufferSize > 0) &&
685 (ZREAD (file->z_filefunc, szComment, uSizeRead) != uSizeRead) )
686 return EXTRACTOR_UNZIP_ERRNO;
687 lSeek += file_info.size_file_comment - uSizeRead;
688 }
689 else
690 lSeek += file_info.size_file_comment;
691
692 if (NULL != pfile_info)
693 *pfile_info = file_info;
694 if (NULL != pfile_info_internal)
695 *pfile_info_internal = file_info_internal;
696 return EXTRACTOR_UNZIP_OK;
697 }
698
699
700 /**
701 * Set the current file of the zipfile to the first file.
702 *
703 * @param file zipfile to manipulate
704 * @return UNZ_OK if there is no problem
705 */
706 int
707 EXTRACTOR_common_unzip_go_to_first_file (struct EXTRACTOR_UnzipFile *file)
708 {
709 int err;
710
711 if (NULL == file)
712 return EXTRACTOR_UNZIP_PARAMERROR;
713 file->pos_in_central_dir = file->offset_central_dir;
714 file->num_file = 0;
715 err = get_current_file_info (file,
716 &file->cur_file_info,
717 &file->cur_file_info_internal,
718 NULL, 0, NULL, 0, NULL, 0);
719 file->current_file_ok = (EXTRACTOR_UNZIP_OK == err);
720 return err;
721 }
722
723
724 /**
725 * Open a Zip file.
726 *
727 * @param ffd IO functions
728 * @return NULL on error
729 */
730 static struct EXTRACTOR_UnzipFile *
731 unzip_open_using_ffd (struct FileFuncDefs *ffd)
732 {
733 struct EXTRACTOR_UnzipFile us;
734 struct EXTRACTOR_UnzipFile *file;
735 uLong central_pos;
736 uLong uL;
737 uLong number_disk; /* number of the current dist, used for
738 spanning ZIP, unsupported, always 0*/
739 uLong number_disk_with_CD; /* number of the disk with central dir, used
740 for spanning ZIP, unsupported, always 0*/
741 uLong number_entry_CD; /* total number of entries in
742 the central dir
743 (same than number_entry on nospan) */
744
745 memset (&us, 0, sizeof(us));
746 us.z_filefunc = *ffd;
747 central_pos = locate_central_directory (&us.z_filefunc);
748 if (0 == central_pos)
749 return NULL;
750 if (0 != ZSEEK (us.z_filefunc,
751 central_pos, SEEK_SET))
752 return NULL;
753
754 /* the signature, already checked */
755 if (EXTRACTOR_UNZIP_OK !=
756 read_long_from_ffd (&us.z_filefunc, &uL))
757 return NULL;
758
759 /* number of this disk */
760 if (EXTRACTOR_UNZIP_OK !=
761 read_short_from_ffd (&us.z_filefunc, &number_disk))
762 return NULL;
763
764 /* number of the disk with the start of the central directory */
765 if (EXTRACTOR_UNZIP_OK !=
766 read_short_from_ffd (&us.z_filefunc, &number_disk_with_CD))
767 return NULL;
768
769 /* total number of entries in the central dir on this disk */
770 if (EXTRACTOR_UNZIP_OK !=
771 read_short_from_ffd (&us.z_filefunc, &us.gi.number_entry))
772 return NULL;
773
774 /* total number of entries in the central dir */
775 if (EXTRACTOR_UNZIP_OK !=
776 read_short_from_ffd (&us.z_filefunc, &number_entry_CD))
777 return NULL;
778
779 if ( (number_entry_CD != us.gi.number_entry) ||
780 (0 != number_disk_with_CD) ||
781 (0 != number_disk) )
782 return NULL;
783
784 /* size of the central directory */
785 if (EXTRACTOR_UNZIP_OK !=
786 read_long_from_ffd (&us.z_filefunc, &us.size_central_dir))
787 return NULL;
788
789 /* offset of start of central directory with respect to the
790 starting disk number */
791 if (EXTRACTOR_UNZIP_OK !=
792 read_long_from_ffd (&us.z_filefunc, &us.offset_central_dir))
793 return NULL;
794
795 /* zipfile comment length */
796 if (EXTRACTOR_UNZIP_OK !=
797 read_short_from_ffd (&us.z_filefunc, &us.gi.size_comment))
798 return NULL;
799 us.gi.offset_comment = ZTELL (us.z_filefunc);
800 if ((central_pos < us.offset_central_dir + us.size_central_dir))
801 return NULL;
802
803 us.byte_before_the_zipfile = central_pos
804 - (us.offset_central_dir + us.size_central_dir);
805 us.central_pos = central_pos;
806 us.pfile_in_zip_read = NULL;
807 us.encrypted = 0;
808
809 if (NULL == (file = malloc (sizeof(struct EXTRACTOR_UnzipFile))))
810 return NULL;
811 *file = us;
812 EXTRACTOR_common_unzip_go_to_first_file (file);
813 return file;
814 }
815
816
817 /**
818 * Close the file in zip opened with #EXTRACTOR_common_unzip_open_current_file().
819 *
820 * @return #EXTRACTOR_UNZIP_CRCERROR if all the file was read but the CRC is not good
821 */
822 int
823 EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile *file)
824 {
825 struct FileInZipReadInfo*pfile_in_zip_read_info;
826 int err = EXTRACTOR_UNZIP_OK;
827
828 if (NULL == file)
829 return EXTRACTOR_UNZIP_PARAMERROR;
830 if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read))
831 return EXTRACTOR_UNZIP_PARAMERROR;
832 if ( (0 == pfile_in_zip_read_info->rest_read_uncompressed) &&
833 (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) )
834 err = EXTRACTOR_UNZIP_CRCERROR;
835 if (NULL != pfile_in_zip_read_info->read_buffer)
836 free (pfile_in_zip_read_info->read_buffer);
837 pfile_in_zip_read_info->read_buffer = NULL;
838 if (pfile_in_zip_read_info->stream_initialised)
839 inflateEnd (&pfile_in_zip_read_info->stream);
840 pfile_in_zip_read_info->stream_initialised = 0;
841 free (pfile_in_zip_read_info);
842 file->pfile_in_zip_read = NULL;
843 return err;
844 }
845
846
847 /**
848 * Close a ZipFile.
849 *
850 * @param file zip file to close
851 * @return #EXTRACTOR_UNZIP_OK if there is no problem.
852 */
853 int
854 EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file)
855 {
856 if (NULL == file)
857 return EXTRACTOR_UNZIP_PARAMERROR;
858 if (NULL != file->pfile_in_zip_read)
859 EXTRACTOR_common_unzip_close_current_file (file);
860 free (file);
861 return EXTRACTOR_UNZIP_OK;
862 }
863
864
865 /**
866 * Obtain the global comment from a ZIP file.
867 *
868 * @param file unzip file to inspect
869 * @param comment where to copy the comment
870 * @param comment_len maximum number of bytes available in comment
871 * @return #EXTRACTOR_UNZIP_OK on success
872 */
873 int
874 EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file,
875 char *comment,
876 size_t comment_len)
877 {
878 if (NULL == file)
879 return EXTRACTOR_UNZIP_PARAMERROR;
880 if (comment_len > file->gi.size_comment)
881 comment_len = file->gi.size_comment + 1;
882 if (0 !=
883 ZSEEK (file->z_filefunc, file->gi.offset_comment, SEEK_SET))
884 return EXTRACTOR_UNZIP_ERRNO;
885 if (comment_len - 1 !=
886 ZREAD (file->z_filefunc, comment, comment_len - 1))
887 return EXTRACTOR_UNZIP_ERRNO;
888 comment[comment_len - 1] = '\0';
889 return EXTRACTOR_UNZIP_OK;
890 }
891
892
893 /**
894 * Write info about the ZipFile in the *pglobal_info structure.
895 * No preparation of the structure is needed.
896 *
897 * @param file zipfile to manipulate
898 * @param pfile_info file information to initialize
899 * @param szFileName where to write the name of the current file
900 * @param fileNameBufferSize number of bytes available in szFileName
901 * @param extraField where to write extra data
902 * @param extraFieldBufferSize number of bytes available in extraField
903 * @param szComment where to write the comment on the current file
904 * @param commentBufferSize number of bytes available in szComment
905 * @return #EXTRACTOR_UNZIP_OK if there is no problem.
906 */
907 int
908 EXTRACTOR_common_unzip_get_current_file_info (struct EXTRACTOR_UnzipFile *file,
909 struct EXTRACTOR_UnzipFileInfo *
910 pfile_info,
911 char *szFileName,
912 uLong fileNameBufferSize,
913 void *extraField,
914 uLong extraFieldBufferSize,
915 char *szComment,
916 uLong commentBufferSize)
917 {
918 return get_current_file_info (file, pfile_info, NULL,
919 szFileName, fileNameBufferSize,
920 extraField, extraFieldBufferSize,
921 szComment, commentBufferSize);
922 }
923
924
925 /**
926 * Set the current file of the zipfile to the next file.
927 *
928 * @param file zipfile to manipulate
929 * @return #EXTRACTOR_UNZIP_OK if there is no problem,
930 * #EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the actual file was the latest.
931 */
932 int
933 EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile *file)
934 {
935 int err;
936
937 if (NULL == file)
938 return EXTRACTOR_UNZIP_PARAMERROR;
939 if (! file->current_file_ok)
940 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
941 if (file->num_file + 1 == file->gi.number_entry)
942 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
943 file->pos_in_central_dir += SIZECENTRALDIRITEM
944 + file->cur_file_info.size_filename
945 + file->cur_file_info.size_file_extra
946 + file->cur_file_info.size_file_comment;
947 file->num_file++;
948 err = get_current_file_info (file,
949 &file->cur_file_info,
950 &file->cur_file_info_internal,
951 NULL, 0, NULL, 0, NULL, 0);
952 file->current_file_ok = (EXTRACTOR_UNZIP_OK == err);
953 return err;
954 }
955
956
957 /**
958 * Try locate the file szFileName in the zipfile.
959 *
960 * @param file zipfile to manipulate
961 * @param szFileName name to find
962 * @param iCaseSensitivity, use 1 for case sensitivity (like strcmp);
963 * 2 for no case sensitivity (like strcmpi or strcasecmp); or
964 * 0 for default of your operating system (like 1 on Unix, 2 on Windows)
965 * @return #EXTRACTOR_UNZIP_OK if the file is found. It becomes the current file.
966 * #EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the file is not found
967 */
968 int
969 EXTRACTOR_common_unzip_go_find_local_file (struct EXTRACTOR_UnzipFile *file,
970 const char *szFileName,
971 int iCaseSensitivity)
972 {
973 int err;
974 /* We remember the 'current' position in the file so that we can jump
975 * back there if we fail.
976 */
977 struct EXTRACTOR_UnzipFileInfo cur_file_infoSaved;
978 struct UnzipFileInfoInternal cur_file_info_internalSaved;
979 uLong num_fileSaved;
980 uLong pos_in_central_dirSaved;
981
982 if (NULL == file)
983 return EXTRACTOR_UNZIP_PARAMERROR;
984 if (strlen (szFileName) >= UNZ_MAXFILENAMEINZIP)
985 return EXTRACTOR_UNZIP_PARAMERROR;
986 if (! file->current_file_ok)
987 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
988
989 /* Save the current state */
990 num_fileSaved = file->num_file;
991 pos_in_central_dirSaved = file->pos_in_central_dir;
992 cur_file_infoSaved = file->cur_file_info;
993 cur_file_info_internalSaved = file->cur_file_info_internal;
994 err = EXTRACTOR_common_unzip_go_to_first_file (file);
995
996 while (EXTRACTOR_UNZIP_OK == err)
997 {
998 char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
999
1000 if (EXTRACTOR_UNZIP_OK !=
1001 (err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL,
1002 szCurrentFileName,
1003 sizeof (
1004 szCurrentFileName)
1005 - 1,
1006 NULL, 0, NULL, 0)))
1007 break;
1008 if (0 ==
1009 EXTRACTOR_common_unzip_string_file_name_compare (szCurrentFileName,
1010 szFileName,
1011 iCaseSensitivity))
1012 return EXTRACTOR_UNZIP_OK;
1013 err = EXTRACTOR_common_unzip_go_to_next_file (file);
1014 }
1015
1016 /* We failed, so restore the state of the 'current file' to where we
1017 * were.
1018 */
1019 file->num_file = num_fileSaved;
1020 file->pos_in_central_dir = pos_in_central_dirSaved;
1021 file->cur_file_info = cur_file_infoSaved;
1022 file->cur_file_info_internal = cur_file_info_internalSaved;
1023 return err;
1024 }
1025
1026
1027 /**
1028 * Read bytes from the current file (must have been opened).
1029 *
1030 * @param buf contain buffer where data must be copied
1031 * @param len the size of buf.
1032 * @return the number of byte copied if some bytes are copied
1033 * 0 if the end of file was reached
1034 * <0 with error code if there is an error
1035 * (#EXTRACTOR_UNZIP_ERRNO for IO error, or zLib error for uncompress error)
1036 */
1037 ssize_t
1038 EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file,
1039 void *buf,
1040 size_t len)
1041 {
1042 int err = EXTRACTOR_UNZIP_OK;
1043 uInt iRead = 0;
1044 struct FileInZipReadInfo *pfile_in_zip_read_info;
1045
1046 if (NULL == file)
1047 return EXTRACTOR_UNZIP_PARAMERROR;
1048 if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read))
1049 return EXTRACTOR_UNZIP_PARAMERROR;
1050 if (NULL == pfile_in_zip_read_info->read_buffer)
1051 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE;
1052 if (0 == len)
1053 return 0;
1054
1055 pfile_in_zip_read_info->stream.next_out = (Bytef *) buf;
1056 pfile_in_zip_read_info->stream.avail_out = (uInt) len;
1057 if (len > pfile_in_zip_read_info->rest_read_uncompressed)
1058 pfile_in_zip_read_info->stream.avail_out =
1059 (uInt) pfile_in_zip_read_info->rest_read_uncompressed;
1060
1061 while (pfile_in_zip_read_info->stream.avail_out > 0)
1062 {
1063 if ( (0 == pfile_in_zip_read_info->stream.avail_in) &&
1064 (pfile_in_zip_read_info->rest_read_compressed > 0) )
1065 {
1066 uInt uReadThis = UNZ_BUFSIZE;
1067 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1068 uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed;
1069 if (0 == uReadThis)
1070 return EXTRACTOR_UNZIP_EOF;
1071 if (0 !=
1072 ZSEEK (pfile_in_zip_read_info->z_filefunc,
1073 pfile_in_zip_read_info->pos_in_zipfile
1074 + pfile_in_zip_read_info->byte_before_the_zipfile,
1075 SEEK_SET))
1076 return EXTRACTOR_UNZIP_ERRNO;
1077 if (ZREAD (pfile_in_zip_read_info->z_filefunc,
1078 pfile_in_zip_read_info->read_buffer,
1079 uReadThis) != uReadThis)
1080 return EXTRACTOR_UNZIP_ERRNO;
1081
1082 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1083 pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
1084 pfile_in_zip_read_info->stream.next_in =
1085 (Bytef *) pfile_in_zip_read_info->read_buffer;
1086 pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis;
1087 }
1088
1089 if (0 == pfile_in_zip_read_info->compression_method)
1090 {
1091 uInt uDoCopy;
1092
1093 if ( (0 == pfile_in_zip_read_info->stream.avail_in) &&
1094 (0 == pfile_in_zip_read_info->rest_read_compressed) )
1095 return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead;
1096
1097 if (pfile_in_zip_read_info->stream.avail_out <
1098 pfile_in_zip_read_info->stream.avail_in)
1099 uDoCopy = pfile_in_zip_read_info->stream.avail_out;
1100 else
1101 uDoCopy = pfile_in_zip_read_info->stream.avail_in;
1102 memcpy (pfile_in_zip_read_info->stream.next_out,
1103 pfile_in_zip_read_info->stream.next_in,
1104 uDoCopy);
1105 pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32,
1106 pfile_in_zip_read_info->stream.
1107 next_out,
1108 uDoCopy);
1109 pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
1110 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1111 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1112 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1113 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1114 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1115 iRead += uDoCopy;
1116 }
1117 else
1118 {
1119 uLong uTotalOutBefore;
1120 uLong uTotalOutAfter;
1121 const Bytef *bufBefore;
1122 uLong uOutThis;
1123 int flush = Z_SYNC_FLUSH;
1124
1125 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1126 bufBefore = pfile_in_zip_read_info->stream.next_out;
1127
1128 /*
1129 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1130 pfile_in_zip_read_info->stream.avail_out) &&
1131 (pfile_in_zip_read_info->rest_read_compressed == 0))
1132 flush = Z_FINISH;
1133 */err = inflate (&pfile_in_zip_read_info->stream, flush);
1134
1135 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1136 uOutThis = uTotalOutAfter - uTotalOutBefore;
1137
1138 pfile_in_zip_read_info->crc32 =
1139 crc32 (pfile_in_zip_read_info->crc32, bufBefore,
1140 (uInt) (uOutThis));
1141
1142 pfile_in_zip_read_info->rest_read_uncompressed -=
1143 uOutThis;
1144
1145 iRead += (uInt) (uTotalOutAfter - uTotalOutBefore);
1146
1147 if (Z_STREAM_END == err)
1148 return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead;
1149 if (Z_OK != err)
1150 break;
1151 }
1152 }
1153
1154 if (Z_OK == err)
1155 return iRead;
1156 return err;
1157 }
1158
1159
1160 /**
1161 * Read the local header of the current zipfile. Check the coherency of
1162 * the local header and info in the end of central directory about
1163 * this file. Store in *piSizeVar the size of extra info in local
1164 * header (filename and size of extra field data)
1165 *
1166 * @param file zipfile to process
1167 * @param piSizeVar where to store the size of the extra info
1168 * @param poffset_local_extrafield where to store the offset of the local extrafield
1169 * @param psoze_local_extrafield where to store the size of the local extrafield
1170 * @return #EXTRACTOR_UNZIP_OK on success
1171 */
1172 static int
1173 parse_current_file_coherency_header (struct EXTRACTOR_UnzipFile *file,
1174 uInt *piSizeVar,
1175 uLong *poffset_local_extrafield,
1176 uInt *psize_local_extrafield)
1177 {
1178 uLong uMagic;
1179 uLong uData;
1180 uLong uFlags;
1181 uLong size_filename;
1182 uLong size_extra_field;
1183
1184 *piSizeVar = 0;
1185 *poffset_local_extrafield = 0;
1186 *psize_local_extrafield = 0;
1187
1188 if (0 != ZSEEK (file->z_filefunc,
1189 file->cur_file_info_internal.offset_curfile
1190 + file->byte_before_the_zipfile,
1191 SEEK_SET))
1192 return EXTRACTOR_UNZIP_ERRNO;
1193 if (EXTRACTOR_UNZIP_OK !=
1194 read_long_from_ffd (&file->z_filefunc,
1195 &uMagic))
1196 return EXTRACTOR_UNZIP_ERRNO;
1197 if (0x04034b50 != uMagic)
1198 return EXTRACTOR_UNZIP_BADZIPFILE;
1199 if ( (EXTRACTOR_UNZIP_OK !=
1200 read_short_from_ffd (&file->z_filefunc, &uData)) ||
1201 (EXTRACTOR_UNZIP_OK !=
1202 read_short_from_ffd (&file->z_filefunc, &uFlags)) )
1203 return EXTRACTOR_UNZIP_ERRNO;
1204 if (EXTRACTOR_UNZIP_OK != read_short_from_ffd (&file->z_filefunc, &uData))
1205 return EXTRACTOR_UNZIP_ERRNO;
1206 if (uData != file->cur_file_info.compression_method)
1207 return EXTRACTOR_UNZIP_BADZIPFILE;
1208 if ( (0 != file->cur_file_info.compression_method) &&
1209 (Z_DEFLATED != file->cur_file_info.compression_method) )
1210 return EXTRACTOR_UNZIP_BADZIPFILE;
1211 if (EXTRACTOR_UNZIP_OK !=
1212 read_long_from_ffd (&file->z_filefunc, &uData)) /* date/time */
1213 return EXTRACTOR_UNZIP_ERRNO;
1214 if (EXTRACTOR_UNZIP_OK !=
1215 read_long_from_ffd (&file->z_filefunc, &uData)) /* crc */
1216 return EXTRACTOR_UNZIP_ERRNO;
1217 if ( (uData != file->cur_file_info.crc) &&
1218 (0 == (uFlags & 8)) )
1219 return EXTRACTOR_UNZIP_BADZIPFILE;
1220 if (EXTRACTOR_UNZIP_OK !=
1221 read_long_from_ffd (&file->z_filefunc, &uData)) /* size compr */
1222 return EXTRACTOR_UNZIP_ERRNO;
1223 if ( (uData != file->cur_file_info.compressed_size) &&
1224 (0 == (uFlags & 8)) )
1225 return EXTRACTOR_UNZIP_BADZIPFILE;
1226 if (EXTRACTOR_UNZIP_OK !=
1227 read_long_from_ffd (&file->z_filefunc,
1228 &uData)) /* size uncompr */
1229 return EXTRACTOR_UNZIP_ERRNO;
1230 if ( (uData != file->cur_file_info.uncompressed_size) &&
1231 (0 == (uFlags & 8)))
1232 return EXTRACTOR_UNZIP_BADZIPFILE;
1233 if (EXTRACTOR_UNZIP_OK !=
1234 read_short_from_ffd (&file->z_filefunc, &size_filename))
1235 return EXTRACTOR_UNZIP_ERRNO;
1236 if (size_filename != file->cur_file_info.size_filename)
1237 return EXTRACTOR_UNZIP_BADZIPFILE;
1238 *piSizeVar += (uInt) size_filename;
1239 if (EXTRACTOR_UNZIP_OK !=
1240 read_short_from_ffd (&file->z_filefunc,
1241 &size_extra_field))
1242 return EXTRACTOR_UNZIP_ERRNO;
1243 *poffset_local_extrafield = file->cur_file_info_internal.offset_curfile
1244 + SIZEZIPLOCALHEADER + size_filename;
1245 *psize_local_extrafield = (uInt) size_extra_field;
1246 *piSizeVar += (uInt) size_extra_field;
1247
1248 return EXTRACTOR_UNZIP_OK;
1249 }
1250
1251
1252 /**
1253 * Open for reading data the current file in the zipfile.
1254 *
1255 * @param file zipfile to manipulate
1256 * @return #EXTRACTOR_UNZIP_OK on success
1257 */
1258 int
1259 EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file)
1260 {
1261 int err;
1262 uInt iSizeVar;
1263 struct FileInZipReadInfo *pfile_in_zip_read_info;
1264 uLong offset_local_extrafield; /* offset of the local extra field */
1265 uInt size_local_extrafield; /* size of the local extra field */
1266
1267 if (NULL == file)
1268 return EXTRACTOR_UNZIP_PARAMERROR;
1269 if (! file->current_file_ok)
1270 return EXTRACTOR_UNZIP_PARAMERROR;
1271 if (NULL != file->pfile_in_zip_read)
1272 EXTRACTOR_common_unzip_close_current_file (file);
1273 if (EXTRACTOR_UNZIP_OK !=
1274 parse_current_file_coherency_header (file,
1275 &iSizeVar,
1276 &offset_local_extrafield,
1277 &size_local_extrafield))
1278 return EXTRACTOR_UNZIP_BADZIPFILE;
1279 if (NULL == (pfile_in_zip_read_info = malloc (sizeof(struct
1280 FileInZipReadInfo))))
1281 return EXTRACTOR_UNZIP_INTERNALERROR;
1282 if (NULL == (pfile_in_zip_read_info->read_buffer = malloc (UNZ_BUFSIZE)))
1283 {
1284 free (pfile_in_zip_read_info);
1285 return EXTRACTOR_UNZIP_INTERNALERROR;
1286 }
1287 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1288 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1289 pfile_in_zip_read_info->pos_local_extrafield = 0;
1290 pfile_in_zip_read_info->stream_initialised = 0;
1291
1292 if ( (0 != file->cur_file_info.compression_method) &&
1293 (Z_DEFLATED != file->cur_file_info.compression_method) )
1294 {
1295 // err = EXTRACTOR_UNZIP_BADZIPFILE;
1296 // FIXME: we don't do anything with this 'err' code.
1297 // Can this happen? Should we abort in this case?
1298 }
1299
1300 pfile_in_zip_read_info->crc32_wait = file->cur_file_info.crc;
1301 pfile_in_zip_read_info->crc32 = 0;
1302 pfile_in_zip_read_info->compression_method =
1303 file->cur_file_info.compression_method;
1304 pfile_in_zip_read_info->z_filefunc = file->z_filefunc;
1305 pfile_in_zip_read_info->byte_before_the_zipfile =
1306 file->byte_before_the_zipfile;
1307 pfile_in_zip_read_info->stream.total_out = 0;
1308 if (Z_DEFLATED == file->cur_file_info.compression_method)
1309 {
1310 pfile_in_zip_read_info->stream.zalloc = (alloc_func) NULL;
1311 pfile_in_zip_read_info->stream.zfree = (free_func) NULL;
1312 pfile_in_zip_read_info->stream.opaque = NULL;
1313 pfile_in_zip_read_info->stream.next_in = NULL;
1314 pfile_in_zip_read_info->stream.avail_in = 0;
1315 if (Z_OK != (err = inflateInit2 (&pfile_in_zip_read_info->stream,
1316 -MAX_WBITS)))
1317 {
1318 free (pfile_in_zip_read_info->read_buffer);
1319 free (pfile_in_zip_read_info);
1320 return err;
1321 }
1322 pfile_in_zip_read_info->stream_initialised = 1;
1323 /* windowBits is passed < 0 to tell that there is no zlib header.
1324 * Note that in this case inflate *requires* an extra "dummy" byte
1325 * after the compressed stream in order to complete decompression and
1326 * return Z_STREAM_END.
1327 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1328 * size of both compressed and uncompressed data
1329 */}
1330 pfile_in_zip_read_info->rest_read_compressed =
1331 file->cur_file_info.compressed_size;
1332 pfile_in_zip_read_info->rest_read_uncompressed =
1333 file->cur_file_info.uncompressed_size;
1334 pfile_in_zip_read_info->pos_in_zipfile =
1335 file->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER
1336 + iSizeVar;
1337 pfile_in_zip_read_info->stream.avail_in = 0;
1338 file->pfile_in_zip_read = pfile_in_zip_read_info;
1339 return EXTRACTOR_UNZIP_OK;
1340 }
1341
1342
1343 /**
1344 * Callback to perform read operation using LE API.
1345 * Note that partial reads are not allowed.
1346 *
1347 * @param opaque the 'struct EXTRACTOR_ExtractContext'
1348 * @param buf where to write bytes read
1349 * @param size number of bytes desired
1350 * @return number of bytes copied to buf
1351 */
1352 static uLong
1353 ec_read_file_func (voidpf opaque,
1354 void*buf,
1355 uLong size)
1356 {
1357 struct EXTRACTOR_ExtractContext *ec = opaque;
1358 void *ptr;
1359 ssize_t ret;
1360 uLong done;
1361
1362 done = 0;
1363 while (done < size)
1364 {
1365 ret = ec->read (ec->cls,
1366 &ptr,
1367 size - done);
1368 if (ret <= 0)
1369 return done;
1370 memcpy (buf + done, ptr, ret);
1371 done += ret;
1372 }
1373 return done;
1374 }
1375
1376
1377 /**
1378 * Callback to obtain current offset in file using LE API.
1379 *
1380 * @param opaque the 'struct EXTRACTOR_ExtractContext'
1381 * @return current offset in file, -1 on error
1382 */
1383 static long
1384 ec_tell_file_func (voidpf opaque)
1385 {
1386 struct EXTRACTOR_ExtractContext *ec = opaque;
1387
1388 return ec->seek (ec->cls, 0, SEEK_CUR);
1389 }
1390
1391
1392 /**
1393 * Callback to perform seek operation using LE API.
1394 *
1395 * @param opaque the 'struct EXTRACTOR_ExtractContext'
1396 * @param offset where to seek
1397 * @param origin relative to where should we seek
1398 * @return #EXTRACTOR_UNZIP_OK on success
1399 */
1400 static long
1401 ec_seek_file_func (voidpf opaque,
1402 uLong offset,
1403 int origin)
1404 {
1405 struct EXTRACTOR_ExtractContext *ec = opaque;
1406
1407 if (-1 == ec->seek (ec->cls, offset, origin))
1408 return EXTRACTOR_UNZIP_INTERNALERROR;
1409 return EXTRACTOR_UNZIP_OK;
1410 }
1411
1412
1413 /**
1414 * Open a zip file for processing using the data access
1415 * functions from the extract context.
1416 *
1417 * @param ec extract context to use
1418 * @return handle to zip data, NULL on error
1419 */
1420 struct EXTRACTOR_UnzipFile *
1421 EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec)
1422 {
1423 struct FileFuncDefs ffd;
1424
1425 ffd.zread_file = &ec_read_file_func;
1426 ffd.ztell_file = &ec_tell_file_func;
1427 ffd.zseek_file = &ec_seek_file_func;
1428 ffd.opaque = ec;
1429
1430 return unzip_open_using_ffd (&ffd);
1431 }
1432
1433
1434 /* end of unzip.c */