~ubuntu-branches/ubuntu/maverick/hedgewars/maverick-proposed

« back to all changes in this revision

Viewing changes to misc/quazip/unzip.c

  • Committer: Package Import Robot
  • Author(s): Evan Broder
  • Date: 2011-11-22 04:49:51 UTC
  • mfrom: (3.2.15 sid)
  • Revision ID: package-import@ubuntu.com-20111122044951-elrt8tvvs5andmuw
Tags: 0.9.17-1~maverick0.1
* Backport 0.9.17-1 to Maverick to fix network play (LP: #852603):
  - debian/patches/haskell-backwards-compat.patch: Replace or
    reimplement functions used by the server that weren't available in
    Maverick's Haskell stack
  - Drop libghc-bytestring-show-dev build-dependency.
  - Add 6's to get libghc6-deepseq-dev, libghc6-utf8-string-dev
    build-dependencies
  - Change libghc6-network-dev build-dependency to libghc6-network-bytestring-dev

Show diffs side-by-side

added added

removed removed

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