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