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