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