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