workaround a problem with the harmattan gcc
[drnoksnes] / unzip.c
1 /* unzip.c -- IO for uncompress .zip files using zlib
2    Version 1.01e, February 12th, 2005
3
4    Copyright (C) 1998-2005 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 = 0;
208     int err = UNZ_OK;
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 = 0;
236     int err = UNZ_OK;
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
617     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
618         err=UNZ_ERRNO;
619
620     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
621         err=UNZ_ERRNO;
622
623     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
624         err=UNZ_ERRNO;
625
626     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
627         err=UNZ_ERRNO;
628
629     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
630         err=UNZ_ERRNO;
631
632     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
633
634     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
635         err=UNZ_ERRNO;
636
637     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
638         err=UNZ_ERRNO;
639
640     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
641         err=UNZ_ERRNO;
642
643     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
644         err=UNZ_ERRNO;
645
646     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
647         err=UNZ_ERRNO;
648
649     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
650         err=UNZ_ERRNO;
651
652     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
653         err=UNZ_ERRNO;
654
655     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
656         err=UNZ_ERRNO;
657
658     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
659         err=UNZ_ERRNO;
660
661     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
662         err=UNZ_ERRNO;
663
664     lSeek+=file_info.size_filename;
665     if ((err==UNZ_OK) && (szFileName!=NULL))
666     {
667         uLong uSizeRead ;
668         if (file_info.size_filename<fileNameBufferSize)
669         {
670             *(szFileName+file_info.size_filename)='\0';
671             uSizeRead = file_info.size_filename;
672         }
673         else
674             uSizeRead = fileNameBufferSize;
675
676         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
677             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
678                 err=UNZ_ERRNO;
679         lSeek -= uSizeRead;
680     }
681
682
683     if ((err==UNZ_OK) && (extraField!=NULL))
684     {
685         uLong uSizeRead ;
686         if (file_info.size_file_extra<extraFieldBufferSize)
687             uSizeRead = file_info.size_file_extra;
688         else
689             uSizeRead = extraFieldBufferSize;
690
691         if (lSeek!=0) {
692             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
693                 lSeek=0;
694             else
695                 err=UNZ_ERRNO;
696         }
697         
698         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
699             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
700                 err=UNZ_ERRNO;
701         lSeek += file_info.size_file_extra - uSizeRead;
702     }
703     else
704         lSeek+=file_info.size_file_extra;
705
706
707     if ((err==UNZ_OK) && (szComment!=NULL))
708     {
709         uLong uSizeRead ;
710         if (file_info.size_file_comment<commentBufferSize)
711         {
712             *(szComment+file_info.size_file_comment)='\0';
713             uSizeRead = file_info.size_file_comment;
714         }
715         else
716             uSizeRead = commentBufferSize;
717
718         if (lSeek!=0) {
719             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
720                 lSeek=0;
721             else
722                 err=UNZ_ERRNO;
723         }
724         
725         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
726             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
727                 err=UNZ_ERRNO;
728         lSeek+=file_info.size_file_comment - uSizeRead;
729     }
730     else
731         lSeek+=file_info.size_file_comment;
732
733     if ((err==UNZ_OK) && (pfile_info!=NULL))
734         *pfile_info=file_info;
735
736     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
737         *pfile_info_internal=file_info_internal;
738
739     return err;
740 }
741
742
743
744 /*
745   Write info about the ZipFile in the *pglobal_info structure.
746   No preparation of the structure is needed
747   return UNZ_OK if there is no problem.
748 */
749 extern int ZEXPORT unzGetCurrentFileInfo (file,
750                                           pfile_info,
751                                           szFileName, fileNameBufferSize,
752                                           extraField, extraFieldBufferSize,
753                                           szComment,  commentBufferSize)
754     unzFile file;
755     unz_file_info *pfile_info;
756     char *szFileName;
757     uLong fileNameBufferSize;
758     void *extraField;
759     uLong extraFieldBufferSize;
760     char *szComment;
761     uLong commentBufferSize;
762 {
763     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
764                                                 szFileName,fileNameBufferSize,
765                                                 extraField,extraFieldBufferSize,
766                                                 szComment,commentBufferSize);
767 }
768
769 /*
770   Set the current file of the zipfile to the first file.
771   return UNZ_OK if there is no problem
772 */
773 extern int ZEXPORT unzGoToFirstFile (file)
774     unzFile file;
775 {
776     int err=UNZ_OK;
777     unz_s* s;
778     if (file==NULL)
779         return UNZ_PARAMERROR;
780     s=(unz_s*)file;
781     s->pos_in_central_dir=s->offset_central_dir;
782     s->num_file=0;
783     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
784                                              &s->cur_file_info_internal,
785                                              NULL,0,NULL,0,NULL,0);
786     s->current_file_ok = (err == UNZ_OK);
787     return err;
788 }
789
790 /*
791   Set the current file of the zipfile to the next file.
792   return UNZ_OK if there is no problem
793   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
794 */
795 extern int ZEXPORT unzGoToNextFile (file)
796     unzFile file;
797 {
798     unz_s* s;
799     int err;
800
801     if (file==NULL)
802         return UNZ_PARAMERROR;
803     s=(unz_s*)file;
804     if (!s->current_file_ok)
805         return UNZ_END_OF_LIST_OF_FILE;
806     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
807       if (s->num_file+1==s->gi.number_entry)
808         return UNZ_END_OF_LIST_OF_FILE;
809
810     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
811             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
812     s->num_file++;
813     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
814                                                &s->cur_file_info_internal,
815                                                NULL,0,NULL,0,NULL,0);
816     s->current_file_ok = (err == UNZ_OK);
817     return err;
818 }
819
820
821 /*
822   Try locate the file szFileName in the zipfile.
823   For the iCaseSensitivity signification, see unzipStringFileNameCompare
824
825   return value :
826   UNZ_OK if the file is found. It becomes the current file.
827   UNZ_END_OF_LIST_OF_FILE if the file is not found
828 */
829 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
830     unzFile file;
831     const char *szFileName;
832     int iCaseSensitivity;
833 {
834     unz_s* s;
835     int err;
836
837     /* We remember the 'current' position in the file so that we can jump
838      * back there if we fail.
839      */
840     unz_file_info cur_file_infoSaved;
841     unz_file_info_internal cur_file_info_internalSaved;
842     uLong num_fileSaved;
843     uLong pos_in_central_dirSaved;
844
845
846     if (file==NULL)
847         return UNZ_PARAMERROR;
848
849     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
850         return UNZ_PARAMERROR;
851
852     s=(unz_s*)file;
853     if (!s->current_file_ok)
854         return UNZ_END_OF_LIST_OF_FILE;
855
856     /* Save the current state */
857     num_fileSaved = s->num_file;
858     pos_in_central_dirSaved = s->pos_in_central_dir;
859     cur_file_infoSaved = s->cur_file_info;
860     cur_file_info_internalSaved = s->cur_file_info_internal;
861
862     err = unzGoToFirstFile(file);
863
864     while (err == UNZ_OK)
865     {
866         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
867         err = unzGetCurrentFileInfo(file,NULL,
868                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
869                                     NULL,0,NULL,0);
870         if (err == UNZ_OK)
871         {
872             if (unzStringFileNameCompare(szCurrentFileName,
873                                             szFileName,iCaseSensitivity)==0)
874                 return UNZ_OK;
875             err = unzGoToNextFile(file);
876         }
877     }
878
879     /* We failed, so restore the state of the 'current file' to where we
880      * were.
881      */
882     s->num_file = num_fileSaved ;
883     s->pos_in_central_dir = pos_in_central_dirSaved ;
884     s->cur_file_info = cur_file_infoSaved;
885     s->cur_file_info_internal = cur_file_info_internalSaved;
886     return err;
887 }
888
889
890 /*
891 ///////////////////////////////////////////
892 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
893 // I need random access
894 //
895 // Further optimization could be realized by adding an ability
896 // to cache the directory in memory. The goal being a single
897 // comprehensive file read to put the file I need in a memory.
898 */
899
900 /*
901 typedef struct unz_file_pos_s
902 {
903     uLong pos_in_zip_directory;   // offset in file
904     uLong num_of_file;            // # of file
905 } unz_file_pos;
906 */
907
908 extern int ZEXPORT unzGetFilePos(file, file_pos)
909     unzFile file;
910     unz_file_pos* file_pos;
911 {
912     unz_s* s;
913
914     if (file==NULL || file_pos==NULL)
915         return UNZ_PARAMERROR;
916     s=(unz_s*)file;
917     if (!s->current_file_ok)
918         return UNZ_END_OF_LIST_OF_FILE;
919
920     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
921     file_pos->num_of_file           = s->num_file;
922
923     return UNZ_OK;
924 }
925
926 extern int ZEXPORT unzGoToFilePos(file, file_pos)
927     unzFile file;
928     unz_file_pos* file_pos;
929 {
930     unz_s* s;
931     int err;
932
933     if (file==NULL || file_pos==NULL)
934         return UNZ_PARAMERROR;
935     s=(unz_s*)file;
936
937     /* jump to the right spot */
938     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
939     s->num_file           = file_pos->num_of_file;
940
941     /* set the current file */
942     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
943                                                &s->cur_file_info_internal,
944                                                NULL,0,NULL,0,NULL,0);
945     /* return results */
946     s->current_file_ok = (err == UNZ_OK);
947     return err;
948 }
949
950 /*
951 // Unzip Helper Functions - should be here?
952 ///////////////////////////////////////////
953 */
954
955 /*
956   Read the local header of the current zipfile
957   Check the coherency of the local header and info in the end of central
958         directory about this file
959   store in *piSizeVar the size of extra info in local header
960         (filename and size of extra field data)
961 */
962 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
963                                                     poffset_local_extrafield,
964                                                     psize_local_extrafield)
965     unz_s* s;
966     uInt* piSizeVar;
967     uLong *poffset_local_extrafield;
968     uInt  *psize_local_extrafield;
969 {
970     uLong uMagic,uData,uFlags;
971     uLong size_filename;
972     uLong size_extra_field;
973     int err=UNZ_OK;
974
975     *piSizeVar = 0;
976     *poffset_local_extrafield = 0;
977     *psize_local_extrafield = 0;
978
979     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
980                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
981         return UNZ_ERRNO;
982
983
984     if (err==UNZ_OK) {
985         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
986             err=UNZ_ERRNO;
987         else if (uMagic!=0x04034b50)
988             err=UNZ_BADZIPFILE;
989     }
990
991     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
992         err=UNZ_ERRNO;
993 /*
994     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
995         err=UNZ_BADZIPFILE;
996 */
997     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
998         err=UNZ_ERRNO;
999
1000     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1001         err=UNZ_ERRNO;
1002     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1003         err=UNZ_BADZIPFILE;
1004
1005     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1006                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1007         err=UNZ_BADZIPFILE;
1008
1009     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1010         err=UNZ_ERRNO;
1011
1012     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1013         err=UNZ_ERRNO;
1014     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1015                               ((uFlags & 8)==0))
1016         err=UNZ_BADZIPFILE;
1017
1018     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1019         err=UNZ_ERRNO;
1020     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1021                               ((uFlags & 8)==0))
1022         err=UNZ_BADZIPFILE;
1023
1024     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1025         err=UNZ_ERRNO;
1026     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1027                               ((uFlags & 8)==0))
1028         err=UNZ_BADZIPFILE;
1029
1030
1031     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1032         err=UNZ_ERRNO;
1033     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1034         err=UNZ_BADZIPFILE;
1035
1036     *piSizeVar += (uInt)size_filename;
1037
1038     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1039         err=UNZ_ERRNO;
1040     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1041                                     SIZEZIPLOCALHEADER + size_filename;
1042     *psize_local_extrafield = (uInt)size_extra_field;
1043
1044     *piSizeVar += (uInt)size_extra_field;
1045
1046     return err;
1047 }
1048
1049 /*
1050   Open for reading data the current file in the zipfile.
1051   If there is no error and the file is opened, the return value is UNZ_OK.
1052 */
1053 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1054     unzFile file;
1055     int* method;
1056     int* level;
1057     int raw;
1058     const char* password;
1059 {
1060     int err=UNZ_OK;
1061     uInt iSizeVar;
1062     unz_s* s;
1063     file_in_zip_read_info_s* pfile_in_zip_read_info;
1064     uLong offset_local_extrafield;  /* offset of the local extra field */
1065     uInt  size_local_extrafield;    /* size of the local extra field */
1066 #    ifndef NOUNCRYPT
1067     char source[12];
1068 #    else
1069     if (password != NULL)
1070         return UNZ_PARAMERROR;
1071 #    endif
1072
1073     if (file==NULL)
1074         return UNZ_PARAMERROR;
1075     s=(unz_s*)file;
1076     if (!s->current_file_ok)
1077         return UNZ_PARAMERROR;
1078
1079     if (s->pfile_in_zip_read != NULL)
1080         unzCloseCurrentFile(file);
1081
1082     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1083                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1084         return UNZ_BADZIPFILE;
1085
1086     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1087                                         ALLOC(sizeof(file_in_zip_read_info_s));
1088     if (pfile_in_zip_read_info==NULL)
1089         return UNZ_INTERNALERROR;
1090
1091     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1092     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1093     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1094     pfile_in_zip_read_info->pos_local_extrafield=0;
1095     pfile_in_zip_read_info->raw=raw;
1096
1097     if (pfile_in_zip_read_info->read_buffer==NULL)
1098     {
1099         TRYFREE(pfile_in_zip_read_info);
1100         return UNZ_INTERNALERROR;
1101     }
1102
1103     pfile_in_zip_read_info->stream_initialised=0;
1104
1105     if (method!=NULL)
1106         *method = (int)s->cur_file_info.compression_method;
1107
1108     if (level!=NULL)
1109     {
1110         *level = 6;
1111         switch (s->cur_file_info.flag & 0x06)
1112         {
1113           case 6 : *level = 1; break;
1114           case 4 : *level = 2; break;
1115           case 2 : *level = 9; break;
1116         }
1117     }
1118
1119     if ((s->cur_file_info.compression_method!=0) &&
1120         (s->cur_file_info.compression_method!=Z_DEFLATED))
1121         err=UNZ_BADZIPFILE;
1122
1123     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1124     pfile_in_zip_read_info->crc32=0;
1125     pfile_in_zip_read_info->compression_method =
1126             s->cur_file_info.compression_method;
1127     pfile_in_zip_read_info->filestream=s->filestream;
1128     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1129     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1130
1131     pfile_in_zip_read_info->stream.total_out = 0;
1132
1133     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1134         (!raw))
1135     {
1136       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1137       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1138       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1139       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1140       pfile_in_zip_read_info->stream.avail_in = 0;
1141
1142       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1143       if (err == Z_OK)
1144         pfile_in_zip_read_info->stream_initialised=1;
1145       else
1146       {
1147         TRYFREE(pfile_in_zip_read_info);
1148         return err;
1149       }
1150         /* windowBits is passed < 0 to tell that there is no zlib header.
1151          * Note that in this case inflate *requires* an extra "dummy" byte
1152          * after the compressed stream in order to complete decompression and
1153          * return Z_STREAM_END.
1154          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1155          * size of both compressed and uncompressed data
1156          */
1157     }
1158     pfile_in_zip_read_info->rest_read_compressed =
1159             s->cur_file_info.compressed_size ;
1160     pfile_in_zip_read_info->rest_read_uncompressed =
1161             s->cur_file_info.uncompressed_size ;
1162
1163
1164     pfile_in_zip_read_info->pos_in_zipfile =
1165             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1166               iSizeVar;
1167
1168     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1169
1170     s->pfile_in_zip_read = pfile_in_zip_read_info;
1171
1172 #    ifndef NOUNCRYPT
1173     if (password != NULL)
1174     {
1175         int i;
1176         s->pcrc_32_tab = get_crc_table();
1177         init_keys(password,s->keys,s->pcrc_32_tab);
1178         if (ZSEEK(s->z_filefunc, s->filestream,
1179                   s->pfile_in_zip_read->pos_in_zipfile +
1180                      s->pfile_in_zip_read->byte_before_the_zipfile,
1181                   SEEK_SET)!=0)
1182             return UNZ_INTERNALERROR;
1183         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1184             return UNZ_INTERNALERROR;
1185
1186         for (i = 0; i<12; i++)
1187             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1188
1189         s->pfile_in_zip_read->pos_in_zipfile+=12;
1190         s->encrypted=1;
1191     }
1192 #    endif
1193
1194
1195     return UNZ_OK;
1196 }
1197
1198 extern int ZEXPORT unzOpenCurrentFile (file)
1199     unzFile file;
1200 {
1201     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1202 }
1203
1204 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1205     unzFile file;
1206     const char* password;
1207 {
1208     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1209 }
1210
1211 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1212     unzFile file;
1213     int* method;
1214     int* level;
1215     int raw;
1216 {
1217     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1218 }
1219
1220 /*
1221   Read bytes from the current file.
1222   buf contain buffer where data must be copied
1223   len the size of buf.
1224
1225   return the number of byte copied if somes bytes are copied
1226   return 0 if the end of file was reached
1227   return <0 with error code if there is an error
1228     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1229 */
1230 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1231     unzFile file;
1232     voidp buf;
1233     unsigned len;
1234 {
1235     int err=UNZ_OK;
1236     uInt iRead = 0;
1237     unz_s* s;
1238     file_in_zip_read_info_s* pfile_in_zip_read_info;
1239     if (file==NULL)
1240         return UNZ_PARAMERROR;
1241     s=(unz_s*)file;
1242     pfile_in_zip_read_info=s->pfile_in_zip_read;
1243
1244     if (pfile_in_zip_read_info==NULL)
1245         return UNZ_PARAMERROR;
1246
1247
1248     if ((pfile_in_zip_read_info->read_buffer == NULL))
1249         return UNZ_END_OF_LIST_OF_FILE;
1250     if (len==0)
1251         return 0;
1252
1253     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1254
1255     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1256
1257     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1258         (!(pfile_in_zip_read_info->raw)))
1259         pfile_in_zip_read_info->stream.avail_out =
1260             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1261
1262     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1263            pfile_in_zip_read_info->stream.avail_in) &&
1264          (pfile_in_zip_read_info->raw))
1265         pfile_in_zip_read_info->stream.avail_out =
1266             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1267             pfile_in_zip_read_info->stream.avail_in;
1268
1269     while (pfile_in_zip_read_info->stream.avail_out>0)
1270     {
1271         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1272             (pfile_in_zip_read_info->rest_read_compressed>0))
1273         {
1274             uInt uReadThis = UNZ_BUFSIZE;
1275             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1276                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1277             if (uReadThis == 0)
1278                 return UNZ_EOF;
1279             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1280                       pfile_in_zip_read_info->filestream,
1281                       pfile_in_zip_read_info->pos_in_zipfile +
1282                          pfile_in_zip_read_info->byte_before_the_zipfile,
1283                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1284                 return UNZ_ERRNO;
1285             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1286                       pfile_in_zip_read_info->filestream,
1287                       pfile_in_zip_read_info->read_buffer,
1288                       uReadThis)!=uReadThis)
1289                 return UNZ_ERRNO;
1290
1291
1292 #            ifndef NOUNCRYPT
1293             if(s->encrypted)
1294             {
1295                 uInt i;
1296                 for(i=0;i<uReadThis;i++)
1297                   pfile_in_zip_read_info->read_buffer[i] =
1298                       zdecode(s->keys,s->pcrc_32_tab,
1299                               pfile_in_zip_read_info->read_buffer[i]);
1300             }
1301 #            endif
1302
1303
1304             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1305
1306             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1307
1308             pfile_in_zip_read_info->stream.next_in =
1309                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1310             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1311         }
1312
1313         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1314         {
1315             uInt uDoCopy,i ;
1316
1317             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1318                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1319                 return (iRead==0) ? UNZ_EOF : iRead;
1320
1321             if (pfile_in_zip_read_info->stream.avail_out <
1322                             pfile_in_zip_read_info->stream.avail_in)
1323                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1324             else
1325                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1326
1327             for (i=0;i<uDoCopy;i++)
1328                 *(pfile_in_zip_read_info->stream.next_out+i) =
1329                         *(pfile_in_zip_read_info->stream.next_in+i);
1330
1331             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1332                                 pfile_in_zip_read_info->stream.next_out,
1333                                 uDoCopy);
1334             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1335             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1336             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1337             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1338             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1339             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1340             iRead += uDoCopy;
1341         }
1342         else
1343         {
1344             uLong uTotalOutBefore,uTotalOutAfter;
1345             const Bytef *bufBefore;
1346             uLong uOutThis;
1347             int flush=Z_SYNC_FLUSH;
1348
1349             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1350             bufBefore = pfile_in_zip_read_info->stream.next_out;
1351
1352             /*
1353             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1354                      pfile_in_zip_read_info->stream.avail_out) &&
1355                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1356                 flush = Z_FINISH;
1357             */
1358             err=inflate(&pfile_in_zip_read_info->stream,flush);
1359
1360             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1361               err = Z_DATA_ERROR;
1362
1363             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1364             uOutThis = uTotalOutAfter-uTotalOutBefore;
1365
1366             pfile_in_zip_read_info->crc32 =
1367                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1368                         (uInt)(uOutThis));
1369
1370             pfile_in_zip_read_info->rest_read_uncompressed -=
1371                 uOutThis;
1372
1373             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1374
1375             if (err==Z_STREAM_END)
1376                 return (iRead==0) ? UNZ_EOF : iRead;
1377             if (err!=Z_OK)
1378                 break;
1379         }
1380     }
1381
1382     if (err==Z_OK)
1383         return iRead;
1384     return err;
1385 }
1386
1387
1388 /*
1389   Give the current position in uncompressed data
1390 */
1391 extern z_off_t ZEXPORT unztell (file)
1392     unzFile file;
1393 {
1394     unz_s* s;
1395     file_in_zip_read_info_s* pfile_in_zip_read_info;
1396     if (file==NULL)
1397         return UNZ_PARAMERROR;
1398     s=(unz_s*)file;
1399     pfile_in_zip_read_info=s->pfile_in_zip_read;
1400
1401     if (pfile_in_zip_read_info==NULL)
1402         return UNZ_PARAMERROR;
1403
1404     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1405 }
1406
1407
1408 /*
1409   return 1 if the end of file was reached, 0 elsewhere
1410 */
1411 extern int ZEXPORT unzeof (file)
1412     unzFile file;
1413 {
1414     unz_s* s;
1415     file_in_zip_read_info_s* pfile_in_zip_read_info;
1416     if (file==NULL)
1417         return UNZ_PARAMERROR;
1418     s=(unz_s*)file;
1419     pfile_in_zip_read_info=s->pfile_in_zip_read;
1420
1421     if (pfile_in_zip_read_info==NULL)
1422         return UNZ_PARAMERROR;
1423
1424     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1425         return 1;
1426     else
1427         return 0;
1428 }
1429
1430
1431
1432 /*
1433   Read extra field from the current file (opened by unzOpenCurrentFile)
1434   This is the local-header version of the extra field (sometimes, there is
1435     more info in the local-header version than in the central-header)
1436
1437   if buf==NULL, it return the size of the local extra field that can be read
1438
1439   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1440     buf.
1441   the return value is the number of bytes copied in buf, or (if <0)
1442     the error code
1443 */
1444 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1445     unzFile file;
1446     voidp buf;
1447     unsigned len;
1448 {
1449     unz_s* s;
1450     file_in_zip_read_info_s* pfile_in_zip_read_info;
1451     uInt read_now;
1452     uLong size_to_read;
1453
1454     if (file==NULL)
1455         return UNZ_PARAMERROR;
1456     s=(unz_s*)file;
1457     pfile_in_zip_read_info=s->pfile_in_zip_read;
1458
1459     if (pfile_in_zip_read_info==NULL)
1460         return UNZ_PARAMERROR;
1461
1462     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1463                 pfile_in_zip_read_info->pos_local_extrafield);
1464
1465     if (buf==NULL)
1466         return (int)size_to_read;
1467
1468     if (len>size_to_read)
1469         read_now = (uInt)size_to_read;
1470     else
1471         read_now = (uInt)len ;
1472
1473     if (read_now==0)
1474         return 0;
1475
1476     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1477               pfile_in_zip_read_info->filestream,
1478               pfile_in_zip_read_info->offset_local_extrafield +
1479               pfile_in_zip_read_info->pos_local_extrafield,
1480               ZLIB_FILEFUNC_SEEK_SET)!=0)
1481         return UNZ_ERRNO;
1482
1483     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1484               pfile_in_zip_read_info->filestream,
1485               buf,read_now)!=read_now)
1486         return UNZ_ERRNO;
1487
1488     return (int)read_now;
1489 }
1490
1491 /*
1492   Close the file in zip opened with unzipOpenCurrentFile
1493   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1494 */
1495 extern int ZEXPORT unzCloseCurrentFile (file)
1496     unzFile file;
1497 {
1498     int err=UNZ_OK;
1499
1500     unz_s* s;
1501     file_in_zip_read_info_s* pfile_in_zip_read_info;
1502     if (file==NULL)
1503         return UNZ_PARAMERROR;
1504     s=(unz_s*)file;
1505     pfile_in_zip_read_info=s->pfile_in_zip_read;
1506
1507     if (pfile_in_zip_read_info==NULL)
1508         return UNZ_PARAMERROR;
1509
1510
1511     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1512         (!pfile_in_zip_read_info->raw))
1513     {
1514         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1515             err=UNZ_CRCERROR;
1516     }
1517
1518
1519     TRYFREE(pfile_in_zip_read_info->read_buffer);
1520     pfile_in_zip_read_info->read_buffer = NULL;
1521     if (pfile_in_zip_read_info->stream_initialised)
1522         inflateEnd(&pfile_in_zip_read_info->stream);
1523
1524     pfile_in_zip_read_info->stream_initialised = 0;
1525     TRYFREE(pfile_in_zip_read_info);
1526
1527     s->pfile_in_zip_read=NULL;
1528
1529     return err;
1530 }
1531
1532
1533 /*
1534   Get the global comment string of the ZipFile, in the szComment buffer.
1535   uSizeBuf is the size of the szComment buffer.
1536   return the number of byte copied or an error code <0
1537 */
1538 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1539     unzFile file;
1540     char *szComment;
1541     uLong uSizeBuf;
1542 {
1543     unz_s* s;
1544     uLong uReadThis ;
1545     if (file==NULL)
1546         return UNZ_PARAMERROR;
1547     s=(unz_s*)file;
1548
1549     uReadThis = uSizeBuf;
1550     if (uReadThis>s->gi.size_comment)
1551         uReadThis = s->gi.size_comment;
1552
1553     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1554         return UNZ_ERRNO;
1555
1556     if (uReadThis>0)
1557     {
1558       *szComment='\0';
1559       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1560         return UNZ_ERRNO;
1561     }
1562
1563     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1564         *(szComment+s->gi.size_comment)='\0';
1565     return (int)uReadThis;
1566 }
1567
1568 /* Additions by RX '2004 */
1569 extern uLong ZEXPORT unzGetOffset (file)
1570     unzFile file;
1571 {
1572     unz_s* s;
1573
1574     if (file==NULL)
1575           return UNZ_PARAMERROR;
1576     s=(unz_s*)file;
1577     if (!s->current_file_ok)
1578       return 0;
1579     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1580       if (s->num_file==s->gi.number_entry)
1581          return 0;
1582     return s->pos_in_central_dir;
1583 }
1584
1585 extern int ZEXPORT unzSetOffset (file, pos)
1586         unzFile file;
1587         uLong pos;
1588 {
1589     unz_s* s;
1590     int err;
1591
1592     if (file==NULL)
1593         return UNZ_PARAMERROR;
1594     s=(unz_s*)file;
1595
1596     s->pos_in_central_dir = pos;
1597     s->num_file = s->gi.number_entry;      /* hack */
1598     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1599                                               &s->cur_file_info_internal,
1600                                               NULL,0,NULL,0,NULL,0);
1601     s->current_file_ok = (err == UNZ_OK);
1602     return err;
1603 }