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