Skip to content

Latest commit

 

History

History
1710 lines (1380 loc) · 53 KB

physfs_archiver_zip.c

File metadata and controls

1710 lines (1380 loc) · 53 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 15, 2017
Jul 15, 2017
60
__PHYSFS_DirTreeEntry tree; /* manages directory tree */
Jul 23, 2002
Jul 23, 2002
61
62
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 */
Jul 28, 2001
Jul 28, 2001
73
74
} ZIPentry;
Jul 13, 2002
Jul 13, 2002
75
76
77
/*
* One ZIPinfo is kept for each open ZIP archive.
*/
Jul 28, 2001
Jul 28, 2001
78
79
typedef struct
{
Jul 15, 2017
Jul 15, 2017
80
__PHYSFS_DirTree tree; /* manages directory tree. */
Sep 12, 2016
Sep 12, 2016
81
82
83
PHYSFS_Io *io; /* the i/o interface for this archive. */
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
84
85
} ZIPinfo;
Jul 13, 2002
Jul 13, 2002
86
87
88
/*
* One ZIPfileinfo is kept for each open file in a ZIP archive.
*/
Jul 15, 2001
Jul 15, 2001
89
90
typedef struct
{
Jul 13, 2002
Jul 13, 2002
91
ZIPentry *entry; /* Info on file. */
Aug 30, 2010
Aug 30, 2010
92
PHYSFS_Io *io; /* physical file handle. */
Jul 13, 2002
Jul 13, 2002
93
94
95
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
96
97
PHYSFS_uint32 crypto_keys[3]; /* for "traditional" crypto. */
PHYSFS_uint32 initial_crypto_keys[3]; /* for "traditional" crypto. */
Jul 13, 2002
Jul 13, 2002
98
z_stream stream; /* zlib stream state. */
Jul 15, 2001
Jul 15, 2001
99
100
101
} ZIPfileinfo;
Jul 13, 2002
Jul 13, 2002
102
/* Magic numbers... */
Jun 1, 2012
Jun 1, 2012
103
104
105
106
107
108
#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
109
110
111
112
113
114
/* compression methods... */
#define COMPMETH_NONE 0
/* ...and others... */
Jul 15, 2002
Jul 15, 2002
115
116
117
#define UNIX_FILETYPE_MASK 0170000
#define UNIX_FILETYPE_SYMLINK 0120000
Sep 12, 2016
Sep 12, 2016
118
119
120
121
122
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
#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
208
BAIL(PHYSFS_ERR_BAD_PASSWORD, 0);
Sep 12, 2016
Sep 12, 2016
209
210
211
212
213
214
/* 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
215
Sep 23, 2004
Sep 23, 2004
216
217
218
219
220
/*
* Bridge physfs allocation functions to zlib's format...
*/
static voidpf zlibPhysfsAlloc(voidpf opaque, uInt items, uInt size)
{
Jan 28, 2010
Jan 28, 2010
221
return ((PHYSFS_Allocator *) opaque)->Malloc(items * size);
Sep 23, 2004
Sep 23, 2004
222
223
224
225
226
227
228
} /* zlibPhysfsAlloc */
/*
* Bridge physfs allocation functions to zlib's format...
*/
static void zlibPhysfsFree(voidpf opaque, voidpf address)
{
Mar 14, 2005
Mar 14, 2005
229
((PHYSFS_Allocator *) opaque)->Free(address);
Sep 23, 2004
Sep 23, 2004
230
231
232
233
234
235
236
237
238
239
240
} /* 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
241
pstr->opaque = &allocator;
Sep 23, 2004
Sep 23, 2004
242
243
244
} /* initializeZStream */
Mar 20, 2012
Mar 20, 2012
245
static PHYSFS_ErrorCode zlib_error_code(int rc)
Jul 13, 2002
Jul 13, 2002
246
247
248
{
switch (rc)
{
Mar 20, 2012
Mar 20, 2012
249
250
251
252
253
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
254
} /* switch */
Jul 28, 2002
Jul 28, 2002
255
256
} /* zlib_error_string */
Jul 13, 2002
Jul 13, 2002
257
Jul 28, 2002
Jul 28, 2002
258
259
260
/*
* Wrap all zlib calls in this, so the physfs error state is set appropriately.
*/
Mar 20, 2012
Mar 20, 2012
261
static int zlib_err(const int rc)
Jul 28, 2002
Jul 28, 2002
262
{
Nov 30, 2012
Nov 30, 2012
263
PHYSFS_setErrorCode(zlib_error_code(rc));
Jan 28, 2010
Jan 28, 2010
264
return rc;
Jul 13, 2002
Jul 13, 2002
265
266
} /* zlib_err */
Jun 1, 2012
Jun 1, 2012
267
268
269
270
271
272
/*
* 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
273
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jun 1, 2012
Jun 1, 2012
274
275
276
277
*val = PHYSFS_swapULE64(v);
return 1;
} /* readui64 */
Jul 13, 2002
Jul 13, 2002
278
279
280
/*
* Read an unsigned 32-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
281
static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
Jul 13, 2002
Jul 13, 2002
282
283
{
PHYSFS_uint32 v;
Jul 6, 2017
Jul 6, 2017
284
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
285
*val = PHYSFS_swapULE32(v);
Jan 28, 2010
Jan 28, 2010
286
return 1;
Jul 13, 2002
Jul 13, 2002
287
288
289
290
291
292
} /* readui32 */
/*
* Read an unsigned 16-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
293
static int readui16(PHYSFS_Io *io, PHYSFS_uint16 *val)
Jul 13, 2002
Jul 13, 2002
294
295
{
PHYSFS_uint16 v;
Jul 6, 2017
Jul 6, 2017
296
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
297
*val = PHYSFS_swapULE16(v);
Jan 28, 2010
Jan 28, 2010
298
return 1;
Jul 13, 2002
Jul 13, 2002
299
300
301
} /* readui16 */
Aug 30, 2010
Aug 30, 2010
302
static PHYSFS_sint64 ZIP_read(PHYSFS_Io *_io, void *buf, PHYSFS_uint64 len)
Jul 8, 2001
Jul 8, 2001
303
{
Aug 30, 2010
Aug 30, 2010
304
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
305
306
ZIPentry *entry = finfo->entry;
PHYSFS_sint64 retval = 0;
Aug 21, 2010
Aug 21, 2010
307
PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
Jul 13, 2002
Jul 13, 2002
308
309
310
311
PHYSFS_sint64 avail = entry->uncompressed_size -
finfo->uncompressed_position;
if (avail < maxread)
Aug 21, 2010
Aug 21, 2010
312
maxread = avail;
Jul 13, 2002
Jul 13, 2002
313
Jul 6, 2017
Jul 6, 2017
314
BAIL_IF_ERRPASS(maxread == 0, 0); /* quick rejection. */
Jul 13, 2002
Jul 13, 2002
315
Aug 21, 2010
Aug 21, 2010
316
if (entry->compression_method == COMPMETH_NONE)
Sep 12, 2016
Sep 12, 2016
317
retval = zip_read_decrypt(finfo, buf, maxread);
Jul 13, 2002
Jul 13, 2002
318
319
320
else
{
finfo->stream.next_out = buf;
Mar 10, 2012
Mar 10, 2012
321
finfo->stream.avail_out = (uInt) maxread;
Jul 13, 2002
Jul 13, 2002
322
323
324
while (retval < maxread)
{
Jul 26, 2017
Jul 26, 2017
325
const PHYSFS_uint32 before = (PHYSFS_uint32) finfo->stream.total_out;
Jul 13, 2002
Jul 13, 2002
326
327
328
329
330
331
332
333
334
335
336
337
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
338
br = zip_read_decrypt(finfo, finfo->buffer, (PHYSFS_uint64) br);
Jul 13, 2002
Jul 13, 2002
339
340
341
if (br <= 0)
break;
Mar 12, 2003
Mar 12, 2003
342
finfo->compressed_position += (PHYSFS_uint32) br;
Jul 13, 2002
Jul 13, 2002
343
finfo->stream.next_in = finfo->buffer;
Jul 13, 2017
Jul 13, 2017
344
finfo->stream.avail_in = (unsigned int) br;
Jul 13, 2002
Jul 13, 2002
345
346
} /* if */
} /* if */
Jul 23, 2001
Jul 23, 2001
347
Jul 13, 2002
Jul 13, 2002
348
349
rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH));
retval += (finfo->stream.total_out - before);
Jul 23, 2001
Jul 23, 2001
350
Jul 13, 2002
Jul 13, 2002
351
352
353
354
355
356
if (rc != Z_OK)
break;
} /* while */
} /* else */
if (retval > 0)
Aug 21, 2010
Aug 21, 2010
357
finfo->uncompressed_position += (PHYSFS_uint32) retval;
Jul 13, 2002
Jul 13, 2002
358
Jan 28, 2010
Jan 28, 2010
359
return retval;
Jul 8, 2001
Jul 8, 2001
360
361
362
} /* ZIP_read */
Aug 30, 2010
Aug 30, 2010
363
static PHYSFS_sint64 ZIP_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
Aug 21, 2002
Aug 21, 2002
364
{
Jul 6, 2017
Jul 6, 2017
365
BAIL(PHYSFS_ERR_READ_ONLY, -1);
Aug 21, 2002
Aug 21, 2002
366
367
368
} /* ZIP_write */
Aug 30, 2010
Aug 30, 2010
369
static PHYSFS_sint64 ZIP_tell(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
370
{
Aug 30, 2010
Aug 30, 2010
371
return ((ZIPfileinfo *) io->opaque)->uncompressed_position;
Jul 8, 2001
Jul 8, 2001
372
373
374
} /* ZIP_tell */
Aug 30, 2010
Aug 30, 2010
375
static int ZIP_seek(PHYSFS_Io *_io, PHYSFS_uint64 offset)
Jul 8, 2001
Jul 8, 2001
376
{
Aug 30, 2010
Aug 30, 2010
377
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
378
ZIPentry *entry = finfo->entry;
Aug 30, 2010
Aug 30, 2010
379
PHYSFS_Io *io = finfo->io;
Sep 12, 2016
Sep 12, 2016
380
const int encrypted = zip_entry_is_tradional_crypto(entry);
Jul 23, 2001
Jul 23, 2001
381
Jul 6, 2017
Jul 6, 2017
382
BAIL_IF(offset > entry->uncompressed_size, PHYSFS_ERR_PAST_EOF, 0);
Jul 23, 2001
Jul 23, 2001
383
Sep 12, 2016
Sep 12, 2016
384
if (!encrypted && (entry->compression_method == COMPMETH_NONE))
Jul 23, 2001
Jul 23, 2001
385
{
Sep 12, 2016
Sep 12, 2016
386
PHYSFS_sint64 newpos = offset + entry->offset;
Jul 6, 2017
Jul 6, 2017
387
BAIL_IF_ERRPASS(!io->seek(io, newpos), 0);
Mar 30, 2003
Mar 30, 2003
388
finfo->uncompressed_position = (PHYSFS_uint32) offset;
Jul 13, 2002
Jul 13, 2002
389
} /* if */
Jul 23, 2001
Jul 23, 2001
390
Jul 13, 2002
Jul 13, 2002
391
else
Jul 23, 2001
Jul 23, 2001
392
{
Jul 13, 2002
Jul 13, 2002
393
394
395
396
/*
* 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
397
* decode, but we don't rewind first.
Jul 13, 2002
Jul 13, 2002
398
399
400
401
402
*/
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
403
initializeZStream(&str);
Jul 13, 2002
Jul 13, 2002
404
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
Jan 28, 2010
Jan 28, 2010
405
return 0;
Jul 13, 2002
Jul 13, 2002
406
Sep 12, 2016
Sep 12, 2016
407
if (!io->seek(io, entry->offset + (encrypted ? 12 : 0)))
Jan 28, 2010
Jan 28, 2010
408
return 0;
Jul 17, 2002
Jul 17, 2002
409
Jul 13, 2002
Jul 13, 2002
410
411
412
inflateEnd(&finfo->stream);
memcpy(&finfo->stream, &str, sizeof (z_stream));
finfo->uncompressed_position = finfo->compressed_position = 0;
Sep 12, 2016
Sep 12, 2016
413
414
415
if (encrypted)
memcpy(finfo->crypto_keys, finfo->initial_crypto_keys, 12);
Jul 13, 2002
Jul 13, 2002
416
417
418
419
420
} /* if */
while (finfo->uncompressed_position != offset)
{
PHYSFS_uint8 buf[512];
Mar 12, 2003
Mar 12, 2003
421
422
423
PHYSFS_uint32 maxread;
maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position);
Jul 13, 2002
Jul 13, 2002
424
425
426
if (maxread > sizeof (buf))
maxread = sizeof (buf);
Aug 30, 2010
Aug 30, 2010
427
if (ZIP_read(_io, buf, maxread) != maxread)
Jan 28, 2010
Jan 28, 2010
428
return 0;
Jul 13, 2002
Jul 13, 2002
429
430
431
} /* while */
} /* else */
Jan 28, 2010
Jan 28, 2010
432
return 1;
Jul 8, 2001
Jul 8, 2001
433
434
435
} /* ZIP_seek */
Aug 30, 2010
Aug 30, 2010
436
static PHYSFS_sint64 ZIP_length(PHYSFS_Io *io)
Jul 9, 2001
Jul 9, 2001
437
{
Aug 30, 2010
Aug 30, 2010
438
const ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
Jun 1, 2012
Jun 1, 2012
439
return (PHYSFS_sint64) finfo->entry->uncompressed_size;
Aug 30, 2010
Aug 30, 2010
440
} /* ZIP_length */
Jul 9, 2001
Jul 9, 2001
441
442
Aug 30, 2010
Aug 30, 2010
443
444
445
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
446
{
Aug 30, 2010
Aug 30, 2010
447
448
449
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
450
451
GOTO_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, failed);
GOTO_IF(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Aug 30, 2010
Aug 30, 2010
452
453
454
455
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
456
GOTO_IF_ERRPASS(!finfo->io, failed);
Aug 30, 2010
Aug 30, 2010
457
Oct 23, 2017
Oct 23, 2017
458
initializeZStream(&finfo->stream);
Aug 30, 2010
Aug 30, 2010
459
460
461
if (finfo->entry->compression_method != COMPMETH_NONE)
{
finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE);
Jul 6, 2017
Jul 6, 2017
462
GOTO_IF(!finfo->buffer, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Mar 24, 2012
Mar 24, 2012
463
464
if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
goto failed;
Aug 30, 2010
Aug 30, 2010
465
466
467
468
469
470
} /* if */
memcpy(retval, io, sizeof (PHYSFS_Io));
retval->opaque = finfo;
return retval;
Mar 24, 2012
Mar 24, 2012
471
failed:
Aug 30, 2010
Aug 30, 2010
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
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
498
499
500
501
502
if (finfo->entry->compression_method != COMPMETH_NONE)
inflateEnd(&finfo->stream);
if (finfo->buffer != NULL)
Mar 14, 2005
Mar 14, 2005
503
allocator.Free(finfo->buffer);
Jul 13, 2002
Jul 13, 2002
504
Mar 14, 2005
Mar 14, 2005
505
allocator.Free(finfo);
Aug 30, 2010
Aug 30, 2010
506
507
508
509
510
511
allocator.Free(io);
} /* ZIP_destroy */
static const PHYSFS_Io ZIP_Io =
{
Mar 25, 2012
Mar 25, 2012
512
CURRENT_PHYSFS_IO_API_VERSION, NULL,
Aug 30, 2010
Aug 30, 2010
513
514
515
516
517
518
519
ZIP_read,
ZIP_write,
ZIP_seek,
ZIP_tell,
ZIP_length,
ZIP_duplicate,
ZIP_flush,
Mar 25, 2012
Mar 25, 2012
520
ZIP_destroy
Aug 30, 2010
Aug 30, 2010
521
522
};
Jul 8, 2001
Jul 8, 2001
523
524
Aug 30, 2010
Aug 30, 2010
525
static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *len)
Jul 13, 2002
Jul 13, 2002
526
{
Jul 23, 2002
Jul 23, 2002
527
PHYSFS_uint8 buf[256];
Mar 25, 2010
Mar 25, 2010
528
PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 };
Jul 27, 2002
Jul 27, 2002
529
PHYSFS_sint32 i = 0;
Jul 13, 2002
Jul 13, 2002
530
531
532
PHYSFS_sint64 filelen;
PHYSFS_sint64 filepos;
PHYSFS_sint32 maxread;
Jul 23, 2002
Jul 23, 2002
533
534
PHYSFS_sint32 totalread = 0;
int found = 0;
Jul 13, 2002
Jul 13, 2002
535
Aug 30, 2010
Aug 30, 2010
536
filelen = io->length(io);
Jul 6, 2017
Jul 6, 2017
537
BAIL_IF_ERRPASS(filelen == -1, -1);
Jul 13, 2002
Jul 13, 2002
538
539
540
541
542
543
544
545
546
/*
* 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
547
548
* searching for that signature after a little more than 64k at most,
* and call it a corrupted zipfile.
Jul 13, 2002
Jul 13, 2002
549
550
551
552
553
554
555
556
557
558
*/
if (sizeof (buf) < filelen)
{
filepos = filelen - sizeof (buf);
maxread = sizeof (buf);
} /* if */
else
{
filepos = 0;
Mar 12, 2003
Mar 12, 2003
559
maxread = (PHYSFS_uint32) filelen;
Jul 13, 2002
Jul 13, 2002
560
561
} /* else */
Jul 23, 2002
Jul 23, 2002
562
while ((totalread < filelen) && (totalread < 65557))
Jul 13, 2002
Jul 13, 2002
563
{
Jul 6, 2017
Jul 6, 2017
564
BAIL_IF_ERRPASS(!io->seek(io, filepos), -1);
Jul 23, 2002
Jul 23, 2002
565
566
567
/* make sure we catch a signature between buffers. */
if (totalread != 0)
Jul 13, 2002
Jul 13, 2002
568
{
Mar 9, 2012
Mar 9, 2012
569
if (!__PHYSFS_readAll(io, buf, maxread - 4))
Jan 28, 2010
Jan 28, 2010
570
return -1;
May 3, 2009
May 3, 2009
571
memcpy(&buf[maxread - 4], &extra, sizeof (extra));
Jul 23, 2002
Jul 23, 2002
572
totalread += maxread - 4;
Jul 13, 2002
Jul 13, 2002
573
} /* if */
Jul 23, 2002
Jul 23, 2002
574
575
else
{
Mar 9, 2012
Mar 9, 2012
576
if (!__PHYSFS_readAll(io, buf, maxread))
Jan 28, 2010
Jan 28, 2010
577
return -1;
Jul 23, 2002
Jul 23, 2002
578
579
580
totalread += maxread;
} /* else */
May 3, 2009
May 3, 2009
581
memcpy(&extra, buf, sizeof (extra));
Jul 13, 2002
Jul 13, 2002
582
Jul 23, 2002
Jul 23, 2002
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
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
599
600
if (filepos < 0)
filepos = 0;
Jul 23, 2002
Jul 23, 2002
601
602
} /* while */
Jul 6, 2017
Jul 6, 2017
603
BAIL_IF(!found, PHYSFS_ERR_UNSUPPORTED, -1);
Jul 13, 2002
Jul 13, 2002
604
605
606
607
if (len != NULL)
*len = filelen;
Jan 28, 2010
Jan 28, 2010
608
return (filepos + i);
Jul 23, 2002
Jul 23, 2002
609
} /* zip_find_end_of_central_dir */
Jul 13, 2002
Jul 13, 2002
610
611
Aug 30, 2010
Aug 30, 2010
612
static int isZip(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
613
{
Aug 30, 2010
Aug 30, 2010
614
PHYSFS_uint32 sig = 0;
Jul 31, 2002
Jul 31, 2002
615
int retval = 0;
Jul 13, 2002
Jul 13, 2002
616
617
618
619
620
/*
* 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
621
if (readui32(io, &sig))
Jul 15, 2001
Jul 15, 2001
622
{
Jul 31, 2002
Jul 31, 2002
623
624
625
626
627
628
629
630
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
631
retval = (zip_find_end_of_central_dir(io, NULL) != -1);
Jul 31, 2002
Jul 31, 2002
632
} /* if */
Jul 15, 2001
Jul 15, 2001
633
634
} /* if */
Jan 28, 2010
Jan 28, 2010
635
return retval;
Aug 24, 2010
Aug 24, 2010
636
} /* isZip */
Jul 8, 2001
Jul 8, 2001
637
638
Jul 23, 2002
Jul 23, 2002
639
/* Convert paths from old, buggy DOS zippers... */
Jul 15, 2017
Jul 15, 2017
640
static void zip_convert_dos_path(const PHYSFS_uint16 entryversion, char *path)
Jul 23, 2002
Jul 23, 2002
641
{
Jul 15, 2017
Jul 15, 2017
642
const PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((entryversion >> 8) & 0xFF);
Jul 23, 2002
Jul 23, 2002
643
644
645
646
647
648
649
650
651
652
if (hosttype == 0) /* FS_FAT_ */
{
while (*path)
{
if (*path == '\\')
*path = '/';
path++;
} /* while */
} /* if */
} /* zip_convert_dos_path */
Jul 13, 2002
Jul 13, 2002
653
654
Jul 23, 2002
Jul 23, 2002
655
static void zip_expand_symlink_path(char *path)
Jul 8, 2001
Jul 8, 2001
656
{
Jul 23, 2002
Jul 23, 2002
657
658
char *ptr = path;
char *prevptr = path;
Jul 15, 2001
Jul 15, 2001
659
Jul 23, 2002
Jul 23, 2002
660
while (1)
Jul 28, 2001
Jul 28, 2001
661
{
Jul 23, 2002
Jul 23, 2002
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
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
697
Jul 23, 2002
Jul 23, 2002
698
699
700
701
702
703
704
705
706
707
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
708
ptr++;
Jul 23, 2002
Jul 23, 2002
709
710
711
} /* else */
} /* while */
} /* zip_expand_symlink_path */
Jul 15, 2001
Jul 15, 2001
712
Aug 14, 2017
Aug 14, 2017
713
Jul 15, 2017
Jul 15, 2017
714
715
716
717
718
static inline ZIPentry *zip_find_entry(ZIPinfo *info, const char *path)
{
return (ZIPentry *) __PHYSFS_DirTreeFind(&info->tree, path);
} /* zip_find_entry */
Sep 29, 2004
Sep 29, 2004
719
/* (forward reference: zip_follow_symlink and zip_resolve call each other.) */
Aug 30, 2010
Aug 30, 2010
720
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry);
Jul 15, 2001
Jul 15, 2001
721
Mar 29, 2002
Mar 29, 2002
722
/*
Jul 23, 2002
Jul 23, 2002
723
724
725
* 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
726
* If there's a problem, return NULL.
Mar 29, 2002
Mar 29, 2002
727
*/
Aug 30, 2010
Aug 30, 2010
728
static ZIPentry *zip_follow_symlink(PHYSFS_Io *io, ZIPinfo *info, char *path)
Jul 28, 2001
Jul 28, 2001
729
{
Jul 23, 2002
Jul 23, 2002
730
731
732
ZIPentry *entry;
zip_expand_symlink_path(path);
Feb 25, 2016
Feb 25, 2016
733
entry = zip_find_entry(info, path);
Jul 23, 2002
Jul 23, 2002
734
735
if (entry != NULL)
{
Aug 30, 2010
Aug 30, 2010
736
if (!zip_resolve(io, info, entry)) /* recursive! */
Jul 23, 2002
Jul 23, 2002
737
738
739
740
741
742
743
744
entry = NULL;
else
{
if (entry->symlink != NULL)
entry = entry->symlink;
} /* else */
} /* if */
Jan 28, 2010
Jan 28, 2010
745
return entry;
Jul 23, 2002
Jul 23, 2002
746
} /* zip_follow_symlink */
Jul 8, 2001
Jul 8, 2001
747
748
Aug 30, 2010
Aug 30, 2010
749
static int zip_resolve_symlink(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2001
Jul 23, 2001
750
{
Aug 15, 2017
Aug 15, 2017
751
const size_t size = (size_t) entry->uncompressed_size;
Mar 24, 2012
Mar 24, 2012
752
char *path = NULL;
Jul 13, 2002
Jul 13, 2002
753
754
int rc = 0;
Jul 23, 2002
Jul 23, 2002
755
756
757
758
759
760
/*
* 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
761
BAIL_IF_ERRPASS(!io->seek(io, entry->offset), 0);
Jul 23, 2002
Jul 23, 2002
762
Mar 24, 2012
Mar 24, 2012
763
path = (char *) __PHYSFS_smallAlloc(size + 1);
Jul 6, 2017
Jul 6, 2017
764
BAIL_IF(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0);
Jul 13, 2002
Jul 13, 2002
765
766
if (entry->compression_method == COMPMETH_NONE)
Mar 9, 2012
Mar 9, 2012
767
rc = __PHYSFS_readAll(io, path, size);
Jul 13, 2002
Jul 13, 2002
768
769
770
771
else /* symlink target path is compressed... */
{
z_stream stream;
Aug 15, 2017
Aug 15, 2017
772
const size_t complen = (size_t) entry->compressed_size;
Mar 24, 2007
Mar 24, 2007
773
PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
Jul 13, 2002
Jul 13, 2002
774
775
if (compressed != NULL)
{
Mar 9, 2012
Mar 9, 2012
776
if (__PHYSFS_readAll(io, compressed, complen))
Jul 13, 2002
Jul 13, 2002
777
{
Sep 23, 2004
Sep 23, 2004
778
initializeZStream(&stream);
Jul 13, 2002
Jul 13, 2002
779
stream.next_in = compressed;
Jul 13, 2017
Jul 13, 2017
780
stream.avail_in = (unsigned int) complen;
Jan 31, 2003
Jan 31, 2003
781
stream.next_out = (unsigned char *) path;
Jul 13, 2017
Jul 13, 2017
782
stream.avail_out = (unsigned int) size;
Jul 13, 2002
Jul 13, 2002
783
784
if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
{
Jul 15, 2002
Jul 15, 2002
785
rc = zlib_err(inflate(&stream, Z_FINISH));
Jul 13, 2002
Jul 13, 2002
786
inflateEnd(&stream);
Jul 15, 2002
Jul 15, 2002
787
788
789
/* both are acceptable outcomes... */
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
Jul 13, 2002
Jul 13, 2002
790
791
} /* if */
} /* if */
Mar 24, 2007
Mar 24, 2007
792
__PHYSFS_smallFree(compressed);
Jul 13, 2002
Jul 13, 2002
793
794
} /* if */
} /* else */
Mar 29, 2002
Mar 29, 2002
795
Mar 24, 2012
Mar 24, 2012
796
if (rc)
Jul 23, 2002
Jul 23, 2002
797
798
{
path[entry->uncompressed_size] = '\0'; /* null-terminate it. */
Jul 15, 2017
Jul 15, 2017
799
zip_convert_dos_path(entry->version, path);
Aug 30, 2010
Aug 30, 2010
800
entry->symlink = zip_follow_symlink(io, info, path);
Jul 23, 2002
Jul 23, 2002
801
802
} /* else */
Mar 24, 2012
Mar 24, 2012
803
804
__PHYSFS_smallFree(path);
Jan 28, 2010
Jan 28, 2010
805
return (entry->symlink != NULL);
Jul 23, 2002
Jul 23, 2002
806
807
808
809
810
811
} /* zip_resolve_symlink */
/*
* Parse the local file header of an entry, and update entry->offset.
*/
Aug 30, 2010
Aug 30, 2010
812
static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
813
814
815
816
817
818
{
PHYSFS_uint32 ui32;
PHYSFS_uint16 ui16;
PHYSFS_uint16 fnamelen;
PHYSFS_uint16 extralen;
Mar 30, 2003
Mar 30, 2003
819
820
821
822
823
/*
* 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
824
825
* 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
826
827
*/
Sep 12, 2016
Sep 12, 2016
828
829
830
831
/* !!! 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
832
833
834
835
836
837
838
839
840
841
842
843
844
845
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
846
847
(ui32 != entry->compressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
848
849
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != 0xFFFFFFFF) &&
Jun 1, 2012
Jun 1, 2012
850
851
(ui32 != entry->uncompressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
852
853
BAIL_IF_ERRPASS(!readui16(io, &fnamelen), 0);
BAIL_IF_ERRPASS(!readui16(io, &extralen), 0);
Jul 23, 2002
Jul 23, 2002
854
855
entry->offset += fnamelen + extralen + 30;
Jan 28, 2010
Jan 28, 2010
856
return 1;
Jul 23, 2002
Jul 23, 2002
857
858
859
} /* zip_parse_local */
Aug 30, 2010
Aug 30, 2010
860
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
861
862
{
int retval = 1;
Feb 25, 2016
Feb 25, 2016
863
864
865
866
const ZipResolveType resolve_type = entry->resolved;
if (resolve_type == ZIP_DIRECTORY)
return 1; /* we're good. */
Jul 23, 2002
Jul 23, 2002
867
868
/* Don't bother if we've failed to resolve this entry before. */
Jul 6, 2017
Jul 6, 2017
869
870
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
871
872
/* uhoh...infinite symlink loop! */
Jul 6, 2017
Jul 6, 2017
873
BAIL_IF(resolve_type == ZIP_RESOLVING, PHYSFS_ERR_SYMLINK_LOOP, 0);
Jul 23, 2002
Jul 23, 2002
874
875
876
877
878
879
880
881
882
883
/*
* 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)
{
Aug 14, 2017
Aug 14, 2017
884
885
886
887
888
if (entry->tree.isdir) /* an ancestor dir that DirTree filled in? */
{
entry->resolved = ZIP_DIRECTORY;
return 1;
} /* if */
Jul 23, 2002
Jul 23, 2002
889
Aug 30, 2010
Aug 30, 2010
890
retval = zip_parse_local(io, entry);
Jul 23, 2002
Jul 23, 2002
891
892
893
894
895
896
897
898
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
899
retval = zip_resolve_symlink(io, info, entry);
Jul 23, 2002
Jul 23, 2002
900
901
902
903
904
905
} /* 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
906
} /* if */
Mar 29, 2002
Mar 29, 2002
907
Jan 28, 2010
Jan 28, 2010
908
return retval;
Jul 23, 2002
Jul 23, 2002
909
} /* zip_resolve */
Jul 23, 2001
Jul 23, 2001
910
911
Feb 25, 2016
Feb 25, 2016
912
913
914
915
916
917
918
919
static int zip_entry_is_symlink(const ZIPentry *entry)
{
return ((entry->resolved == ZIP_UNRESOLVED_SYMLINK) ||
(entry->resolved == ZIP_BROKEN_SYMLINK) ||
(entry->symlink));
} /* zip_entry_is_symlink */
Jul 23, 2002
Jul 23, 2002
920
static int zip_version_does_symlinks(PHYSFS_uint32 version)
Jul 23, 2001
Jul 23, 2001
921
922
{
int retval = 0;
Apr 3, 2002
Apr 3, 2002
923
PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((version >> 8) & 0xFF);
Jul 23, 2001
Jul 23, 2001
924
925
926
switch (hosttype)
{
Jul 15, 2002
Jul 15, 2002
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
/*
* These are the platforms that can NOT build an archive with
* symlinks, according to the Info-ZIP project.
*/
case 0: /* FS_FAT_ */
case 1: /* AMIGA_ */
case 2: /* VMS_ */
case 4: /* VM_CSM_ */
case 6: /* FS_HPFS_ */
case 11: /* FS_NTFS_ */
case 14: /* FS_VFAT_ */
case 13: /* ACORN_ */
case 15: /* MVS_ */
case 18: /* THEOS_ */
break; /* do nothing. */
default: /* assume the rest to be unix-like. */
Jul 23, 2001
Jul 23, 2001
944
945
946
947
retval = 1;
break;
} /* switch */
Jan 28, 2010
Jan 28, 2010
948
return retval;
Jul 23, 2002
Jul 23, 2002
949
950
951
} /* zip_version_does_symlinks */
Jul 15, 2017
Jul 15, 2017
952
953
static inline int zip_has_symlink_attr(const ZIPentry *entry,
const PHYSFS_uint32 extern_attr)
Jul 23, 2001
Jul 23, 2001
954
{
Jul 15, 2002
Jul 15, 2002
955
PHYSFS_uint16 xattr = ((extern_attr >> 16) & 0xFFFF);
Jan 28, 2010
Jan 28, 2010
956
957
958
return ( (zip_version_does_symlinks(entry->version)) &&
(entry->uncompressed_size > 0) &&
((xattr & UNIX_FILETYPE_MASK) == UNIX_FILETYPE_SYMLINK) );
Jul 23, 2002
Jul 23, 2002
959
} /* zip_has_symlink_attr */
Jul 23, 2001
Jul 23, 2001
960
961
Jan 31, 2003
Jan 31, 2003
962
static PHYSFS_sint64 zip_dos_time_to_physfs_time(PHYSFS_uint32 dostime)
Jul 23, 2001
Jul 23, 2001
963
{
Jul 23, 2002
Jul 23, 2002
964
PHYSFS_uint32 dosdate;
Jul 13, 2002
Jul 13, 2002
965
966
struct tm unixtime;
memset(&unixtime, '\0', sizeof (unixtime));
Jul 28, 2001
Jul 28, 2001
967
Jul 23, 2002
Jul 23, 2002
968
969
dosdate = (PHYSFS_uint32) ((dostime >> 16) & 0xFFFF);
dostime &= 0xFFFF;
Jul 23, 2001
Jul 23, 2001
970
Jul 23, 2002
Jul 23, 2002
971
972
973
974
975
976
977
978
979
980
981
982
/* dissect date */
unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
unixtime.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
unixtime.tm_mday = ((dosdate ) & 0x1F);
/* dissect time */
unixtime.tm_hour = ((dostime >> 11) & 0x1F);
unixtime.tm_min = ((dostime >> 5) & 0x3F);
unixtime.tm_sec = ((dostime << 1) & 0x3E);
/* let mktime calculate daylight savings time. */
unixtime.tm_isdst = -1;
Jul 28, 2001
Jul 28, 2001
983
Jan 28, 2010
Jan 28, 2010
984
return ((PHYSFS_sint64) mktime(&unixtime));
Jul 23, 2002
Jul 23, 2002
985
} /* zip_dos_time_to_physfs_time */
Jul 13, 2002
Jul 13, 2002
986
987
Jul 15, 2017
Jul 15, 2017
988
static ZIPentry *zip_load_entry(ZIPinfo *info, const int zip64,
Feb 25, 2016
Feb 25, 2016
989
const PHYSFS_uint64 ofs_fixup)
Jul 13, 2002
Jul 13, 2002
990
{
Jul 15, 2017
Jul 15, 2017
991
PHYSFS_Io *io = info->io;
Feb 25, 2016
Feb 25, 2016
992
993
ZIPentry entry;
ZIPentry *retval = NULL;
Jul 13, 2002
Jul 13, 2002
994
995
PHYSFS_uint16 fnamelen, extralen, commentlen;
PHYSFS_uint32 external_attr;
Jun 1, 2012
Jun 1, 2012
996
997
PHYSFS_uint32 starting_disk;
PHYSFS_uint64 offset;
Jul 13, 2002
Jul 13, 2002
998
999
1000
PHYSFS_uint16 ui16;
PHYSFS_uint32 ui32;
PHYSFS_sint64 si64;