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