merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / macosx / spotlight / unzip.m
blobfe8fad538a86b6e71f6c1548b0ff5b4885bd86b6
1 /*************************************************************************
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  * 
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26 *************************************************************************/
28 /* unzip.c -- IO for uncompress .zip files using zlib
29    Version 1.01e, February 12th, 2005
31    Copyright (C) 1998-2005 Gilles Vollant
33    Read unzip.h for more info
36 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
37 compatibility with older software. The following is from the original crypt.c. Code
38 woven in by Terry Thorsen 1/2003.
41   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
43   See the accompanying file LICENSE, version 2000-Apr-09 or later
44   (the contents of which are also included in zip.h) for terms of use.
45   If, for some reason, all these files are missing, the Info-ZIP license
46   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
49   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
51   The encryption/decryption parts of this source code (as opposed to the
52   non-echoing password parts) were originally written in Europe.  The
53   whole source package can be freely distributed, including from the USA.
54   (Prior to January 2000, re-export from the US was a violation of US law.)
55  */
58   This encryption code is a direct transcription of the algorithm from
59   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
60   file (appnote.txt) is distributed with the PKZIP program (even in the
61   version without encryption capabilities).
62  */
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <zlib.h>
69 #include "ioapi.h"
70 #include "unzip.h"
72 #ifdef STDC
73 #  include <stddef.h>
74 #  include <string.h>
75 #  include <stdlib.h>
76 #endif
77 #ifdef NO_ERRNO_H
78     extern int errno;
79 #else
80 #   include <errno.h>
81 #endif
84 #ifndef local
85 #  define local static
86 #endif
87 /* compile with -Dlocal if your debugger can't find static symbols */
90 #ifndef CASESENSITIVITYDEFAULT_NO
91 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
92 #    define CASESENSITIVITYDEFAULT_NO
93 #  endif
94 #endif
97 #ifndef UNZ_BUFSIZE
98 #define UNZ_BUFSIZE (16384)
99 #endif
101 #ifndef UNZ_MAXFILENAMEINZIP
102 #define UNZ_MAXFILENAMEINZIP (256)
103 #endif
105 #ifndef ALLOC
106 # define ALLOC(size) (malloc(size))
107 #endif
108 #ifndef TRYFREE
109 # define TRYFREE(p) {if (p) free(p);}
110 #endif
112 #define SIZECENTRALDIRITEM (0x2e)
113 #define SIZEZIPLOCALHEADER (0x1e)
118 const char unz_copyright[] =
119    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
121 /* unz_file_info_interntal contain internal info about a file in zipfile*/
122 typedef struct unz_file_info_internal_s
124     uLong offset_curfile;/* relative offset of local header 4 bytes */
125 } unz_file_info_internal;
128 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
129     when reading and decompress it */
130 typedef struct
132     char  *read_buffer;         /* internal buffer for compressed data */
133     z_stream stream;            /* zLib stream structure for inflate */
135     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
136     uLong stream_initialised;   /* flag set if stream structure is initialised*/
138     uLong offset_local_extrafield;/* offset of the local extra field */
139     uInt  size_local_extrafield;/* size of the local extra field */
140     uLong pos_local_extrafield;   /* position in the local extra field in read*/
142     uLong crc32;                /* crc32 of all data uncompressed */
143     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
144     uLong rest_read_compressed; /* number of byte to be decompressed */
145     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
146     zlib_filefunc_def z_filefunc;
147     voidpf filestream;        /* io structore of the zipfile */
148     uLong compression_method;   /* compression method (0==store) */
149     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
150     int   raw;
151 } file_in_zip_read_info_s;
154 /* unz_s contain internal information about the zipfile
156 typedef struct
158     zlib_filefunc_def z_filefunc;
159     voidpf filestream;        /* io structore of the zipfile */
160     unz_global_info gi;       /* public global information */
161     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
162     uLong num_file;             /* number of the current file in the zipfile*/
163     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
164     uLong current_file_ok;      /* flag about the usability of the current file*/
165     uLong central_pos;          /* position of the beginning of the central dir*/
167     uLong size_central_dir;     /* size of the central directory  */
168     uLong offset_central_dir;   /* offset of start of central directory with
169                                    respect to the starting disk number */
171     unz_file_info cur_file_info; /* public info about the current file in zip*/
172     unz_file_info_internal cur_file_info_internal; /* private info about it*/
173     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
174                                         file if we are decompressing it */
175     int encrypted;
176 } unz_s;
180 /* ===========================================================================
181      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
182    for end of file.
183    IN assertion: the stream s has been sucessfully opened for reading.
187 local int unzlocal_getByte OF((
188     const zlib_filefunc_def* pzlib_filefunc_def,
189     voidpf filestream,
190     int *pi));
192 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
193     const zlib_filefunc_def* pzlib_filefunc_def;
194     voidpf filestream;
195     int *pi;
197     unsigned char c;
198     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
199     if (err==1)
200     {
201         *pi = (int)c;
202         return UNZ_OK;
203     }
204     else
205     {
206         if (ZERROR(*pzlib_filefunc_def,filestream))
207             return UNZ_ERRNO;
208         else
209             return UNZ_EOF;
210     }
214 /* ===========================================================================
215    Reads a long in LSB order from the given gz_stream. Sets
217 local int unzlocal_getShort OF((
218     const zlib_filefunc_def* pzlib_filefunc_def,
219     voidpf filestream,
220     uLong *pX));
222 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
223     const zlib_filefunc_def* pzlib_filefunc_def;
224     voidpf filestream;
225     uLong *pX;
227     uLong x ;
228     int i;
229     int err;
231     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
232     x = (uLong)i;
234     if (err==UNZ_OK)
235         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
236     x += ((uLong)i)<<8;
238     if (err==UNZ_OK)
239         *pX = x;
240     else
241         *pX = 0;
242     return err;
245 local int unzlocal_getLong OF((
246     const zlib_filefunc_def* pzlib_filefunc_def,
247     voidpf filestream,
248     uLong *pX));
250 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
251     const zlib_filefunc_def* pzlib_filefunc_def;
252     voidpf filestream;
253     uLong *pX;
255     uLong x ;
256     int i;
257     int err;
259     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
260     x = (uLong)i;
262     if (err==UNZ_OK)
263         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
264     x += ((uLong)i)<<8;
266     if (err==UNZ_OK)
267         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
268     x += ((uLong)i)<<16;
270     if (err==UNZ_OK)
271         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
272     x += ((uLong)i)<<24;
274     if (err==UNZ_OK)
275         *pX = x;
276     else
277         *pX = 0;
278     return err;
282 /* My own strcmpi / strcasecmp */
283 local int strcmpcasenosensitive_internal (fileName1,fileName2)
284     const char* fileName1;
285     const char* fileName2;
287     for (;;)
288     {
289         char c1=*(fileName1++);
290         char c2=*(fileName2++);
291         if ((c1>='a') && (c1<='z'))
292             c1 -= 0x20;
293         if ((c2>='a') && (c2<='z'))
294             c2 -= 0x20;
295         if (c1=='\0')
296             return ((c2=='\0') ? 0 : -1);
297         if (c2=='\0')
298             return 1;
299         if (c1<c2)
300             return -1;
301         if (c1>c2)
302             return 1;
303     }
307 #ifdef  CASESENSITIVITYDEFAULT_NO
308 #define CASESENSITIVITYDEFAULTVALUE 2
309 #else
310 #define CASESENSITIVITYDEFAULTVALUE 1
311 #endif
313 #ifndef STRCMPCASENOSENTIVEFUNCTION
314 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
315 #endif
318    Compare two filename (fileName1,fileName2).
319    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
320    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
321                                                                 or strcasecmp)
322    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
323         (like 1 on Unix, 2 on Windows)
326 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
327     const char* fileName1;
328     const char* fileName2;
329     int iCaseSensitivity;
331     if (iCaseSensitivity==0)
332         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
334     if (iCaseSensitivity==1)
335         return strcmp(fileName1,fileName2);
337     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
340 #ifndef BUFREADCOMMENT
341 #define BUFREADCOMMENT (0x400)
342 #endif
345   Locate the Central directory of a zipfile (at the end, just before
346     the global comment)
348 local uLong unzlocal_SearchCentralDir OF((
349     const zlib_filefunc_def* pzlib_filefunc_def,
350     voidpf filestream));
352 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
353     const zlib_filefunc_def* pzlib_filefunc_def;
354     voidpf filestream;
356     unsigned char* buf;
357     uLong uSizeFile;
358     uLong uBackRead;
359     uLong uMaxBack=0xffff; /* maximum size of global comment */
360     uLong uPosFound=0;
362     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
363         return 0;
366     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
368     if (uMaxBack>uSizeFile)
369         uMaxBack = uSizeFile;
371     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
372     if (buf==NULL)
373         return 0;
375     uBackRead = 4;
376     while (uBackRead<uMaxBack)
377     {
378         uLong uReadSize,uReadPos ;
379         int i;
380         if (uBackRead+BUFREADCOMMENT>uMaxBack)
381             uBackRead = uMaxBack;
382         else
383             uBackRead+=BUFREADCOMMENT;
384         uReadPos = uSizeFile-uBackRead ;
386         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
387                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
388         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
389             break;
391         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
392             break;
394         for (i=(int)uReadSize-3; (i--)>0;)
395             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
396                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
397             {
398                 uPosFound = uReadPos+i;
399                 break;
400             }
402         if (uPosFound!=0)
403             break;
404     }
405     TRYFREE(buf);
406     return uPosFound;
410   Open a Zip file. path contain the full pathname (by example,
411      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
412      "zlib/zlib114.zip".
413      If the zipfile cannot be opened (file doesn't exist or in not valid), the
414        return value is NULL.
415      Else, the return value is a unzFile Handle, usable with other function
416        of this unzip package.
418 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
419     const char *path;
420     zlib_filefunc_def* pzlib_filefunc_def;
422     unz_s us;
423     unz_s *s;
424     uLong central_pos,uL;
426     uLong number_disk;          /* number of the current dist, used for
427                                    spaning ZIP, unsupported, always 0*/
428     uLong number_disk_with_CD;  /* number the the disk with central dir, used
429                                    for spaning ZIP, unsupported, always 0*/
430     uLong number_entry_CD;      /* total number of entries in
431                                    the central dir
432                                    (same than number_entry on nospan) */
434     int err=UNZ_OK;
436     if (unz_copyright[0]!=' ')
437         return NULL;
439     if (pzlib_filefunc_def==NULL)
440         fill_fopen_filefunc(&us.z_filefunc);
441     else
442         us.z_filefunc = *pzlib_filefunc_def;
444     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
445                                                  path,
446                                                  ZLIB_FILEFUNC_MODE_READ |
447                                                  ZLIB_FILEFUNC_MODE_EXISTING);
448     if (us.filestream==NULL)
449         return NULL;
451     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
452     if (central_pos==0)
453         err=UNZ_ERRNO;
455     if (ZSEEK(us.z_filefunc, us.filestream,
456                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
457         err=UNZ_ERRNO;
459     /* the signature, already checked */
460     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
461         err=UNZ_ERRNO;
463     /* number of this disk */
464     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
465         err=UNZ_ERRNO;
467     /* number of the disk with the start of the central directory */
468     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
469         err=UNZ_ERRNO;
471     /* total number of entries in the central dir on this disk */
472     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
473         err=UNZ_ERRNO;
475     /* total number of entries in the central dir */
476     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
477         err=UNZ_ERRNO;
479     if ((number_entry_CD!=us.gi.number_entry) ||
480         (number_disk_with_CD!=0) ||
481         (number_disk!=0))
482         err=UNZ_BADZIPFILE;
484     /* size of the central directory */
485     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
486         err=UNZ_ERRNO;
488     /* offset of start of central directory with respect to the
489           starting disk number */
490     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
491         err=UNZ_ERRNO;
493     /* zipfile comment length */
494     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
495         err=UNZ_ERRNO;
497     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
498         (err==UNZ_OK))
499         err=UNZ_BADZIPFILE;
501     if (err!=UNZ_OK)
502     {
503         ZCLOSE(us.z_filefunc, us.filestream);
504         return NULL;
505     }
507     us.byte_before_the_zipfile = central_pos -
508                             (us.offset_central_dir+us.size_central_dir);
509     us.central_pos = central_pos;
510     us.pfile_in_zip_read = NULL;
511     us.encrypted = 0;
514     s=(unz_s*)ALLOC(sizeof(unz_s));
515     *s=us;
516     unzGoToFirstFile((unzFile)s);
517     return (unzFile)s;
521 extern unzFile ZEXPORT unzOpen (path)
522     const char *path;
524     return unzOpen2(path, NULL);
528   Close a ZipFile opened with unzipOpen.
529   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
530     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
531   return UNZ_OK if there is no problem. */
532 extern int ZEXPORT unzClose (file)
533     unzFile file;
535     unz_s* s;
536     if (file==NULL)
537         return UNZ_PARAMERROR;
538     s=(unz_s*)file;
540     if (s->pfile_in_zip_read!=NULL)
541         unzCloseCurrentFile(file);
543     ZCLOSE(s->z_filefunc, s->filestream);
544     TRYFREE(s);
545     return UNZ_OK;
550   Write info about the ZipFile in the *pglobal_info structure.
551   No preparation of the structure is needed
552   return UNZ_OK if there is no problem. */
553 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
554     unzFile file;
555     unz_global_info *pglobal_info;
557     unz_s* s;
558     if (file==NULL)
559         return UNZ_PARAMERROR;
560     s=(unz_s*)file;
561     *pglobal_info=s->gi;
562     return UNZ_OK;
567    Translate date/time from Dos format to tm_unz (readable more easilty)
569 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
570     uLong ulDosDate;
571     tm_unz* ptm;
573     uLong uDate;
574     uDate = (uLong)(ulDosDate>>16);
575     ptm->tm_mday = (uInt)(uDate&0x1f) ;
576     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
577     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
579     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
580     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
581     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
585   Get Info about the current file in the zipfile, with internal only info
587 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
588                                                   unz_file_info *pfile_info,
589                                                   unz_file_info_internal
590                                                   *pfile_info_internal,
591                                                   char *szFileName,
592                                                   uLong fileNameBufferSize,
593                                                   void *extraField,
594                                                   uLong extraFieldBufferSize,
595                                                   char *szComment,
596                                                   uLong commentBufferSize));
598 local int unzlocal_GetCurrentFileInfoInternal (file,
599                                               pfile_info,
600                                               pfile_info_internal,
601                                               szFileName, fileNameBufferSize,
602                                               extraField, extraFieldBufferSize,
603                                               szComment,  commentBufferSize)
604     unzFile file;
605     unz_file_info *pfile_info;
606     unz_file_info_internal *pfile_info_internal;
607     char *szFileName;
608     uLong fileNameBufferSize;
609     void *extraField;
610     uLong extraFieldBufferSize;
611     char *szComment;
612     uLong commentBufferSize;
614     unz_s* s;
615     unz_file_info file_info;
616     unz_file_info_internal file_info_internal;
617     int err=UNZ_OK;
618     uLong uMagic;
619     long lSeek=0;
621     if (file==NULL)
622         return UNZ_PARAMERROR;
623     s=(unz_s*)file;
624     if (ZSEEK(s->z_filefunc, s->filestream,
625               s->pos_in_central_dir+s->byte_before_the_zipfile,
626               ZLIB_FILEFUNC_SEEK_SET)!=0)
627         err=UNZ_ERRNO;
630     /* we check the magic */
631     if (err==UNZ_OK) {
632         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
633             err=UNZ_ERRNO;
634         else if (uMagic!=0x02014b50)
635             err=UNZ_BADZIPFILE;
636     }
638     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
639         err=UNZ_ERRNO;
641     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
642         err=UNZ_ERRNO;
644     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
645         err=UNZ_ERRNO;
647     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
648         err=UNZ_ERRNO;
650     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
651         err=UNZ_ERRNO;
653     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
655     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
656         err=UNZ_ERRNO;
658     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
659         err=UNZ_ERRNO;
661     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
662         err=UNZ_ERRNO;
664     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
665         err=UNZ_ERRNO;
667     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
668         err=UNZ_ERRNO;
670     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
671         err=UNZ_ERRNO;
673     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
674         err=UNZ_ERRNO;
676     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
677         err=UNZ_ERRNO;
679     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
680         err=UNZ_ERRNO;
682     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
683         err=UNZ_ERRNO;
685     lSeek+=file_info.size_filename;
686     if ((err==UNZ_OK) && (szFileName!=NULL))
687     {
688         uLong uSizeRead ;
689         if (file_info.size_filename<fileNameBufferSize)
690         {
691             *(szFileName+file_info.size_filename)='\0';
692             uSizeRead = file_info.size_filename;
693         }
694         else
695             uSizeRead = fileNameBufferSize;
697         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
698             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
699                 err=UNZ_ERRNO;
700         lSeek -= uSizeRead;
701     }
704     if ((err==UNZ_OK) && (extraField!=NULL))
705     {
706         uLong uSizeRead ;
707         if (file_info.size_file_extra<extraFieldBufferSize)
708             uSizeRead = file_info.size_file_extra;
709         else
710             uSizeRead = extraFieldBufferSize;
712         if (lSeek!=0) {
713             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
714                 lSeek=0;
715             else
716                 err=UNZ_ERRNO;
717         }
718         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
719             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
720                 err=UNZ_ERRNO;
721         lSeek += file_info.size_file_extra - uSizeRead;
722     }
723     else
724         lSeek+=file_info.size_file_extra;
727     if ((err==UNZ_OK) && (szComment!=NULL))
728     {
729         uLong uSizeRead ;
730         if (file_info.size_file_comment<commentBufferSize)
731         {
732             *(szComment+file_info.size_file_comment)='\0';
733             uSizeRead = file_info.size_file_comment;
734         }
735         else
736             uSizeRead = commentBufferSize;
738         if (lSeek!=0) {
739             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
740                 lSeek=0;
741             else
742                 err=UNZ_ERRNO;
743         }
744         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
745             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
746                 err=UNZ_ERRNO;
747         lSeek+=file_info.size_file_comment - uSizeRead;
748     }
749     else
750         lSeek+=file_info.size_file_comment;
752     if ((err==UNZ_OK) && (pfile_info!=NULL))
753         *pfile_info=file_info;
755     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
756         *pfile_info_internal=file_info_internal;
758     return err;
764   Write info about the ZipFile in the *pglobal_info structure.
765   No preparation of the structure is needed
766   return UNZ_OK if there is no problem.
768 extern int ZEXPORT unzGetCurrentFileInfo (file,
769                                           pfile_info,
770                                           szFileName, fileNameBufferSize,
771                                           extraField, extraFieldBufferSize,
772                                           szComment,  commentBufferSize)
773     unzFile file;
774     unz_file_info *pfile_info;
775     char *szFileName;
776     uLong fileNameBufferSize;
777     void *extraField;
778     uLong extraFieldBufferSize;
779     char *szComment;
780     uLong commentBufferSize;
782     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
783                                                 szFileName,fileNameBufferSize,
784                                                 extraField,extraFieldBufferSize,
785                                                 szComment,commentBufferSize);
789   Set the current file of the zipfile to the first file.
790   return UNZ_OK if there is no problem
792 extern int ZEXPORT unzGoToFirstFile (file)
793     unzFile file;
795     int err=UNZ_OK;
796     unz_s* s;
797     if (file==NULL)
798         return UNZ_PARAMERROR;
799     s=(unz_s*)file;
800     s->pos_in_central_dir=s->offset_central_dir;
801     s->num_file=0;
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;
810   Set the current file of the zipfile to the next file.
811   return UNZ_OK if there is no problem
812   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
814 extern int ZEXPORT unzGoToNextFile (file)
815     unzFile file;
817     unz_s* s;
818     int err;
820     if (file==NULL)
821         return UNZ_PARAMERROR;
822     s=(unz_s*)file;
823     if (!s->current_file_ok)
824         return UNZ_END_OF_LIST_OF_FILE;
825     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
826       if (s->num_file+1==s->gi.number_entry)
827         return UNZ_END_OF_LIST_OF_FILE;
829     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
830             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
831     s->num_file++;
832     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
833                                                &s->cur_file_info_internal,
834                                                NULL,0,NULL,0,NULL,0);
835     s->current_file_ok = (err == UNZ_OK);
836     return err;
841   Try locate the file szFileName in the zipfile.
842   For the iCaseSensitivity signification, see unzipStringFileNameCompare
844   return value :
845   UNZ_OK if the file is found. It becomes the current file.
846   UNZ_END_OF_LIST_OF_FILE if the file is not found
848 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
849     unzFile file;
850     const char *szFileName;
851     int iCaseSensitivity;
853     unz_s* s;
854     int err;
856     /* We remember the 'current' position in the file so that we can jump
857      * back there if we fail.
858      */
859     unz_file_info cur_file_infoSaved;
860     unz_file_info_internal cur_file_info_internalSaved;
861     uLong num_fileSaved;
862     uLong pos_in_central_dirSaved;
865     if (file==NULL)
866         return UNZ_PARAMERROR;
868     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
869         return UNZ_PARAMERROR;
871     s=(unz_s*)file;
872     if (!s->current_file_ok)
873         return UNZ_END_OF_LIST_OF_FILE;
875     /* Save the current state */
876     num_fileSaved = s->num_file;
877     pos_in_central_dirSaved = s->pos_in_central_dir;
878     cur_file_infoSaved = s->cur_file_info;
879     cur_file_info_internalSaved = s->cur_file_info_internal;
881     err = unzGoToFirstFile(file);
883     while (err == UNZ_OK)
884     {
885         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
886         err = unzGetCurrentFileInfo(file,NULL,
887                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
888                                     NULL,0,NULL,0);
889         if (err == UNZ_OK)
890         {
891             if (unzStringFileNameCompare(szCurrentFileName,
892                                             szFileName,iCaseSensitivity)==0)
893                 return UNZ_OK;
894             err = unzGoToNextFile(file);
895         }
896     }
898     /* We failed, so restore the state of the 'current file' to where we
899      * were.
900      */
901     s->num_file = num_fileSaved ;
902     s->pos_in_central_dir = pos_in_central_dirSaved ;
903     s->cur_file_info = cur_file_infoSaved;
904     s->cur_file_info_internal = cur_file_info_internalSaved;
905     return err;
910 ///////////////////////////////////////////
911 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
912 // I need random access
914 // Further optimization could be realized by adding an ability
915 // to cache the directory in memory. The goal being a single
916 // comprehensive file read to put the file I need in a memory.
920 typedef struct unz_file_pos_s
922     uLong pos_in_zip_directory;   // offset in file
923     uLong num_of_file;            // # of file
924 } unz_file_pos;
927 extern int ZEXPORT unzGetFilePos(file, file_pos)
928     unzFile file;
929     unz_file_pos* file_pos;
931     unz_s* s;
933     if (file==NULL || file_pos==NULL)
934         return UNZ_PARAMERROR;
935     s=(unz_s*)file;
936     if (!s->current_file_ok)
937         return UNZ_END_OF_LIST_OF_FILE;
939     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
940     file_pos->num_of_file           = s->num_file;
942     return UNZ_OK;
945 extern int ZEXPORT unzGoToFilePos(file, file_pos)
946     unzFile file;
947     unz_file_pos* file_pos;
949     unz_s* s;
950     int err;
952     if (file==NULL || file_pos==NULL)
953         return UNZ_PARAMERROR;
954     s=(unz_s*)file;
956     /* jump to the right spot */
957     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
958     s->num_file           = file_pos->num_of_file;
960     /* set the current file */
961     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
962                                                &s->cur_file_info_internal,
963                                                NULL,0,NULL,0,NULL,0);
964     /* return results */
965     s->current_file_ok = (err == UNZ_OK);
966     return err;
970 // Unzip Helper Functions - should be here?
971 ///////////////////////////////////////////
975   Read the local header of the current zipfile
976   Check the coherency of the local header and info in the end of central
977         directory about this file
978   store in *piSizeVar the size of extra info in local header
979         (filename and size of extra field data)
981 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
982                                                     poffset_local_extrafield,
983                                                     psize_local_extrafield)
984     unz_s* s;
985     uInt* piSizeVar;
986     uLong *poffset_local_extrafield;
987     uInt  *psize_local_extrafield;
989     uLong uMagic,uData,uFlags;
990     uLong size_filename;
991     uLong size_extra_field;
992     int err=UNZ_OK;
994     *piSizeVar = 0;
995     *poffset_local_extrafield = 0;
996     *psize_local_extrafield = 0;
998     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
999                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1000         return UNZ_ERRNO;
1003     if (err==UNZ_OK) {
1004         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1005             err=UNZ_ERRNO;
1006         else if (uMagic!=0x04034b50)
1007             err=UNZ_BADZIPFILE;
1008     }
1010     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1011         err=UNZ_ERRNO;
1013     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1014         err=UNZ_BADZIPFILE;
1016     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1017         err=UNZ_ERRNO;
1019     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1020         err=UNZ_ERRNO;
1021     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1022         err=UNZ_BADZIPFILE;
1024     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1025                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1026         err=UNZ_BADZIPFILE;
1028     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1029         err=UNZ_ERRNO;
1031     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1032         err=UNZ_ERRNO;
1033     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1034                               ((uFlags & 8)==0))
1035         err=UNZ_BADZIPFILE;
1037     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1038         err=UNZ_ERRNO;
1039     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1040                               ((uFlags & 8)==0))
1041         err=UNZ_BADZIPFILE;
1043     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1044         err=UNZ_ERRNO;
1045     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1046                               ((uFlags & 8)==0))
1047         err=UNZ_BADZIPFILE;
1050     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1051         err=UNZ_ERRNO;
1052     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1053         err=UNZ_BADZIPFILE;
1055     *piSizeVar += (uInt)size_filename;
1057     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1058         err=UNZ_ERRNO;
1059     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1060                                     SIZEZIPLOCALHEADER + size_filename;
1061     *psize_local_extrafield = (uInt)size_extra_field;
1063     *piSizeVar += (uInt)size_extra_field;
1065     return err;
1069   Open for reading data the current file in the zipfile.
1070   If there is no error and the file is opened, the return value is UNZ_OK.
1072 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1073     unzFile file;
1074     int* method;
1075     int* level;
1076     int raw;
1077     const char* password;
1079     int err=UNZ_OK;
1080     uInt iSizeVar;
1081     unz_s* s;
1082     file_in_zip_read_info_s* pfile_in_zip_read_info;
1083     uLong offset_local_extrafield;  /* offset of the local extra field */
1084     uInt  size_local_extrafield;    /* size of the local extra field */
1085     if (password != NULL)
1086         return UNZ_PARAMERROR;
1088     if (file==NULL)
1089         return UNZ_PARAMERROR;
1090     s=(unz_s*)file;
1091     if (!s->current_file_ok)
1092         return UNZ_PARAMERROR;
1094     if (s->pfile_in_zip_read != NULL)
1095         unzCloseCurrentFile(file);
1097     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1098                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1099         return UNZ_BADZIPFILE;
1101     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1102                                         ALLOC(sizeof(file_in_zip_read_info_s));
1103     if (pfile_in_zip_read_info==NULL)
1104         return UNZ_INTERNALERROR;
1106     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1107     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1108     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1109     pfile_in_zip_read_info->pos_local_extrafield=0;
1110     pfile_in_zip_read_info->raw=raw;
1112     if (pfile_in_zip_read_info->read_buffer==NULL)
1113     {
1114         TRYFREE(pfile_in_zip_read_info);
1115         return UNZ_INTERNALERROR;
1116     }
1118     pfile_in_zip_read_info->stream_initialised=0;
1120     if (method!=NULL)
1121         *method = (int)s->cur_file_info.compression_method;
1123     if (level!=NULL)
1124     {
1125         *level = 6;
1126         switch (s->cur_file_info.flag & 0x06)
1127         {
1128           case 6 : *level = 1; break;
1129           case 4 : *level = 2; break;
1130           case 2 : *level = 9; break;
1131         }
1132     }
1134     if ((s->cur_file_info.compression_method!=0) &&
1135         (s->cur_file_info.compression_method!=Z_DEFLATED))
1136         err=UNZ_BADZIPFILE;
1138     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1139     pfile_in_zip_read_info->crc32=0;
1140     pfile_in_zip_read_info->compression_method =
1141             s->cur_file_info.compression_method;
1142     pfile_in_zip_read_info->filestream=s->filestream;
1143     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1144     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1146     pfile_in_zip_read_info->stream.total_out = 0;
1148     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1149         (!raw))
1150     {
1151       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1152       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1153       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1154       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1155       pfile_in_zip_read_info->stream.avail_in = 0;
1157       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1158       if (err == Z_OK)
1159         pfile_in_zip_read_info->stream_initialised=1;
1160       else
1161       {
1162         TRYFREE(pfile_in_zip_read_info);
1163         return err;
1164       }
1165         /* windowBits is passed < 0 to tell that there is no zlib header.
1166          * Note that in this case inflate *requires* an extra "dummy" byte
1167          * after the compressed stream in order to complete decompression and
1168          * return Z_STREAM_END.
1169          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1170          * size of both compressed and uncompressed data
1171          */
1172     }
1173     pfile_in_zip_read_info->rest_read_compressed =
1174             s->cur_file_info.compressed_size ;
1175     pfile_in_zip_read_info->rest_read_uncompressed =
1176             s->cur_file_info.uncompressed_size ;
1179     pfile_in_zip_read_info->pos_in_zipfile =
1180             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1181               iSizeVar;
1183     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1185     s->pfile_in_zip_read = pfile_in_zip_read_info;
1187     return UNZ_OK;
1190 extern int ZEXPORT unzOpenCurrentFile (file)
1191     unzFile file;
1193     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1196 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1197     unzFile file;
1198     const char* password;
1200     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1203 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1204     unzFile file;
1205     int* method;
1206     int* level;
1207     int raw;
1209     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1213   Read bytes from the current file.
1214   buf contain buffer where data must be copied
1215   len the size of buf.
1217   return the number of byte copied if somes bytes are copied
1218   return 0 if the end of file was reached
1219   return <0 with error code if there is an error
1220     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1222 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1223     unzFile file;
1224     voidp buf;
1225     unsigned len;
1227     int err=UNZ_OK;
1228     uInt iRead = 0;
1229     unz_s* s;
1230     file_in_zip_read_info_s* pfile_in_zip_read_info;
1231     if (file==NULL)
1232         return UNZ_PARAMERROR;
1233     s=(unz_s*)file;
1234     pfile_in_zip_read_info=s->pfile_in_zip_read;
1236     if (pfile_in_zip_read_info==NULL)
1237         return UNZ_PARAMERROR;
1240     if ((pfile_in_zip_read_info->read_buffer == NULL))
1241         return UNZ_END_OF_LIST_OF_FILE;
1242     if (len==0)
1243         return 0;
1245     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1247     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1249     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1250         (!(pfile_in_zip_read_info->raw)))
1251         pfile_in_zip_read_info->stream.avail_out =
1252             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1254     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1255            pfile_in_zip_read_info->stream.avail_in) &&
1256          (pfile_in_zip_read_info->raw))
1257         pfile_in_zip_read_info->stream.avail_out =
1258             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1259             pfile_in_zip_read_info->stream.avail_in;
1261     while (pfile_in_zip_read_info->stream.avail_out>0)
1262     {
1263         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1264             (pfile_in_zip_read_info->rest_read_compressed>0))
1265         {
1266             uInt uReadThis = UNZ_BUFSIZE;
1267             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1268                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1269             if (uReadThis == 0)
1270                 return UNZ_EOF;
1271             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1272                       pfile_in_zip_read_info->filestream,
1273                       pfile_in_zip_read_info->pos_in_zipfile +
1274                          pfile_in_zip_read_info->byte_before_the_zipfile,
1275                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1276                 return UNZ_ERRNO;
1277             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1278                       pfile_in_zip_read_info->filestream,
1279                       pfile_in_zip_read_info->read_buffer,
1280                       uReadThis)!=uReadThis)
1281                 return UNZ_ERRNO;
1286             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1288             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1290             pfile_in_zip_read_info->stream.next_in =
1291                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1292             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1293         }
1295         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1296         {
1297             uInt uDoCopy,i ;
1299             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1300                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1301                 return (iRead==0) ? UNZ_EOF : iRead;
1303             if (pfile_in_zip_read_info->stream.avail_out <
1304                             pfile_in_zip_read_info->stream.avail_in)
1305                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1306             else
1307                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1309             for (i=0;i<uDoCopy;i++)
1310                 *(pfile_in_zip_read_info->stream.next_out+i) =
1311                         *(pfile_in_zip_read_info->stream.next_in+i);
1313             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1314                                 pfile_in_zip_read_info->stream.next_out,
1315                                 uDoCopy);
1316             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1317             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1318             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1319             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1320             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1321             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1322             iRead += uDoCopy;
1323         }
1324         else
1325         {
1326             uLong uTotalOutBefore,uTotalOutAfter;
1327             const Bytef *bufBefore;
1328             uLong uOutThis;
1329             int flush=Z_SYNC_FLUSH;
1331             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1332             bufBefore = pfile_in_zip_read_info->stream.next_out;
1334             /*
1335             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1336                      pfile_in_zip_read_info->stream.avail_out) &&
1337                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1338                 flush = Z_FINISH;
1339             */
1340             err=inflate(&pfile_in_zip_read_info->stream,flush);
1342             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1343               err = Z_DATA_ERROR;
1345             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1346             uOutThis = uTotalOutAfter-uTotalOutBefore;
1348             pfile_in_zip_read_info->crc32 =
1349                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1350                         (uInt)(uOutThis));
1352             pfile_in_zip_read_info->rest_read_uncompressed -=
1353                 uOutThis;
1355             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1357             if (err==Z_STREAM_END)
1358                 return (iRead==0) ? UNZ_EOF : iRead;
1359             if (err!=Z_OK)
1360                 break;
1361         }
1362     }
1364     if (err==Z_OK)
1365         return iRead;
1366     return err;
1371   Give the current position in uncompressed data
1373 extern z_off_t ZEXPORT unztell (file)
1374     unzFile file;
1376     unz_s* s;
1377     file_in_zip_read_info_s* pfile_in_zip_read_info;
1378     if (file==NULL)
1379         return UNZ_PARAMERROR;
1380     s=(unz_s*)file;
1381     pfile_in_zip_read_info=s->pfile_in_zip_read;
1383     if (pfile_in_zip_read_info==NULL)
1384         return UNZ_PARAMERROR;
1386     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1391   return 1 if the end of file was reached, 0 elsewhere
1393 extern int ZEXPORT unzeof (file)
1394     unzFile file;
1396     unz_s* s;
1397     file_in_zip_read_info_s* pfile_in_zip_read_info;
1398     if (file==NULL)
1399         return UNZ_PARAMERROR;
1400     s=(unz_s*)file;
1401     pfile_in_zip_read_info=s->pfile_in_zip_read;
1403     if (pfile_in_zip_read_info==NULL)
1404         return UNZ_PARAMERROR;
1406     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1407         return 1;
1408     else
1409         return 0;
1415   Read extra field from the current file (opened by unzOpenCurrentFile)
1416   This is the local-header version of the extra field (sometimes, there is
1417     more info in the local-header version than in the central-header)
1419   if buf==NULL, it return the size of the local extra field that can be read
1421   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1422     buf.
1423   the return value is the number of bytes copied in buf, or (if <0)
1424     the error code
1426 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1427     unzFile file;
1428     voidp buf;
1429     unsigned len;
1431     unz_s* s;
1432     file_in_zip_read_info_s* pfile_in_zip_read_info;
1433     uInt read_now;
1434     uLong size_to_read;
1436     if (file==NULL)
1437         return UNZ_PARAMERROR;
1438     s=(unz_s*)file;
1439     pfile_in_zip_read_info=s->pfile_in_zip_read;
1441     if (pfile_in_zip_read_info==NULL)
1442         return UNZ_PARAMERROR;
1444     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1445                 pfile_in_zip_read_info->pos_local_extrafield);
1447     if (buf==NULL)
1448         return (int)size_to_read;
1450     if (len>size_to_read)
1451         read_now = (uInt)size_to_read;
1452     else
1453         read_now = (uInt)len ;
1455     if (read_now==0)
1456         return 0;
1458     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1459               pfile_in_zip_read_info->filestream,
1460               pfile_in_zip_read_info->offset_local_extrafield +
1461               pfile_in_zip_read_info->pos_local_extrafield,
1462               ZLIB_FILEFUNC_SEEK_SET)!=0)
1463         return UNZ_ERRNO;
1465     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1466               pfile_in_zip_read_info->filestream,
1467               buf,read_now)!=read_now)
1468         return UNZ_ERRNO;
1470     return (int)read_now;
1474   Close the file in zip opened with unzipOpenCurrentFile
1475   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1477 extern int ZEXPORT unzCloseCurrentFile (file)
1478     unzFile file;
1480     int err=UNZ_OK;
1482     unz_s* s;
1483     file_in_zip_read_info_s* pfile_in_zip_read_info;
1484     if (file==NULL)
1485         return UNZ_PARAMERROR;
1486     s=(unz_s*)file;
1487     pfile_in_zip_read_info=s->pfile_in_zip_read;
1489     if (pfile_in_zip_read_info==NULL)
1490         return UNZ_PARAMERROR;
1493     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1494         (!pfile_in_zip_read_info->raw))
1495     {
1496         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1497             err=UNZ_CRCERROR;
1498     }
1501     TRYFREE(pfile_in_zip_read_info->read_buffer);
1502     pfile_in_zip_read_info->read_buffer = NULL;
1503     if (pfile_in_zip_read_info->stream_initialised)
1504         inflateEnd(&pfile_in_zip_read_info->stream);
1506     pfile_in_zip_read_info->stream_initialised = 0;
1507     TRYFREE(pfile_in_zip_read_info);
1509     s->pfile_in_zip_read=NULL;
1511     return err;
1516   Get the global comment string of the ZipFile, in the szComment buffer.
1517   uSizeBuf is the size of the szComment buffer.
1518   return the number of byte copied or an error code <0
1520 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1521     unzFile file;
1522     char *szComment;
1523     uLong uSizeBuf;
1525 //    int err=UNZ_OK;
1526     unz_s* s;
1527     uLong uReadThis ;
1528     if (file==NULL)
1529         return UNZ_PARAMERROR;
1530     s=(unz_s*)file;
1532     uReadThis = uSizeBuf;
1533     if (uReadThis>s->gi.size_comment)
1534         uReadThis = s->gi.size_comment;
1536     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1537         return UNZ_ERRNO;
1539     if (uReadThis>0)
1540     {
1541       *szComment='\0';
1542       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1543         return UNZ_ERRNO;
1544     }
1546     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1547         *(szComment+s->gi.size_comment)='\0';
1548     return (int)uReadThis;
1551 /* Additions by RX '2004 */
1552 extern uLong ZEXPORT unzGetOffset (file)
1553     unzFile file;
1555     unz_s* s;
1557     if (file==NULL)
1558           return UNZ_PARAMERROR;
1559     s=(unz_s*)file;
1560     if (!s->current_file_ok)
1561       return 0;
1562     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1563       if (s->num_file==s->gi.number_entry)
1564          return 0;
1565     return s->pos_in_central_dir;
1568 extern int ZEXPORT unzSetOffset (file, pos)
1569         unzFile file;
1570         uLong pos;
1572     unz_s* s;
1573     int err;
1575     if (file==NULL)
1576         return UNZ_PARAMERROR;
1577     s=(unz_s*)file;
1579     s->pos_in_central_dir = pos;
1580     s->num_file = s->gi.number_entry;      /* hack */
1581     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1582                                               &s->cur_file_info_internal,
1583                                               NULL,0,NULL,0,NULL,0);
1584     s->current_file_ok = (err == UNZ_OK);
1585     return err;