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