]> git.saurik.com Git - wxWidgets.git/blob - src/common/unzip.c
partially applied patch #895170: "Building with minimal setup.h - continuation"
[wxWidgets.git] / src / common / unzip.c
1 /*
2
3 This 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
101 const 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*/
105 typedef 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 */
113 typedef 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 */
137 typedef 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 */
159 int 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
174 local 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 */
198 local 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
220 local 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 */
252 local 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 */
295 extern 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 */
315 local 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 */
380 extern 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. */
479 extern 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. */
500 extern 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 */
516 local 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 */
534 local 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
545 local 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 lSeek=0;
690 else
691 err=UNZ_ERRNO;
692 }
693
694 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
695 if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
696 err=UNZ_ERRNO;
697 lSeek+=file_info.size_file_comment - uSizeRead;
698 }
699 else
700 lSeek+=file_info.size_file_comment;
701
702 if ((err==UNZ_OK) && (pfile_info!=NULL))
703 *pfile_info=file_info;
704
705 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
706 *pfile_info_internal=file_info_internal;
707
708 return err;
709 }
710
711
712
713 /*
714 Write info about the ZipFile in the *pglobal_info structure.
715 No preparation of the structure is needed
716 return UNZ_OK if there is no problem.
717 */
718 extern int ZEXPORT unzGetCurrentFileInfo (file,
719 pfile_info,
720 szFileName, fileNameBufferSize,
721 extraField, extraFieldBufferSize,
722 szComment, commentBufferSize)
723 unzFile file;
724 unz_file_info *pfile_info;
725 char *szFileName;
726 uLong fileNameBufferSize;
727 void *extraField;
728 uLong extraFieldBufferSize;
729 char *szComment;
730 uLong commentBufferSize;
731 {
732 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
733 szFileName,fileNameBufferSize,
734 extraField,extraFieldBufferSize,
735 szComment,commentBufferSize);
736 }
737
738 /*
739 Set the current file of the zipfile to the first file.
740 return UNZ_OK if there is no problem
741 */
742 extern int ZEXPORT unzGoToFirstFile (file)
743 unzFile file;
744 {
745 int err=UNZ_OK;
746 unz_s* s;
747 if (file==NULL)
748 return UNZ_PARAMERROR;
749 s=(unz_s*)file;
750 s->pos_in_central_dir=s->offset_central_dir;
751 s->num_file=0;
752 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
753 &s->cur_file_info_internal,
754 NULL,0,NULL,0,NULL,0);
755 s->current_file_ok = (err == UNZ_OK);
756 return err;
757 }
758
759
760 /*
761 Set the current file of the zipfile to the next file.
762 return UNZ_OK if there is no problem
763 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
764 */
765 extern int ZEXPORT unzGoToNextFile (file)
766 unzFile file;
767 {
768 unz_s* s;
769 int err;
770
771 if (file==NULL)
772 return UNZ_PARAMERROR;
773 s=(unz_s*)file;
774 if (!s->current_file_ok)
775 return UNZ_END_OF_LIST_OF_FILE;
776 if (s->num_file+1==s->gi.number_entry)
777 return UNZ_END_OF_LIST_OF_FILE;
778
779 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
780 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
781 s->num_file++;
782 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
783 &s->cur_file_info_internal,
784 NULL,0,NULL,0,NULL,0);
785 s->current_file_ok = (err == UNZ_OK);
786 return err;
787 }
788
789
790 /*
791 Try locate the file szFileName in the zipfile.
792 For the iCaseSensitivity signification, see unzipStringFileNameCompare
793
794 return value :
795 UNZ_OK if the file is found. It becomes the current file.
796 UNZ_END_OF_LIST_OF_FILE if the file is not found
797 */
798 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
799 unzFile file;
800 const char *szFileName;
801 int iCaseSensitivity;
802 {
803 unz_s* s;
804 int err;
805 const char *c;
806 char *c2;
807 char szFileName2[UNZ_MAXFILENAMEINZIP+1];
808
809 uLong num_fileSaved;
810 uLong pos_in_central_dirSaved;
811
812 for (c = szFileName, c2 = szFileName2; *c != '\0'; c++, c2++)
813 if (*c == '\\') *c2 = '/';
814 else *c2 = *c;
815 *c2 = '\0';
816
817 if (file==NULL)
818 return UNZ_PARAMERROR;
819
820 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
821 return UNZ_PARAMERROR;
822
823 s=(unz_s*)file;
824 if (!s->current_file_ok)
825 return UNZ_END_OF_LIST_OF_FILE;
826
827 num_fileSaved = s->num_file;
828 pos_in_central_dirSaved = s->pos_in_central_dir;
829
830 err = unzGoToFirstFile(file);
831
832 while (err == UNZ_OK)
833 {
834 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
835 unzGetCurrentFileInfo(file,NULL,
836 szCurrentFileName,sizeof(szCurrentFileName)-1,
837 NULL,0,NULL,0);
838 for (c2 = szCurrentFileName; *c2 != '\0'; c2++) if (*c2 == '\\') *c2 = '/';
839 if (unzStringFileNameCompare(szCurrentFileName,
840 szFileName2,iCaseSensitivity)==0)
841 return UNZ_OK;
842 err = unzGoToNextFile(file);
843 }
844
845 s->num_file = num_fileSaved ;
846 s->pos_in_central_dir = pos_in_central_dirSaved ;
847 return err;
848 }
849
850
851 /*
852 Read the local header of the current zipfile
853 Check the coherency of the local header and info in the end of central
854 directory about this file
855 store in *piSizeVar the size of extra info in local header
856 (filename and size of extra field data)
857 */
858 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
859 poffset_local_extrafield,
860 psize_local_extrafield)
861 unz_s* s;
862 uInt* piSizeVar;
863 uLong *poffset_local_extrafield;
864 uInt *psize_local_extrafield;
865 {
866 uLong uMagic,uData,uFlags;
867 uLong size_filename;
868 uLong size_extra_field;
869 int err=UNZ_OK;
870
871 *piSizeVar = 0;
872 *poffset_local_extrafield = 0;
873 *psize_local_extrafield = 0;
874
875 if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
876 s->byte_before_the_zipfile,SEEK_SET)!=0)
877 return UNZ_ERRNO;
878
879
880 if (err==UNZ_OK)
881 {
882 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
883 err=UNZ_ERRNO;
884 else if (uMagic!=0x04034b50)
885 err=UNZ_BADZIPFILE;
886 }
887
888 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
889 err=UNZ_ERRNO;
890 /*
891 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
892 err=UNZ_BADZIPFILE;
893 */
894 if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
895 err=UNZ_ERRNO;
896
897 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
898 err=UNZ_ERRNO;
899 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
900 err=UNZ_BADZIPFILE;
901
902 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
903 (s->cur_file_info.compression_method!=Z_DEFLATED))
904 err=UNZ_BADZIPFILE;
905
906 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
907 err=UNZ_ERRNO;
908
909 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
910 err=UNZ_ERRNO;
911 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
912 ((uFlags & 8)==0))
913 err=UNZ_BADZIPFILE;
914
915 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
916 err=UNZ_ERRNO;
917 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
918 ((uFlags & 8)==0))
919 err=UNZ_BADZIPFILE;
920
921 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
922 err=UNZ_ERRNO;
923 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
924 ((uFlags & 8)==0))
925 err=UNZ_BADZIPFILE;
926
927
928 if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
929 err=UNZ_ERRNO;
930 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
931 err=UNZ_BADZIPFILE;
932
933 *piSizeVar += (uInt)size_filename;
934
935 if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
936 err=UNZ_ERRNO;
937 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
938 SIZEZIPLOCALHEADER + size_filename;
939 *psize_local_extrafield = (uInt)size_extra_field;
940
941 *piSizeVar += (uInt)size_extra_field;
942
943 return err;
944 }
945
946 /*
947 Open for reading data the current file in the zipfile.
948 If there is no error and the file is opened, the return value is UNZ_OK.
949 */
950 extern int ZEXPORT unzOpenCurrentFile (file)
951 unzFile file;
952 {
953 int err=UNZ_OK;
954 int Store;
955 uInt iSizeVar;
956 unz_s* s;
957 file_in_zip_read_info_s* pfile_in_zip_read_info;
958 uLong offset_local_extrafield; /* offset of the local extra field */
959 uInt size_local_extrafield; /* size of the local extra field */
960
961 if (file==NULL)
962 return UNZ_PARAMERROR;
963 s=(unz_s*)file;
964 if (!s->current_file_ok)
965 return UNZ_PARAMERROR;
966
967 if (s->pfile_in_zip_read != NULL)
968 unzCloseCurrentFile(file);
969
970 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
971 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
972 return UNZ_BADZIPFILE;
973
974 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
975 ALLOC(sizeof(file_in_zip_read_info_s));
976 if (pfile_in_zip_read_info==NULL)
977 return UNZ_INTERNALERROR;
978
979 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
980 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
981 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
982 pfile_in_zip_read_info->pos_local_extrafield=0;
983
984 if (pfile_in_zip_read_info->read_buffer==NULL)
985 {
986 TRYFREE(pfile_in_zip_read_info);
987 return UNZ_INTERNALERROR;
988 }
989
990 pfile_in_zip_read_info->stream_initialised=0;
991
992 if ((s->cur_file_info.compression_method!=0) &&
993 (s->cur_file_info.compression_method!=Z_DEFLATED))
994 err=UNZ_BADZIPFILE;
995 Store = s->cur_file_info.compression_method==0;
996
997 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
998 pfile_in_zip_read_info->crc32=0;
999 pfile_in_zip_read_info->compression_method =
1000 s->cur_file_info.compression_method;
1001 pfile_in_zip_read_info->file=s->file;
1002 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1003
1004 pfile_in_zip_read_info->stream.total_out = 0;
1005
1006 if (!Store)
1007 {
1008 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1009 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1010 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1011
1012 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1013 if (err == Z_OK)
1014 pfile_in_zip_read_info->stream_initialised=1;
1015 /* windowBits is passed < 0 to tell that there is no zlib header.
1016 * Note that in this case inflate *requires* an extra "dummy" byte
1017 * after the compressed stream in order to complete decompression and
1018 * return Z_STREAM_END.
1019 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1020 * size of both compressed and uncompressed data
1021 */
1022 }
1023 pfile_in_zip_read_info->rest_read_compressed =
1024 s->cur_file_info.compressed_size ;
1025 pfile_in_zip_read_info->rest_read_uncompressed =
1026 s->cur_file_info.uncompressed_size ;
1027
1028
1029 pfile_in_zip_read_info->pos_in_zipfile =
1030 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1031 iSizeVar;
1032
1033 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1034
1035
1036 s->pfile_in_zip_read = pfile_in_zip_read_info;
1037 return UNZ_OK;
1038 }
1039
1040
1041 /*
1042 Read bytes from the current file.
1043 buf contain buffer where data must be copied
1044 len the size of buf.
1045
1046 return the number of byte copied if somes bytes are copied
1047 return 0 if the end of file was reached
1048 return <0 with error code if there is an error
1049 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1050 */
1051 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1052 unzFile file;
1053 voidp buf;
1054 unsigned len;
1055 {
1056 int err=UNZ_OK;
1057 uInt iRead = 0;
1058 unz_s* s;
1059 file_in_zip_read_info_s* pfile_in_zip_read_info;
1060 if (file==NULL)
1061 return UNZ_PARAMERROR;
1062 s=(unz_s*)file;
1063 pfile_in_zip_read_info=s->pfile_in_zip_read;
1064
1065 if (pfile_in_zip_read_info==NULL)
1066 return UNZ_PARAMERROR;
1067
1068
1069 if ((pfile_in_zip_read_info->read_buffer == NULL))
1070 return UNZ_END_OF_LIST_OF_FILE;
1071 if (len==0)
1072 return 0;
1073
1074 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1075
1076 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1077
1078 if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1079 pfile_in_zip_read_info->stream.avail_out =
1080 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1081
1082 while (pfile_in_zip_read_info->stream.avail_out>0)
1083 {
1084 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1085 (pfile_in_zip_read_info->rest_read_compressed>0))
1086 {
1087 uInt uReadThis = UNZ_BUFSIZE;
1088 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1089 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1090 if (uReadThis == 0)
1091 return UNZ_EOF;
1092 if (fseek(pfile_in_zip_read_info->file,
1093 pfile_in_zip_read_info->pos_in_zipfile +
1094 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1095 return UNZ_ERRNO;
1096 if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1097 pfile_in_zip_read_info->file)!=1)
1098 return UNZ_ERRNO;
1099 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1100
1101 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1102
1103 pfile_in_zip_read_info->stream.next_in =
1104 (Bytef*)pfile_in_zip_read_info->read_buffer;
1105 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1106 }
1107
1108 if (pfile_in_zip_read_info->compression_method==0)
1109 {
1110 uInt uDoCopy,i ;
1111 if (pfile_in_zip_read_info->stream.avail_out <
1112 pfile_in_zip_read_info->stream.avail_in)
1113 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1114 else
1115 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1116
1117 for (i=0;i<uDoCopy;i++)
1118 *(pfile_in_zip_read_info->stream.next_out+i) =
1119 *(pfile_in_zip_read_info->stream.next_in+i);
1120
1121 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1122 pfile_in_zip_read_info->stream.next_out,
1123 uDoCopy);
1124 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1125 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1126 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1127 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1128 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1129 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1130 iRead += uDoCopy;
1131 }
1132 else
1133 {
1134 uLong uTotalOutBefore,uTotalOutAfter;
1135 const Bytef *bufBefore;
1136 uLong uOutThis;
1137 int flush=Z_SYNC_FLUSH;
1138
1139 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1140 bufBefore = pfile_in_zip_read_info->stream.next_out;
1141
1142 /*
1143 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1144 pfile_in_zip_read_info->stream.avail_out) &&
1145 (pfile_in_zip_read_info->rest_read_compressed == 0))
1146 flush = Z_FINISH;
1147 */
1148 err=inflate(&pfile_in_zip_read_info->stream,flush);
1149
1150 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1151 uOutThis = uTotalOutAfter-uTotalOutBefore;
1152
1153 pfile_in_zip_read_info->crc32 =
1154 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1155 (uInt)(uOutThis));
1156
1157 pfile_in_zip_read_info->rest_read_uncompressed -=
1158 uOutThis;
1159
1160 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1161
1162 if (err==Z_STREAM_END)
1163 return (iRead==0) ? UNZ_EOF : iRead;
1164 if (err!=Z_OK)
1165 break;
1166 }
1167 }
1168
1169 if (err==Z_OK)
1170 return iRead;
1171 return err;
1172 }
1173
1174
1175 /*
1176 Give the current position in uncompressed data
1177 */
1178 extern z_off_t ZEXPORT unztell (file)
1179 unzFile file;
1180 {
1181 unz_s* s;
1182 file_in_zip_read_info_s* pfile_in_zip_read_info;
1183 if (file==NULL)
1184 return UNZ_PARAMERROR;
1185 s=(unz_s*)file;
1186 pfile_in_zip_read_info=s->pfile_in_zip_read;
1187
1188 if (pfile_in_zip_read_info==NULL)
1189 return UNZ_PARAMERROR;
1190
1191 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1192 }
1193
1194
1195 /*
1196 return 1 if the end of file was reached, 0 elsewhere
1197 */
1198 extern int ZEXPORT unzeof (file)
1199 unzFile file;
1200 {
1201 unz_s* s;
1202 file_in_zip_read_info_s* pfile_in_zip_read_info;
1203 if (file==NULL)
1204 return UNZ_PARAMERROR;
1205 s=(unz_s*)file;
1206 pfile_in_zip_read_info=s->pfile_in_zip_read;
1207
1208 if (pfile_in_zip_read_info==NULL)
1209 return UNZ_PARAMERROR;
1210
1211 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1212 return 1;
1213 else
1214 return 0;
1215 }
1216
1217
1218
1219 /*
1220 Read extra field from the current file (opened by unzOpenCurrentFile)
1221 This is the local-header version of the extra field (sometimes, there is
1222 more info in the local-header version than in the central-header)
1223
1224 if buf==NULL, it return the size of the local extra field that can be read
1225
1226 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1227 buf.
1228 the return value is the number of bytes copied in buf, or (if <0)
1229 the error code
1230 */
1231 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1232 unzFile file;
1233 voidp buf;
1234 unsigned len;
1235 {
1236 unz_s* s;
1237 file_in_zip_read_info_s* pfile_in_zip_read_info;
1238 uInt read_now;
1239 uLong size_to_read;
1240
1241 if (file==NULL)
1242 return UNZ_PARAMERROR;
1243 s=(unz_s*)file;
1244 pfile_in_zip_read_info=s->pfile_in_zip_read;
1245
1246 if (pfile_in_zip_read_info==NULL)
1247 return UNZ_PARAMERROR;
1248
1249 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1250 pfile_in_zip_read_info->pos_local_extrafield);
1251
1252 if (buf==NULL)
1253 return (int)size_to_read;
1254
1255 if (len>size_to_read)
1256 read_now = (uInt)size_to_read;
1257 else
1258 read_now = (uInt)len ;
1259
1260 if (read_now==0)
1261 return 0;
1262
1263 if (fseek(pfile_in_zip_read_info->file,
1264 pfile_in_zip_read_info->offset_local_extrafield +
1265 pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1266 return UNZ_ERRNO;
1267
1268 if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1269 return UNZ_ERRNO;
1270
1271 return (int)read_now;
1272 }
1273
1274 /*
1275 Close the file in zip opened with unzipOpenCurrentFile
1276 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1277 */
1278 extern int ZEXPORT unzCloseCurrentFile (file)
1279 unzFile file;
1280 {
1281 int err=UNZ_OK;
1282
1283 unz_s* s;
1284 file_in_zip_read_info_s* pfile_in_zip_read_info;
1285 if (file==NULL)
1286 return UNZ_PARAMERROR;
1287 s=(unz_s*)file;
1288 pfile_in_zip_read_info=s->pfile_in_zip_read;
1289
1290 if (pfile_in_zip_read_info==NULL)
1291 return UNZ_PARAMERROR;
1292
1293
1294 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1295 {
1296 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1297 err=UNZ_CRCERROR;
1298 }
1299
1300
1301 TRYFREE(pfile_in_zip_read_info->read_buffer);
1302 pfile_in_zip_read_info->read_buffer = NULL;
1303 if (pfile_in_zip_read_info->stream_initialised)
1304 inflateEnd(&pfile_in_zip_read_info->stream);
1305
1306 pfile_in_zip_read_info->stream_initialised = 0;
1307 TRYFREE(pfile_in_zip_read_info);
1308
1309 s->pfile_in_zip_read=NULL;
1310
1311 return err;
1312 }
1313
1314
1315 /*
1316 Get the global comment string of the ZipFile, in the szComment buffer.
1317 uSizeBuf is the size of the szComment buffer.
1318 return the number of byte copied or an error code <0
1319 */
1320 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1321 unzFile file;
1322 char *szComment;
1323 uLong uSizeBuf;
1324 {
1325 unz_s* s;
1326 uLong uReadThis ;
1327 if (file==NULL)
1328 return UNZ_PARAMERROR;
1329 s=(unz_s*)file;
1330
1331 uReadThis = uSizeBuf;
1332 if (uReadThis>s->gi.size_comment)
1333 uReadThis = s->gi.size_comment;
1334
1335 if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1336 return UNZ_ERRNO;
1337
1338 if (uReadThis>0)
1339 {
1340 *szComment='\0';
1341 if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1342 return UNZ_ERRNO;
1343 }
1344
1345 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1346 *(szComment+s->gi.size_comment)='\0';
1347 return (int)uReadThis;
1348 }
1349
1350 #else
1351
1352 /* the file shouldn't be empty, som compilers don't like it */
1353 static const int dummyVariableInUnzip = 17;
1354
1355 #endif /* wxUSE_ZLIB && wxUSE_ZIPSTREAM */