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