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