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