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