]> git.mxchange.org Git - simgear.git/blob - simgear/package/unzip.c
Pkg: qualified ID accessor.
[simgear.git] / simgear / package / unzip.c
1 /* unzip.c -- IO for uncompress .zip files using zlib
2    Version 1.01h, December 28th, 2009
3
4    Copyright (C) 1998-2009 Gilles Vollant
5
6    Read unzip.h for more info
7 */
8
9 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
10 compatibility with older software. The following is from the original crypt.c. Code
11 woven in by Terry Thorsen 1/2003.
12 */
13 /*
14   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
15
16   See the accompanying file LICENSE, version 2000-Apr-09 or later
17   (the contents of which are also included in zip.h) for terms of use.
18   If, for some reason, all these files are missing, the Info-ZIP license
19   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
20 */
21 /*
22   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
23
24   The encryption/decryption parts of this source code (as opposed to the
25   non-echoing password parts) were originally written in Europe.  The
26   whole source package can be freely distributed, including from the USA.
27   (Prior to January 2000, re-export from the US was a violation of US law.)
28  */
29
30 /*
31   This encryption code is a direct transcription of the algorithm from
32   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
33   file (appnote.txt) is distributed with the PKZIP program (even in the
34   version without encryption capabilities).
35  */
36
37 #define NOUNCRYPT
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "zlib.h"
43 #include "unzip.h"
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 #ifndef CASESENSITIVITYDEFAULT_NO
64 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
65 #    define CASESENSITIVITYDEFAULT_NO
66 #  endif
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
90
91 const char unz_copyright[] =
92    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
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 #ifdef HAVE_BZIP2
108     bz_stream bstream;          /* bzLib stream structure for bziped */
109 #endif
110
111     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
112     uLong stream_initialised;   /* flag set if stream structure is initialised*/
113
114     uLong offset_local_extrafield;/* offset of the local extra field */
115     uInt  size_local_extrafield;/* size of the local extra field */
116     uLong pos_local_extrafield;   /* position in the local extra field in read*/
117
118     uLong crc32;                /* crc32 of all data uncompressed */
119     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
120     uLong rest_read_compressed; /* number of byte to be decompressed */
121     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
122     zlib_filefunc_def z_filefunc;
123     voidpf filestream;        /* io structore of the zipfile */
124     uLong compression_method;   /* compression method (0==store) */
125     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
126     int   raw;
127 } file_in_zip_read_info_s;
128
129
130 /* unz_s contain internal information about the zipfile
131 */
132 typedef struct
133 {
134     zlib_filefunc_def z_filefunc;
135     voidpf filestream;        /* io structore of the zipfile */
136     unz_global_info gi;       /* public global information */
137     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
138     uLong num_file;             /* number of the current file in the zipfile*/
139     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
140     uLong current_file_ok;      /* flag about the usability of the current file*/
141     uLong central_pos;          /* position of the beginning of the central dir*/
142
143     uLong size_central_dir;     /* size of the central directory  */
144     uLong offset_central_dir;   /* offset of start of central directory with
145                                    respect to the starting disk number */
146
147     unz_file_info cur_file_info; /* public info about the current file in zip*/
148     unz_file_info_internal cur_file_info_internal; /* private info about it*/
149     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
150                                         file if we are decompressing it */
151     int encrypted;
152 #    ifndef NOUNCRYPT
153     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
154     const unsigned long* pcrc_32_tab;
155 #    endif
156 } unz_s;
157
158
159 #ifndef NOUNCRYPT
160 #include "crypt.h"
161 #endif
162
163 /* ===========================================================================
164      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
165    for end of file.
166    IN assertion: the stream s has been sucessfully opened for reading.
167 */
168
169
170 local int unzlocal_getByte OF((
171     const zlib_filefunc_def* pzlib_filefunc_def,
172     voidpf filestream,
173     int *pi));
174
175 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
176     const zlib_filefunc_def* pzlib_filefunc_def;
177     voidpf filestream;
178     int *pi;
179 {
180     unsigned char c;
181     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
182     if (err==1)
183     {
184         *pi = (int)c;
185         return UNZ_OK;
186     }
187     else
188     {
189         if (ZERROR(*pzlib_filefunc_def,filestream))
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 OF((
201     const zlib_filefunc_def* pzlib_filefunc_def,
202     voidpf filestream,
203     uLong *pX));
204
205 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
206     const zlib_filefunc_def* pzlib_filefunc_def;
207     voidpf filestream;
208     uLong *pX;
209 {
210     uLong x ;
211     int i = 0;
212     int err;
213
214     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
215     x = (uLong)i;
216
217     if (err==UNZ_OK)
218         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
219     x += ((uLong)i)<<8;
220
221     if (err==UNZ_OK)
222         *pX = x;
223     else
224         *pX = 0;
225     return err;
226 }
227
228 local int unzlocal_getLong OF((
229     const zlib_filefunc_def* pzlib_filefunc_def,
230     voidpf filestream,
231     uLong *pX));
232
233 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
234     const zlib_filefunc_def* pzlib_filefunc_def;
235     voidpf filestream;
236     uLong *pX;
237 {
238     uLong x ;
239     int i = 0;
240     int err;
241
242     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
243     x = (uLong)i;
244
245     if (err==UNZ_OK)
246         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
247     x += ((uLong)i)<<8;
248
249     if (err==UNZ_OK)
250         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
251     x += ((uLong)i)<<16;
252
253     if (err==UNZ_OK)
254         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
255     x += ((uLong)i)<<24;
256
257     if (err==UNZ_OK)
258         *pX = x;
259     else
260         *pX = 0;
261     return err;
262 }
263
264
265 /* My own strcmpi / strcasecmp */
266 local int strcmpcasenosensitive_internal (fileName1,fileName2)
267     const char* fileName1;
268     const char* fileName2;
269 {
270     for (;;)
271     {
272         char c1=*(fileName1++);
273         char c2=*(fileName2++);
274         if ((c1>='a') && (c1<='z'))
275             c1 -= 0x20;
276         if ((c2>='a') && (c2<='z'))
277             c2 -= 0x20;
278         if (c1=='\0')
279             return ((c2=='\0') ? 0 : -1);
280         if (c2=='\0')
281             return 1;
282         if (c1<c2)
283             return -1;
284         if (c1>c2)
285             return 1;
286     }
287 }
288
289
290 #ifdef  CASESENSITIVITYDEFAULT_NO
291 #define CASESENSITIVITYDEFAULTVALUE 2
292 #else
293 #define CASESENSITIVITYDEFAULTVALUE 1
294 #endif
295
296 #ifndef STRCMPCASENOSENTIVEFUNCTION
297 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
298 #endif
299
300 /*
301    Compare two filename (fileName1,fileName2).
302    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
303    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
304                                                                 or strcasecmp)
305    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
306         (like 1 on Unix, 2 on Windows)
307
308 */
309 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
310     const char* fileName1;
311     const char* fileName2;
312     int iCaseSensitivity;
313 {
314     if (iCaseSensitivity==0)
315         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
316
317     if (iCaseSensitivity==1)
318         return strcmp(fileName1,fileName2);
319
320     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
321 }
322
323 #ifndef BUFREADCOMMENT
324 #define BUFREADCOMMENT (0x400)
325 #endif
326
327 /*
328   Locate the Central directory of a zipfile (at the end, just before
329     the global comment)
330 */
331 local uLong unzlocal_SearchCentralDir OF((
332     const zlib_filefunc_def* pzlib_filefunc_def,
333     voidpf filestream));
334
335 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
336     const zlib_filefunc_def* pzlib_filefunc_def;
337     voidpf filestream;
338 {
339     unsigned char* buf;
340     uLong uSizeFile;
341     uLong uBackRead;
342     uLong uMaxBack=0xffff; /* maximum size of global comment */
343     uLong uPosFound=0;
344
345     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
346         return 0;
347
348
349     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
350
351     if (uMaxBack>uSizeFile)
352         uMaxBack = uSizeFile;
353
354     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
355     if (buf==NULL)
356         return 0;
357
358     uBackRead = 4;
359     while (uBackRead<uMaxBack)
360     {
361         uLong uReadSize,uReadPos ;
362         int i;
363         if (uBackRead+BUFREADCOMMENT>uMaxBack)
364             uBackRead = uMaxBack;
365         else
366             uBackRead+=BUFREADCOMMENT;
367         uReadPos = uSizeFile-uBackRead ;
368
369         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
370                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
371         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
372             break;
373
374         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
375             break;
376
377         for (i=(int)uReadSize-3; (i--)>0;)
378             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
379                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
380             {
381                 uPosFound = uReadPos+i;
382                 break;
383             }
384
385         if (uPosFound!=0)
386             break;
387     }
388     TRYFREE(buf);
389     return uPosFound;
390 }
391
392 /*
393   Open a Zip file. path contain the full pathname (by example,
394      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
395      "zlib/zlib114.zip".
396      If the zipfile cannot be opened (file doesn't exist or in not valid), the
397        return value is NULL.
398      Else, the return value is a unzFile Handle, usable with other function
399        of this unzip package.
400 */
401 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
402     const char *path;
403     zlib_filefunc_def* pzlib_filefunc_def;
404 {
405     unz_s us;
406     unz_s *s;
407     uLong central_pos,uL;
408
409     uLong number_disk;          /* number of the current dist, used for
410                                    spaning ZIP, unsupported, always 0*/
411     uLong number_disk_with_CD;  /* number the the disk with central dir, used
412                                    for spaning ZIP, unsupported, always 0*/
413     uLong number_entry_CD;      /* total number of entries in
414                                    the central dir
415                                    (same than number_entry on nospan) */
416
417     int err=UNZ_OK;
418
419     if (unz_copyright[0]!=' ')
420         return NULL;
421
422     if (pzlib_filefunc_def==NULL)
423         fill_fopen_filefunc(&us.z_filefunc);
424     else
425         us.z_filefunc = *pzlib_filefunc_def;
426
427     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
428                                                  path,
429                                                  ZLIB_FILEFUNC_MODE_READ |
430                                                  ZLIB_FILEFUNC_MODE_EXISTING);
431     if (us.filestream==NULL)
432         return NULL;
433
434     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
435     if (central_pos==0)
436         err=UNZ_ERRNO;
437
438     if (ZSEEK(us.z_filefunc, us.filestream,
439                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
440         err=UNZ_ERRNO;
441
442     /* the signature, already checked */
443     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
444         err=UNZ_ERRNO;
445
446     /* number of this disk */
447     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
448         err=UNZ_ERRNO;
449
450     /* number of the disk with the start of the central directory */
451     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
452         err=UNZ_ERRNO;
453
454     /* total number of entries in the central dir on this disk */
455     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
456         err=UNZ_ERRNO;
457
458     /* total number of entries in the central dir */
459     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
460         err=UNZ_ERRNO;
461
462     if ((number_entry_CD!=us.gi.number_entry) ||
463         (number_disk_with_CD!=0) ||
464         (number_disk!=0))
465         err=UNZ_BADZIPFILE;
466
467     /* size of the central directory */
468     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
469         err=UNZ_ERRNO;
470
471     /* offset of start of central directory with respect to the
472           starting disk number */
473     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
474         err=UNZ_ERRNO;
475
476     /* zipfile comment length */
477     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
478         err=UNZ_ERRNO;
479
480     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
481         (err==UNZ_OK))
482         err=UNZ_BADZIPFILE;
483
484     if (err!=UNZ_OK)
485     {
486         ZCLOSE(us.z_filefunc, us.filestream);
487         return NULL;
488     }
489
490     us.byte_before_the_zipfile = central_pos -
491                             (us.offset_central_dir+us.size_central_dir);
492     us.central_pos = central_pos;
493     us.pfile_in_zip_read = NULL;
494     us.encrypted = 0;
495
496
497     s=(unz_s*)ALLOC(sizeof(unz_s));
498     if (s!=NULL)
499     {
500         *s=us;
501         unzGoToFirstFile((unzFile)s);
502     }
503     return (unzFile)s;
504 }
505
506
507 extern unzFile ZEXPORT unzOpen (path)
508     const char *path;
509 {
510     return unzOpen2(path, NULL);
511 }
512
513 /*
514   Close a ZipFile opened with unzipOpen.
515   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
516     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
517   return UNZ_OK if there is no problem. */
518 extern int ZEXPORT unzClose (file)
519     unzFile file;
520 {
521     unz_s* s;
522     if (file==NULL)
523         return UNZ_PARAMERROR;
524     s=(unz_s*)file;
525
526     if (s->pfile_in_zip_read!=NULL)
527         unzCloseCurrentFile(file);
528
529     ZCLOSE(s->z_filefunc, s->filestream);
530     TRYFREE(s);
531     return UNZ_OK;
532 }
533
534
535 /*
536   Write info about the ZipFile in the *pglobal_info structure.
537   No preparation of the structure is needed
538   return UNZ_OK if there is no problem. */
539 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
540     unzFile file;
541     unz_global_info *pglobal_info;
542 {
543     unz_s* s;
544     if (file==NULL)
545         return UNZ_PARAMERROR;
546     s=(unz_s*)file;
547     *pglobal_info=s->gi;
548     return UNZ_OK;
549 }
550
551
552 /*
553    Translate date/time from Dos format to tm_unz (readable more easilty)
554 */
555 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
556     uLong ulDosDate;
557     tm_unz* ptm;
558 {
559     uLong uDate;
560     uDate = (uLong)(ulDosDate>>16);
561     ptm->tm_mday = (uInt)(uDate&0x1f) ;
562     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
563     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
564
565     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
566     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
567     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
568 }
569
570 /*
571   Get Info about the current file in the zipfile, with internal only info
572 */
573 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
574                                                   unz_file_info *pfile_info,
575                                                   unz_file_info_internal
576                                                   *pfile_info_internal,
577                                                   char *szFileName,
578                                                   uLong fileNameBufferSize,
579                                                   void *extraField,
580                                                   uLong extraFieldBufferSize,
581                                                   char *szComment,
582                                                   uLong commentBufferSize));
583
584 local int unzlocal_GetCurrentFileInfoInternal (file,
585                                               pfile_info,
586                                               pfile_info_internal,
587                                               szFileName, fileNameBufferSize,
588                                               extraField, extraFieldBufferSize,
589                                               szComment,  commentBufferSize)
590     unzFile file;
591     unz_file_info *pfile_info;
592     unz_file_info_internal *pfile_info_internal;
593     char *szFileName;
594     uLong fileNameBufferSize;
595     void *extraField;
596     uLong extraFieldBufferSize;
597     char *szComment;
598     uLong commentBufferSize;
599 {
600     unz_s* s;
601     unz_file_info file_info;
602     unz_file_info_internal file_info_internal;
603     int err=UNZ_OK;
604     uLong uMagic;
605     long lSeek=0;
606
607     if (file==NULL)
608         return UNZ_PARAMERROR;
609     s=(unz_s*)file;
610     if (ZSEEK(s->z_filefunc, s->filestream,
611               s->pos_in_central_dir+s->byte_before_the_zipfile,
612               ZLIB_FILEFUNC_SEEK_SET)!=0)
613         err=UNZ_ERRNO;
614
615
616     /* we check the magic */
617     if (err==UNZ_OK)
618     {
619         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
620             err=UNZ_ERRNO;
621         else if (uMagic!=0x02014b50)
622             err=UNZ_BADZIPFILE;
623     }
624
625     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
626         err=UNZ_ERRNO;
627
628     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
629         err=UNZ_ERRNO;
630
631     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
632         err=UNZ_ERRNO;
633
634     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
635         err=UNZ_ERRNO;
636
637     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
638         err=UNZ_ERRNO;
639
640     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
641
642     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
643         err=UNZ_ERRNO;
644
645     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
646         err=UNZ_ERRNO;
647
648     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
649         err=UNZ_ERRNO;
650
651     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
652         err=UNZ_ERRNO;
653
654     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
655         err=UNZ_ERRNO;
656
657     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
658         err=UNZ_ERRNO;
659
660     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
661         err=UNZ_ERRNO;
662
663     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
664         err=UNZ_ERRNO;
665
666     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
667         err=UNZ_ERRNO;
668
669     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
670         err=UNZ_ERRNO;
671
672     lSeek+=file_info.size_filename;
673     if ((err==UNZ_OK) && (szFileName!=NULL))
674     {
675         uLong uSizeRead ;
676         if (file_info.size_filename<fileNameBufferSize)
677         {
678             *(szFileName+file_info.size_filename)='\0';
679             uSizeRead = file_info.size_filename;
680         }
681         else
682             uSizeRead = fileNameBufferSize;
683
684         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
685             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
686                 err=UNZ_ERRNO;
687         lSeek -= uSizeRead;
688     }
689
690
691     if ((err==UNZ_OK) && (extraField!=NULL))
692     {
693         uLong uSizeRead ;
694         if (file_info.size_file_extra<extraFieldBufferSize)
695             uSizeRead = file_info.size_file_extra;
696         else
697             uSizeRead = extraFieldBufferSize;
698
699         if (lSeek!=0)
700         {
701             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
702                 lSeek=0;
703             else
704                 err=UNZ_ERRNO;
705         }
706
707         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
708             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
709                 err=UNZ_ERRNO;
710         lSeek += file_info.size_file_extra - uSizeRead;
711     }
712     else
713         lSeek+=file_info.size_file_extra;
714
715
716     if ((err==UNZ_OK) && (szComment!=NULL))
717     {
718         uLong uSizeRead ;
719         if (file_info.size_file_comment<commentBufferSize)
720         {
721             *(szComment+file_info.size_file_comment)='\0';
722             uSizeRead = file_info.size_file_comment;
723         }
724         else
725             uSizeRead = commentBufferSize;
726
727         if (lSeek!=0)
728         {
729             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
730                 lSeek=0;
731             else
732                 err=UNZ_ERRNO;
733         }
734
735         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
736             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
737                 err=UNZ_ERRNO;
738         lSeek+=file_info.size_file_comment - uSizeRead;
739     }
740     else
741         lSeek+=file_info.size_file_comment;
742
743     if ((err==UNZ_OK) && (pfile_info!=NULL))
744         *pfile_info=file_info;
745
746     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
747         *pfile_info_internal=file_info_internal;
748
749     return err;
750 }
751
752
753
754 /*
755   Write info about the ZipFile in the *pglobal_info structure.
756   No preparation of the structure is needed
757   return UNZ_OK if there is no problem.
758 */
759 extern int ZEXPORT unzGetCurrentFileInfo (file,
760                                           pfile_info,
761                                           szFileName, fileNameBufferSize,
762                                           extraField, extraFieldBufferSize,
763                                           szComment,  commentBufferSize)
764     unzFile file;
765     unz_file_info *pfile_info;
766     char *szFileName;
767     uLong fileNameBufferSize;
768     void *extraField;
769     uLong extraFieldBufferSize;
770     char *szComment;
771     uLong commentBufferSize;
772 {
773     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
774                                                 szFileName,fileNameBufferSize,
775                                                 extraField,extraFieldBufferSize,
776                                                 szComment,commentBufferSize);
777 }
778
779 /*
780   Set the current file of the zipfile to the first file.
781   return UNZ_OK if there is no problem
782 */
783 extern int ZEXPORT unzGoToFirstFile (file)
784     unzFile file;
785 {
786     int err=UNZ_OK;
787     unz_s* s;
788     if (file==NULL)
789         return UNZ_PARAMERROR;
790     s=(unz_s*)file;
791     s->pos_in_central_dir=s->offset_central_dir;
792     s->num_file=0;
793     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
794                                              &s->cur_file_info_internal,
795                                              NULL,0,NULL,0,NULL,0);
796     s->current_file_ok = (err == UNZ_OK);
797     return err;
798 }
799
800 /*
801   Set the current file of the zipfile to the next file.
802   return UNZ_OK if there is no problem
803   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
804 */
805 extern int ZEXPORT unzGoToNextFile (file)
806     unzFile file;
807 {
808     unz_s* s;
809     int err;
810
811     if (file==NULL)
812         return UNZ_PARAMERROR;
813     s=(unz_s*)file;
814     if (!s->current_file_ok)
815         return UNZ_END_OF_LIST_OF_FILE;
816     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
817       if (s->num_file+1==s->gi.number_entry)
818         return UNZ_END_OF_LIST_OF_FILE;
819
820     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
821             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
822     s->num_file++;
823     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
824                                                &s->cur_file_info_internal,
825                                                NULL,0,NULL,0,NULL,0);
826     s->current_file_ok = (err == UNZ_OK);
827     return err;
828 }
829
830
831 /*
832   Try locate the file szFileName in the zipfile.
833   For the iCaseSensitivity signification, see unzipStringFileNameCompare
834
835   return value :
836   UNZ_OK if the file is found. It becomes the current file.
837   UNZ_END_OF_LIST_OF_FILE if the file is not found
838 */
839 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
840     unzFile file;
841     const char *szFileName;
842     int iCaseSensitivity;
843 {
844     unz_s* s;
845     int err;
846
847     /* We remember the 'current' position in the file so that we can jump
848      * back there if we fail.
849      */
850     unz_file_info cur_file_infoSaved;
851     unz_file_info_internal cur_file_info_internalSaved;
852     uLong num_fileSaved;
853     uLong pos_in_central_dirSaved;
854
855
856     if (file==NULL)
857         return UNZ_PARAMERROR;
858
859     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
860         return UNZ_PARAMERROR;
861
862     s=(unz_s*)file;
863     if (!s->current_file_ok)
864         return UNZ_END_OF_LIST_OF_FILE;
865
866     /* Save the current state */
867     num_fileSaved = s->num_file;
868     pos_in_central_dirSaved = s->pos_in_central_dir;
869     cur_file_infoSaved = s->cur_file_info;
870     cur_file_info_internalSaved = s->cur_file_info_internal;
871
872     err = unzGoToFirstFile(file);
873
874     while (err == UNZ_OK)
875     {
876         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
877         err = unzGetCurrentFileInfo(file,NULL,
878                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
879                                     NULL,0,NULL,0);
880         if (err == UNZ_OK)
881         {
882             if (unzStringFileNameCompare(szCurrentFileName,
883                                             szFileName,iCaseSensitivity)==0)
884                 return UNZ_OK;
885             err = unzGoToNextFile(file);
886         }
887     }
888
889     /* We failed, so restore the state of the 'current file' to where we
890      * were.
891      */
892     s->num_file = num_fileSaved ;
893     s->pos_in_central_dir = pos_in_central_dirSaved ;
894     s->cur_file_info = cur_file_infoSaved;
895     s->cur_file_info_internal = cur_file_info_internalSaved;
896     return err;
897 }
898
899
900 /*
901 ///////////////////////////////////////////
902 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
903 // I need random access
904 //
905 // Further optimization could be realized by adding an ability
906 // to cache the directory in memory. The goal being a single
907 // comprehensive file read to put the file I need in a memory.
908 */
909
910 /*
911 typedef struct unz_file_pos_s
912 {
913     uLong pos_in_zip_directory;   // offset in file
914     uLong num_of_file;            // # of file
915 } unz_file_pos;
916 */
917
918 extern int ZEXPORT unzGetFilePos(file, file_pos)
919     unzFile file;
920     unz_file_pos* file_pos;
921 {
922     unz_s* s;
923
924     if (file==NULL || file_pos==NULL)
925         return UNZ_PARAMERROR;
926     s=(unz_s*)file;
927     if (!s->current_file_ok)
928         return UNZ_END_OF_LIST_OF_FILE;
929
930     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
931     file_pos->num_of_file           = s->num_file;
932
933     return UNZ_OK;
934 }
935
936 extern int ZEXPORT unzGoToFilePos(file, file_pos)
937     unzFile file;
938     unz_file_pos* file_pos;
939 {
940     unz_s* s;
941     int err;
942
943     if (file==NULL || file_pos==NULL)
944         return UNZ_PARAMERROR;
945     s=(unz_s*)file;
946
947     /* jump to the right spot */
948     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
949     s->num_file           = file_pos->num_of_file;
950
951     /* set the current file */
952     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
953                                                &s->cur_file_info_internal,
954                                                NULL,0,NULL,0,NULL,0);
955     /* return results */
956     s->current_file_ok = (err == UNZ_OK);
957     return err;
958 }
959
960 /*
961 // Unzip Helper Functions - should be here?
962 ///////////////////////////////////////////
963 */
964
965 /*
966   Read the local header of the current zipfile
967   Check the coherency of the local header and info in the end of central
968         directory about this file
969   store in *piSizeVar the size of extra info in local header
970         (filename and size of extra field data)
971 */
972 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
973                                                     poffset_local_extrafield,
974                                                     psize_local_extrafield)
975     unz_s* s;
976     uInt* piSizeVar;
977     uLong *poffset_local_extrafield;
978     uInt  *psize_local_extrafield;
979 {
980     uLong uMagic,uData,uFlags;
981     uLong size_filename;
982     uLong size_extra_field;
983     int err=UNZ_OK;
984
985     *piSizeVar = 0;
986     *poffset_local_extrafield = 0;
987     *psize_local_extrafield = 0;
988
989     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
990                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
991         return UNZ_ERRNO;
992
993
994     if (err==UNZ_OK)
995     {
996         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
997             err=UNZ_ERRNO;
998         else if (uMagic!=0x04034b50)
999             err=UNZ_BADZIPFILE;
1000     }
1001
1002     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1003         err=UNZ_ERRNO;
1004 /*
1005     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1006         err=UNZ_BADZIPFILE;
1007 */
1008     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1009         err=UNZ_ERRNO;
1010
1011     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1012         err=UNZ_ERRNO;
1013     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1014         err=UNZ_BADZIPFILE;
1015
1016     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1017 /* #ifdef HAVE_BZIP2 */
1018                          (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1019 /* #endif */
1020                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1021         err=UNZ_BADZIPFILE;
1022
1023     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1024         err=UNZ_ERRNO;
1025
1026     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1027         err=UNZ_ERRNO;
1028     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1029                               ((uFlags & 8)==0))
1030         err=UNZ_BADZIPFILE;
1031
1032     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1033         err=UNZ_ERRNO;
1034     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1035                               ((uFlags & 8)==0))
1036         err=UNZ_BADZIPFILE;
1037
1038     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1039         err=UNZ_ERRNO;
1040     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1041                               ((uFlags & 8)==0))
1042         err=UNZ_BADZIPFILE;
1043
1044
1045     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1046         err=UNZ_ERRNO;
1047     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1048         err=UNZ_BADZIPFILE;
1049
1050     *piSizeVar += (uInt)size_filename;
1051
1052     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1053         err=UNZ_ERRNO;
1054     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1055                                     SIZEZIPLOCALHEADER + size_filename;
1056     *psize_local_extrafield = (uInt)size_extra_field;
1057
1058     *piSizeVar += (uInt)size_extra_field;
1059
1060     return err;
1061 }
1062
1063 /*
1064   Open for reading data the current file in the zipfile.
1065   If there is no error and the file is opened, the return value is UNZ_OK.
1066 */
1067 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1068     unzFile file;
1069     int* method;
1070     int* level;
1071     int raw;
1072     const char* password;
1073 {
1074     int err=UNZ_OK;
1075     uInt iSizeVar;
1076     unz_s* s;
1077     file_in_zip_read_info_s* pfile_in_zip_read_info;
1078     uLong offset_local_extrafield;  /* offset of the local extra field */
1079     uInt  size_local_extrafield;    /* size of the local extra field */
1080 #    ifndef NOUNCRYPT
1081     char source[12];
1082 #    else
1083     if (password != NULL)
1084         return UNZ_PARAMERROR;
1085 #    endif
1086
1087     if (file==NULL)
1088         return UNZ_PARAMERROR;
1089     s=(unz_s*)file;
1090     if (!s->current_file_ok)
1091         return UNZ_PARAMERROR;
1092
1093     if (s->pfile_in_zip_read != NULL)
1094         unzCloseCurrentFile(file);
1095
1096     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1097                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1098         return UNZ_BADZIPFILE;
1099
1100     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1101                                         ALLOC(sizeof(file_in_zip_read_info_s));
1102     if (pfile_in_zip_read_info==NULL)
1103         return UNZ_INTERNALERROR;
1104
1105     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1106     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1107     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1108     pfile_in_zip_read_info->pos_local_extrafield=0;
1109     pfile_in_zip_read_info->raw=raw;
1110
1111     if (pfile_in_zip_read_info->read_buffer==NULL)
1112     {
1113         TRYFREE(pfile_in_zip_read_info);
1114         return UNZ_INTERNALERROR;
1115     }
1116
1117     pfile_in_zip_read_info->stream_initialised=0;
1118
1119     if (method!=NULL)
1120         *method = (int)s->cur_file_info.compression_method;
1121
1122     if (level!=NULL)
1123     {
1124         *level = 6;
1125         switch (s->cur_file_info.flag & 0x06)
1126         {
1127           case 6 : *level = 1; break;
1128           case 4 : *level = 2; break;
1129           case 2 : *level = 9; break;
1130         }
1131     }
1132
1133     if ((s->cur_file_info.compression_method!=0) &&
1134 /* #ifdef HAVE_BZIP2 */
1135         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1136 /* #endif */
1137         (s->cur_file_info.compression_method!=Z_DEFLATED))
1138         err=UNZ_BADZIPFILE;
1139
1140     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1141     pfile_in_zip_read_info->crc32=0;
1142     pfile_in_zip_read_info->compression_method =
1143             s->cur_file_info.compression_method;
1144     pfile_in_zip_read_info->filestream=s->filestream;
1145     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1146     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1147
1148     pfile_in_zip_read_info->stream.total_out = 0;
1149
1150     if ((s->cur_file_info.compression_method==Z_BZIP2ED) &&
1151         (!raw))
1152     {
1153 #ifdef HAVE_BZIP2
1154       pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1155       pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1156       pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1157       pfile_in_zip_read_info->bstream.state = (voidpf)0;
1158
1159       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1160       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1161       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1162       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1163       pfile_in_zip_read_info->stream.avail_in = 0;
1164
1165       err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1166       if (err == Z_OK)
1167         pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
1168       else
1169       {
1170         TRYFREE(pfile_in_zip_read_info);
1171         return err;
1172       }
1173 #else
1174       pfile_in_zip_read_info->raw=1;
1175 #endif
1176     }
1177     else
1178     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1179         (!raw))
1180     {
1181       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1182       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1183       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1184       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1185       pfile_in_zip_read_info->stream.avail_in = 0;
1186
1187       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1188       if (err == Z_OK)
1189         pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
1190       else
1191       {
1192         TRYFREE(pfile_in_zip_read_info);
1193         return err;
1194       }
1195         /* windowBits is passed < 0 to tell that there is no zlib header.
1196          * Note that in this case inflate *requires* an extra "dummy" byte
1197          * after the compressed stream in order to complete decompression and
1198          * return Z_STREAM_END.
1199          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1200          * size of both compressed and uncompressed data
1201          */
1202     }
1203     pfile_in_zip_read_info->rest_read_compressed =
1204             s->cur_file_info.compressed_size ;
1205     pfile_in_zip_read_info->rest_read_uncompressed =
1206             s->cur_file_info.uncompressed_size ;
1207
1208
1209     pfile_in_zip_read_info->pos_in_zipfile =
1210             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1211               iSizeVar;
1212
1213     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1214
1215     s->pfile_in_zip_read = pfile_in_zip_read_info;
1216
1217     s->encrypted = 0;
1218
1219 #    ifndef NOUNCRYPT
1220     if (password != NULL)
1221     {
1222         int i;
1223         s->pcrc_32_tab = get_crc_table();
1224         init_keys(password,s->keys,s->pcrc_32_tab);
1225         if (ZSEEK(s->z_filefunc, s->filestream,
1226                   s->pfile_in_zip_read->pos_in_zipfile +
1227                      s->pfile_in_zip_read->byte_before_the_zipfile,
1228                   SEEK_SET)!=0)
1229             return UNZ_INTERNALERROR;
1230         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1231             return UNZ_INTERNALERROR;
1232
1233         for (i = 0; i<12; i++)
1234             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1235
1236         s->pfile_in_zip_read->pos_in_zipfile+=12;
1237         s->encrypted=1;
1238     }
1239 #    endif
1240
1241
1242     return UNZ_OK;
1243 }
1244
1245 extern int ZEXPORT unzOpenCurrentFile (file)
1246     unzFile file;
1247 {
1248     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1249 }
1250
1251 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1252     unzFile file;
1253     const char* password;
1254 {
1255     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1256 }
1257
1258 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1259     unzFile file;
1260     int* method;
1261     int* level;
1262     int raw;
1263 {
1264     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1265 }
1266
1267 /*
1268   Read bytes from the current file.
1269   buf contain buffer where data must be copied
1270   len the size of buf.
1271
1272   return the number of byte copied if somes bytes are copied
1273   return 0 if the end of file was reached
1274   return <0 with error code if there is an error
1275     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1276 */
1277 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1278     unzFile file;
1279     voidp buf;
1280     unsigned len;
1281 {
1282     int err=UNZ_OK;
1283     uInt iRead = 0;
1284     unz_s* s;
1285     file_in_zip_read_info_s* pfile_in_zip_read_info;
1286     if (file==NULL)
1287         return UNZ_PARAMERROR;
1288     s=(unz_s*)file;
1289     pfile_in_zip_read_info=s->pfile_in_zip_read;
1290
1291     if (pfile_in_zip_read_info==NULL)
1292         return UNZ_PARAMERROR;
1293
1294
1295     if (pfile_in_zip_read_info->read_buffer == NULL)
1296         return UNZ_END_OF_LIST_OF_FILE;
1297     if (len==0)
1298         return 0;
1299
1300     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1301
1302     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1303
1304     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1305         (!(pfile_in_zip_read_info->raw)))
1306         pfile_in_zip_read_info->stream.avail_out =
1307             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1308
1309     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1310            pfile_in_zip_read_info->stream.avail_in) &&
1311          (pfile_in_zip_read_info->raw))
1312         pfile_in_zip_read_info->stream.avail_out =
1313             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1314             pfile_in_zip_read_info->stream.avail_in;
1315
1316     while (pfile_in_zip_read_info->stream.avail_out>0)
1317     {
1318         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1319             (pfile_in_zip_read_info->rest_read_compressed>0))
1320         {
1321             uInt uReadThis = UNZ_BUFSIZE;
1322             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1323                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1324             if (uReadThis == 0)
1325                 return UNZ_EOF;
1326             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1327                       pfile_in_zip_read_info->filestream,
1328                       pfile_in_zip_read_info->pos_in_zipfile +
1329                          pfile_in_zip_read_info->byte_before_the_zipfile,
1330                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1331                 return UNZ_ERRNO;
1332             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1333                       pfile_in_zip_read_info->filestream,
1334                       pfile_in_zip_read_info->read_buffer,
1335                       uReadThis)!=uReadThis)
1336                 return UNZ_ERRNO;
1337
1338
1339 #            ifndef NOUNCRYPT
1340             if(s->encrypted)
1341             {
1342                 uInt i;
1343                 for(i=0;i<uReadThis;i++)
1344                   pfile_in_zip_read_info->read_buffer[i] =
1345                       zdecode(s->keys,s->pcrc_32_tab,
1346                               pfile_in_zip_read_info->read_buffer[i]);
1347             }
1348 #            endif
1349
1350
1351             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1352
1353             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1354
1355             pfile_in_zip_read_info->stream.next_in =
1356                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1357             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1358         }
1359
1360         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1361         {
1362             uInt uDoCopy,i ;
1363
1364             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1365                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1366                 return (iRead==0) ? UNZ_EOF : iRead;
1367
1368             if (pfile_in_zip_read_info->stream.avail_out <
1369                             pfile_in_zip_read_info->stream.avail_in)
1370                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1371             else
1372                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1373
1374             for (i=0;i<uDoCopy;i++)
1375                 *(pfile_in_zip_read_info->stream.next_out+i) =
1376                         *(pfile_in_zip_read_info->stream.next_in+i);
1377
1378             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1379                                 pfile_in_zip_read_info->stream.next_out,
1380                                 uDoCopy);
1381             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1382             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1383             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1384             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1385             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1386             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1387             iRead += uDoCopy;
1388         }
1389         else
1390         if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
1391         {
1392 #ifdef HAVE_BZIP2
1393             uLong uTotalOutBefore,uTotalOutAfter;
1394             const Bytef *bufBefore;
1395             uLong uOutThis;
1396
1397             pfile_in_zip_read_info->bstream.next_in        = pfile_in_zip_read_info->stream.next_in;
1398             pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
1399             pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
1400             pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
1401             pfile_in_zip_read_info->bstream.next_out       = pfile_in_zip_read_info->stream.next_out;
1402             pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
1403             pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1404             pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1405
1406             uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1407             bufBefore = pfile_in_zip_read_info->bstream.next_out;
1408
1409             err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
1410
1411             uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1412             uOutThis = uTotalOutAfter-uTotalOutBefore;
1413
1414             pfile_in_zip_read_info->crc32 =
1415                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1416                         (uInt)(uOutThis));
1417
1418             pfile_in_zip_read_info->rest_read_uncompressed -=
1419                 uOutThis;
1420
1421             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1422
1423             pfile_in_zip_read_info->stream.next_in   = pfile_in_zip_read_info->bstream.next_in;
1424             pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
1425             pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
1426             pfile_in_zip_read_info->stream.next_out  = pfile_in_zip_read_info->bstream.next_out;
1427             pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1428             pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1429
1430             if (err==BZ_STREAM_END)
1431                 return (iRead==0) ? UNZ_EOF : iRead;
1432             if (err!=BZ_OK)
1433                 break;
1434 #endif
1435         }
1436         else
1437         {
1438             uLong uTotalOutBefore,uTotalOutAfter;
1439             const Bytef *bufBefore;
1440             uLong uOutThis;
1441             int flush=Z_SYNC_FLUSH;
1442
1443             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1444             bufBefore = pfile_in_zip_read_info->stream.next_out;
1445
1446             /*
1447             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1448                      pfile_in_zip_read_info->stream.avail_out) &&
1449                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1450                 flush = Z_FINISH;
1451             */
1452             err=inflate(&pfile_in_zip_read_info->stream,flush);
1453
1454             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1455               err = Z_DATA_ERROR;
1456
1457             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1458             uOutThis = uTotalOutAfter-uTotalOutBefore;
1459
1460             pfile_in_zip_read_info->crc32 =
1461                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1462                         (uInt)(uOutThis));
1463
1464             pfile_in_zip_read_info->rest_read_uncompressed -=
1465                 uOutThis;
1466
1467             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1468
1469             if (err==Z_STREAM_END)
1470                 return (iRead==0) ? UNZ_EOF : iRead;
1471             if (err!=Z_OK)
1472                 break;
1473         }
1474     }
1475
1476     if (err==Z_OK)
1477         return iRead;
1478     return err;
1479 }
1480
1481
1482 /*
1483   Give the current position in uncompressed data
1484 */
1485 extern z_off_t ZEXPORT unztell (file)
1486     unzFile file;
1487 {
1488     unz_s* s;
1489     file_in_zip_read_info_s* pfile_in_zip_read_info;
1490     if (file==NULL)
1491         return UNZ_PARAMERROR;
1492     s=(unz_s*)file;
1493     pfile_in_zip_read_info=s->pfile_in_zip_read;
1494
1495     if (pfile_in_zip_read_info==NULL)
1496         return UNZ_PARAMERROR;
1497
1498     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1499 }
1500
1501
1502 /*
1503   return 1 if the end of file was reached, 0 elsewhere
1504 */
1505 extern int ZEXPORT unzeof (file)
1506     unzFile file;
1507 {
1508     unz_s* s;
1509     file_in_zip_read_info_s* pfile_in_zip_read_info;
1510     if (file==NULL)
1511         return UNZ_PARAMERROR;
1512     s=(unz_s*)file;
1513     pfile_in_zip_read_info=s->pfile_in_zip_read;
1514
1515     if (pfile_in_zip_read_info==NULL)
1516         return UNZ_PARAMERROR;
1517
1518     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1519         return 1;
1520     else
1521         return 0;
1522 }
1523
1524
1525
1526 /*
1527   Read extra field from the current file (opened by unzOpenCurrentFile)
1528   This is the local-header version of the extra field (sometimes, there is
1529     more info in the local-header version than in the central-header)
1530
1531   if buf==NULL, it return the size of the local extra field that can be read
1532
1533   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1534     buf.
1535   the return value is the number of bytes copied in buf, or (if <0)
1536     the error code
1537 */
1538 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1539     unzFile file;
1540     voidp buf;
1541     unsigned len;
1542 {
1543     unz_s* s;
1544     file_in_zip_read_info_s* pfile_in_zip_read_info;
1545     uInt read_now;
1546     uLong size_to_read;
1547
1548     if (file==NULL)
1549         return UNZ_PARAMERROR;
1550     s=(unz_s*)file;
1551     pfile_in_zip_read_info=s->pfile_in_zip_read;
1552
1553     if (pfile_in_zip_read_info==NULL)
1554         return UNZ_PARAMERROR;
1555
1556     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1557                 pfile_in_zip_read_info->pos_local_extrafield);
1558
1559     if (buf==NULL)
1560         return (int)size_to_read;
1561
1562     if (len>size_to_read)
1563         read_now = (uInt)size_to_read;
1564     else
1565         read_now = (uInt)len ;
1566
1567     if (read_now==0)
1568         return 0;
1569
1570     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1571               pfile_in_zip_read_info->filestream,
1572               pfile_in_zip_read_info->offset_local_extrafield +
1573               pfile_in_zip_read_info->pos_local_extrafield,
1574               ZLIB_FILEFUNC_SEEK_SET)!=0)
1575         return UNZ_ERRNO;
1576
1577     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1578               pfile_in_zip_read_info->filestream,
1579               buf,read_now)!=read_now)
1580         return UNZ_ERRNO;
1581
1582     return (int)read_now;
1583 }
1584
1585 /*
1586   Close the file in zip opened with unzipOpenCurrentFile
1587   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1588 */
1589 extern int ZEXPORT unzCloseCurrentFile (file)
1590     unzFile file;
1591 {
1592     int err=UNZ_OK;
1593
1594     unz_s* s;
1595     file_in_zip_read_info_s* pfile_in_zip_read_info;
1596     if (file==NULL)
1597         return UNZ_PARAMERROR;
1598     s=(unz_s*)file;
1599     pfile_in_zip_read_info=s->pfile_in_zip_read;
1600
1601     if (pfile_in_zip_read_info==NULL)
1602         return UNZ_PARAMERROR;
1603
1604
1605     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1606         (!pfile_in_zip_read_info->raw))
1607     {
1608         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1609             err=UNZ_CRCERROR;
1610     }
1611
1612
1613     TRYFREE(pfile_in_zip_read_info->read_buffer);
1614     pfile_in_zip_read_info->read_buffer = NULL;
1615     if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1616         inflateEnd(&pfile_in_zip_read_info->stream);
1617 #ifdef HAVE_BZIP2
1618     else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1619         BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
1620 #endif
1621
1622     pfile_in_zip_read_info->stream_initialised = 0;
1623     TRYFREE(pfile_in_zip_read_info);
1624
1625     s->pfile_in_zip_read=NULL;
1626
1627     return err;
1628 }
1629
1630
1631 /*
1632   Get the global comment string of the ZipFile, in the szComment buffer.
1633   uSizeBuf is the size of the szComment buffer.
1634   return the number of byte copied or an error code <0
1635 */
1636 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1637     unzFile file;
1638     char *szComment;
1639     uLong uSizeBuf;
1640 {
1641     unz_s* s;
1642     uLong uReadThis ;
1643     if (file==NULL)
1644         return UNZ_PARAMERROR;
1645     s=(unz_s*)file;
1646
1647     uReadThis = uSizeBuf;
1648     if (uReadThis>s->gi.size_comment)
1649         uReadThis = s->gi.size_comment;
1650
1651     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1652         return UNZ_ERRNO;
1653
1654     if (uReadThis>0)
1655     {
1656       *szComment='\0';
1657       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1658         return UNZ_ERRNO;
1659     }
1660
1661     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1662         *(szComment+s->gi.size_comment)='\0';
1663     return (int)uReadThis;
1664 }
1665
1666 /* Additions by RX '2004 */
1667 extern uLong ZEXPORT unzGetOffset (file)
1668     unzFile file;
1669 {
1670     unz_s* s;
1671
1672     if (file==NULL)
1673           return 0;
1674     s=(unz_s*)file;
1675     if (!s->current_file_ok)
1676       return 0;
1677     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1678       if (s->num_file==s->gi.number_entry)
1679          return 0;
1680     return s->pos_in_central_dir;
1681 }
1682
1683 extern int ZEXPORT unzSetOffset (file, pos)
1684         unzFile file;
1685         uLong pos;
1686 {
1687     unz_s* s;
1688     int err;
1689
1690     if (file==NULL)
1691         return UNZ_PARAMERROR;
1692     s=(unz_s*)file;
1693
1694     s->pos_in_central_dir = pos;
1695     s->num_file = s->gi.number_entry;      /* hack */
1696     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1697                                               &s->cur_file_info_internal,
1698                                               NULL,0,NULL,0,NULL,0);
1699     s->current_file_ok = (err == UNZ_OK);
1700     return err;
1701 }