CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libzip/zip_dirent.c
Views: 1401
1
/*
2
zip_dirent.c -- read directory entry (local or central), clean dirent
3
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
4
5
This file is part of libzip, a library to manipulate ZIP archives.
6
The authors can be contacted at <[email protected]>
7
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
10
are met:
11
1. Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
2. Redistributions in binary form must reproduce the above copyright
14
notice, this list of conditions and the following disclaimer in
15
the documentation and/or other materials provided with the
16
distribution.
17
3. The names of the authors may not be used to endorse or promote
18
products derived from this software without specific prior
19
written permission.
20
21
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <sys/types.h>
39
#include <time.h>
40
41
#include "zipint.h"
42
43
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str);
44
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
45
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
46
47
48
void
49
_zip_cdir_free(zip_cdir_t *cd) {
50
zip_uint64_t i;
51
52
if (!cd)
53
return;
54
55
for (i = 0; i < cd->nentry; i++)
56
_zip_entry_finalize(cd->entry + i);
57
free(cd->entry);
58
_zip_string_free(cd->comment);
59
free(cd);
60
}
61
62
63
zip_cdir_t *
64
_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) {
65
zip_cdir_t *cd;
66
67
if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
68
zip_error_set(error, ZIP_ER_MEMORY, 0);
69
return NULL;
70
}
71
72
cd->entry = NULL;
73
cd->nentry = cd->nentry_alloc = 0;
74
cd->size = cd->offset = 0;
75
cd->comment = NULL;
76
cd->is_zip64 = false;
77
78
if (!_zip_cdir_grow(cd, nentry, error)) {
79
_zip_cdir_free(cd);
80
return NULL;
81
}
82
83
return cd;
84
}
85
86
87
bool
88
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
89
zip_uint64_t i, new_alloc;
90
zip_entry_t *new_entry;
91
92
if (additional_entries == 0) {
93
return true;
94
}
95
96
new_alloc = cd->nentry_alloc + additional_entries;
97
98
if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) {
99
zip_error_set(error, ZIP_ER_MEMORY, 0);
100
return false;
101
}
102
103
if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) {
104
zip_error_set(error, ZIP_ER_MEMORY, 0);
105
return false;
106
}
107
108
cd->entry = new_entry;
109
110
for (i = cd->nentry; i < new_alloc; i++) {
111
_zip_entry_init(cd->entry + i);
112
}
113
114
cd->nentry = cd->nentry_alloc = new_alloc;
115
116
return true;
117
}
118
119
120
zip_int64_t
121
_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
122
zip_uint64_t offset, size;
123
zip_string_t *comment;
124
zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
125
zip_buffer_t *buffer;
126
zip_int64_t off;
127
zip_uint64_t i;
128
bool is_zip64;
129
int ret;
130
131
if ((off = zip_source_tell_write(za->src)) < 0) {
132
_zip_error_set_from_source(&za->error, za->src);
133
return -1;
134
}
135
offset = (zip_uint64_t)off;
136
137
is_zip64 = false;
138
139
for (i = 0; i < survivors; i++) {
140
zip_entry_t *entry = za->entry + filelist[i].idx;
141
142
if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
143
return -1;
144
if (ret)
145
is_zip64 = true;
146
}
147
148
if ((off = zip_source_tell_write(za->src)) < 0) {
149
_zip_error_set_from_source(&za->error, za->src);
150
return -1;
151
}
152
size = (zip_uint64_t)off - offset;
153
154
if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
155
is_zip64 = true;
156
157
158
if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
159
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
160
return -1;
161
}
162
163
if (is_zip64) {
164
_zip_buffer_put(buffer, EOCD64_MAGIC, 4);
165
_zip_buffer_put_64(buffer, EOCD64LEN - 12);
166
_zip_buffer_put_16(buffer, 45);
167
_zip_buffer_put_16(buffer, 45);
168
_zip_buffer_put_32(buffer, 0);
169
_zip_buffer_put_32(buffer, 0);
170
_zip_buffer_put_64(buffer, survivors);
171
_zip_buffer_put_64(buffer, survivors);
172
_zip_buffer_put_64(buffer, size);
173
_zip_buffer_put_64(buffer, offset);
174
_zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
175
_zip_buffer_put_32(buffer, 0);
176
_zip_buffer_put_64(buffer, offset + size);
177
_zip_buffer_put_32(buffer, 1);
178
}
179
180
_zip_buffer_put(buffer, EOCD_MAGIC, 4);
181
_zip_buffer_put_32(buffer, 0);
182
_zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
183
_zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
184
_zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
185
_zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
186
187
comment = za->comment_changed ? za->comment_changes : za->comment_orig;
188
189
_zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
190
191
if (!_zip_buffer_ok(buffer)) {
192
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
193
_zip_buffer_free(buffer);
194
return -1;
195
}
196
197
if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
198
_zip_buffer_free(buffer);
199
return -1;
200
}
201
202
_zip_buffer_free(buffer);
203
204
if (comment) {
205
if (_zip_write(za, comment->raw, comment->length) < 0) {
206
return -1;
207
}
208
}
209
210
return (zip_int64_t)size;
211
}
212
213
214
zip_dirent_t *
215
_zip_dirent_clone(const zip_dirent_t *sde) {
216
zip_dirent_t *tde;
217
218
if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
219
return NULL;
220
221
if (sde)
222
memcpy(tde, sde, sizeof(*sde));
223
else
224
_zip_dirent_init(tde);
225
226
tde->changed = 0;
227
tde->cloned = 1;
228
229
return tde;
230
}
231
232
233
void
234
_zip_dirent_finalize(zip_dirent_t *zde) {
235
if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
236
_zip_string_free(zde->filename);
237
zde->filename = NULL;
238
}
239
if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
240
_zip_ef_free(zde->extra_fields);
241
zde->extra_fields = NULL;
242
}
243
if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
244
_zip_string_free(zde->comment);
245
zde->comment = NULL;
246
}
247
if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
248
if (zde->password) {
249
_zip_crypto_clear(zde->password, strlen(zde->password));
250
}
251
free(zde->password);
252
zde->password = NULL;
253
}
254
}
255
256
257
void
258
_zip_dirent_free(zip_dirent_t *zde) {
259
if (zde == NULL)
260
return;
261
262
_zip_dirent_finalize(zde);
263
free(zde);
264
}
265
266
267
void
268
_zip_dirent_init(zip_dirent_t *de) {
269
de->changed = 0;
270
de->local_extra_fields_read = 0;
271
de->cloned = 0;
272
273
de->crc_valid = true;
274
de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
275
de->version_needed = 10; /* 1.0 */
276
de->bitflags = 0;
277
de->comp_method = ZIP_CM_DEFAULT;
278
de->last_mod = 0;
279
de->crc = 0;
280
de->comp_size = 0;
281
de->uncomp_size = 0;
282
de->filename = NULL;
283
de->extra_fields = NULL;
284
de->comment = NULL;
285
de->disk_number = 0;
286
de->int_attrib = 0;
287
de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
288
de->offset = 0;
289
de->compression_level = 0;
290
de->encryption_method = ZIP_EM_NONE;
291
de->password = NULL;
292
}
293
294
295
bool
296
_zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
297
if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
298
return true;
299
300
return false;
301
}
302
303
304
zip_dirent_t *
305
_zip_dirent_new(void) {
306
zip_dirent_t *de;
307
308
if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
309
return NULL;
310
311
_zip_dirent_init(de);
312
return de;
313
}
314
315
316
/* _zip_dirent_read(zde, fp, bufp, left, localp, error):
317
Fills the zip directory entry zde.
318
319
If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
320
321
If local is true, it reads a local header instead of a central directory entry.
322
323
Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
324
*/
325
326
zip_int64_t
327
_zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error) {
328
zip_uint8_t buf[CDENTRYSIZE];
329
zip_uint16_t dostime, dosdate;
330
zip_uint32_t size, variable_size;
331
zip_uint16_t filename_len, comment_len, ef_len;
332
333
bool from_buffer = (buffer != NULL);
334
335
size = local ? LENTRYSIZE : CDENTRYSIZE;
336
337
if (buffer) {
338
if (_zip_buffer_left(buffer) < size) {
339
zip_error_set(error, ZIP_ER_NOZIP, 0);
340
return -1;
341
}
342
}
343
else {
344
if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
345
return -1;
346
}
347
}
348
349
if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
350
zip_error_set(error, ZIP_ER_NOZIP, 0);
351
if (!from_buffer) {
352
_zip_buffer_free(buffer);
353
}
354
return -1;
355
}
356
357
/* convert buffercontents to zip_dirent */
358
359
_zip_dirent_init(zde);
360
if (!local)
361
zde->version_madeby = _zip_buffer_get_16(buffer);
362
else
363
zde->version_madeby = 0;
364
zde->version_needed = _zip_buffer_get_16(buffer);
365
zde->bitflags = _zip_buffer_get_16(buffer);
366
zde->comp_method = _zip_buffer_get_16(buffer);
367
368
/* convert to time_t */
369
dostime = _zip_buffer_get_16(buffer);
370
dosdate = _zip_buffer_get_16(buffer);
371
zde->last_mod = _zip_d2u_time(dostime, dosdate);
372
373
zde->crc = _zip_buffer_get_32(buffer);
374
zde->comp_size = _zip_buffer_get_32(buffer);
375
zde->uncomp_size = _zip_buffer_get_32(buffer);
376
377
filename_len = _zip_buffer_get_16(buffer);
378
ef_len = _zip_buffer_get_16(buffer);
379
380
if (local) {
381
comment_len = 0;
382
zde->disk_number = 0;
383
zde->int_attrib = 0;
384
zde->ext_attrib = 0;
385
zde->offset = 0;
386
}
387
else {
388
comment_len = _zip_buffer_get_16(buffer);
389
zde->disk_number = _zip_buffer_get_16(buffer);
390
zde->int_attrib = _zip_buffer_get_16(buffer);
391
zde->ext_attrib = _zip_buffer_get_32(buffer);
392
zde->offset = _zip_buffer_get_32(buffer);
393
}
394
395
if (!_zip_buffer_ok(buffer)) {
396
zip_error_set(error, ZIP_ER_INTERNAL, 0);
397
if (!from_buffer) {
398
_zip_buffer_free(buffer);
399
}
400
return -1;
401
}
402
403
if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
404
if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
405
/* TODO */
406
zde->encryption_method = ZIP_EM_UNKNOWN;
407
}
408
else {
409
zde->encryption_method = ZIP_EM_TRAD_PKWARE;
410
}
411
}
412
else {
413
zde->encryption_method = ZIP_EM_NONE;
414
}
415
416
zde->filename = NULL;
417
zde->extra_fields = NULL;
418
zde->comment = NULL;
419
420
variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
421
422
if (from_buffer) {
423
if (_zip_buffer_left(buffer) < variable_size) {
424
zip_error_set(error, ZIP_ER_INCONS, 0);
425
return -1;
426
}
427
}
428
else {
429
_zip_buffer_free(buffer);
430
431
if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
432
return -1;
433
}
434
}
435
436
if (filename_len) {
437
zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
438
if (!zde->filename) {
439
if (zip_error_code_zip(error) == ZIP_ER_EOF) {
440
zip_error_set(error, ZIP_ER_INCONS, 0);
441
}
442
if (!from_buffer) {
443
_zip_buffer_free(buffer);
444
}
445
return -1;
446
}
447
448
if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
449
if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
450
zip_error_set(error, ZIP_ER_INCONS, 0);
451
if (!from_buffer) {
452
_zip_buffer_free(buffer);
453
}
454
return -1;
455
}
456
}
457
}
458
459
if (ef_len) {
460
zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
461
462
if (ef == NULL) {
463
if (!from_buffer) {
464
_zip_buffer_free(buffer);
465
}
466
return -1;
467
}
468
if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
469
free(ef);
470
if (!from_buffer) {
471
_zip_buffer_free(buffer);
472
}
473
return -1;
474
}
475
free(ef);
476
if (local)
477
zde->local_extra_fields_read = 1;
478
}
479
480
if (comment_len) {
481
zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
482
if (!zde->comment) {
483
if (!from_buffer) {
484
_zip_buffer_free(buffer);
485
}
486
return -1;
487
}
488
if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
489
if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
490
zip_error_set(error, ZIP_ER_INCONS, 0);
491
if (!from_buffer) {
492
_zip_buffer_free(buffer);
493
}
494
return -1;
495
}
496
}
497
}
498
499
zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename);
500
zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment);
501
502
/* Zip64 */
503
504
if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
505
zip_uint16_t got_len;
506
zip_buffer_t *ef_buffer;
507
const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
508
/* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
509
if (ef == NULL) {
510
if (!from_buffer) {
511
_zip_buffer_free(buffer);
512
}
513
return -1;
514
}
515
516
if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
517
zip_error_set(error, ZIP_ER_MEMORY, 0);
518
if (!from_buffer) {
519
_zip_buffer_free(buffer);
520
}
521
return -1;
522
}
523
524
if (zde->uncomp_size == ZIP_UINT32_MAX) {
525
zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
526
}
527
else if (local) {
528
/* From appnote.txt: This entry in the Local header MUST
529
include BOTH original and compressed file size fields. */
530
(void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
531
}
532
if (zde->comp_size == ZIP_UINT32_MAX) {
533
zde->comp_size = _zip_buffer_get_64(ef_buffer);
534
}
535
if (!local) {
536
if (zde->offset == ZIP_UINT32_MAX) {
537
zde->offset = _zip_buffer_get_64(ef_buffer);
538
}
539
if (zde->disk_number == ZIP_UINT16_MAX) {
540
zde->disk_number = _zip_buffer_get_32(ef_buffer);
541
}
542
}
543
544
if (!_zip_buffer_eof(ef_buffer)) {
545
/* accept additional fields if values match */
546
bool ok = true;
547
switch (got_len) {
548
case 28:
549
_zip_buffer_set_offset(ef_buffer, 24);
550
if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
551
ok = false;
552
}
553
/* fallthrough */
554
case 24:
555
_zip_buffer_set_offset(ef_buffer, 0);
556
if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) {
557
ok = false;
558
}
559
break;
560
561
default:
562
ok = false;
563
}
564
if (!ok) {
565
zip_error_set(error, ZIP_ER_INCONS, 0);
566
_zip_buffer_free(ef_buffer);
567
if (!from_buffer) {
568
_zip_buffer_free(buffer);
569
}
570
return -1;
571
}
572
}
573
_zip_buffer_free(ef_buffer);
574
}
575
576
if (!_zip_buffer_ok(buffer)) {
577
zip_error_set(error, ZIP_ER_INTERNAL, 0);
578
if (!from_buffer) {
579
_zip_buffer_free(buffer);
580
}
581
return -1;
582
}
583
if (!from_buffer) {
584
_zip_buffer_free(buffer);
585
}
586
587
/* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
588
if (zde->offset > ZIP_INT64_MAX) {
589
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
590
return -1;
591
}
592
593
if (!_zip_dirent_process_winzip_aes(zde, error)) {
594
return -1;
595
}
596
597
zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
598
599
return (zip_int64_t)size + (zip_int64_t)variable_size;
600
}
601
602
603
static zip_string_t *
604
_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str) {
605
zip_uint16_t ef_len;
606
zip_uint32_t ef_crc;
607
zip_buffer_t *buffer;
608
609
const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
610
611
if (ef == NULL || ef_len < 5 || ef[0] != 1) {
612
return str;
613
}
614
615
if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
616
return str;
617
}
618
619
_zip_buffer_get_8(buffer);
620
ef_crc = _zip_buffer_get_32(buffer);
621
622
if (_zip_string_crc32(str) == ef_crc) {
623
zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
624
zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
625
626
if (ef_str != NULL) {
627
_zip_string_free(str);
628
str = ef_str;
629
}
630
}
631
632
_zip_buffer_free(buffer);
633
634
return str;
635
}
636
637
638
static bool
639
_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
640
zip_uint16_t ef_len;
641
zip_buffer_t *buffer;
642
const zip_uint8_t *ef;
643
bool crc_valid;
644
zip_uint16_t enc_method;
645
646
647
if (de->comp_method != ZIP_CM_WINZIP_AES) {
648
return true;
649
}
650
651
ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
652
653
if (ef == NULL || ef_len < 7) {
654
zip_error_set(error, ZIP_ER_INCONS, 0);
655
return false;
656
}
657
658
if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
659
zip_error_set(error, ZIP_ER_INTERNAL, 0);
660
return false;
661
}
662
663
/* version */
664
665
crc_valid = true;
666
switch (_zip_buffer_get_16(buffer)) {
667
case 1:
668
break;
669
670
case 2:
671
if (de->uncomp_size < 20 /* TODO: constant */) {
672
crc_valid = false;
673
}
674
break;
675
676
default:
677
zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
678
_zip_buffer_free(buffer);
679
return false;
680
}
681
682
/* vendor */
683
if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
684
zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
685
_zip_buffer_free(buffer);
686
return false;
687
}
688
689
/* mode */
690
switch (_zip_buffer_get_8(buffer)) {
691
case 1:
692
enc_method = ZIP_EM_AES_128;
693
break;
694
case 2:
695
enc_method = ZIP_EM_AES_192;
696
break;
697
case 3:
698
enc_method = ZIP_EM_AES_256;
699
break;
700
default:
701
zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
702
_zip_buffer_free(buffer);
703
return false;
704
}
705
706
if (ef_len != 7) {
707
zip_error_set(error, ZIP_ER_INCONS, 0);
708
_zip_buffer_free(buffer);
709
return false;
710
}
711
712
de->crc_valid = crc_valid;
713
de->encryption_method = enc_method;
714
de->comp_method = _zip_buffer_get_16(buffer);
715
716
_zip_buffer_free(buffer);
717
return true;
718
}
719
720
721
zip_int32_t
722
_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
723
zip_int32_t size;
724
bool local = (flags & ZIP_EF_LOCAL) != 0;
725
int i;
726
zip_uint8_t b[6];
727
zip_buffer_t *buffer;
728
729
size = local ? LENTRYSIZE : CDENTRYSIZE;
730
731
if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
732
_zip_error_set_from_source(error, src);
733
return -1;
734
}
735
736
if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
737
return -1;
738
}
739
740
for (i = 0; i < (local ? 2 : 3); i++) {
741
size += _zip_buffer_get_16(buffer);
742
}
743
744
if (!_zip_buffer_eof(buffer)) {
745
zip_error_set(error, ZIP_ER_INTERNAL, 0);
746
_zip_buffer_free(buffer);
747
return -1;
748
}
749
750
_zip_buffer_free(buffer);
751
return size;
752
}
753
754
755
/* _zip_dirent_write
756
Writes zip directory entry.
757
758
If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
759
directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
760
761
Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
762
returned.
763
*/
764
765
int
766
_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
767
zip_uint16_t dostime, dosdate;
768
zip_encoding_type_t com_enc, name_enc;
769
zip_extra_field_t *ef;
770
zip_extra_field_t *ef64;
771
zip_uint32_t ef_total_size;
772
bool is_zip64;
773
bool is_really_zip64;
774
bool is_winzip_aes;
775
zip_uint8_t buf[CDENTRYSIZE];
776
zip_buffer_t *buffer;
777
778
ef = NULL;
779
780
name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
781
com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
782
783
if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
784
de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
785
else {
786
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
787
if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
788
ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
789
if (ef == NULL)
790
return -1;
791
}
792
if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
793
zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
794
if (ef2 == NULL) {
795
_zip_ef_free(ef);
796
return -1;
797
}
798
ef2->next = ef;
799
ef = ef2;
800
}
801
}
802
803
if (de->encryption_method == ZIP_EM_NONE) {
804
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
805
}
806
else {
807
de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
808
}
809
810
is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
811
is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
812
is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
813
814
if (is_zip64) {
815
zip_uint8_t ef_zip64[EFZIP64SIZE];
816
zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
817
if (ef_buffer == NULL) {
818
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
819
_zip_ef_free(ef);
820
return -1;
821
}
822
823
if (flags & ZIP_FL_LOCAL) {
824
if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
825
_zip_buffer_put_64(ef_buffer, de->uncomp_size);
826
_zip_buffer_put_64(ef_buffer, de->comp_size);
827
}
828
}
829
else {
830
if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
831
if (de->uncomp_size >= ZIP_UINT32_MAX) {
832
_zip_buffer_put_64(ef_buffer, de->uncomp_size);
833
}
834
if (de->comp_size >= ZIP_UINT32_MAX) {
835
_zip_buffer_put_64(ef_buffer, de->comp_size);
836
}
837
if (de->offset >= ZIP_UINT32_MAX) {
838
_zip_buffer_put_64(ef_buffer, de->offset);
839
}
840
}
841
}
842
843
if (!_zip_buffer_ok(ef_buffer)) {
844
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
845
_zip_buffer_free(ef_buffer);
846
_zip_ef_free(ef);
847
return -1;
848
}
849
850
ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
851
_zip_buffer_free(ef_buffer);
852
ef64->next = ef;
853
ef = ef64;
854
}
855
856
if (is_winzip_aes) {
857
zip_uint8_t data[EF_WINZIP_AES_SIZE];
858
zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
859
zip_extra_field_t *ef_winzip;
860
861
if (ef_buffer == NULL) {
862
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
863
_zip_ef_free(ef);
864
return -1;
865
}
866
867
_zip_buffer_put_16(ef_buffer, 2);
868
_zip_buffer_put(ef_buffer, "AE", 2);
869
_zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
870
_zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
871
872
if (!_zip_buffer_ok(ef_buffer)) {
873
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
874
_zip_buffer_free(ef_buffer);
875
_zip_ef_free(ef);
876
return -1;
877
}
878
879
ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
880
_zip_buffer_free(ef_buffer);
881
ef_winzip->next = ef;
882
ef = ef_winzip;
883
}
884
885
if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
886
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
887
_zip_ef_free(ef);
888
return -1;
889
}
890
891
_zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
892
893
if ((flags & ZIP_FL_LOCAL) == 0) {
894
_zip_buffer_put_16(buffer, de->version_madeby);
895
}
896
_zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
897
_zip_buffer_put_16(buffer, de->bitflags);
898
if (is_winzip_aes) {
899
_zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
900
}
901
else {
902
_zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
903
}
904
905
_zip_u2d_time(de->last_mod, &dostime, &dosdate);
906
_zip_buffer_put_16(buffer, dostime);
907
_zip_buffer_put_16(buffer, dosdate);
908
909
if (is_winzip_aes && de->uncomp_size < 20) {
910
_zip_buffer_put_32(buffer, 0);
911
}
912
else {
913
_zip_buffer_put_32(buffer, de->crc);
914
}
915
916
if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
917
/* In local headers, if a ZIP64 EF is written, it MUST contain
918
* both compressed and uncompressed sizes (even if one of the
919
* two is smaller than 0xFFFFFFFF); on the other hand, those
920
* may only appear when the corresponding standard entry is
921
* 0xFFFFFFFF. (appnote.txt 4.5.3) */
922
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
923
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
924
}
925
else {
926
if (de->comp_size < ZIP_UINT32_MAX) {
927
_zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
928
}
929
else {
930
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
931
}
932
if (de->uncomp_size < ZIP_UINT32_MAX) {
933
_zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
934
}
935
else {
936
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
937
}
938
}
939
940
_zip_buffer_put_16(buffer, _zip_string_length(de->filename));
941
/* TODO: check for overflow */
942
ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
943
_zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
944
945
if ((flags & ZIP_FL_LOCAL) == 0) {
946
_zip_buffer_put_16(buffer, _zip_string_length(de->comment));
947
_zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
948
_zip_buffer_put_16(buffer, de->int_attrib);
949
_zip_buffer_put_32(buffer, de->ext_attrib);
950
if (de->offset < ZIP_UINT32_MAX)
951
_zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
952
else
953
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
954
}
955
956
if (!_zip_buffer_ok(buffer)) {
957
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
958
_zip_buffer_free(buffer);
959
_zip_ef_free(ef);
960
return -1;
961
}
962
963
if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
964
_zip_buffer_free(buffer);
965
_zip_ef_free(ef);
966
return -1;
967
}
968
969
_zip_buffer_free(buffer);
970
971
if (de->filename) {
972
if (_zip_string_write(za, de->filename) < 0) {
973
_zip_ef_free(ef);
974
return -1;
975
}
976
}
977
978
if (ef) {
979
if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
980
_zip_ef_free(ef);
981
return -1;
982
}
983
}
984
_zip_ef_free(ef);
985
if (de->extra_fields) {
986
if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
987
return -1;
988
}
989
}
990
991
if ((flags & ZIP_FL_LOCAL) == 0) {
992
if (de->comment) {
993
if (_zip_string_write(za, de->comment) < 0) {
994
return -1;
995
}
996
}
997
}
998
999
1000
return is_zip64;
1001
}
1002
1003
1004
time_t
1005
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) {
1006
struct tm tm;
1007
1008
memset(&tm, 0, sizeof(tm));
1009
1010
/* let mktime decide if DST is in effect */
1011
tm.tm_isdst = -1;
1012
1013
tm.tm_year = ((ddate >> 9) & 127) + 1980 - 1900;
1014
tm.tm_mon = ((ddate >> 5) & 15) - 1;
1015
tm.tm_mday = ddate & 31;
1016
1017
tm.tm_hour = (dtime >> 11) & 31;
1018
tm.tm_min = (dtime >> 5) & 63;
1019
tm.tm_sec = (dtime << 1) & 62;
1020
1021
return mktime(&tm);
1022
}
1023
1024
1025
static zip_extra_field_t *
1026
_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
1027
const zip_uint8_t *raw;
1028
zip_uint32_t len;
1029
zip_buffer_t *buffer;
1030
zip_extra_field_t *ef;
1031
1032
if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
1033
/* error already set */
1034
return NULL;
1035
}
1036
1037
if (len + 5 > ZIP_UINT16_MAX) {
1038
zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
1039
return NULL;
1040
}
1041
1042
if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
1043
zip_error_set(error, ZIP_ER_MEMORY, 0);
1044
return NULL;
1045
}
1046
1047
_zip_buffer_put_8(buffer, 1);
1048
_zip_buffer_put_32(buffer, _zip_string_crc32(str));
1049
_zip_buffer_put(buffer, raw, len);
1050
1051
if (!_zip_buffer_ok(buffer)) {
1052
zip_error_set(error, ZIP_ER_INTERNAL, 0);
1053
_zip_buffer_free(buffer);
1054
return NULL;
1055
}
1056
1057
ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
1058
_zip_buffer_free(buffer);
1059
1060
return ef;
1061
}
1062
1063
1064
zip_dirent_t *
1065
_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1066
if (error == NULL)
1067
error = &za->error;
1068
1069
if (idx >= za->nentry) {
1070
zip_error_set(error, ZIP_ER_INVAL, 0);
1071
return NULL;
1072
}
1073
1074
if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1075
if (za->entry[idx].orig == NULL) {
1076
zip_error_set(error, ZIP_ER_INVAL, 0);
1077
return NULL;
1078
}
1079
if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
1080
zip_error_set(error, ZIP_ER_DELETED, 0);
1081
return NULL;
1082
}
1083
return za->entry[idx].orig;
1084
}
1085
else
1086
return za->entry[idx].changes;
1087
}
1088
1089
1090
void
1091
_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
1092
struct tm *tpm;
1093
1094
#ifdef HAVE_LOCALTIME_R
1095
struct tm tm;
1096
tpm = localtime_r(&intime, &tm);
1097
#else
1098
tpm = localtime(&intime);
1099
#endif
1100
if (tpm == NULL) {
1101
/* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
1102
*ddate = (1 << 5) + 1;
1103
*dtime = 0;
1104
return;
1105
}
1106
if (tpm->tm_year < 80) {
1107
tpm->tm_year = 80;
1108
}
1109
1110
*ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1111
*dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1112
1113
return;
1114
}
1115
1116
1117
void
1118
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) {
1119
zip_uint16_t length;
1120
1121
if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1122
zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1123
de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1124
}
1125
if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
1126
de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
1127
}
1128
/* manually set attributes are preferred over attributes provided by source */
1129
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
1130
de->ext_attrib = attributes->external_file_attributes;
1131
}
1132
1133
if (de->comp_method == ZIP_CM_LZMA) {
1134
de->version_needed = 63;
1135
}
1136
else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1137
de->version_needed = 51;
1138
}
1139
else if (de->comp_method == ZIP_CM_BZIP2) {
1140
de->version_needed = 46;
1141
}
1142
else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1143
de->version_needed = 45;
1144
}
1145
else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1146
de->version_needed = 20;
1147
}
1148
else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
1149
de->version_needed = 20;
1150
}
1151
else {
1152
de->version_needed = 10;
1153
}
1154
1155
if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1156
de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
1157
}
1158
1159
de->version_madeby = 63 | (de->version_madeby & 0xff00);
1160
if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
1161
de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
1162
}
1163
}
1164
1165