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