update dev300-m58
[ooovba.git] / extensions / source / macosx / spotlight / unzip.m
blob34241ba500c26a5c79f8adcb843b235aa3efe615
1 /*************************************************************************
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  * 
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: unzip.m,v $
10  * $Revision: 1.3 $
11  *
12  * This file is part of OpenOffice.org.
13  *
14  * OpenOffice.org is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License version 3
16  * only, as published by the Free Software Foundation.
17  *
18  * OpenOffice.org is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU Lesser General Public License version 3 for more details
22  * (a copy is included in the LICENSE file that accompanied this code).
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * version 3 along with OpenOffice.org.  If not, see
26  * <http://www.openoffice.org/license.html>
27  * for a copy of the LGPLv3 License.
28  *
29 *************************************************************************/
31 /* unzip.c -- IO for uncompress .zip files using zlib
32    Version 1.01e, February 12th, 2005
34    Copyright (C) 1998-2005 Gilles Vollant
36    Read unzip.h for more info
39 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
40 compatibility with older software. The following is from the original crypt.c. Code
41 woven in by Terry Thorsen 1/2003.
44   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
46   See the accompanying file LICENSE, version 2000-Apr-09 or later
47   (the contents of which are also included in zip.h) for terms of use.
48   If, for some reason, all these files are missing, the Info-ZIP license
49   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
52   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
54   The encryption/decryption parts of this source code (as opposed to the
55   non-echoing password parts) were originally written in Europe.  The
56   whole source package can be freely distributed, including from the USA.
57   (Prior to January 2000, re-export from the US was a violation of US law.)
58  */
61   This encryption code is a direct transcription of the algorithm from
62   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
63   file (appnote.txt) is distributed with the PKZIP program (even in the
64   version without encryption capabilities).
65  */
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <zlib.h>
72 #include "ioapi.h"
73 #include "unzip.h"
75 #ifdef STDC
76 #  include <stddef.h>
77 #  include <string.h>
78 #  include <stdlib.h>
79 #endif
80 #ifdef NO_ERRNO_H
81     extern int errno;
82 #else
83 #   include <errno.h>
84 #endif
87 #ifndef local
88 #  define local static
89 #endif
90 /* compile with -Dlocal if your debugger can't find static symbols */
93 #ifndef CASESENSITIVITYDEFAULT_NO
94 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
95 #    define CASESENSITIVITYDEFAULT_NO
96 #  endif
97 #endif
100 #ifndef UNZ_BUFSIZE
101 #define UNZ_BUFSIZE (16384)
102 #endif
104 #ifndef UNZ_MAXFILENAMEINZIP
105 #define UNZ_MAXFILENAMEINZIP (256)
106 #endif
108 #ifndef ALLOC
109 # define ALLOC(size) (malloc(size))
110 #endif
111 #ifndef TRYFREE
112 # define TRYFREE(p) {if (p) free(p);}
113 #endif
115 #define SIZECENTRALDIRITEM (0x2e)
116 #define SIZEZIPLOCALHEADER (0x1e)
121 const char unz_copyright[] =
122    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
124 /* unz_file_info_interntal contain internal info about a file in zipfile*/
125 typedef struct unz_file_info_internal_s
127     uLong offset_curfile;/* relative offset of local header 4 bytes */
128 } unz_file_info_internal;
131 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
132     when reading and decompress it */
133 typedef struct
135     char  *read_buffer;         /* internal buffer for compressed data */
136     z_stream stream;            /* zLib stream structure for inflate */
138     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
139     uLong stream_initialised;   /* flag set if stream structure is initialised*/
141     uLong offset_local_extrafield;/* offset of the local extra field */
142     uInt  size_local_extrafield;/* size of the local extra field */
143     uLong pos_local_extrafield;   /* position in the local extra field in read*/
145     uLong crc32;                /* crc32 of all data uncompressed */
146     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
147     uLong rest_read_compressed; /* number of byte to be decompressed */
148     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
149     zlib_filefunc_def z_filefunc;
150     voidpf filestream;        /* io structore of the zipfile */
151     uLong compression_method;   /* compression method (0==store) */
152     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
153     int   raw;
154 } file_in_zip_read_info_s;
157 /* unz_s contain internal information about the zipfile
159 typedef struct
161     zlib_filefunc_def z_filefunc;
162     voidpf filestream;        /* io structore of the zipfile */
163     unz_global_info gi;       /* public global information */
164     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
165     uLong num_file;             /* number of the current file in the zipfile*/
166     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
167     uLong current_file_ok;      /* flag about the usability of the current file*/
168     uLong central_pos;          /* position of the beginning of the central dir*/
170     uLong size_central_dir;     /* size of the central directory  */
171     uLong offset_central_dir;   /* offset of start of central directory with
172                                    respect to the starting disk number */
174     unz_file_info cur_file_info; /* public info about the current file in zip*/
175     unz_file_info_internal cur_file_info_internal; /* private info about it*/
176     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
177                                         file if we are decompressing it */
178     int encrypted;
179 } unz_s;
183 /* ===========================================================================
184      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
185    for end of file.
186    IN assertion: the stream s has been sucessfully opened for reading.
190 local int unzlocal_getByte OF((
191     const zlib_filefunc_def* pzlib_filefunc_def,
192     voidpf filestream,
193     int *pi));
195 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
196     const zlib_filefunc_def* pzlib_filefunc_def;
197     voidpf filestream;
198     int *pi;
200     unsigned char c;
201     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
202     if (err==1)
203     {
204         *pi = (int)c;
205         return UNZ_OK;
206     }
207     else
208     {
209         if (ZERROR(*pzlib_filefunc_def,filestream))
210             return UNZ_ERRNO;
211         else
212             return UNZ_EOF;
213     }
217 /* ===========================================================================
218    Reads a long in LSB order from the given gz_stream. Sets
220 local int unzlocal_getShort OF((
221     const zlib_filefunc_def* pzlib_filefunc_def,
222     voidpf filestream,
223     uLong *pX));
225 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
226     const zlib_filefunc_def* pzlib_filefunc_def;
227     voidpf filestream;
228     uLong *pX;
230     uLong x ;
231     int i;
232     int err;
234     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
235     x = (uLong)i;
237     if (err==UNZ_OK)
238         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
239     x += ((uLong)i)<<8;
241     if (err==UNZ_OK)
242         *pX = x;
243     else
244         *pX = 0;
245     return err;
248 local int unzlocal_getLong OF((
249     const zlib_filefunc_def* pzlib_filefunc_def,
250     voidpf filestream,
251     uLong *pX));
253 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
254     const zlib_filefunc_def* pzlib_filefunc_def;
255     voidpf filestream;
256     uLong *pX;
258     uLong x ;
259     int i;
260     int err;
262     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
263     x = (uLong)i;
265     if (err==UNZ_OK)
266         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
267     x += ((uLong)i)<<8;
269     if (err==UNZ_OK)
270         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
271     x += ((uLong)i)<<16;
273     if (err==UNZ_OK)
274         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
275     x += ((uLong)i)<<24;
277     if (err==UNZ_OK)
278         *pX = x;
279     else
280         *pX = 0;
281     return err;
285 /* My own strcmpi / strcasecmp */
286 local int strcmpcasenosensitive_internal (fileName1,fileName2)
287     const char* fileName1;
288     const char* fileName2;
290     for (;;)
291     {
292         char c1=*(fileName1++);
293         char c2=*(fileName2++);
294         if ((c1>='a') && (c1<='z'))
295             c1 -= 0x20;
296         if ((c2>='a') && (c2<='z'))
297             c2 -= 0x20;
298         if (c1=='\0')
299             return ((c2=='\0') ? 0 : -1);
300         if (c2=='\0')
301             return 1;
302         if (c1<c2)
303             return -1;
304         if (c1>c2)
305             return 1;
306     }
310 #ifdef  CASESENSITIVITYDEFAULT_NO
311 #define CASESENSITIVITYDEFAULTVALUE 2
312 #else
313 #define CASESENSITIVITYDEFAULTVALUE 1
314 #endif
316 #ifndef STRCMPCASENOSENTIVEFUNCTION
317 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
318 #endif
321    Compare two filename (fileName1,fileName2).
322    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
323    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
324                                                                 or strcasecmp)
325    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
326         (like 1 on Unix, 2 on Windows)
329 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
330     const char* fileName1;
331     const char* fileName2;
332     int iCaseSensitivity;
334     if (iCaseSensitivity==0)
335         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
337     if (iCaseSensitivity==1)
338         return strcmp(fileName1,fileName2);
340     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
343 #ifndef BUFREADCOMMENT
344 #define BUFREADCOMMENT (0x400)
345 #endif
348   Locate the Central directory of a zipfile (at the end, just before
349     the global comment)
351 local uLong unzlocal_SearchCentralDir OF((
352     const zlib_filefunc_def* pzlib_filefunc_def,
353     voidpf filestream));
355 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
356     const zlib_filefunc_def* pzlib_filefunc_def;
357     voidpf filestream;
359     unsigned char* buf;
360     uLong uSizeFile;
361     uLong uBackRead;
362     uLong uMaxBack=0xffff; /* maximum size of global comment */
363     uLong uPosFound=0;
365     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
366         return 0;
369     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
371     if (uMaxBack>uSizeFile)
372         uMaxBack = uSizeFile;
374     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
375     if (buf==NULL)
376         return 0;
378     uBackRead = 4;
379     while (uBackRead<uMaxBack)
380     {
381         uLong uReadSize,uReadPos ;
382         int i;
383         if (uBackRead+BUFREADCOMMENT>uMaxBack)
384             uBackRead = uMaxBack;
385         else
386             uBackRead+=BUFREADCOMMENT;
387         uReadPos = uSizeFile-uBackRead ;
389         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
390                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
391         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
392             break;
394         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
395             break;
397         for (i=(int)uReadSize-3; (i--)>0;)
398             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
399                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
400             {
401                 uPosFound = uReadPos+i;
402                 break;
403             }
405         if (uPosFound!=0)
406             break;
407     }
408     TRYFREE(buf);
409     return uPosFound;
413   Open a Zip file. path contain the full pathname (by example,
414      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
415      "zlib/zlib114.zip".
416      If the zipfile cannot be opened (file doesn't exist or in not valid), the
417        return value is NULL.
418      Else, the return value is a unzFile Handle, usable with other function
419        of this unzip package.
421 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
422     const char *path;
423     zlib_filefunc_def* pzlib_filefunc_def;
425     unz_s us;
426     unz_s *s;
427     uLong central_pos,uL;
429     uLong number_disk;          /* number of the current dist, used for
430                                    spaning ZIP, unsupported, always 0*/
431     uLong number_disk_with_CD;  /* number the the disk with central dir, used
432                                    for spaning ZIP, unsupported, always 0*/
433     uLong number_entry_CD;      /* total number of entries in
434                                    the central dir
435                                    (same than number_entry on nospan) */
437     int err=UNZ_OK;
439     if (unz_copyright[0]!=' ')
440         return NULL;
442     if (pzlib_filefunc_def==NULL)
443         fill_fopen_filefunc(&us.z_filefunc);
444     else
445         us.z_filefunc = *pzlib_filefunc_def;
447     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
448                                                  path,
449                                                  ZLIB_FILEFUNC_MODE_READ |
450                                                  ZLIB_FILEFUNC_MODE_EXISTING);
451     if (us.filestream==NULL)
452         return NULL;
454     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
455     if (central_pos==0)
456         err=UNZ_ERRNO;
458     if (ZSEEK(us.z_filefunc, us.filestream,
459                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
460         err=UNZ_ERRNO;
462     /* the signature, already checked */
463     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
464         err=UNZ_ERRNO;
466     /* number of this disk */
467     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
468         err=UNZ_ERRNO;
470     /* number of the disk with the start of the central directory */
471     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
472         err=UNZ_ERRNO;
474     /* total number of entries in the central dir on this disk */
475     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
476         err=UNZ_ERRNO;
478     /* total number of entries in the central dir */
479     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
480         err=UNZ_ERRNO;
482     if ((number_entry_CD!=us.gi.number_entry) ||
483         (number_disk_with_CD!=0) ||
484         (number_disk!=0))
485         err=UNZ_BADZIPFILE;
487     /* size of the central directory */
488     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
489         err=UNZ_ERRNO;
491     /* offset of start of central directory with respect to the
492           starting disk number */
493     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
494         err=UNZ_ERRNO;
496     /* zipfile comment length */
497     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
498         err=UNZ_ERRNO;
500     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
501         (err==UNZ_OK))
502         err=UNZ_BADZIPFILE;
504     if (err!=UNZ_OK)
505     {
506         ZCLOSE(us.z_filefunc, us.filestream);
507         return NULL;
508     }
510     us.byte_before_the_zipfile = central_pos -
511                             (us.offset_central_dir+us.size_central_dir);
512     us.central_pos = central_pos;
513     us.pfile_in_zip_read = NULL;
514     us.encrypted = 0;
517     s=(unz_s*)ALLOC(sizeof(unz_s));
518     *s=us;
519     unzGoToFirstFile((unzFile)s);
520     return (unzFile)s;
524 extern unzFile ZEXPORT unzOpen (path)
525     const char *path;
527     return unzOpen2(path, NULL);
531   Close a ZipFile opened with unzipOpen.
532   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
533     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
534   return UNZ_OK if there is no problem. */
535 extern int ZEXPORT unzClose (file)
536     unzFile file;
538     unz_s* s;
539     if (file==NULL)
540         return UNZ_PARAMERROR;
541     s=(unz_s*)file;
543     if (s->pfile_in_zip_read!=NULL)
544         unzCloseCurrentFile(file);
546     ZCLOSE(s->z_filefunc, s->filestream);
547     TRYFREE(s);
548     return UNZ_OK;
553   Write info about the ZipFile in the *pglobal_info structure.
554   No preparation of the structure is needed
555   return UNZ_OK if there is no problem. */
556 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
557     unzFile file;
558     unz_global_info *pglobal_info;
560     unz_s* s;
561     if (file==NULL)
562         return UNZ_PARAMERROR;
563     s=(unz_s*)file;
564     *pglobal_info=s->gi;
565     return UNZ_OK;
570    Translate date/time from Dos format to tm_unz (readable more easilty)
572 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
573     uLong ulDosDate;
574     tm_unz* ptm;
576     uLong uDate;
577     uDate = (uLong)(ulDosDate>>16);
578     ptm->tm_mday = (uInt)(uDate&0x1f) ;
579     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
580     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
582     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
583     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
584     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
588   Get Info about the current file in the zipfile, with internal only info
590 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
591                                                   unz_file_info *pfile_info,
592                                                   unz_file_info_internal
593                                                   *pfile_info_internal,
594                                                   char *szFileName,
595                                                   uLong fileNameBufferSize,
596                                                   void *extraField,
597                                                   uLong extraFieldBufferSize,
598                                                   char *szComment,
599                                                   uLong commentBufferSize));
601 local int unzlocal_GetCurrentFileInfoInternal (file,
602                                               pfile_info,
603                                               pfile_info_internal,
604                                               szFileName, fileNameBufferSize,
605                                               extraField, extraFieldBufferSize,
606                                               szComment,  commentBufferSize)
607     unzFile file;
608     unz_file_info *pfile_info;
609     unz_file_info_internal *pfile_info_internal;
610     char *szFileName;
611     uLong fileNameBufferSize;
612     void *extraField;
613     uLong extraFieldBufferSize;
614     char *szComment;
615     uLong commentBufferSize;
617     unz_s* s;
618     unz_file_info file_info;
619     unz_file_info_internal file_info_internal;
620     int err=UNZ_OK;
621     uLong uMagic;
622     long lSeek=0;
624     if (file==NULL)
625         return UNZ_PARAMERROR;
626     s=(unz_s*)file;
627     if (ZSEEK(s->z_filefunc, s->filestream,
628               s->pos_in_central_dir+s->byte_before_the_zipfile,
629               ZLIB_FILEFUNC_SEEK_SET)!=0)
630         err=UNZ_ERRNO;
633     /* we check the magic */
634     if (err==UNZ_OK) {
635         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
636             err=UNZ_ERRNO;
637         else if (uMagic!=0x02014b50)
638             err=UNZ_BADZIPFILE;
639     }
641     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
642         err=UNZ_ERRNO;
644     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
645         err=UNZ_ERRNO;
647     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
648         err=UNZ_ERRNO;
650     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
651         err=UNZ_ERRNO;
653     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
654         err=UNZ_ERRNO;
656     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
658     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
659         err=UNZ_ERRNO;
661     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
662         err=UNZ_ERRNO;
664     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
665         err=UNZ_ERRNO;
667     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
668         err=UNZ_ERRNO;
670     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
671         err=UNZ_ERRNO;
673     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
674         err=UNZ_ERRNO;
676     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
677         err=UNZ_ERRNO;
679     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
680         err=UNZ_ERRNO;
682     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
683         err=UNZ_ERRNO;
685     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
686         err=UNZ_ERRNO;
688     lSeek+=file_info.size_filename;
689     if ((err==UNZ_OK) && (szFileName!=NULL))
690     {
691         uLong uSizeRead ;
692         if (file_info.size_filename<fileNameBufferSize)
693         {
694             *(szFileName+file_info.size_filename)='\0';
695             uSizeRead = file_info.size_filename;
696         }
697         else
698             uSizeRead = fileNameBufferSize;
700         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
701             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
702                 err=UNZ_ERRNO;
703         lSeek -= uSizeRead;
704     }
707     if ((err==UNZ_OK) && (extraField!=NULL))
708     {
709         uLong uSizeRead ;
710         if (file_info.size_file_extra<extraFieldBufferSize)
711             uSizeRead = file_info.size_file_extra;
712         else
713             uSizeRead = extraFieldBufferSize;
715         if (lSeek!=0) {
716             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
717                 lSeek=0;
718             else
719                 err=UNZ_ERRNO;
720         }
721         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
722             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
723                 err=UNZ_ERRNO;
724         lSeek += file_info.size_file_extra - uSizeRead;
725     }
726     else
727         lSeek+=file_info.size_file_extra;
730     if ((err==UNZ_OK) && (szComment!=NULL))
731     {
732         uLong uSizeRead ;
733         if (file_info.size_file_comment<commentBufferSize)
734         {
735             *(szComment+file_info.size_file_comment)='\0';
736             uSizeRead = file_info.size_file_comment;
737         }
738         else
739             uSizeRead = commentBufferSize;
741         if (lSeek!=0) {
742             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
743                 lSeek=0;
744             else
745                 err=UNZ_ERRNO;
746         }
747         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
748             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
749                 err=UNZ_ERRNO;
750         lSeek+=file_info.size_file_comment - uSizeRead;
751     }
752     else
753         lSeek+=file_info.size_file_comment;
755     if ((err==UNZ_OK) && (pfile_info!=NULL))
756         *pfile_info=file_info;
758     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
759         *pfile_info_internal=file_info_internal;
761     return err;
767   Write info about the ZipFile in the *pglobal_info structure.
768   No preparation of the structure is needed
769   return UNZ_OK if there is no problem.
771 extern int ZEXPORT unzGetCurrentFileInfo (file,
772                                           pfile_info,
773                                           szFileName, fileNameBufferSize,
774                                           extraField, extraFieldBufferSize,
775                                           szComment,  commentBufferSize)
776     unzFile file;
777     unz_file_info *pfile_info;
778     char *szFileName;
779     uLong fileNameBufferSize;
780     void *extraField;
781     uLong extraFieldBufferSize;
782     char *szComment;
783     uLong commentBufferSize;
785     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
786                                                 szFileName,fileNameBufferSize,
787                                                 extraField,extraFieldBufferSize,
788                                                 szComment,commentBufferSize);
792   Set the current file of the zipfile to the first file.
793   return UNZ_OK if there is no problem
795 extern int ZEXPORT unzGoToFirstFile (file)
796     unzFile file;
798     int err=UNZ_OK;
799     unz_s* s;
800     if (file==NULL)
801         return UNZ_PARAMERROR;
802     s=(unz_s*)file;
803     s->pos_in_central_dir=s->offset_central_dir;
804     s->num_file=0;
805     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
806                                              &s->cur_file_info_internal,
807                                              NULL,0,NULL,0,NULL,0);
808     s->current_file_ok = (err == UNZ_OK);
809     return err;
813   Set the current file of the zipfile to the next file.
814   return UNZ_OK if there is no problem
815   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
817 extern int ZEXPORT unzGoToNextFile (file)
818     unzFile file;
820     unz_s* s;
821     int err;
823     if (file==NULL)
824         return UNZ_PARAMERROR;
825     s=(unz_s*)file;
826     if (!s->current_file_ok)
827         return UNZ_END_OF_LIST_OF_FILE;
828     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
829       if (s->num_file+1==s->gi.number_entry)
830         return UNZ_END_OF_LIST_OF_FILE;
832     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
833             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
834     s->num_file++;
835     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
836                                                &s->cur_file_info_internal,
837                                                NULL,0,NULL,0,NULL,0);
838     s->current_file_ok = (err == UNZ_OK);
839     return err;
844   Try locate the file szFileName in the zipfile.
845   For the iCaseSensitivity signification, see unzipStringFileNameCompare
847   return value :
848   UNZ_OK if the file is found. It becomes the current file.
849   UNZ_END_OF_LIST_OF_FILE if the file is not found
851 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
852     unzFile file;
853     const char *szFileName;
854     int iCaseSensitivity;
856     unz_s* s;
857     int err;
859     /* We remember the 'current' position in the file so that we can jump
860      * back there if we fail.
861      */
862     unz_file_info cur_file_infoSaved;
863     unz_file_info_internal cur_file_info_internalSaved;
864     uLong num_fileSaved;
865     uLong pos_in_central_dirSaved;
868     if (file==NULL)
869         return UNZ_PARAMERROR;
871     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
872         return UNZ_PARAMERROR;
874     s=(unz_s*)file;
875     if (!s->current_file_ok)
876         return UNZ_END_OF_LIST_OF_FILE;
878     /* Save the current state */
879     num_fileSaved = s->num_file;
880     pos_in_central_dirSaved = s->pos_in_central_dir;
881     cur_file_infoSaved = s->cur_file_info;
882     cur_file_info_internalSaved = s->cur_file_info_internal;
884     err = unzGoToFirstFile(file);
886     while (err == UNZ_OK)
887     {
888         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
889         err = unzGetCurrentFileInfo(file,NULL,
890                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
891                                     NULL,0,NULL,0);
892         if (err == UNZ_OK)
893         {
894             if (unzStringFileNameCompare(szCurrentFileName,
895                                             szFileName,iCaseSensitivity)==0)
896                 return UNZ_OK;
897             err = unzGoToNextFile(file);
898         }
899     }
901     /* We failed, so restore the state of the 'current file' to where we
902      * were.
903      */
904     s->num_file = num_fileSaved ;
905     s->pos_in_central_dir = pos_in_central_dirSaved ;
906     s->cur_file_info = cur_file_infoSaved;
907     s->cur_file_info_internal = cur_file_info_internalSaved;
908     return err;
913 ///////////////////////////////////////////
914 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
915 // I need random access
917 // Further optimization could be realized by adding an ability
918 // to cache the directory in memory. The goal being a single
919 // comprehensive file read to put the file I need in a memory.
923 typedef struct unz_file_pos_s
925     uLong pos_in_zip_directory;   // offset in file
926     uLong num_of_file;            // # of file
927 } unz_file_pos;
930 extern int ZEXPORT unzGetFilePos(file, file_pos)
931     unzFile file;
932     unz_file_pos* file_pos;
934     unz_s* s;
936     if (file==NULL || file_pos==NULL)
937         return UNZ_PARAMERROR;
938     s=(unz_s*)file;
939     if (!s->current_file_ok)
940         return UNZ_END_OF_LIST_OF_FILE;
942     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
943     file_pos->num_of_file           = s->num_file;
945     return UNZ_OK;
948 extern int ZEXPORT unzGoToFilePos(file, file_pos)
949     unzFile file;
950     unz_file_pos* file_pos;
952     unz_s* s;
953     int err;
955     if (file==NULL || file_pos==NULL)
956         return UNZ_PARAMERROR;
957     s=(unz_s*)file;
959     /* jump to the right spot */
960     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
961     s->num_file           = file_pos->num_of_file;
963     /* set the current file */
964     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
965                                                &s->cur_file_info_internal,
966                                                NULL,0,NULL,0,NULL,0);
967     /* return results */
968     s->current_file_ok = (err == UNZ_OK);
969     return err;
973 // Unzip Helper Functions - should be here?
974 ///////////////////////////////////////////
978   Read the local header of the current zipfile
979   Check the coherency of the local header and info in the end of central
980         directory about this file
981   store in *piSizeVar the size of extra info in local header
982         (filename and size of extra field data)
984 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
985                                                     poffset_local_extrafield,
986                                                     psize_local_extrafield)
987     unz_s* s;
988     uInt* piSizeVar;
989     uLong *poffset_local_extrafield;
990     uInt  *psize_local_extrafield;
992     uLong uMagic,uData,uFlags;
993     uLong size_filename;
994     uLong size_extra_field;
995     int err=UNZ_OK;
997     *piSizeVar = 0;
998     *poffset_local_extrafield = 0;
999     *psize_local_extrafield = 0;
1001     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1002                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1003         return UNZ_ERRNO;
1006     if (err==UNZ_OK) {
1007         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1008             err=UNZ_ERRNO;
1009         else if (uMagic!=0x04034b50)
1010             err=UNZ_BADZIPFILE;
1011     }
1013     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1014         err=UNZ_ERRNO;
1016     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1017         err=UNZ_BADZIPFILE;
1019     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1020         err=UNZ_ERRNO;
1022     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1023         err=UNZ_ERRNO;
1024     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1025         err=UNZ_BADZIPFILE;
1027     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1028                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1029         err=UNZ_BADZIPFILE;
1031     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1032         err=UNZ_ERRNO;
1034     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1035         err=UNZ_ERRNO;
1036     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1037                               ((uFlags & 8)==0))
1038         err=UNZ_BADZIPFILE;
1040     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1041         err=UNZ_ERRNO;
1042     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1043                               ((uFlags & 8)==0))
1044         err=UNZ_BADZIPFILE;
1046     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1047         err=UNZ_ERRNO;
1048     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1049                               ((uFlags & 8)==0))
1050         err=UNZ_BADZIPFILE;
1053     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1054         err=UNZ_ERRNO;
1055     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1056         err=UNZ_BADZIPFILE;
1058     *piSizeVar += (uInt)size_filename;
1060     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1061         err=UNZ_ERRNO;
1062     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1063                                     SIZEZIPLOCALHEADER + size_filename;
1064     *psize_local_extrafield = (uInt)size_extra_field;
1066     *piSizeVar += (uInt)size_extra_field;
1068     return err;
1072   Open for reading data the current file in the zipfile.
1073   If there is no error and the file is opened, the return value is UNZ_OK.
1075 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1076     unzFile file;
1077     int* method;
1078     int* level;
1079     int raw;
1080     const char* password;
1082     int err=UNZ_OK;
1083     uInt iSizeVar;
1084     unz_s* s;
1085     file_in_zip_read_info_s* pfile_in_zip_read_info;
1086     uLong offset_local_extrafield;  /* offset of the local extra field */
1087     uInt  size_local_extrafield;    /* size of the local extra field */
1088     if (password != NULL)
1089         return UNZ_PARAMERROR;
1091     if (file==NULL)
1092         return UNZ_PARAMERROR;
1093     s=(unz_s*)file;
1094     if (!s->current_file_ok)
1095         return UNZ_PARAMERROR;
1097     if (s->pfile_in_zip_read != NULL)
1098         unzCloseCurrentFile(file);
1100     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1101                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1102         return UNZ_BADZIPFILE;
1104     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1105                                         ALLOC(sizeof(file_in_zip_read_info_s));
1106     if (pfile_in_zip_read_info==NULL)
1107         return UNZ_INTERNALERROR;
1109     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1110     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1111     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1112     pfile_in_zip_read_info->pos_local_extrafield=0;
1113     pfile_in_zip_read_info->raw=raw;
1115     if (pfile_in_zip_read_info->read_buffer==NULL)
1116     {
1117         TRYFREE(pfile_in_zip_read_info);
1118         return UNZ_INTERNALERROR;
1119     }
1121     pfile_in_zip_read_info->stream_initialised=0;
1123     if (method!=NULL)
1124         *method = (int)s->cur_file_info.compression_method;
1126     if (level!=NULL)
1127     {
1128         *level = 6;
1129         switch (s->cur_file_info.flag & 0x06)
1130         {
1131           case 6 : *level = 1; break;
1132           case 4 : *level = 2; break;
1133           case 2 : *level = 9; break;
1134         }
1135     }
1137     if ((s->cur_file_info.compression_method!=0) &&
1138         (s->cur_file_info.compression_method!=Z_DEFLATED))
1139         err=UNZ_BADZIPFILE;
1141     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1142     pfile_in_zip_read_info->crc32=0;
1143     pfile_in_zip_read_info->compression_method =
1144             s->cur_file_info.compression_method;
1145     pfile_in_zip_read_info->filestream=s->filestream;
1146     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1147     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1149     pfile_in_zip_read_info->stream.total_out = 0;
1151     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1152         (!raw))
1153     {
1154       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1155       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1156       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1157       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1158       pfile_in_zip_read_info->stream.avail_in = 0;
1160       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1161       if (err == Z_OK)
1162         pfile_in_zip_read_info->stream_initialised=1;
1163       else
1164       {
1165         TRYFREE(pfile_in_zip_read_info);
1166         return err;
1167       }
1168         /* windowBits is passed < 0 to tell that there is no zlib header.
1169          * Note that in this case inflate *requires* an extra "dummy" byte
1170          * after the compressed stream in order to complete decompression and
1171          * return Z_STREAM_END.
1172          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1173          * size of both compressed and uncompressed data
1174          */
1175     }
1176     pfile_in_zip_read_info->rest_read_compressed =
1177             s->cur_file_info.compressed_size ;
1178     pfile_in_zip_read_info->rest_read_uncompressed =
1179             s->cur_file_info.uncompressed_size ;
1182     pfile_in_zip_read_info->pos_in_zipfile =
1183             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1184               iSizeVar;
1186     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1188     s->pfile_in_zip_read = pfile_in_zip_read_info;
1190     return UNZ_OK;
1193 extern int ZEXPORT unzOpenCurrentFile (file)
1194     unzFile file;
1196     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1199 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1200     unzFile file;
1201     const char* password;
1203     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1206 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1207     unzFile file;
1208     int* method;
1209     int* level;
1210     int raw;
1212     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1216   Read bytes from the current file.
1217   buf contain buffer where data must be copied
1218   len the size of buf.
1220   return the number of byte copied if somes bytes are copied
1221   return 0 if the end of file was reached
1222   return <0 with error code if there is an error
1223     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1225 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1226     unzFile file;
1227     voidp buf;
1228     unsigned len;
1230     int err=UNZ_OK;
1231     uInt iRead = 0;
1232     unz_s* s;
1233     file_in_zip_read_info_s* pfile_in_zip_read_info;
1234     if (file==NULL)
1235         return UNZ_PARAMERROR;
1236     s=(unz_s*)file;
1237     pfile_in_zip_read_info=s->pfile_in_zip_read;
1239     if (pfile_in_zip_read_info==NULL)
1240         return UNZ_PARAMERROR;
1243     if ((pfile_in_zip_read_info->read_buffer == NULL))
1244         return UNZ_END_OF_LIST_OF_FILE;
1245     if (len==0)
1246         return 0;
1248     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1250     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1252     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1253         (!(pfile_in_zip_read_info->raw)))
1254         pfile_in_zip_read_info->stream.avail_out =
1255             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1257     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1258            pfile_in_zip_read_info->stream.avail_in) &&
1259          (pfile_in_zip_read_info->raw))
1260         pfile_in_zip_read_info->stream.avail_out =
1261             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1262             pfile_in_zip_read_info->stream.avail_in;
1264     while (pfile_in_zip_read_info->stream.avail_out>0)
1265     {
1266         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1267             (pfile_in_zip_read_info->rest_read_compressed>0))
1268         {
1269             uInt uReadThis = UNZ_BUFSIZE;
1270             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1271                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1272             if (uReadThis == 0)
1273                 return UNZ_EOF;
1274             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1275                       pfile_in_zip_read_info->filestream,
1276                       pfile_in_zip_read_info->pos_in_zipfile +
1277                          pfile_in_zip_read_info->byte_before_the_zipfile,
1278                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1279                 return UNZ_ERRNO;
1280             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1281                       pfile_in_zip_read_info->filestream,
1282                       pfile_in_zip_read_info->read_buffer,
1283                       uReadThis)!=uReadThis)
1284                 return UNZ_ERRNO;
1289             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1291             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1293             pfile_in_zip_read_info->stream.next_in =
1294                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1295             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1296         }
1298         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1299         {
1300             uInt uDoCopy,i ;
1302             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1303                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1304                 return (iRead==0) ? UNZ_EOF : iRead;
1306             if (pfile_in_zip_read_info->stream.avail_out <
1307                             pfile_in_zip_read_info->stream.avail_in)
1308                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1309             else
1310                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1312             for (i=0;i<uDoCopy;i++)
1313                 *(pfile_in_zip_read_info->stream.next_out+i) =
1314                         *(pfile_in_zip_read_info->stream.next_in+i);
1316             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1317                                 pfile_in_zip_read_info->stream.next_out,
1318                                 uDoCopy);
1319             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1320             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1321             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1322             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1323             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1324             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1325             iRead += uDoCopy;
1326         }
1327         else
1328         {
1329             uLong uTotalOutBefore,uTotalOutAfter;
1330             const Bytef *bufBefore;
1331             uLong uOutThis;
1332             int flush=Z_SYNC_FLUSH;
1334             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1335             bufBefore = pfile_in_zip_read_info->stream.next_out;
1337             /*
1338             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1339                      pfile_in_zip_read_info->stream.avail_out) &&
1340                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1341                 flush = Z_FINISH;
1342             */
1343             err=inflate(&pfile_in_zip_read_info->stream,flush);
1345             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1346               err = Z_DATA_ERROR;
1348             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1349             uOutThis = uTotalOutAfter-uTotalOutBefore;
1351             pfile_in_zip_read_info->crc32 =
1352                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1353                         (uInt)(uOutThis));
1355             pfile_in_zip_read_info->rest_read_uncompressed -=
1356                 uOutThis;
1358             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1360             if (err==Z_STREAM_END)
1361                 return (iRead==0) ? UNZ_EOF : iRead;
1362             if (err!=Z_OK)
1363                 break;
1364         }
1365     }
1367     if (err==Z_OK)
1368         return iRead;
1369     return err;
1374   Give the current position in uncompressed data
1376 extern z_off_t ZEXPORT unztell (file)
1377     unzFile file;
1379     unz_s* s;
1380     file_in_zip_read_info_s* pfile_in_zip_read_info;
1381     if (file==NULL)
1382         return UNZ_PARAMERROR;
1383     s=(unz_s*)file;
1384     pfile_in_zip_read_info=s->pfile_in_zip_read;
1386     if (pfile_in_zip_read_info==NULL)
1387         return UNZ_PARAMERROR;
1389     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1394   return 1 if the end of file was reached, 0 elsewhere
1396 extern int ZEXPORT unzeof (file)
1397     unzFile file;
1399     unz_s* s;
1400     file_in_zip_read_info_s* pfile_in_zip_read_info;
1401     if (file==NULL)
1402         return UNZ_PARAMERROR;
1403     s=(unz_s*)file;
1404     pfile_in_zip_read_info=s->pfile_in_zip_read;
1406     if (pfile_in_zip_read_info==NULL)
1407         return UNZ_PARAMERROR;
1409     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1410         return 1;
1411     else
1412         return 0;
1418   Read extra field from the current file (opened by unzOpenCurrentFile)
1419   This is the local-header version of the extra field (sometimes, there is
1420     more info in the local-header version than in the central-header)
1422   if buf==NULL, it return the size of the local extra field that can be read
1424   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1425     buf.
1426   the return value is the number of bytes copied in buf, or (if <0)
1427     the error code
1429 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1430     unzFile file;
1431     voidp buf;
1432     unsigned len;
1434     unz_s* s;
1435     file_in_zip_read_info_s* pfile_in_zip_read_info;
1436     uInt read_now;
1437     uLong size_to_read;
1439     if (file==NULL)
1440         return UNZ_PARAMERROR;
1441     s=(unz_s*)file;
1442     pfile_in_zip_read_info=s->pfile_in_zip_read;
1444     if (pfile_in_zip_read_info==NULL)
1445         return UNZ_PARAMERROR;
1447     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1448                 pfile_in_zip_read_info->pos_local_extrafield);
1450     if (buf==NULL)
1451         return (int)size_to_read;
1453     if (len>size_to_read)
1454         read_now = (uInt)size_to_read;
1455     else
1456         read_now = (uInt)len ;
1458     if (read_now==0)
1459         return 0;
1461     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1462               pfile_in_zip_read_info->filestream,
1463               pfile_in_zip_read_info->offset_local_extrafield +
1464               pfile_in_zip_read_info->pos_local_extrafield,
1465               ZLIB_FILEFUNC_SEEK_SET)!=0)
1466         return UNZ_ERRNO;
1468     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1469               pfile_in_zip_read_info->filestream,
1470               buf,read_now)!=read_now)
1471         return UNZ_ERRNO;
1473     return (int)read_now;
1477   Close the file in zip opened with unzipOpenCurrentFile
1478   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1480 extern int ZEXPORT unzCloseCurrentFile (file)
1481     unzFile file;
1483     int err=UNZ_OK;
1485     unz_s* s;
1486     file_in_zip_read_info_s* pfile_in_zip_read_info;
1487     if (file==NULL)
1488         return UNZ_PARAMERROR;
1489     s=(unz_s*)file;
1490     pfile_in_zip_read_info=s->pfile_in_zip_read;
1492     if (pfile_in_zip_read_info==NULL)
1493         return UNZ_PARAMERROR;
1496     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1497         (!pfile_in_zip_read_info->raw))
1498     {
1499         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1500             err=UNZ_CRCERROR;
1501     }
1504     TRYFREE(pfile_in_zip_read_info->read_buffer);
1505     pfile_in_zip_read_info->read_buffer = NULL;
1506     if (pfile_in_zip_read_info->stream_initialised)
1507         inflateEnd(&pfile_in_zip_read_info->stream);
1509     pfile_in_zip_read_info->stream_initialised = 0;
1510     TRYFREE(pfile_in_zip_read_info);
1512     s->pfile_in_zip_read=NULL;
1514     return err;
1519   Get the global comment string of the ZipFile, in the szComment buffer.
1520   uSizeBuf is the size of the szComment buffer.
1521   return the number of byte copied or an error code <0
1523 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1524     unzFile file;
1525     char *szComment;
1526     uLong uSizeBuf;
1528 //    int err=UNZ_OK;
1529     unz_s* s;
1530     uLong uReadThis ;
1531     if (file==NULL)
1532         return UNZ_PARAMERROR;
1533     s=(unz_s*)file;
1535     uReadThis = uSizeBuf;
1536     if (uReadThis>s->gi.size_comment)
1537         uReadThis = s->gi.size_comment;
1539     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1540         return UNZ_ERRNO;
1542     if (uReadThis>0)
1543     {
1544       *szComment='\0';
1545       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1546         return UNZ_ERRNO;
1547     }
1549     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1550         *(szComment+s->gi.size_comment)='\0';
1551     return (int)uReadThis;
1554 /* Additions by RX '2004 */
1555 extern uLong ZEXPORT unzGetOffset (file)
1556     unzFile file;
1558     unz_s* s;
1560     if (file==NULL)
1561           return UNZ_PARAMERROR;
1562     s=(unz_s*)file;
1563     if (!s->current_file_ok)
1564       return 0;
1565     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1566       if (s->num_file==s->gi.number_entry)
1567          return 0;
1568     return s->pos_in_central_dir;
1571 extern int ZEXPORT unzSetOffset (file, pos)
1572         unzFile file;
1573         uLong pos;
1575     unz_s* s;
1576     int err;
1578     if (file==NULL)
1579         return UNZ_PARAMERROR;
1580     s=(unz_s*)file;
1582     s->pos_in_central_dir = pos;
1583     s->num_file = s->gi.number_entry;      /* hack */
1584     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1585                                               &s->cur_file_info_internal,
1586                                               NULL,0,NULL,0,NULL,0);
1587     s->current_file_ok = (err == UNZ_OK);
1588     return err;