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