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