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