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