Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8614 maxcodehac 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
10
compatibility with older software. The following is from the original crypt.c. Code
11
woven 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 
39
#include 
40
#include 
41
#include "zlib.h"
42
#include "unzip.h"
43
 
44
#ifdef STDC
45
#  include 
46
#  include 
47
#  include 
48
#endif
49
#ifdef NO_ERRNO_H
50
    extern int errno;
51
#else
52
#   include 
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
 
90
const 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*/
94
typedef 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 */
102
typedef 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
*/
128
typedef 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
 
166
local int unzlocal_getByte OF((
167
    const zlib_filefunc_def* pzlib_filefunc_def,
168
    voidpf filestream,
169
    int *pi));
170
 
171
local 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
*/
196
local int unzlocal_getShort OF((
197
    const zlib_filefunc_def* pzlib_filefunc_def,
198
    voidpf filestream,
199
    uLong *pX));
200
 
201
local 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
 
224
local int unzlocal_getLong OF((
225
    const zlib_filefunc_def* pzlib_filefunc_def,
226
    voidpf filestream,
227
    uLong *pX));
228
 
229
local 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 */
262
local 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
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
*/
305
extern 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
*/
327
local uLong unzlocal_SearchCentralDir OF((
328
    const zlib_filefunc_def* pzlib_filefunc_def,
329
    voidpf filestream));
330
 
331
local 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
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
*/
397
extern 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
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
 
500
extern 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. */
511
extern 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. */
532
extern 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
*/
548
local 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
*/
566
local 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
 
577
local 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
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
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
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
*/
744
extern 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
*/
768
extern 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
*/
790
extern 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
*/
824
extern 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
/*
896
typedef 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
 
903
extern 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
 
921
extern 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
*/
957
local 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
*/
1047
extern 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
 
1192
extern int ZEXPORT unzOpenCurrentFile (file)
1193
    unzFile file;
1194
{
1195
    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1196
}
1197
 
1198
extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1199
    unzFile file;
1200
    const char* password;
1201
{
1202
    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1203
}
1204
 
1205
extern 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
*/
1224
extern 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
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
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
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
*/
1385
extern 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
*/
1405
extern 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
*/
1438
extern 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
*/
1489
extern 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
*/
1532
extern 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 */
1564
extern 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
 
1580
extern 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
}