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