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