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