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