Skip to content

Latest commit

 

History

History
1873 lines (1520 loc) · 57.7 KB

archiver_zip.c

File metadata and controls

1873 lines (1520 loc) · 57.7 KB
 
Jul 7, 2001
Jul 7, 2001
1
2
3
/*
* ZIP support routines for PhysicsFS.
*
Mar 11, 2007
Mar 11, 2007
4
* Please see the file LICENSE.txt in the source's root directory.
Jul 7, 2001
Jul 7, 2001
5
*
Jul 13, 2002
Jul 13, 2002
6
7
* This file written by Ryan C. Gordon, with some peeking at "unzip.c"
* by Gilles Vollant.
Jul 7, 2001
Jul 7, 2001
8
9
*/
Mar 23, 2012
Mar 23, 2012
10
11
12
13
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
#if PHYSFS_SUPPORTS_ZIP
May 10, 2002
May 10, 2002
14
Jul 13, 2002
Jul 13, 2002
15
#include <errno.h>
Nov 22, 2002
Nov 22, 2002
16
#include <time.h>
Sep 6, 2010
Sep 6, 2010
17
Mar 10, 2012
Mar 10, 2012
18
19
#include "physfs_miniz.h"
Jul 13, 2002
Jul 13, 2002
20
/*
Mar 14, 2005
Mar 14, 2005
21
22
* A buffer of ZIP_READBUFSIZE is allocated for each compressed file opened,
* and is freed when you close the file; compressed data is read into
Jul 13, 2002
Jul 13, 2002
23
24
25
26
27
28
29
30
31
32
33
* this buffer, and then is decompressed into the buffer passed to
* PHYSFS_read().
*
* Uncompressed entries in a zipfile do not allocate this buffer; they just
* read data directly into the buffer passed to PHYSFS_read().
*
* Depending on your speed and memory requirements, you should tweak this
* value.
*/
#define ZIP_READBUFSIZE (16 * 1024)
Jul 23, 2002
Jul 23, 2002
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
* Entries are "unresolved" until they are first opened. At that time,
* local file headers parsed/validated, data offsets will be updated to look
* at the actual file data instead of the header, and symlinks will be
* followed and optimized. This means that we don't seek and read around the
* archive until forced to do so, and after the first time, we had to do
* less reading and parsing, which is very CD-ROM friendly.
*/
typedef enum
{
ZIP_UNRESOLVED_FILE,
ZIP_UNRESOLVED_SYMLINK,
ZIP_RESOLVING,
ZIP_RESOLVED,
Feb 25, 2016
Feb 25, 2016
49
ZIP_DIRECTORY,
Jul 23, 2002
Jul 23, 2002
50
ZIP_BROKEN_FILE,
Jan 31, 2003
Jan 31, 2003
51
ZIP_BROKEN_SYMLINK
Jul 23, 2002
Jul 23, 2002
52
53
54
} ZipResolveType;
Jul 13, 2002
Jul 13, 2002
55
56
57
/*
* One ZIPentry is kept for each file in an open ZIP archive.
*/
Jul 23, 2002
Jul 23, 2002
58
typedef struct _ZIPentry
Jul 15, 2001
Jul 15, 2001
59
{
Jul 23, 2002
Jul 23, 2002
60
61
62
char *name; /* Name of file in archive */
struct _ZIPentry *symlink; /* NULL or file we symlink to */
ZipResolveType resolved; /* Have we resolved file/symlink? */
Jun 1, 2012
Jun 1, 2012
63
PHYSFS_uint64 offset; /* offset of data in archive */
Jul 23, 2002
Jul 23, 2002
64
65
PHYSFS_uint16 version; /* version made by */
PHYSFS_uint16 version_needed; /* version needed to extract */
Sep 12, 2016
Sep 12, 2016
66
PHYSFS_uint16 general_bits; /* general purpose bits */
Jul 23, 2002
Jul 23, 2002
67
68
PHYSFS_uint16 compression_method; /* compression method */
PHYSFS_uint32 crc; /* crc-32 */
Jun 1, 2012
Jun 1, 2012
69
70
PHYSFS_uint64 compressed_size; /* compressed size */
PHYSFS_uint64 uncompressed_size; /* uncompressed size */
Jul 23, 2002
Jul 23, 2002
71
PHYSFS_sint64 last_mod_time; /* last file mod time */
Sep 12, 2016
Sep 12, 2016
72
PHYSFS_uint32 dos_mod_time; /* original MS-DOS style mod time */
Feb 25, 2016
Feb 25, 2016
73
74
75
struct _ZIPentry *hashnext; /* next item in this hash bucket */
struct _ZIPentry *children; /* linked list of kids, if dir */
struct _ZIPentry *sibling; /* next item in same dir */
Jul 28, 2001
Jul 28, 2001
76
77
} ZIPentry;
Jul 13, 2002
Jul 13, 2002
78
79
80
/*
* One ZIPinfo is kept for each open ZIP archive.
*/
Jul 28, 2001
Jul 28, 2001
81
82
typedef struct
{
Sep 12, 2016
Sep 12, 2016
83
84
85
86
87
88
PHYSFS_Io *io; /* the i/o interface for this archive. */
ZIPentry root; /* root of directory tree. */
ZIPentry **hash; /* all entries hashed for fast lookup. */
size_t hashBuckets; /* number of buckets in hash. */
int zip64; /* non-zero if this is a Zip64 archive. */
int has_crypto; /* non-zero if any entry uses encryption. */
Jul 15, 2001
Jul 15, 2001
89
90
} ZIPinfo;
Jul 13, 2002
Jul 13, 2002
91
92
93
/*
* One ZIPfileinfo is kept for each open file in a ZIP archive.
*/
Jul 15, 2001
Jul 15, 2001
94
95
typedef struct
{
Jul 13, 2002
Jul 13, 2002
96
ZIPentry *entry; /* Info on file. */
Aug 30, 2010
Aug 30, 2010
97
PHYSFS_Io *io; /* physical file handle. */
Jul 13, 2002
Jul 13, 2002
98
99
100
PHYSFS_uint32 compressed_position; /* offset in compressed data. */
PHYSFS_uint32 uncompressed_position; /* tell() position. */
PHYSFS_uint8 *buffer; /* decompression buffer. */
Sep 12, 2016
Sep 12, 2016
101
102
PHYSFS_uint32 crypto_keys[3]; /* for "traditional" crypto. */
PHYSFS_uint32 initial_crypto_keys[3]; /* for "traditional" crypto. */
Jul 13, 2002
Jul 13, 2002
103
z_stream stream; /* zlib stream state. */
Jul 15, 2001
Jul 15, 2001
104
105
106
} ZIPfileinfo;
Jul 13, 2002
Jul 13, 2002
107
/* Magic numbers... */
Jun 1, 2012
Jun 1, 2012
108
109
110
111
112
113
#define ZIP_LOCAL_FILE_SIG 0x04034b50
#define ZIP_CENTRAL_DIR_SIG 0x02014b50
#define ZIP_END_OF_CENTRAL_DIR_SIG 0x06054b50
#define ZIP64_END_OF_CENTRAL_DIR_SIG 0x06064b50
#define ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG 0x07064b50
#define ZIP64_EXTENDED_INFO_EXTRA_FIELD_SIG 0x0001
Jul 13, 2002
Jul 13, 2002
114
115
116
117
118
119
/* compression methods... */
#define COMPMETH_NONE 0
/* ...and others... */
Jul 15, 2002
Jul 15, 2002
120
121
122
#define UNIX_FILETYPE_MASK 0170000
#define UNIX_FILETYPE_SYMLINK 0120000
Sep 12, 2016
Sep 12, 2016
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#define ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO (1 << 0)
#define ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER (1 << 3)
/* support for "traditional" PKWARE encryption. */
static int zip_entry_is_tradional_crypto(const ZIPentry *entry)
{
return (entry->general_bits & ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO) != 0;
} /* zip_entry_is_traditional_crypto */
static int zip_entry_ignore_local_header(const ZIPentry *entry)
{
return (entry->general_bits & ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER) != 0;
} /* zip_entry_is_traditional_crypto */
static PHYSFS_uint32 zip_crypto_crc32(const PHYSFS_uint32 crc, const PHYSFS_uint8 val)
{
int i;
PHYSFS_uint32 xorval = (crc ^ ((PHYSFS_uint32) val)) & 0xFF;
for (i = 0; i < 8; i++)
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
return xorval ^ (crc >> 8);
} /* zip_crc32 */
static void zip_update_crypto_keys(PHYSFS_uint32 *keys, const PHYSFS_uint8 val)
{
keys[0] = zip_crypto_crc32(keys[0], val);
keys[1] = keys[1] + (keys[0] & 0x000000FF);
keys[1] = (keys[1] * 134775813) + 1;
keys[2] = zip_crypto_crc32(keys[2], (PHYSFS_uint8) ((keys[1] >> 24) & 0xFF));
} /* zip_update_crypto_keys */
static PHYSFS_uint8 zip_decrypt_byte(const PHYSFS_uint32 *keys)
{
const PHYSFS_uint16 tmp = keys[2] | 2;
return (PHYSFS_uint8) ((tmp * (tmp ^ 1)) >> 8);
} /* zip_decrypt_byte */
static PHYSFS_sint64 zip_read_decrypt(ZIPfileinfo *finfo, void *buf, PHYSFS_uint64 len)
{
PHYSFS_Io *io = finfo->io;
const PHYSFS_sint64 br = io->read(io, buf, len);
/* Decompression the new data if necessary. */
if (zip_entry_is_tradional_crypto(finfo->entry) && (br > 0))
{
PHYSFS_uint32 *keys = finfo->crypto_keys;
PHYSFS_uint8 *ptr = (PHYSFS_uint8 *) buf;
PHYSFS_sint64 i;
for (i = 0; i < br; i++, ptr++)
{
const PHYSFS_uint8 ch = *ptr ^ zip_decrypt_byte(keys);
zip_update_crypto_keys(keys, ch);
*ptr = ch;
} /* for */
} /* if */
return br;
} /* zip_read_decrypt */
static int zip_prep_crypto_keys(ZIPfileinfo *finfo, const PHYSFS_uint8 *crypto_header, const PHYSFS_uint8 *password)
{
/* It doesn't appear to be documented in PKWare's APPNOTE.TXT, but you
need to use a different byte in the header to verify the password
if general purpose bit 3 is set. Discovered this from Info-Zip.
That's what the (verifier) value is doing, below. */
PHYSFS_uint32 *keys = finfo->crypto_keys;
const ZIPentry *entry = finfo->entry;
const int usedate = zip_entry_ignore_local_header(entry);
const PHYSFS_uint8 verifier = (PHYSFS_uint8) ((usedate ? (entry->dos_mod_time >> 8) : (entry->crc >> 24)) & 0xFF);
PHYSFS_uint8 finalbyte = 0;
int i = 0;
/* initialize vector with defaults, then password, then header. */
keys[0] = 305419896;
keys[1] = 591751049;
keys[2] = 878082192;
while (*password)
zip_update_crypto_keys(keys, *(password++));
for (i = 0; i < 12; i++)
{
const PHYSFS_uint8 c = crypto_header[i] ^ zip_decrypt_byte(keys);
zip_update_crypto_keys(keys, c);
finalbyte = c;
} /* for */
/* you have a 1/256 chance of passing this test incorrectly. :/ */
if (finalbyte != verifier)
Jul 6, 2017
Jul 6, 2017
213
BAIL(PHYSFS_ERR_BAD_PASSWORD, 0);
Sep 12, 2016
Sep 12, 2016
214
215
216
217
218
219
/* save the initial vector for seeking purposes. Not secure!! */
memcpy(finfo->initial_crypto_keys, finfo->crypto_keys, 12);
return 1;
} /* zip_prep_crypto_keys */
Jul 15, 2002
Jul 15, 2002
220
Sep 23, 2004
Sep 23, 2004
221
222
223
224
225
/*
* Bridge physfs allocation functions to zlib's format...
*/
static voidpf zlibPhysfsAlloc(voidpf opaque, uInt items, uInt size)
{
Jan 28, 2010
Jan 28, 2010
226
return ((PHYSFS_Allocator *) opaque)->Malloc(items * size);
Sep 23, 2004
Sep 23, 2004
227
228
229
230
231
232
233
} /* zlibPhysfsAlloc */
/*
* Bridge physfs allocation functions to zlib's format...
*/
static void zlibPhysfsFree(voidpf opaque, voidpf address)
{
Mar 14, 2005
Mar 14, 2005
234
((PHYSFS_Allocator *) opaque)->Free(address);
Sep 23, 2004
Sep 23, 2004
235
236
237
238
239
240
241
242
243
244
245
} /* zlibPhysfsFree */
/*
* Construct a new z_stream to a sane state.
*/
static void initializeZStream(z_stream *pstr)
{
memset(pstr, '\0', sizeof (z_stream));
pstr->zalloc = zlibPhysfsAlloc;
pstr->zfree = zlibPhysfsFree;
Mar 14, 2005
Mar 14, 2005
246
pstr->opaque = &allocator;
Sep 23, 2004
Sep 23, 2004
247
248
249
} /* initializeZStream */
Mar 20, 2012
Mar 20, 2012
250
static PHYSFS_ErrorCode zlib_error_code(int rc)
Jul 13, 2002
Jul 13, 2002
251
252
253
{
switch (rc)
{
Mar 20, 2012
Mar 20, 2012
254
255
256
257
258
case Z_OK: return PHYSFS_ERR_OK; /* not an error. */
case Z_STREAM_END: return PHYSFS_ERR_OK; /* not an error. */
case Z_ERRNO: return PHYSFS_ERR_IO;
case Z_MEM_ERROR: return PHYSFS_ERR_OUT_OF_MEMORY;
default: return PHYSFS_ERR_CORRUPT;
Jul 13, 2002
Jul 13, 2002
259
} /* switch */
Jul 28, 2002
Jul 28, 2002
260
261
} /* zlib_error_string */
Jul 13, 2002
Jul 13, 2002
262
Jul 28, 2002
Jul 28, 2002
263
264
265
/*
* Wrap all zlib calls in this, so the physfs error state is set appropriately.
*/
Mar 20, 2012
Mar 20, 2012
266
static int zlib_err(const int rc)
Jul 28, 2002
Jul 28, 2002
267
{
Nov 30, 2012
Nov 30, 2012
268
PHYSFS_setErrorCode(zlib_error_code(rc));
Jan 28, 2010
Jan 28, 2010
269
return rc;
Jul 13, 2002
Jul 13, 2002
270
271
} /* zlib_err */
Feb 25, 2016
Feb 25, 2016
272
273
274
275
276
277
278
/*
* Hash a string for lookup an a ZIPinfo hashtable.
*/
static inline PHYSFS_uint32 zip_hash_string(const ZIPinfo *info, const char *s)
{
return __PHYSFS_hashString(s, strlen(s)) % info->hashBuckets;
} /* zip_hash_string */
Jul 13, 2002
Jul 13, 2002
279
Jun 1, 2012
Jun 1, 2012
280
281
282
283
284
285
/*
* Read an unsigned 64-bit int and swap to native byte order.
*/
static int readui64(PHYSFS_Io *io, PHYSFS_uint64 *val)
{
PHYSFS_uint64 v;
Jul 6, 2017
Jul 6, 2017
286
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jun 1, 2012
Jun 1, 2012
287
288
289
290
*val = PHYSFS_swapULE64(v);
return 1;
} /* readui64 */
Jul 13, 2002
Jul 13, 2002
291
292
293
/*
* Read an unsigned 32-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
294
static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
Jul 13, 2002
Jul 13, 2002
295
296
{
PHYSFS_uint32 v;
Jul 6, 2017
Jul 6, 2017
297
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
298
*val = PHYSFS_swapULE32(v);
Jan 28, 2010
Jan 28, 2010
299
return 1;
Jul 13, 2002
Jul 13, 2002
300
301
302
303
304
305
} /* readui32 */
/*
* Read an unsigned 16-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
306
static int readui16(PHYSFS_Io *io, PHYSFS_uint16 *val)
Jul 13, 2002
Jul 13, 2002
307
308
{
PHYSFS_uint16 v;
Jul 6, 2017
Jul 6, 2017
309
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
310
*val = PHYSFS_swapULE16(v);
Jan 28, 2010
Jan 28, 2010
311
return 1;
Jul 13, 2002
Jul 13, 2002
312
313
314
} /* readui16 */
Aug 30, 2010
Aug 30, 2010
315
static PHYSFS_sint64 ZIP_read(PHYSFS_Io *_io, void *buf, PHYSFS_uint64 len)
Jul 8, 2001
Jul 8, 2001
316
{
Aug 30, 2010
Aug 30, 2010
317
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
318
319
ZIPentry *entry = finfo->entry;
PHYSFS_sint64 retval = 0;
Aug 21, 2010
Aug 21, 2010
320
PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
Jul 13, 2002
Jul 13, 2002
321
322
323
324
PHYSFS_sint64 avail = entry->uncompressed_size -
finfo->uncompressed_position;
if (avail < maxread)
Aug 21, 2010
Aug 21, 2010
325
maxread = avail;
Jul 13, 2002
Jul 13, 2002
326
Jul 6, 2017
Jul 6, 2017
327
BAIL_IF_ERRPASS(maxread == 0, 0); /* quick rejection. */
Jul 13, 2002
Jul 13, 2002
328
Aug 21, 2010
Aug 21, 2010
329
if (entry->compression_method == COMPMETH_NONE)
Sep 12, 2016
Sep 12, 2016
330
retval = zip_read_decrypt(finfo, buf, maxread);
Jul 13, 2002
Jul 13, 2002
331
332
333
else
{
finfo->stream.next_out = buf;
Mar 10, 2012
Mar 10, 2012
334
finfo->stream.avail_out = (uInt) maxread;
Jul 13, 2002
Jul 13, 2002
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
while (retval < maxread)
{
PHYSFS_uint32 before = finfo->stream.total_out;
int rc;
if (finfo->stream.avail_in == 0)
{
PHYSFS_sint64 br;
br = entry->compressed_size - finfo->compressed_position;
if (br > 0)
{
if (br > ZIP_READBUFSIZE)
br = ZIP_READBUFSIZE;
Sep 12, 2016
Sep 12, 2016
351
br = zip_read_decrypt(finfo, finfo->buffer, (PHYSFS_uint64) br);
Jul 13, 2002
Jul 13, 2002
352
353
354
if (br <= 0)
break;
Mar 12, 2003
Mar 12, 2003
355
finfo->compressed_position += (PHYSFS_uint32) br;
Jul 13, 2002
Jul 13, 2002
356
finfo->stream.next_in = finfo->buffer;
Mar 12, 2003
Mar 12, 2003
357
finfo->stream.avail_in = (PHYSFS_uint32) br;
Jul 13, 2002
Jul 13, 2002
358
359
} /* if */
} /* if */
Jul 23, 2001
Jul 23, 2001
360
Jul 13, 2002
Jul 13, 2002
361
362
rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH));
retval += (finfo->stream.total_out - before);
Jul 23, 2001
Jul 23, 2001
363
Jul 13, 2002
Jul 13, 2002
364
365
366
367
368
369
if (rc != Z_OK)
break;
} /* while */
} /* else */
if (retval > 0)
Aug 21, 2010
Aug 21, 2010
370
finfo->uncompressed_position += (PHYSFS_uint32) retval;
Jul 13, 2002
Jul 13, 2002
371
Jan 28, 2010
Jan 28, 2010
372
return retval;
Jul 8, 2001
Jul 8, 2001
373
374
375
} /* ZIP_read */
Aug 30, 2010
Aug 30, 2010
376
static PHYSFS_sint64 ZIP_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
Aug 21, 2002
Aug 21, 2002
377
{
Jul 6, 2017
Jul 6, 2017
378
BAIL(PHYSFS_ERR_READ_ONLY, -1);
Aug 21, 2002
Aug 21, 2002
379
380
381
} /* ZIP_write */
Aug 30, 2010
Aug 30, 2010
382
static PHYSFS_sint64 ZIP_tell(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
383
{
Aug 30, 2010
Aug 30, 2010
384
return ((ZIPfileinfo *) io->opaque)->uncompressed_position;
Jul 8, 2001
Jul 8, 2001
385
386
387
} /* ZIP_tell */
Aug 30, 2010
Aug 30, 2010
388
static int ZIP_seek(PHYSFS_Io *_io, PHYSFS_uint64 offset)
Jul 8, 2001
Jul 8, 2001
389
{
Aug 30, 2010
Aug 30, 2010
390
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
391
ZIPentry *entry = finfo->entry;
Aug 30, 2010
Aug 30, 2010
392
PHYSFS_Io *io = finfo->io;
Sep 12, 2016
Sep 12, 2016
393
const int encrypted = zip_entry_is_tradional_crypto(entry);
Jul 23, 2001
Jul 23, 2001
394
Jul 6, 2017
Jul 6, 2017
395
BAIL_IF(offset > entry->uncompressed_size, PHYSFS_ERR_PAST_EOF, 0);
Jul 23, 2001
Jul 23, 2001
396
Sep 12, 2016
Sep 12, 2016
397
if (!encrypted && (entry->compression_method == COMPMETH_NONE))
Jul 23, 2001
Jul 23, 2001
398
{
Sep 12, 2016
Sep 12, 2016
399
PHYSFS_sint64 newpos = offset + entry->offset;
Jul 6, 2017
Jul 6, 2017
400
BAIL_IF_ERRPASS(!io->seek(io, newpos), 0);
Mar 30, 2003
Mar 30, 2003
401
finfo->uncompressed_position = (PHYSFS_uint32) offset;
Jul 13, 2002
Jul 13, 2002
402
} /* if */
Jul 23, 2001
Jul 23, 2001
403
Jul 13, 2002
Jul 13, 2002
404
else
Jul 23, 2001
Jul 23, 2001
405
{
Jul 13, 2002
Jul 13, 2002
406
407
408
409
/*
* If seeking backwards, we need to redecode the file
* from the start and throw away the compressed bits until we hit
* the offset we need. If seeking forward, we still need to
Jul 23, 2002
Jul 23, 2002
410
* decode, but we don't rewind first.
Jul 13, 2002
Jul 13, 2002
411
412
413
414
415
*/
if (offset < finfo->uncompressed_position)
{
/* we do a copy so state is sane if inflateInit2() fails. */
z_stream str;
Sep 23, 2004
Sep 23, 2004
416
initializeZStream(&str);
Jul 13, 2002
Jul 13, 2002
417
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
Jan 28, 2010
Jan 28, 2010
418
return 0;
Jul 13, 2002
Jul 13, 2002
419
Sep 12, 2016
Sep 12, 2016
420
if (!io->seek(io, entry->offset + (encrypted ? 12 : 0)))
Jan 28, 2010
Jan 28, 2010
421
return 0;
Jul 17, 2002
Jul 17, 2002
422
Jul 13, 2002
Jul 13, 2002
423
424
425
inflateEnd(&finfo->stream);
memcpy(&finfo->stream, &str, sizeof (z_stream));
finfo->uncompressed_position = finfo->compressed_position = 0;
Sep 12, 2016
Sep 12, 2016
426
427
428
if (encrypted)
memcpy(finfo->crypto_keys, finfo->initial_crypto_keys, 12);
Jul 13, 2002
Jul 13, 2002
429
430
431
432
433
} /* if */
while (finfo->uncompressed_position != offset)
{
PHYSFS_uint8 buf[512];
Mar 12, 2003
Mar 12, 2003
434
435
436
PHYSFS_uint32 maxread;
maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position);
Jul 13, 2002
Jul 13, 2002
437
438
439
if (maxread > sizeof (buf))
maxread = sizeof (buf);
Aug 30, 2010
Aug 30, 2010
440
if (ZIP_read(_io, buf, maxread) != maxread)
Jan 28, 2010
Jan 28, 2010
441
return 0;
Jul 13, 2002
Jul 13, 2002
442
443
444
} /* while */
} /* else */
Jan 28, 2010
Jan 28, 2010
445
return 1;
Jul 8, 2001
Jul 8, 2001
446
447
448
} /* ZIP_seek */
Aug 30, 2010
Aug 30, 2010
449
static PHYSFS_sint64 ZIP_length(PHYSFS_Io *io)
Jul 9, 2001
Jul 9, 2001
450
{
Aug 30, 2010
Aug 30, 2010
451
const ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
Jun 1, 2012
Jun 1, 2012
452
return (PHYSFS_sint64) finfo->entry->uncompressed_size;
Aug 30, 2010
Aug 30, 2010
453
} /* ZIP_length */
Jul 9, 2001
Jul 9, 2001
454
455
Aug 30, 2010
Aug 30, 2010
456
457
458
static PHYSFS_Io *zip_get_io(PHYSFS_Io *io, ZIPinfo *inf, ZIPentry *entry);
static PHYSFS_Io *ZIP_duplicate(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
459
{
Aug 30, 2010
Aug 30, 2010
460
461
462
ZIPfileinfo *origfinfo = (ZIPfileinfo *) io->opaque;
PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
ZIPfileinfo *finfo = (ZIPfileinfo *) allocator.Malloc(sizeof (ZIPfileinfo));
Jul 6, 2017
Jul 6, 2017
463
464
GOTO_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, failed);
GOTO_IF(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Aug 30, 2010
Aug 30, 2010
465
466
467
468
memset(finfo, '\0', sizeof (*finfo));
finfo->entry = origfinfo->entry;
finfo->io = zip_get_io(origfinfo->io, NULL, finfo->entry);
Jul 6, 2017
Jul 6, 2017
469
GOTO_IF_ERRPASS(!finfo->io, failed);
Aug 30, 2010
Aug 30, 2010
470
471
472
473
if (finfo->entry->compression_method != COMPMETH_NONE)
{
finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE);
Jul 6, 2017
Jul 6, 2017
474
GOTO_IF(!finfo->buffer, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Mar 24, 2012
Mar 24, 2012
475
476
if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
goto failed;
Aug 30, 2010
Aug 30, 2010
477
478
479
480
481
482
} /* if */
memcpy(retval, io, sizeof (PHYSFS_Io));
retval->opaque = finfo;
return retval;
Mar 24, 2012
Mar 24, 2012
483
failed:
Aug 30, 2010
Aug 30, 2010
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
if (finfo != NULL)
{
if (finfo->io != NULL)
finfo->io->destroy(finfo->io);
if (finfo->buffer != NULL)
{
allocator.Free(finfo->buffer);
inflateEnd(&finfo->stream);
} /* if */
allocator.Free(finfo);
} /* if */
if (retval != NULL)
allocator.Free(retval);
return NULL;
} /* ZIP_duplicate */
static int ZIP_flush(PHYSFS_Io *io) { return 1; /* no write support. */ }
static void ZIP_destroy(PHYSFS_Io *io)
{
ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
finfo->io->destroy(finfo->io);
Jul 13, 2002
Jul 13, 2002
510
511
512
513
514
if (finfo->entry->compression_method != COMPMETH_NONE)
inflateEnd(&finfo->stream);
if (finfo->buffer != NULL)
Mar 14, 2005
Mar 14, 2005
515
allocator.Free(finfo->buffer);
Jul 13, 2002
Jul 13, 2002
516
Mar 14, 2005
Mar 14, 2005
517
allocator.Free(finfo);
Aug 30, 2010
Aug 30, 2010
518
519
520
521
522
523
allocator.Free(io);
} /* ZIP_destroy */
static const PHYSFS_Io ZIP_Io =
{
Mar 25, 2012
Mar 25, 2012
524
CURRENT_PHYSFS_IO_API_VERSION, NULL,
Aug 30, 2010
Aug 30, 2010
525
526
527
528
529
530
531
ZIP_read,
ZIP_write,
ZIP_seek,
ZIP_tell,
ZIP_length,
ZIP_duplicate,
ZIP_flush,
Mar 25, 2012
Mar 25, 2012
532
ZIP_destroy
Aug 30, 2010
Aug 30, 2010
533
534
};
Jul 8, 2001
Jul 8, 2001
535
536
Aug 30, 2010
Aug 30, 2010
537
static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *len)
Jul 13, 2002
Jul 13, 2002
538
{
Jul 23, 2002
Jul 23, 2002
539
PHYSFS_uint8 buf[256];
Mar 25, 2010
Mar 25, 2010
540
PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 };
Jul 27, 2002
Jul 27, 2002
541
PHYSFS_sint32 i = 0;
Jul 13, 2002
Jul 13, 2002
542
543
544
PHYSFS_sint64 filelen;
PHYSFS_sint64 filepos;
PHYSFS_sint32 maxread;
Jul 23, 2002
Jul 23, 2002
545
546
PHYSFS_sint32 totalread = 0;
int found = 0;
Jul 13, 2002
Jul 13, 2002
547
Aug 30, 2010
Aug 30, 2010
548
filelen = io->length(io);
Jul 6, 2017
Jul 6, 2017
549
BAIL_IF_ERRPASS(filelen == -1, -1);
Jul 13, 2002
Jul 13, 2002
550
551
552
553
554
555
556
557
558
/*
* Jump to the end of the file and start reading backwards.
* The last thing in the file is the zipfile comment, which is variable
* length, and the field that specifies its size is before it in the
* file (argh!)...this means that we need to scan backwards until we
* hit the end-of-central-dir signature. We can then sanity check that
* the comment was as big as it should be to make sure we're in the
* right place. The comment length field is 16 bits, so we can stop
Jul 23, 2002
Jul 23, 2002
559
560
* searching for that signature after a little more than 64k at most,
* and call it a corrupted zipfile.
Jul 13, 2002
Jul 13, 2002
561
562
563
564
565
566
567
568
569
570
*/
if (sizeof (buf) < filelen)
{
filepos = filelen - sizeof (buf);
maxread = sizeof (buf);
} /* if */
else
{
filepos = 0;
Mar 12, 2003
Mar 12, 2003
571
maxread = (PHYSFS_uint32) filelen;
Jul 13, 2002
Jul 13, 2002
572
573
} /* else */
Jul 23, 2002
Jul 23, 2002
574
while ((totalread < filelen) && (totalread < 65557))
Jul 13, 2002
Jul 13, 2002
575
{
Jul 6, 2017
Jul 6, 2017
576
BAIL_IF_ERRPASS(!io->seek(io, filepos), -1);
Jul 23, 2002
Jul 23, 2002
577
578
579
/* make sure we catch a signature between buffers. */
if (totalread != 0)
Jul 13, 2002
Jul 13, 2002
580
{
Mar 9, 2012
Mar 9, 2012
581
if (!__PHYSFS_readAll(io, buf, maxread - 4))
Jan 28, 2010
Jan 28, 2010
582
return -1;
May 3, 2009
May 3, 2009
583
memcpy(&buf[maxread - 4], &extra, sizeof (extra));
Jul 23, 2002
Jul 23, 2002
584
totalread += maxread - 4;
Jul 13, 2002
Jul 13, 2002
585
} /* if */
Jul 23, 2002
Jul 23, 2002
586
587
else
{
Mar 9, 2012
Mar 9, 2012
588
if (!__PHYSFS_readAll(io, buf, maxread))
Jan 28, 2010
Jan 28, 2010
589
return -1;
Jul 23, 2002
Jul 23, 2002
590
591
592
totalread += maxread;
} /* else */
May 3, 2009
May 3, 2009
593
memcpy(&extra, buf, sizeof (extra));
Jul 13, 2002
Jul 13, 2002
594
Jul 23, 2002
Jul 23, 2002
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
for (i = maxread - 4; i > 0; i--)
{
if ((buf[i + 0] == 0x50) &&
(buf[i + 1] == 0x4B) &&
(buf[i + 2] == 0x05) &&
(buf[i + 3] == 0x06) )
{
found = 1; /* that's the signature! */
break;
} /* if */
} /* for */
if (found)
break;
filepos -= (maxread - 4);
May 5, 2007
May 5, 2007
611
612
if (filepos < 0)
filepos = 0;
Jul 23, 2002
Jul 23, 2002
613
614
} /* while */
Jul 6, 2017
Jul 6, 2017
615
BAIL_IF(!found, PHYSFS_ERR_UNSUPPORTED, -1);
Jul 13, 2002
Jul 13, 2002
616
617
618
619
if (len != NULL)
*len = filelen;
Jan 28, 2010
Jan 28, 2010
620
return (filepos + i);
Jul 23, 2002
Jul 23, 2002
621
} /* zip_find_end_of_central_dir */
Jul 13, 2002
Jul 13, 2002
622
623
Aug 30, 2010
Aug 30, 2010
624
static int isZip(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
625
{
Aug 30, 2010
Aug 30, 2010
626
PHYSFS_uint32 sig = 0;
Jul 31, 2002
Jul 31, 2002
627
int retval = 0;
Jul 13, 2002
Jul 13, 2002
628
629
630
631
632
/*
* The first thing in a zip file might be the signature of the
* first local file record, so it makes for a quick determination.
*/
Aug 30, 2010
Aug 30, 2010
633
if (readui32(io, &sig))
Jul 15, 2001
Jul 15, 2001
634
{
Jul 31, 2002
Jul 31, 2002
635
636
637
638
639
640
641
642
retval = (sig == ZIP_LOCAL_FILE_SIG);
if (!retval)
{
/*
* No sig...might be a ZIP with data at the start
* (a self-extracting executable, etc), so we'll have to do
* it the hard way...
*/
Aug 30, 2010
Aug 30, 2010
643
retval = (zip_find_end_of_central_dir(io, NULL) != -1);
Jul 31, 2002
Jul 31, 2002
644
} /* if */
Jul 15, 2001
Jul 15, 2001
645
646
} /* if */
Jan 28, 2010
Jan 28, 2010
647
return retval;
Aug 24, 2010
Aug 24, 2010
648
} /* isZip */
Jul 8, 2001
Jul 8, 2001
649
650
Feb 25, 2016
Feb 25, 2016
651
652
/* Find the ZIPentry for a path in platform-independent notation. */
static ZIPentry *zip_find_entry(ZIPinfo *info, const char *path)
Jul 13, 2002
Jul 13, 2002
653
{
Feb 25, 2016
Feb 25, 2016
654
655
656
PHYSFS_uint32 hashval;
ZIPentry *prev = NULL;
ZIPentry *retval;
Jul 23, 2002
Jul 23, 2002
657
Feb 25, 2016
Feb 25, 2016
658
659
if (*path == '\0')
return &info->root;
Jul 23, 2002
Jul 23, 2002
660
Feb 25, 2016
Feb 25, 2016
661
662
hashval = zip_hash_string(info, path);
for (retval = info->hash[hashval]; retval; retval = retval->hashnext)
Jul 23, 2002
Jul 23, 2002
663
{
Feb 25, 2016
Feb 25, 2016
664
if (strcmp(retval->name, path) == 0)
Aug 30, 2002
Aug 30, 2002
665
{
Feb 25, 2016
Feb 25, 2016
666
if (prev != NULL) /* move this to the front of the list */
Aug 28, 2002
Aug 28, 2002
667
{
Feb 25, 2016
Feb 25, 2016
668
669
670
prev->hashnext = retval->hashnext;
retval->hashnext = info->hash[hashval];
info->hash[hashval] = retval;
Aug 28, 2002
Aug 28, 2002
671
672
} /* if */
Feb 25, 2016
Feb 25, 2016
673
return retval;
Aug 30, 2002
Aug 30, 2002
674
} /* if */
Aug 28, 2002
Aug 28, 2002
675
Feb 25, 2016
Feb 25, 2016
676
677
prev = retval;
} /* for */
Jul 23, 2002
Jul 23, 2002
678
Jul 6, 2017
Jul 6, 2017
679
BAIL(PHYSFS_ERR_NOT_FOUND, NULL);
Jul 23, 2002
Jul 23, 2002
680
} /* zip_find_entry */
Jul 13, 2002
Jul 13, 2002
681
682
Jul 23, 2002
Jul 23, 2002
683
684
685
686
687
688
689
690
691
692
693
694
695
696
/* Convert paths from old, buggy DOS zippers... */
static void zip_convert_dos_path(ZIPentry *entry, char *path)
{
PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((entry->version >> 8) & 0xFF);
if (hosttype == 0) /* FS_FAT_ */
{
while (*path)
{
if (*path == '\\')
*path = '/';
path++;
} /* while */
} /* if */
} /* zip_convert_dos_path */
Jul 13, 2002
Jul 13, 2002
697
698
Jul 23, 2002
Jul 23, 2002
699
static void zip_expand_symlink_path(char *path)
Jul 8, 2001
Jul 8, 2001
700
{
Jul 23, 2002
Jul 23, 2002
701
702
char *ptr = path;
char *prevptr = path;
Jul 15, 2001
Jul 15, 2001
703
Jul 23, 2002
Jul 23, 2002
704
while (1)
Jul 28, 2001
Jul 28, 2001
705
{
Jul 23, 2002
Jul 23, 2002
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
ptr = strchr(ptr, '/');
if (ptr == NULL)
break;
if (*(ptr + 1) == '.')
{
if (*(ptr + 2) == '/')
{
/* current dir in middle of string: ditch it. */
memmove(ptr, ptr + 2, strlen(ptr + 2) + 1);
} /* else if */
else if (*(ptr + 2) == '\0')
{
/* current dir at end of string: ditch it. */
*ptr = '\0';
} /* else if */
else if (*(ptr + 2) == '.')
{
if (*(ptr + 3) == '/')
{
/* parent dir in middle: move back one, if possible. */
memmove(prevptr, ptr + 4, strlen(ptr + 4) + 1);
ptr = prevptr;
while (prevptr != path)
{
prevptr--;
if (*prevptr == '/')
{
prevptr++;
break;
} /* if */
} /* while */
} /* if */
Jul 15, 2001
Jul 15, 2001
741
Jul 23, 2002
Jul 23, 2002
742
743
744
745
746
747
748
749
750
751
if (*(ptr + 3) == '\0')
{
/* parent dir at end: move back one, if possible. */
*prevptr = '\0';
} /* if */
} /* if */
} /* if */
else
{
prevptr = ptr;
Jun 1, 2011
Jun 1, 2011
752
ptr++;
Jul 23, 2002
Jul 23, 2002
753
754
755
} /* else */
} /* while */
} /* zip_expand_symlink_path */
Jul 15, 2001
Jul 15, 2001
756
Sep 29, 2004
Sep 29, 2004
757
/* (forward reference: zip_follow_symlink and zip_resolve call each other.) */
Aug 30, 2010
Aug 30, 2010
758
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry);
Jul 15, 2001
Jul 15, 2001
759
Mar 29, 2002
Mar 29, 2002
760
/*
Jul 23, 2002
Jul 23, 2002
761
762
763
* Look for the entry named by (path). If it exists, resolve it, and return
* a pointer to that entry. If it's another symlink, keep resolving until you
* hit a real file and then return a pointer to the final non-symlink entry.
Mar 24, 2012
Mar 24, 2012
764
* If there's a problem, return NULL.
Mar 29, 2002
Mar 29, 2002
765
*/
Aug 30, 2010
Aug 30, 2010
766
static ZIPentry *zip_follow_symlink(PHYSFS_Io *io, ZIPinfo *info, char *path)
Jul 28, 2001
Jul 28, 2001
767
{
Jul 23, 2002
Jul 23, 2002
768
769
770
ZIPentry *entry;
zip_expand_symlink_path(path);
Feb 25, 2016
Feb 25, 2016
771
entry = zip_find_entry(info, path);
Jul 23, 2002
Jul 23, 2002
772
773
if (entry != NULL)
{
Aug 30, 2010
Aug 30, 2010
774
if (!zip_resolve(io, info, entry)) /* recursive! */
Jul 23, 2002
Jul 23, 2002
775
776
777
778
779
780
781
782
entry = NULL;
else
{
if (entry->symlink != NULL)
entry = entry->symlink;
} /* else */
} /* if */
Jan 28, 2010
Jan 28, 2010
783
return entry;
Jul 23, 2002
Jul 23, 2002
784
} /* zip_follow_symlink */
Jul 8, 2001
Jul 8, 2001
785
786
Aug 30, 2010
Aug 30, 2010
787
static int zip_resolve_symlink(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2001
Jul 23, 2001
788
{
Jun 1, 2012
Jun 1, 2012
789
const PHYSFS_uint64 size = entry->uncompressed_size;
Mar 24, 2012
Mar 24, 2012
790
char *path = NULL;
Jul 13, 2002
Jul 13, 2002
791
792
int rc = 0;
Jul 23, 2002
Jul 23, 2002
793
794
795
796
797
798
/*
* We've already parsed the local file header of the symlink at this
* point. Now we need to read the actual link from the file data and
* follow it.
*/
Jul 6, 2017
Jul 6, 2017
799
BAIL_IF_ERRPASS(!io->seek(io, entry->offset), 0);
Jul 23, 2002
Jul 23, 2002
800
Mar 24, 2012
Mar 24, 2012
801
path = (char *) __PHYSFS_smallAlloc(size + 1);
Jul 6, 2017
Jul 6, 2017
802
BAIL_IF(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0);
Jul 13, 2002
Jul 13, 2002
803
804
if (entry->compression_method == COMPMETH_NONE)
Mar 9, 2012
Mar 9, 2012
805
rc = __PHYSFS_readAll(io, path, size);
Jul 13, 2002
Jul 13, 2002
806
807
808
809
else /* symlink target path is compressed... */
{
z_stream stream;
Jun 1, 2012
Jun 1, 2012
810
const PHYSFS_uint64 complen = entry->compressed_size;
Mar 24, 2007
Mar 24, 2007
811
PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
Jul 13, 2002
Jul 13, 2002
812
813
if (compressed != NULL)
{
Mar 9, 2012
Mar 9, 2012
814
if (__PHYSFS_readAll(io, compressed, complen))
Jul 13, 2002
Jul 13, 2002
815
{
Sep 23, 2004
Sep 23, 2004
816
initializeZStream(&stream);
Jul 13, 2002
Jul 13, 2002
817
stream.next_in = compressed;
Mar 24, 2007
Mar 24, 2007
818
stream.avail_in = complen;
Jan 31, 2003
Jan 31, 2003
819
stream.next_out = (unsigned char *) path;
Jul 13, 2002
Jul 13, 2002
820
821
822
stream.avail_out = size;
if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
{
Jul 15, 2002
Jul 15, 2002
823
rc = zlib_err(inflate(&stream, Z_FINISH));
Jul 13, 2002
Jul 13, 2002
824
inflateEnd(&stream);
Jul 15, 2002
Jul 15, 2002
825
826
827
/* both are acceptable outcomes... */
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
Jul 13, 2002
Jul 13, 2002
828
829
} /* if */
} /* if */
Mar 24, 2007
Mar 24, 2007
830
__PHYSFS_smallFree(compressed);
Jul 13, 2002
Jul 13, 2002
831
832
} /* if */
} /* else */
Mar 29, 2002
Mar 29, 2002
833
Mar 24, 2012
Mar 24, 2012
834
if (rc)
Jul 23, 2002
Jul 23, 2002
835
836
837
{
path[entry->uncompressed_size] = '\0'; /* null-terminate it. */
zip_convert_dos_path(entry, path);
Aug 30, 2010
Aug 30, 2010
838
entry->symlink = zip_follow_symlink(io, info, path);
Jul 23, 2002
Jul 23, 2002
839
840
} /* else */
Mar 24, 2012
Mar 24, 2012
841
842
__PHYSFS_smallFree(path);
Jan 28, 2010
Jan 28, 2010
843
return (entry->symlink != NULL);
Jul 23, 2002
Jul 23, 2002
844
845
846
847
848
849
} /* zip_resolve_symlink */
/*
* Parse the local file header of an entry, and update entry->offset.
*/
Aug 30, 2010
Aug 30, 2010
850
static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
851
852
853
854
855
856
{
PHYSFS_uint32 ui32;
PHYSFS_uint16 ui16;
PHYSFS_uint16 fnamelen;
PHYSFS_uint16 extralen;
Mar 30, 2003
Mar 30, 2003
857
858
859
860
861
/*
* crc and (un)compressed_size are always zero if this is a "JAR"
* archive created with Sun's Java tools, apparently. We only
* consider this archive corrupted if those entries don't match and
* aren't zero. That seems to work well.
Jun 1, 2012
Jun 1, 2012
862
863
* We also ignore a mismatch if the value is 0xFFFFFFFF here, since it's
* possible that's a Zip64 thing.
Mar 30, 2003
Mar 30, 2003
864
865
*/
Sep 12, 2016
Sep 12, 2016
866
867
868
869
/* !!! FIXME: apparently these are zero if general purpose bit 3 is set,
!!! FIXME: which is probably true for Jar files, fwiw, but we don't
!!! FIXME: care about these values anyhow. */
Jul 6, 2017
Jul 6, 2017
870
871
872
873
874
875
876
877
878
879
880
881
882
883
BAIL_IF_ERRPASS(!io->seek(io, entry->offset), 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
BAIL_IF(ui16 != entry->version_needed, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0); /* general bits. */
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
BAIL_IF(ui16 != entry->compression_method, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0); /* date/time */
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != entry->crc), PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != 0xFFFFFFFF) &&
Jun 1, 2012
Jun 1, 2012
884
885
(ui32 != entry->compressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
886
887
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != 0xFFFFFFFF) &&
Jun 1, 2012
Jun 1, 2012
888
889
(ui32 != entry->uncompressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
890
891
BAIL_IF_ERRPASS(!readui16(io, &fnamelen), 0);
BAIL_IF_ERRPASS(!readui16(io, &extralen), 0);
Jul 23, 2002
Jul 23, 2002
892
893
entry->offset += fnamelen + extralen + 30;
Jan 28, 2010
Jan 28, 2010
894
return 1;
Jul 23, 2002
Jul 23, 2002
895
896
897
} /* zip_parse_local */
Aug 30, 2010
Aug 30, 2010
898
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
899
900
{
int retval = 1;
Feb 25, 2016
Feb 25, 2016
901
902
903
904
const ZipResolveType resolve_type = entry->resolved;
if (resolve_type == ZIP_DIRECTORY)
return 1; /* we're good. */
Jul 23, 2002
Jul 23, 2002
905
906
/* Don't bother if we've failed to resolve this entry before. */
Jul 6, 2017
Jul 6, 2017
907
908
BAIL_IF(resolve_type == ZIP_BROKEN_FILE, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF(resolve_type == ZIP_BROKEN_SYMLINK, PHYSFS_ERR_CORRUPT, 0);
Jul 23, 2002
Jul 23, 2002
909
910
/* uhoh...infinite symlink loop! */
Jul 6, 2017
Jul 6, 2017
911
BAIL_IF(resolve_type == ZIP_RESOLVING, PHYSFS_ERR_SYMLINK_LOOP, 0);
Jul 23, 2002
Jul 23, 2002
912
913
914
915
916
917
918
919
920
921
922
923
/*
* We fix up the offset to point to the actual data on the
* first open, since we don't want to seek across the whole file on
* archive open (can be SLOW on large, CD-stored files), but we
* need to check the local file header...not just for corruption,
* but since it stores offset info the central directory does not.
*/
if (resolve_type != ZIP_RESOLVED)
{
entry->resolved = ZIP_RESOLVING;
Aug 30, 2010
Aug 30, 2010
924
retval = zip_parse_local(io, entry);
Jul 23, 2002
Jul 23, 2002
925
926
927
928
929
930
931
932
if (retval)
{
/*
* If it's a symlink, find the original file. This will cause
* resolution of other entries (other symlinks and, eventually,
* the real file) if all goes well.
*/
if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
Aug 30, 2010
Aug 30, 2010
933
retval = zip_resolve_symlink(io, info, entry);
Jul 23, 2002
Jul 23, 2002
934
935
936
937
938
939
} /* if */
if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_SYMLINK);
else if (resolve_type == ZIP_UNRESOLVED_FILE)
entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_FILE);
Jul 13, 2002
Jul 13, 2002
940
} /* if */
Mar 29, 2002
Mar 29, 2002
941
Jan 28, 2010
Jan 28, 2010
942
return retval;
Jul 23, 2002
Jul 23, 2002
943
} /* zip_resolve */
Jul 23, 2001
Jul 23, 2001
944
945
Feb 25, 2016
Feb 25, 2016
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
static int zip_hash_entry(ZIPinfo *info, ZIPentry *entry);
/* Fill in missing parent directories. */
static ZIPentry *zip_hash_ancestors(ZIPinfo *info, char *name)
{
ZIPentry *retval = &info->root;
char *sep = strrchr(name, '/');
if (sep)
{
const size_t namelen = (sep - name) + 1;
*sep = '\0'; /* chop off last piece. */
retval = zip_find_entry(info, name);
*sep = '/';
if (retval != NULL)
{
if (retval->resolved != ZIP_DIRECTORY)
Jul 6, 2017
Jul 6, 2017
965
BAIL(PHYSFS_ERR_CORRUPT, NULL);
Feb 25, 2016
Feb 25, 2016
966
967
968
969
970
return retval; /* already hashed. */
} /* if */
/* okay, this is a new dir. Build and hash us. */
retval = (ZIPentry *) allocator.Malloc(sizeof (ZIPentry) + namelen);
Jul 6, 2017
Jul 6, 2017
971
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Feb 25, 2016
Feb 25, 2016
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
memset(retval, '\0', sizeof (*retval));
retval->name = ((char *) retval) + sizeof (ZIPentry);
memcpy(retval->name, name, namelen);
retval->name[namelen] = '\0';
retval->resolved = ZIP_DIRECTORY;
if (!zip_hash_entry(info, retval))
{
allocator.Free(retval);
return NULL;
} /* if */
} /* else */
return retval;
} /* zip_hash_ancestors */
static int zip_hash_entry(ZIPinfo *info, ZIPentry *entry)
{
PHYSFS_uint32 hashval;
ZIPentry *parent;
assert(!zip_find_entry(info, entry->name)); /* checked elsewhere */
parent = zip_hash_ancestors(info, entry->name);
if (!parent)
return 0;
hashval = zip_hash_string(info, entry->name);
entry->hashnext = info->hash[hashval];