comparison src/common/unzip.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
comparison
equal deleted inserted replaced
0:8ced16adf2e1 1:f9f4f1b99eed
1 /* unzip.c -- IO on .zip files using zlib
2 Version 0.15 beta, Mar 19th, 1998,
3
4 Read unzip.h for more info
5 */
6
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstring>
10 #include "zlib.h"
11 #include "unzip.h"
12
13 #ifdef NO_ERRNO_H
14 extern int errno;
15 #else
16 # include <cerrno>
17 #endif
18
19 #ifndef local
20 # define local static
21 #endif
22 /* compile with -Dlocal if your debugger can't find static symbols */
23
24 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
25 !defined(CASESENSITIVITYDEFAULT_NO)
26 #define CASESENSITIVITYDEFAULT_NO
27 #endif
28
29 #ifndef UNZ_BUFSIZE
30 #define UNZ_BUFSIZE (16384)
31 #endif
32
33 #ifndef UNZ_MAXFILENAMEINZIP
34 #define UNZ_MAXFILENAMEINZIP (256)
35 #endif
36
37 #ifndef ALLOC
38 # define ALLOC(size) (malloc(size))
39 #endif
40 #ifndef TRYFREE
41 # define TRYFREE(p) {if (p) \
42 free(p);}
43 #endif
44
45 #define SIZECENTRALDIRITEM (0x2e)
46 #define SIZEZIPLOCALHEADER (0x1e)
47
48 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
49
50 #ifndef SEEK_CUR
51 #define SEEK_CUR 1
52 #endif
53
54 #ifndef SEEK_END
55 #define SEEK_END 2
56 #endif
57
58 #ifndef SEEK_SET
59 #define SEEK_SET 0
60 #endif
61
62 const char unz_copyright[] =
63 " unzip 0.15 Copyright 1998 Gilles Vollant ";
64
65 /* unz_file_info_interntal contain internal info about a file in zipfile*/
66 typedef struct unz_file_info_internal_s
67 {
68 uLong offset_curfile; /* relative offset of local header 4 bytes */
69 } unz_file_info_internal;
70
71 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
72 when reading and decompress it */
73 typedef struct
74 {
75 char * read_buffer; /* internal buffer for compressed data */
76 z_stream stream; /* zLib stream structure for inflate */
77
78 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
79 uLong stream_initialised; /* flag set if stream structure is initialised*/
80
81 uLong offset_local_extrafield; /* offset of the local extra field */
82 uInt size_local_extrafield; /* size of the local extra field */
83 uLong pos_local_extrafield; /* position in the local extra field in read*/
84
85 uLong crc32; /* crc32 of all data uncompressed */
86 uLong crc32_wait; /* crc32 we must obtain after decompress all */
87 uLong rest_read_compressed; /* number of byte to be decompressed */
88 uLong rest_read_uncompressed; /*number of byte to be obtained after decomp*/
89 FILE* file; /* io structore of the zipfile */
90 uLong compression_method; /* compression method (0==store) */
91 uLong byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
92 } file_in_zip_read_info_s;
93
94 /* unz_s contain internal information about the zipfile
95 */
96 typedef struct
97 {
98 FILE*file; /* io structore of the zipfile */
99 unz_global_info gi; /* public global information */
100 uLong byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
101 uLong num_file; /* number of the current file in the zipfile*/
102 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
103 uLong current_file_ok; /* flag about the usability of the current file*/
104 uLong central_pos; /* position of the beginning of the central dir*/
105
106 uLong size_central_dir; /* size of the central directory */
107 uLong offset_central_dir; /* offset of start of central directory with
108 respect to the starting disk number */
109
110 unz_file_info cur_file_info; /* public info about the current file in zip*/
111 unz_file_info_internal cur_file_info_internal; /* private info about it*/
112 file_in_zip_read_info_s*pfile_in_zip_read; /* structure about the current
113 file if we are decompressing it */
114 } unz_s;
115
116 /* ===========================================================================
117 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
118 for end of file.
119 IN assertion: the stream s has been sucessfully opened for reading.
120 */
121
122 local int unzlocal_getByte(FILE *fin, int *pi)
123 {
124 unsigned char c;
125 int err = fread(&c, 1, 1, fin);
126 if (err == 1)
127 {
128 *pi = (int)c;
129 return UNZ_OK;
130 }
131 else
132 {
133 if (ferror(fin))
134 return UNZ_ERRNO;
135 else
136 return UNZ_EOF;
137 }
138 }
139
140 /* ===========================================================================
141 Reads a long in LSB order from the given gz_stream. Sets
142 */
143 local int unzlocal_getShort(FILE *fin, uLong *pX)
144 {
145 uLong x ;
146 int i;
147 int err;
148
149 err = unzlocal_getByte(fin, &i);
150 x = (uLong)i;
151
152 if (err == UNZ_OK)
153 err = unzlocal_getByte(fin, &i);
154 x += ((uLong)i)<<8;
155
156 if (err == UNZ_OK)
157 *pX = x;
158 else
159 *pX = 0;
160 return err;
161 }
162
163 local int unzlocal_getLong(FILE *fin, uLong *pX)
164 {
165 uLong x ;
166 int i;
167 int err;
168
169 err = unzlocal_getByte(fin, &i);
170 x = (uLong)i;
171
172 if (err == UNZ_OK)
173 err = unzlocal_getByte(fin, &i);
174 x += ((uLong)i)<<8;
175
176 if (err == UNZ_OK)
177 err = unzlocal_getByte(fin, &i);
178 x += ((uLong)i)<<16;
179
180 if (err == UNZ_OK)
181 err = unzlocal_getByte(fin, &i);
182 x += ((uLong)i)<<24;
183
184 if (err == UNZ_OK)
185 *pX = x;
186 else
187 *pX = 0;
188 return err;
189 }
190
191 /* My own strcmpi / strcasecmp */
192 local int strcmpcasenosensitive_internal(const char *fileName1,
193 const char *fileName2)
194 {
195 for (;;)
196 {
197 char c1 = *(fileName1++);
198 char c2 = *(fileName2++);
199 if ((c1 >= 'a') && (c1 <= 'z'))
200 c1 -= 0x20;
201 if ((c2 >= 'a') && (c2 <= 'z'))
202 c2 -= 0x20;
203 if (c1 == '\0')
204 return ((c2 == '\0') ? 0 : -1);
205 if (c2 == '\0')
206 return 1;
207 if (c1 < c2)
208 return -1;
209 if (c1 > c2)
210 return 1;
211 }
212 }
213
214 #ifdef CASESENSITIVITYDEFAULT_NO
215 #define CASESENSITIVITYDEFAULTVALUE 2
216 #else
217 #define CASESENSITIVITYDEFAULTVALUE 1
218 #endif
219
220 #ifndef STRCMPCASENOSENTIVEFUNCTION
221 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
222 #endif
223
224 /*
225 Compare two filename (fileName1,fileName2).
226 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
227 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
228 or strcasecmp)
229 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
230 (like 1 on Unix, 2 on Windows)
231
232 */
233 extern int ZEXPORT unzStringFileNameCompare(const char *fileName1,
234 const char *fileName2,
235 int iCaseSensitivity)
236 {
237 if (iCaseSensitivity == 0)
238 iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
239
240 if (iCaseSensitivity == 1)
241 return strcmp(fileName1, fileName2);
242
243 return STRCMPCASENOSENTIVEFUNCTION(fileName1, fileName2);
244 }
245
246 #define BUFREADCOMMENT (0x400)
247
248 /*
249 Locate the Central directory of a zipfile (at the end, just before
250 the global comment)
251 */
252 local uLong unzlocal_SearchCentralDir(FILE *fin)
253 {
254 unsigned char*buf;
255 uLong uSizeFile;
256 uLong uBackRead;
257 uLong uMaxBack = 0xffff; /* maximum size of global comment */
258 uLong uPosFound = 0;
259
260 if (fseek(fin, 0, SEEK_END) != 0)
261 return 0;
262
263 uSizeFile = ftell(fin);
264
265 if (uMaxBack > uSizeFile)
266 uMaxBack = uSizeFile;
267
268 buf = (unsigned char *)ALLOC(BUFREADCOMMENT+4);
269 if (buf == NULL)
270 return 0;
271
272 uBackRead = 4;
273 while (uBackRead < uMaxBack)
274 {
275 uLong uReadSize, uReadPos ;
276 int i;
277 if (uBackRead+BUFREADCOMMENT > uMaxBack)
278 uBackRead = uMaxBack;
279 else
280 uBackRead += BUFREADCOMMENT;
281 uReadPos = uSizeFile-uBackRead ;
282
283 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
284 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
285 if (fseek(fin, uReadPos, SEEK_SET) != 0)
286 break;
287
288 if (fread(buf, (uInt)uReadSize, 1, fin) != 1)
289 break;
290
291 for (i = (int)uReadSize-3; (i--) > 0;)
292 if (((*(buf+i)) == 0x50) && ((*(buf+i+1)) == 0x4b) &&
293 ((*(buf+i+2)) == 0x05) && ((*(buf+i+3)) == 0x06))
294 {
295 uPosFound = uReadPos+i;
296 break;
297 }
298
299 if (uPosFound != 0)
300 break;
301 }
302 TRYFREE(buf);
303 return uPosFound;
304 }
305
306 /*
307 Open a Zip file. path contain the full pathname (by example,
308 on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
309 "zlib/zlib109.zip".
310 If the zipfile cannot be opened (file don't exist or in not valid), the
311 return value is NULL.
312 Else, the return value is a unzFile Handle, usable with other function
313 of this unzip package.
314 */
315 extern unzFile ZEXPORT unzOpen(const char *path)
316 {
317 unz_s us;
318 unz_s *s;
319 uLong central_pos, uL;
320 FILE * fin ;
321
322 uLong number_disk; /* number of the current dist, used for
323 spaning ZIP, unsupported, always 0*/
324 uLong number_disk_with_CD; /* number the the disk with central dir, used
325 for spaning ZIP, unsupported, always 0*/
326 uLong number_entry_CD; /* total number of entries in
327 the central dir
328 (same than number_entry on nospan) */
329
330 int err = UNZ_OK;
331
332 if (unz_copyright[0] != ' ')
333 return NULL;
334
335 fin = fopen(path, "rb");
336 if (fin == NULL)
337 return NULL;
338
339 central_pos = unzlocal_SearchCentralDir(fin);
340 if (central_pos == 0)
341 err = UNZ_ERRNO;
342
343 if (fseek(fin, central_pos, SEEK_SET) != 0)
344 err = UNZ_ERRNO;
345
346 /* the signature, already checked */
347 if (unzlocal_getLong(fin, &uL) != UNZ_OK)
348 err = UNZ_ERRNO;
349
350 /* number of this disk */
351 if (unzlocal_getShort(fin, &number_disk) != UNZ_OK)
352 err = UNZ_ERRNO;
353
354 /* number of the disk with the start of the central directory */
355 if (unzlocal_getShort(fin, &number_disk_with_CD) != UNZ_OK)
356 err = UNZ_ERRNO;
357
358 /* total number of entries in the central dir on this disk */
359 if (unzlocal_getShort(fin, &us.gi.number_entry) != UNZ_OK)
360 err = UNZ_ERRNO;
361
362 /* total number of entries in the central dir */
363 if (unzlocal_getShort(fin, &number_entry_CD) != UNZ_OK)
364 err = UNZ_ERRNO;
365
366 if ((number_entry_CD != us.gi.number_entry) ||
367 (number_disk_with_CD != 0) ||
368 (number_disk != 0))
369 err = UNZ_BADZIPFILE;
370
371 /* size of the central directory */
372 if (unzlocal_getLong(fin, &us.size_central_dir) != UNZ_OK)
373 err = UNZ_ERRNO;
374
375 /* offset of start of central directory with respect to the
376 starting disk number */
377 if (unzlocal_getLong(fin, &us.offset_central_dir) != UNZ_OK)
378 err = UNZ_ERRNO;
379
380 /* zipfile comment length */
381 if (unzlocal_getShort(fin, &us.gi.size_comment) != UNZ_OK)
382 err = UNZ_ERRNO;
383
384 if ((central_pos < us.offset_central_dir+us.size_central_dir) &&
385 (err == UNZ_OK))
386 err = UNZ_BADZIPFILE;
387
388 if (err != UNZ_OK)
389 {
390 fclose(fin);
391 return NULL;
392 }
393
394 us.file = fin;
395 us.byte_before_the_zipfile = central_pos -
396 (us.offset_central_dir+us.size_central_dir);
397 us.central_pos = central_pos;
398 us.pfile_in_zip_read = NULL;
399
400 s = (unz_s *)ALLOC(sizeof(unz_s));
401 *s = us;
402 unzGoToFirstFile((unzFile)s);
403 return (unzFile)s;
404 }
405
406 /*
407 Close a ZipFile opened with unzipOpen.
408 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
409 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
410 return UNZ_OK if there is no problem. */
411 extern int ZEXPORT unzClose(unzFile file)
412 {
413 unz_s*s;
414 if (file == NULL)
415 return UNZ_PARAMERROR;
416 s = (unz_s *)file;
417
418 if (s->pfile_in_zip_read != NULL)
419 unzCloseCurrentFile(file);
420
421 fclose(s->file);
422 TRYFREE(s);
423 return UNZ_OK;
424 }
425
426 /*
427 Write info about the ZipFile in the *pglobal_info structure.
428 No preparation of the structure is needed
429 return UNZ_OK if there is no problem. */
430 extern int ZEXPORT unzGetGlobalInfo(unzFile file,
431 unz_global_info *pglobal_info)
432 {
433 unz_s*s;
434 if (file == NULL)
435 return UNZ_PARAMERROR;
436 s = (unz_s *)file;
437 *pglobal_info = s->gi;
438 return UNZ_OK;
439 }
440
441 /*
442 Translate date/time from Dos format to tm_unz (readable more easilty)
443 */
444 local void unzlocal_DosDateToTmuDate(uLong ulDosDate, tm_unz *ptm)
445 {
446 uLong uDate;
447 uDate = (uLong)(ulDosDate>>16);
448 ptm->tm_mday = (uInt)(uDate&0x1f) ;
449 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
450 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
451
452 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
453 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
454 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
455 }
456
457 /*
458 Get Info about the current file in the zipfile, with internal only info
459 */
460 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
461 unz_file_info *pfile_info,
462 unz_file_info_internal
463 *pfile_info_internal,
464 char *szFileName,
465 uLong fileNameBufferSize,
466 void *extraField,
467 uLong extraFieldBufferSize,
468 char *szComment,
469 uLong commentBufferSize));
470
471 local int unzlocal_GetCurrentFileInfoInternal(unzFile file,
472 unz_file_info *pfile_info,
473 unz_file_info_internal *pfile_info_internal,
474 char *szFileName,
475 uLong fileNameBufferSize,
476 void *extraField,
477 uLong extraFieldBufferSize,
478 char *szComment,
479 uLong commentBufferSize)
480 {
481 unz_s* s;
482 unz_file_info file_info;
483 unz_file_info_internal file_info_internal;
484 int err = UNZ_OK;
485 uLong uMagic;
486 long lSeek = 0;
487
488 if (file == NULL)
489 return UNZ_PARAMERROR;
490 s = (unz_s *)file;
491 if (fseek(s->file, s->pos_in_central_dir+s->byte_before_the_zipfile, SEEK_SET) != 0)
492 err = UNZ_ERRNO;
493
494 /* we check the magic */
495 if (err == UNZ_OK)
496 if (unzlocal_getLong(s->file, &uMagic) != UNZ_OK)
497 err = UNZ_ERRNO;
498 else if (uMagic != 0x02014b50)
499 err = UNZ_BADZIPFILE;
500
501 if (unzlocal_getShort(s->file, &file_info.version) != UNZ_OK)
502 err = UNZ_ERRNO;
503
504 if (unzlocal_getShort(s->file, &file_info.version_needed) != UNZ_OK)
505 err = UNZ_ERRNO;
506
507 if (unzlocal_getShort(s->file, &file_info.flag) != UNZ_OK)
508 err = UNZ_ERRNO;
509
510 if (unzlocal_getShort(s->file, &file_info.compression_method) != UNZ_OK)
511 err = UNZ_ERRNO;
512
513 if (unzlocal_getLong(s->file, &file_info.dosDate) != UNZ_OK)
514 err = UNZ_ERRNO;
515
516 unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date);
517
518 if (unzlocal_getLong(s->file, &file_info.crc) != UNZ_OK)
519 err = UNZ_ERRNO;
520
521 if (unzlocal_getLong(s->file, &file_info.compressed_size) != UNZ_OK)
522 err = UNZ_ERRNO;
523
524 if (unzlocal_getLong(s->file, &file_info.uncompressed_size) != UNZ_OK)
525 err = UNZ_ERRNO;
526
527 if (unzlocal_getShort(s->file, &file_info.size_filename) != UNZ_OK)
528 err = UNZ_ERRNO;
529
530 if (unzlocal_getShort(s->file, &file_info.size_file_extra) != UNZ_OK)
531 err = UNZ_ERRNO;
532
533 if (unzlocal_getShort(s->file, &file_info.size_file_comment) != UNZ_OK)
534 err = UNZ_ERRNO;
535
536 if (unzlocal_getShort(s->file, &file_info.disk_num_start) != UNZ_OK)
537 err = UNZ_ERRNO;
538
539 if (unzlocal_getShort(s->file, &file_info.internal_fa) != UNZ_OK)
540 err = UNZ_ERRNO;
541
542 if (unzlocal_getLong(s->file, &file_info.external_fa) != UNZ_OK)
543 err = UNZ_ERRNO;
544
545 if (unzlocal_getLong(s->file, &file_info_internal.offset_curfile) != UNZ_OK)
546 err = UNZ_ERRNO;
547
548 lSeek += file_info.size_filename;
549 if ((err == UNZ_OK) && (szFileName != NULL))
550 {
551 uLong uSizeRead ;
552 if (file_info.size_filename < fileNameBufferSize)
553 {
554 *(szFileName+file_info.size_filename) = '\0';
555 uSizeRead = file_info.size_filename;
556 }
557 else
558 uSizeRead = fileNameBufferSize;
559
560 if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
561 if (fread(szFileName, (uInt)uSizeRead, 1, s->file) != 1)
562 err = UNZ_ERRNO;
563 lSeek -= uSizeRead;
564 }
565
566 if ((err == UNZ_OK) && (extraField != NULL))
567 {
568 uLong uSizeRead ;
569 if (file_info.size_file_extra < extraFieldBufferSize)
570 uSizeRead = file_info.size_file_extra;
571 else
572 uSizeRead = extraFieldBufferSize;
573
574 if (lSeek != 0)
575 if (fseek(s->file, lSeek, SEEK_CUR) == 0)
576 lSeek = 0;
577 else
578 err = UNZ_ERRNO;
579 if ((file_info.size_file_extra > 0) && (extraFieldBufferSize > 0))
580 if (fread(extraField, (uInt)uSizeRead, 1, s->file) != 1)
581 err = UNZ_ERRNO;
582 lSeek += file_info.size_file_extra - uSizeRead;
583 }
584 else
585 lSeek += file_info.size_file_extra;
586
587 if ((err == UNZ_OK) && (szComment != NULL))
588 {
589 uLong uSizeRead ;
590 if (file_info.size_file_comment < commentBufferSize)
591 {
592 *(szComment+file_info.size_file_comment) = '\0';
593 uSizeRead = file_info.size_file_comment;
594 }
595 else
596 uSizeRead = commentBufferSize;
597
598 if (lSeek != 0)
599 if (fseek(s->file, lSeek, SEEK_CUR) == 0)
600 lSeek = 0;
601 else
602 err = UNZ_ERRNO;
603 if ((file_info.size_file_comment > 0) && (commentBufferSize > 0))
604 if (fread(szComment, (uInt)uSizeRead, 1, s->file) != 1)
605 err = UNZ_ERRNO;
606 lSeek += file_info.size_file_comment - uSizeRead;
607 }
608 else
609 lSeek += file_info.size_file_comment;
610
611 if ((err == UNZ_OK) && (pfile_info != NULL))
612 *pfile_info = file_info;
613
614 if ((err == UNZ_OK) && (pfile_info_internal != NULL))
615 *pfile_info_internal = file_info_internal;
616
617 return err;
618 }
619
620 /*
621 Write info about the ZipFile in the *pglobal_info structure.
622 No preparation of the structure is needed
623 return UNZ_OK if there is no problem.
624 */
625 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
626 unz_file_info *pfile_info,
627 char *szFileName,
628 uLong fileNameBufferSize,
629 void *extraField,
630 uLong extraFieldBufferSize,
631 char *szComment,
632 uLong commentBufferSize)
633 {
634 return unzlocal_GetCurrentFileInfoInternal(file, pfile_info, NULL,
635 szFileName, fileNameBufferSize,
636 extraField, extraFieldBufferSize,
637 szComment, commentBufferSize);
638 }
639
640 /*
641 Set the current file of the zipfile to the first file.
642 return UNZ_OK if there is no problem
643 */
644 extern int ZEXPORT unzGoToFirstFile(unzFile file)
645 {
646 int err = UNZ_OK;
647 unz_s*s;
648 if (file == NULL)
649 return UNZ_PARAMERROR;
650 s = (unz_s *)file;
651 s->pos_in_central_dir = s->offset_central_dir;
652 s->num_file = 0;
653 err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info,
654 &s->cur_file_info_internal,
655 NULL, 0, NULL, 0, NULL, 0);
656 s->current_file_ok = (err == UNZ_OK);
657 return err;
658 }
659
660 /*
661 Set the current file of the zipfile to the next file.
662 return UNZ_OK if there is no problem
663 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
664 */
665 extern int ZEXPORT unzGoToNextFile(unzFile file)
666 {
667 unz_s*s;
668 int err;
669
670 if (file == NULL)
671 return UNZ_PARAMERROR;
672 s = (unz_s *)file;
673 if (!s->current_file_ok)
674 return UNZ_END_OF_LIST_OF_FILE;
675 if (s->num_file+1 == s->gi.number_entry)
676 return UNZ_END_OF_LIST_OF_FILE;
677
678 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
679 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
680 s->num_file++;
681 err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info,
682 &s->cur_file_info_internal,
683 NULL, 0, NULL, 0, NULL, 0);
684 s->current_file_ok = (err == UNZ_OK);
685 return err;
686 }
687
688 /*
689 Try locate the file szFileName in the zipfile.
690 For the iCaseSensitivity signification, see unzipStringFileNameCompare
691
692 return value :
693 UNZ_OK if the file is found. It becomes the current file.
694 UNZ_END_OF_LIST_OF_FILE if the file is not found
695 */
696 extern int ZEXPORT unzLocateFile(unzFile file,
697 const char *szFileName,
698 int iCaseSensitivity)
699 {
700 unz_s*s;
701 int err;
702
703 uLong num_fileSaved;
704 uLong pos_in_central_dirSaved;
705
706 if (file == NULL)
707 return UNZ_PARAMERROR;
708
709 if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP)
710 return UNZ_PARAMERROR;
711
712 s = (unz_s *)file;
713 if (!s->current_file_ok)
714 return UNZ_END_OF_LIST_OF_FILE;
715
716 num_fileSaved = s->num_file;
717 pos_in_central_dirSaved = s->pos_in_central_dir;
718
719 err = unzGoToFirstFile(file);
720
721 while (err == UNZ_OK)
722 {
723 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
724 unzGetCurrentFileInfo(file, NULL,
725 szCurrentFileName, sizeof(szCurrentFileName)-1,
726 NULL, 0, NULL, 0);
727 if (unzStringFileNameCompare(szCurrentFileName,
728 szFileName, iCaseSensitivity) == 0)
729 return UNZ_OK;
730 err = unzGoToNextFile(file);
731 }
732
733 s->num_file = num_fileSaved ;
734 s->pos_in_central_dir = pos_in_central_dirSaved ;
735 return err;
736 }
737
738 /*
739 Read the local header of the current zipfile
740 Check the coherency of the local header and info in the end of central
741 directory about this file
742 store in *piSizeVar the size of extra info in local header
743 (filename and size of extra field data)
744 */
745 local int unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s,
746 uInt *piSizeVar,
747 uLong *poffset_local_extrafield,
748 uInt *psize_local_extrafield)
749 {
750 uLong uMagic, uData, uFlags;
751 uLong size_filename;
752 uLong size_extra_field;
753 int err = UNZ_OK;
754
755 *piSizeVar = 0;
756 *poffset_local_extrafield = 0;
757 *psize_local_extrafield = 0;
758
759 if (fseek(s->file, s->cur_file_info_internal.offset_curfile +
760 s->byte_before_the_zipfile, SEEK_SET) != 0)
761 return UNZ_ERRNO;
762
763 if (err == UNZ_OK)
764 if (unzlocal_getLong(s->file, &uMagic) != UNZ_OK)
765 err = UNZ_ERRNO;
766 else if (uMagic != 0x04034b50)
767 err = UNZ_BADZIPFILE;
768
769 if (unzlocal_getShort(s->file, &uData) != UNZ_OK)
770 err = UNZ_ERRNO;
771 /*
772 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
773 err=UNZ_BADZIPFILE;
774 */
775 if (unzlocal_getShort(s->file, &uFlags) != UNZ_OK)
776 err = UNZ_ERRNO;
777
778 if (unzlocal_getShort(s->file, &uData) != UNZ_OK)
779 err = UNZ_ERRNO;
780 else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
781 err = UNZ_BADZIPFILE;
782
783 if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) &&
784 (s->cur_file_info.compression_method != Z_DEFLATED))
785 err = UNZ_BADZIPFILE;
786
787 if (unzlocal_getLong(s->file, &uData) != UNZ_OK) /* date/time */
788 err = UNZ_ERRNO;
789
790 if (unzlocal_getLong(s->file, &uData) != UNZ_OK) /* crc */
791 err = UNZ_ERRNO;
792 else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
793 ((uFlags & 8) == 0))
794 err = UNZ_BADZIPFILE;
795
796 if (unzlocal_getLong(s->file, &uData) != UNZ_OK) /* size compr */
797 err = UNZ_ERRNO;
798 else if ((err == UNZ_OK) && (uData != s->cur_file_info.compressed_size) &&
799 ((uFlags & 8) == 0))
800 err = UNZ_BADZIPFILE;
801
802 if (unzlocal_getLong(s->file, &uData) != UNZ_OK) /* size uncompr */
803 err = UNZ_ERRNO;
804 else if ((err == UNZ_OK) && (uData != s->cur_file_info.uncompressed_size) &&
805 ((uFlags & 8) == 0))
806 err = UNZ_BADZIPFILE;
807
808 if (unzlocal_getShort(s->file, &size_filename) != UNZ_OK)
809 err = UNZ_ERRNO;
810 else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename))
811 err = UNZ_BADZIPFILE;
812
813 *piSizeVar += (uInt)size_filename;
814
815 if (unzlocal_getShort(s->file, &size_extra_field) != UNZ_OK)
816 err = UNZ_ERRNO;
817 *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile +
818 SIZEZIPLOCALHEADER + size_filename;
819 *psize_local_extrafield = (uInt)size_extra_field;
820
821 *piSizeVar += (uInt)size_extra_field;
822
823 return err;
824 }
825
826 /*
827 Open for reading data the current file in the zipfile.
828 If there is no error and the file is opened, the return value is UNZ_OK.
829 */
830 extern int ZEXPORT unzOpenCurrentFile(unzFile file)
831 {
832 int err = UNZ_OK;
833 int Store;
834 uInt iSizeVar;
835 unz_s*s;
836 file_in_zip_read_info_s*pfile_in_zip_read_info;
837 uLong offset_local_extrafield; /* offset of the local extra field */
838 uInt size_local_extrafield; /* size of the local extra field */
839
840 if (file == NULL)
841 return UNZ_PARAMERROR;
842 s = (unz_s *)file;
843 if (!s->current_file_ok)
844 return UNZ_PARAMERROR;
845
846 if (s->pfile_in_zip_read != NULL)
847 unzCloseCurrentFile(file);
848
849 if (unzlocal_CheckCurrentFileCoherencyHeader(s, &iSizeVar,
850 &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
851 return UNZ_BADZIPFILE;
852
853 pfile_in_zip_read_info = (file_in_zip_read_info_s *)
854 ALLOC(sizeof(file_in_zip_read_info_s));
855 if (pfile_in_zip_read_info == NULL)
856 return UNZ_INTERNALERROR;
857
858 pfile_in_zip_read_info->read_buffer = (char *)ALLOC(UNZ_BUFSIZE);
859 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
860 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
861 pfile_in_zip_read_info->pos_local_extrafield = 0;
862
863 if (pfile_in_zip_read_info->read_buffer == NULL)
864 {
865 TRYFREE(pfile_in_zip_read_info);
866 return UNZ_INTERNALERROR;
867 }
868
869 pfile_in_zip_read_info->stream_initialised = 0;
870
871 if ((s->cur_file_info.compression_method != 0) &&
872 (s->cur_file_info.compression_method != Z_DEFLATED))
873 err = UNZ_BADZIPFILE;
874 Store = s->cur_file_info.compression_method == 0;
875
876 pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
877 pfile_in_zip_read_info->crc32 = 0;
878 pfile_in_zip_read_info->compression_method =
879 s->cur_file_info.compression_method;
880 pfile_in_zip_read_info->file = s->file;
881 pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
882
883 pfile_in_zip_read_info->stream.total_out = 0;
884
885 if (!Store)
886 {
887 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
888 pfile_in_zip_read_info->stream.zfree = (free_func)0;
889 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
890
891 err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
892 if (err == Z_OK)
893 pfile_in_zip_read_info->stream_initialised = 1;
894 /* windowBits is passed < 0 to tell that there is no zlib header.
895 * Note that in this case inflate *requires* an extra "dummy" byte
896 * after the compressed stream in order to complete decompression and
897 * return Z_STREAM_END.
898 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
899 * size of both compressed and uncompressed data
900 */
901 }
902 pfile_in_zip_read_info->rest_read_compressed =
903 s->cur_file_info.compressed_size ;
904 pfile_in_zip_read_info->rest_read_uncompressed =
905 s->cur_file_info.uncompressed_size ;
906
907 pfile_in_zip_read_info->pos_in_zipfile =
908 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
909 iSizeVar;
910
911 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
912
913 s->pfile_in_zip_read = pfile_in_zip_read_info;
914 return UNZ_OK;
915 }
916
917 /*
918 Read bytes from the current file.
919 buf contain buffer where data must be copied
920 len the size of buf.
921
922 return the number of byte copied if somes bytes are copied
923 return 0 if the end of file was reached
924 return <0 with error code if there is an error
925 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
926 */
927 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
928 {
929 int err = UNZ_OK;
930 uInt iRead = 0;
931 unz_s*s;
932 file_in_zip_read_info_s*pfile_in_zip_read_info;
933 if (file == NULL)
934 return UNZ_PARAMERROR;
935 s = (unz_s *)file;
936 pfile_in_zip_read_info = s->pfile_in_zip_read;
937
938 if (pfile_in_zip_read_info == NULL)
939 return UNZ_PARAMERROR;
940
941 if ((pfile_in_zip_read_info->read_buffer == NULL))
942 return UNZ_END_OF_LIST_OF_FILE;
943 if (len == 0)
944 return 0;
945
946 pfile_in_zip_read_info->stream.next_out = (Bytef *)buf;
947
948 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
949
950 if (len > pfile_in_zip_read_info->rest_read_uncompressed)
951 pfile_in_zip_read_info->stream.avail_out =
952 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
953
954 while (pfile_in_zip_read_info->stream.avail_out > 0)
955 {
956 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
957 (pfile_in_zip_read_info->rest_read_compressed > 0))
958 {
959 uInt uReadThis = UNZ_BUFSIZE;
960 if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
961 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
962 if (uReadThis == 0)
963 return UNZ_EOF;
964 if (fseek(pfile_in_zip_read_info->file,
965 pfile_in_zip_read_info->pos_in_zipfile +
966 pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0)
967 return UNZ_ERRNO;
968 if (fread(pfile_in_zip_read_info->read_buffer, uReadThis, 1,
969 pfile_in_zip_read_info->file) != 1)
970 return UNZ_ERRNO;
971 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
972
973 pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
974
975 pfile_in_zip_read_info->stream.next_in =
976 (Bytef *)pfile_in_zip_read_info->read_buffer;
977 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
978 }
979
980 if (pfile_in_zip_read_info->compression_method == 0)
981 {
982 uInt uDoCopy, i ;
983 if (pfile_in_zip_read_info->stream.avail_out <
984 pfile_in_zip_read_info->stream.avail_in)
985 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
986 else
987 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
988
989 for (i = 0; i < uDoCopy; i++)
990 *(pfile_in_zip_read_info->stream.next_out+i) =
991 *(pfile_in_zip_read_info->stream.next_in+i);
992
993 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
994 pfile_in_zip_read_info->stream.next_out,
995 uDoCopy);
996 pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
997 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
998 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
999 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1000 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1001 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1002 iRead += uDoCopy;
1003 }
1004 else
1005 {
1006 uLong uTotalOutBefore, uTotalOutAfter;
1007 const Bytef *bufBefore;
1008 uLong uOutThis;
1009 int flush = Z_SYNC_FLUSH;
1010
1011 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1012 bufBefore = pfile_in_zip_read_info->stream.next_out;
1013
1014 /*
1015 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1016 pfile_in_zip_read_info->stream.avail_out) &&
1017 (pfile_in_zip_read_info->rest_read_compressed == 0))
1018 flush = Z_FINISH;
1019 */
1020 err = inflate(&pfile_in_zip_read_info->stream, flush);
1021
1022 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1023 uOutThis = uTotalOutAfter-uTotalOutBefore;
1024
1025 pfile_in_zip_read_info->crc32 =
1026 crc32(pfile_in_zip_read_info->crc32, bufBefore,
1027 (uInt)(uOutThis));
1028
1029 pfile_in_zip_read_info->rest_read_uncompressed -=
1030 uOutThis;
1031
1032 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1033
1034 if (err == Z_STREAM_END)
1035 return (iRead == 0) ? UNZ_EOF : iRead;
1036 if (err != Z_OK)
1037 break;
1038 }
1039 }
1040
1041 if (err == Z_OK)
1042 return iRead;
1043 return err;
1044 }
1045
1046 /*
1047 Give the current position in uncompressed data
1048 */
1049 extern z_off_t ZEXPORT unztell(unzFile file)
1050 {
1051 unz_s*s;
1052 file_in_zip_read_info_s*pfile_in_zip_read_info;
1053 if (file == NULL)
1054 return UNZ_PARAMERROR;
1055 s = (unz_s *)file;
1056 pfile_in_zip_read_info = s->pfile_in_zip_read;
1057
1058 if (pfile_in_zip_read_info == NULL)
1059 return UNZ_PARAMERROR;
1060
1061 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1062 }
1063
1064 /*
1065 return 1 if the end of file was reached, 0 elsewhere
1066 */
1067 extern int ZEXPORT unzeof(unzFile file)
1068 {
1069 unz_s*s;
1070 file_in_zip_read_info_s*pfile_in_zip_read_info;
1071 if (file == NULL)
1072 return UNZ_PARAMERROR;
1073 s = (unz_s *)file;
1074 pfile_in_zip_read_info = s->pfile_in_zip_read;
1075
1076 if (pfile_in_zip_read_info == NULL)
1077 return UNZ_PARAMERROR;
1078
1079 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1080 return 1;
1081 else
1082 return 0;
1083 }
1084
1085 /*
1086 Read extra field from the current file (opened by unzOpenCurrentFile)
1087 This is the local-header version of the extra field (sometimes, there is
1088 more info in the local-header version than in the central-header)
1089
1090 if buf==NULL, it return the size of the local extra field that can be read
1091
1092 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1093 buf.
1094 the return value is the number of bytes copied in buf, or (if <0)
1095 the error code
1096 */
1097 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len)
1098 {
1099 unz_s*s;
1100 file_in_zip_read_info_s*pfile_in_zip_read_info;
1101 uInt read_now;
1102 uLong size_to_read;
1103
1104 if (file == NULL)
1105 return UNZ_PARAMERROR;
1106 s = (unz_s *)file;
1107 pfile_in_zip_read_info = s->pfile_in_zip_read;
1108
1109 if (pfile_in_zip_read_info == NULL)
1110 return UNZ_PARAMERROR;
1111
1112 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1113 pfile_in_zip_read_info->pos_local_extrafield);
1114
1115 if (buf == NULL)
1116 return (int)size_to_read;
1117
1118 if (len > size_to_read)
1119 read_now = (uInt)size_to_read;
1120 else
1121 read_now = (uInt)len ;
1122
1123 if (read_now == 0)
1124 return 0;
1125
1126 if (fseek(pfile_in_zip_read_info->file,
1127 pfile_in_zip_read_info->offset_local_extrafield +
1128 pfile_in_zip_read_info->pos_local_extrafield, SEEK_SET) != 0)
1129 return UNZ_ERRNO;
1130
1131 if (fread(buf, (uInt)size_to_read, 1, pfile_in_zip_read_info->file) != 1)
1132 return UNZ_ERRNO;
1133
1134 return (int)read_now;
1135 }
1136
1137 /*
1138 Close the file in zip opened with unzipOpenCurrentFile
1139 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1140 */
1141 extern int ZEXPORT unzCloseCurrentFile(unzFile file)
1142 {
1143 int err = UNZ_OK;
1144
1145 unz_s*s;
1146 file_in_zip_read_info_s*pfile_in_zip_read_info;
1147 if (file == NULL)
1148 return UNZ_PARAMERROR;
1149 s = (unz_s *)file;
1150 pfile_in_zip_read_info = s->pfile_in_zip_read;
1151
1152 if (pfile_in_zip_read_info == NULL)
1153 return UNZ_PARAMERROR;
1154
1155 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1156 {
1157 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1158 err = UNZ_CRCERROR;
1159 }
1160
1161 TRYFREE(pfile_in_zip_read_info->read_buffer);
1162 pfile_in_zip_read_info->read_buffer = NULL;
1163 if (pfile_in_zip_read_info->stream_initialised)
1164 inflateEnd(&pfile_in_zip_read_info->stream);
1165
1166 pfile_in_zip_read_info->stream_initialised = 0;
1167 TRYFREE(pfile_in_zip_read_info);
1168
1169 s->pfile_in_zip_read = NULL;
1170
1171 return err;
1172 }
1173
1174 /*
1175 Get the global comment string of the ZipFile, in the szComment buffer.
1176 uSizeBuf is the size of the szComment buffer.
1177 return the number of byte copied or an error code <0
1178 */
1179 extern int ZEXPORT unzGetGlobalComment(unzFile file,
1180 char *szComment,
1181 uLong uSizeBuf)
1182 {
1183 //int err=UNZ_OK;
1184 unz_s*s;
1185 uLong uReadThis ;
1186 if (file == NULL)
1187 return UNZ_PARAMERROR;
1188 s = (unz_s *)file;
1189
1190 uReadThis = uSizeBuf;
1191 if (uReadThis > s->gi.size_comment)
1192 uReadThis = s->gi.size_comment;
1193
1194 if (fseek(s->file, s->central_pos+22, SEEK_SET) != 0)
1195 return UNZ_ERRNO;
1196
1197 if (uReadThis > 0)
1198 {
1199 *szComment = '\0';
1200 if (fread(szComment, (uInt)uReadThis, 1, s->file) != 1)
1201 return UNZ_ERRNO;
1202 }
1203
1204 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1205 *(szComment+s->gi.size_comment) = '\0';
1206 return (int)uReadThis;
1207 }
1208