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