Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzip/lib/zip_dirent.c
Line
Count
Source
1
/*
2
  zip_dirent.c -- read directory entry (local or central), clean dirent
3
  Copyright (C) 1999-2025 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 <info@libzip.org>
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
#include "zipint.h"
35
36
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <sys/types.h>
41
#include <time.h>
42
#include <zlib.h>
43
44
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency);
45
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
46
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
47
48
49
0
void _zip_cdir_free(zip_cdir_t *cd) {
50
0
    zip_uint64_t i;
51
52
0
    if (cd == NULL) {
53
0
        return;
54
0
    }
55
56
0
    for (i = 0; i < cd->nentry; i++) {
57
0
        _zip_entry_finalize(cd->entry + i);
58
0
    }
59
0
    free(cd->entry);
60
0
    _zip_string_free(cd->comment);
61
0
    free(cd);
62
0
}
63
64
65
0
zip_cdir_t *_zip_cdir_new(zip_error_t *error) {
66
0
    zip_cdir_t *cd;
67
68
0
    if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
69
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
70
0
        return NULL;
71
0
    }
72
73
0
    cd->entry = NULL;
74
0
    cd->nentry = cd->nentry_alloc = 0;
75
0
    cd->size = cd->offset = 0;
76
0
    cd->comment = NULL;
77
0
    cd->is_zip64 = false;
78
79
0
    return cd;
80
0
}
81
82
83
0
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
84
0
    zip_uint64_t i;
85
86
0
    if (additional_entries == 0) {
87
0
        return true;
88
0
    }
89
90
0
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
91
0
        return false;
92
0
    }
93
94
0
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
95
0
        _zip_entry_init(cd->entry + i);
96
0
    }
97
98
0
    cd->nentry = cd->nentry_alloc;
99
100
0
    return true;
101
0
}
102
103
104
0
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
105
0
    zip_uint64_t offset, size;
106
0
    zip_string_t *comment;
107
0
    zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
108
0
    zip_buffer_t *buffer;
109
0
    zip_int64_t off;
110
0
    zip_uint64_t i;
111
0
    zip_uint32_t cdir_crc;
112
113
0
    if ((off = zip_source_tell_write(za->src)) < 0) {
114
0
        zip_error_set_from_source(&za->error, za->src);
115
0
        return -1;
116
0
    }
117
0
    offset = (zip_uint64_t)off;
118
119
0
    if (ZIP_WANT_TORRENTZIP(za)) {
120
0
        cdir_crc = (zip_uint32_t)crc32(0, NULL, 0);
121
0
        za->write_crc = &cdir_crc;
122
0
    }
123
124
0
    for (i = 0; i < survivors; i++) {
125
0
        zip_entry_t *entry = za->entry + filelist[i].idx;
126
127
0
        if (_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL) < 0) {
128
0
            za->write_crc = NULL;
129
0
            return -1;
130
0
        }
131
0
    }
132
133
0
    za->write_crc = NULL;
134
135
0
    if ((off = zip_source_tell_write(za->src)) < 0) {
136
0
        zip_error_set_from_source(&za->error, za->src);
137
0
        return -1;
138
0
    }
139
0
    size = (zip_uint64_t)off - offset;
140
141
0
    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
142
0
        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
143
0
        return -1;
144
0
    }
145
146
0
    if (survivors > ZIP_UINT16_MAX || offset > ZIP_UINT32_MAX || size > ZIP_UINT32_MAX) {
147
0
        _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
148
0
        _zip_buffer_put_64(buffer, EOCD64LEN - 12);
149
0
        _zip_buffer_put_16(buffer, 45);
150
0
        _zip_buffer_put_16(buffer, 45);
151
0
        _zip_buffer_put_32(buffer, 0);
152
0
        _zip_buffer_put_32(buffer, 0);
153
0
        _zip_buffer_put_64(buffer, survivors);
154
0
        _zip_buffer_put_64(buffer, survivors);
155
0
        _zip_buffer_put_64(buffer, size);
156
0
        _zip_buffer_put_64(buffer, offset);
157
0
        _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
158
0
        _zip_buffer_put_32(buffer, 0);
159
0
        _zip_buffer_put_64(buffer, offset + size);
160
0
        _zip_buffer_put_32(buffer, 1);
161
0
    }
162
163
0
    _zip_buffer_put(buffer, EOCD_MAGIC, 4);
164
0
    _zip_buffer_put_32(buffer, 0);
165
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
166
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
167
0
    _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
168
0
    _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
169
170
0
    comment = za->comment_changed ? za->comment_changes : za->comment_orig;
171
172
0
    if (ZIP_WANT_TORRENTZIP(za)) {
173
0
        _zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH);
174
0
    }
175
0
    else {
176
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
177
0
    }
178
179
180
0
    if (!_zip_buffer_ok(buffer)) {
181
0
        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
182
0
        _zip_buffer_free(buffer);
183
0
        return -1;
184
0
    }
185
186
0
    if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
187
0
        _zip_buffer_free(buffer);
188
0
        return -1;
189
0
    }
190
191
0
    _zip_buffer_free(buffer);
192
193
0
    if (ZIP_WANT_TORRENTZIP(za)) {
194
0
        char torrentzip_comment[TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH + 1];
195
0
        snprintf(torrentzip_comment, sizeof(torrentzip_comment), TORRENTZIP_SIGNATURE "%08X", cdir_crc);
196
197
0
        if (_zip_write(za, torrentzip_comment, strlen(torrentzip_comment)) < 0) {
198
0
            return -1;
199
0
        }
200
0
    }
201
0
    else if (comment != NULL) {
202
0
        if (_zip_write(za, comment->raw, comment->length) < 0) {
203
0
            return -1;
204
0
        }
205
0
    }
206
207
0
    return (zip_int64_t)size;
208
0
}
209
210
211
0
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *sde) {
212
0
    zip_dirent_t *tde;
213
214
0
    if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL) {
215
0
        return NULL;
216
0
    }
217
218
0
    if (sde) {
219
0
        (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
220
0
    }
221
0
    else {
222
0
        _zip_dirent_init(tde);
223
0
    }
224
225
0
    tde->changed = 0;
226
0
    tde->cloned = 1;
227
228
0
    return tde;
229
0
}
230
231
232
0
void _zip_dirent_finalize(zip_dirent_t *zde) {
233
0
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
234
0
        _zip_string_free(zde->filename);
235
0
        zde->filename = NULL;
236
0
    }
237
0
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
238
0
        _zip_ef_free(zde->extra_fields);
239
0
        zde->extra_fields = NULL;
240
0
    }
241
0
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
242
0
        _zip_string_free(zde->comment);
243
0
        zde->comment = NULL;
244
0
    }
245
0
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
246
0
        if (zde->password) {
247
0
            _zip_crypto_clear(zde->password, strlen(zde->password));
248
0
        }
249
0
        free(zde->password);
250
0
        zde->password = NULL;
251
0
    }
252
0
}
253
254
255
0
void _zip_dirent_free(zip_dirent_t *zde) {
256
0
    if (zde == NULL) {
257
0
        return;
258
0
    }
259
260
0
    _zip_dirent_finalize(zde);
261
0
    free(zde);
262
0
}
263
264
265
0
bool _zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error) {
266
0
    if (!de->cloned) {
267
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
268
0
        return false;
269
0
    }
270
271
0
    if (!(de->changed & ZIP_DIRENT_ATTRIBUTES)) {
272
0
        de->ext_attrib = de_orig->ext_attrib;
273
0
        de->int_attrib = de_orig->int_attrib;
274
0
    }
275
0
    if (!(de->changed & ZIP_DIRENT_COMMENT)) {
276
0
        de->comment = de_orig->comment;
277
0
    }
278
0
    if (!(de->changed & ZIP_DIRENT_COMP_METHOD)) {
279
0
        if (replacing_data) {
280
0
            de->comp_method = ZIP_CM_DEFAULT;
281
0
            de->compression_level = 0;
282
0
        }
283
0
        else {
284
0
            de->comp_method = de_orig->comp_method;
285
0
            de->compression_level = de_orig->compression_level;
286
0
        }
287
0
    }
288
0
    if (!(de->changed & ZIP_DIRENT_ENCRYPTION_METHOD)) {
289
0
        if (replacing_data) {
290
0
            de->encryption_method = ZIP_EM_NONE;
291
0
        }
292
0
        else {
293
0
            de->encryption_method = de_orig->encryption_method;
294
0
        }
295
0
    }
296
0
    if (!(de->changed & ZIP_DIRENT_EXTRA_FIELD)) {
297
0
        de->extra_fields = de_orig->extra_fields;
298
0
    }
299
0
    if (!(de->changed & ZIP_DIRENT_FILENAME)) {
300
0
        de->filename = de_orig->filename;
301
0
    }
302
0
    if (!(de->changed & ZIP_DIRENT_LAST_MOD)) {
303
0
        de->last_mod = de_orig->last_mod;
304
0
    }
305
0
    if (!(de->changed & ZIP_DIRENT_PASSWORD)) {
306
0
        de->password = de_orig->password;
307
0
    }
308
309
0
    return true;
310
0
}
311
312
313
0
void _zip_dirent_init(zip_dirent_t *de) {
314
0
    de->changed = 0;
315
0
    de->local_extra_fields_read = 0;
316
0
    de->cloned = 0;
317
318
0
    de->crc_valid = true;
319
0
    de->last_mod_mtime_valid = false;
320
0
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
321
0
    de->version_needed = 10; /* 1.0 */
322
0
    de->bitflags = 0;
323
0
    de->comp_method = ZIP_CM_DEFAULT;
324
0
    de->last_mod.date = 0;
325
0
    de->last_mod.time = 0;
326
0
    de->crc = 0;
327
0
    de->comp_size = 0;
328
0
    de->uncomp_size = 0;
329
0
    de->filename = NULL;
330
0
    de->extra_fields = NULL;
331
0
    de->comment = NULL;
332
0
    de->disk_number = 0;
333
0
    de->int_attrib = 0;
334
0
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
335
0
    de->offset = 0;
336
0
    de->compression_level = 0;
337
0
    de->encryption_method = ZIP_EM_NONE;
338
0
    de->password = NULL;
339
0
}
340
341
342
0
bool _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
343
0
    if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) {
344
0
        return true;
345
0
    }
346
347
0
    return false;
348
0
}
349
350
351
0
zip_dirent_t *_zip_dirent_new(void) {
352
0
    zip_dirent_t *de;
353
354
0
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) {
355
0
        return NULL;
356
0
    }
357
358
0
    _zip_dirent_init(de);
359
0
    return de;
360
0
}
361
362
363
/*
364
   Fills the zip directory entry zde.
365
366
   If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
367
368
   If local is true, it reads a local header instead of a central directory entry.
369
370
   Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
371
*/
372
373
0
zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_uint64_t central_compressed_size, bool check_consistency, zip_error_t *error) {
374
0
    zip_uint8_t buf[CDENTRYSIZE];
375
0
    zip_uint32_t size, variable_size;
376
0
    zip_uint16_t filename_len, comment_len, ef_len;
377
0
    zip_string_t *utf8_string;
378
0
    bool is_zip64 = false;
379
380
0
    bool from_buffer = (buffer != NULL);
381
382
0
    size = local ? LENTRYSIZE : CDENTRYSIZE;
383
384
0
    if (buffer) {
385
0
        if (_zip_buffer_left(buffer) < size) {
386
0
            zip_error_set(error, ZIP_ER_NOZIP, 0);
387
0
            return -1;
388
0
        }
389
0
    }
390
0
    else {
391
0
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
392
0
            return -1;
393
0
        }
394
0
    }
395
396
0
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
397
0
        zip_error_set(error, ZIP_ER_NOZIP, 0);
398
0
        if (!from_buffer) {
399
0
            _zip_buffer_free(buffer);
400
0
        }
401
0
        return -1;
402
0
    }
403
404
    /* convert buffercontents to zip_dirent */
405
406
0
    _zip_dirent_init(zde);
407
0
    if (!local) {
408
0
        zde->version_madeby = _zip_buffer_get_16(buffer);
409
0
    }
410
0
    else {
411
0
        zde->version_madeby = 0;
412
0
    }
413
0
    zde->version_needed = _zip_buffer_get_16(buffer);
414
0
    zde->bitflags = _zip_buffer_get_16(buffer);
415
0
    zde->comp_method = _zip_buffer_get_16(buffer);
416
417
    /* convert to time_t */
418
0
    zde->last_mod.time = _zip_buffer_get_16(buffer);
419
0
    zde->last_mod.date = _zip_buffer_get_16(buffer);
420
421
0
    zde->crc = _zip_buffer_get_32(buffer);
422
0
    zde->comp_size = _zip_buffer_get_32(buffer);
423
0
    zde->uncomp_size = _zip_buffer_get_32(buffer);
424
425
0
    filename_len = _zip_buffer_get_16(buffer);
426
0
    ef_len = _zip_buffer_get_16(buffer);
427
428
0
    if (local) {
429
0
        comment_len = 0;
430
0
        zde->disk_number = 0;
431
0
        zde->int_attrib = 0;
432
0
        zde->ext_attrib = 0;
433
0
        zde->offset = 0;
434
0
    }
435
0
    else {
436
0
        comment_len = _zip_buffer_get_16(buffer);
437
0
        zde->disk_number = _zip_buffer_get_16(buffer);
438
0
        zde->int_attrib = _zip_buffer_get_16(buffer);
439
0
        zde->ext_attrib = _zip_buffer_get_32(buffer);
440
0
        zde->offset = _zip_buffer_get_32(buffer);
441
0
    }
442
443
0
    if (!_zip_buffer_ok(buffer)) {
444
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
445
0
        if (!from_buffer) {
446
0
            _zip_buffer_free(buffer);
447
0
        }
448
0
        return -1;
449
0
    }
450
451
0
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
452
0
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
453
            /* TODO */
454
0
            zde->encryption_method = ZIP_EM_UNKNOWN;
455
0
        }
456
0
        else {
457
0
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
458
0
        }
459
0
    }
460
0
    else {
461
0
        zde->encryption_method = ZIP_EM_NONE;
462
0
    }
463
464
0
    zde->filename = NULL;
465
0
    zde->extra_fields = NULL;
466
0
    zde->comment = NULL;
467
468
0
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
469
470
0
    if (from_buffer) {
471
0
        if (_zip_buffer_left(buffer) < variable_size) {
472
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
473
0
            return -1;
474
0
        }
475
0
    }
476
0
    else {
477
0
        _zip_buffer_free(buffer);
478
479
0
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
480
0
            return -1;
481
0
        }
482
0
    }
483
484
0
    if (filename_len) {
485
0
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
486
0
        if (zde->filename == NULL) {
487
0
            if (zip_error_code_zip(error) == ZIP_ER_EOF) {
488
0
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
489
0
            }
490
0
            if (!from_buffer) {
491
0
                _zip_buffer_free(buffer);
492
0
            }
493
0
            return -1;
494
0
        }
495
496
0
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
497
0
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
498
0
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
499
0
                if (!from_buffer) {
500
0
                    _zip_buffer_free(buffer);
501
0
                }
502
0
                return -1;
503
0
            }
504
0
        }
505
506
0
        if (check_consistency) {
507
0
            zip_uint8_t *p;
508
509
0
            for (p = zde->filename->raw; p < zde->filename->raw + zde->filename->length; p++) {
510
0
                if (*p == 0) {
511
0
                    zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_NUL_IN_FILENAME);
512
0
                    if (!from_buffer) {
513
0
                        _zip_buffer_free(buffer);
514
0
                    }
515
0
                    return -1;
516
0
                }
517
0
            }
518
0
        }
519
0
    }
520
521
0
    if (ef_len) {
522
0
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
523
524
0
        if (ef == NULL) {
525
0
            if (!from_buffer) {
526
0
                _zip_buffer_free(buffer);
527
0
            }
528
0
            return -1;
529
0
        }
530
0
        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
531
0
            free(ef);
532
0
            if (!from_buffer) {
533
0
                _zip_buffer_free(buffer);
534
0
            }
535
0
            return -1;
536
0
        }
537
0
        free(ef);
538
0
        if (local) {
539
0
            zde->local_extra_fields_read = 1;
540
0
        }
541
0
    }
542
543
0
    if (comment_len) {
544
0
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
545
0
        if (zde->comment == NULL) {
546
0
            if (!from_buffer) {
547
0
                _zip_buffer_free(buffer);
548
0
            }
549
0
            return -1;
550
0
        }
551
0
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
552
0
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
553
0
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
554
0
                if (!from_buffer) {
555
0
                    _zip_buffer_free(buffer);
556
0
                }
557
0
                return -1;
558
0
            }
559
0
        }
560
0
    }
561
562
0
    if ((utf8_string = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename, check_consistency)) == NULL && zde->filename != NULL) {
563
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_UTF8_FILENAME_MISMATCH);
564
0
        if (!from_buffer) {
565
0
            _zip_buffer_free(buffer);
566
0
        }
567
0
        return -1;
568
0
    }
569
0
    zde->filename = utf8_string;
570
0
    if (!local) {
571
0
        if ((utf8_string = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment, check_consistency)) == NULL && zde->comment != NULL) {
572
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_UTF8_COMMENT_MISMATCH);
573
0
            if (!from_buffer) {
574
0
                _zip_buffer_free(buffer);
575
0
            }
576
0
            return -1;
577
0
        }
578
0
        zde->comment = utf8_string;
579
0
    }
580
581
    /* Zip64 */
582
583
0
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
584
0
        zip_uint16_t got_len;
585
0
        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);
586
0
        if (ef != NULL) {
587
0
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
588
0
                if (!from_buffer) {
589
0
                    _zip_buffer_free(buffer);
590
0
                }
591
0
                return -1;
592
0
            }
593
0
        }
594
0
        is_zip64 = true;
595
0
    }
596
597
598
0
    if (!_zip_buffer_ok(buffer)) {
599
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
600
0
        if (!from_buffer) {
601
0
            _zip_buffer_free(buffer);
602
0
        }
603
0
        return -1;
604
0
    }
605
606
0
    if (!from_buffer) {
607
0
        _zip_buffer_free(buffer);
608
0
    }
609
610
0
    if (local && zde->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
611
0
        zip_uint32_t df_crc;
612
0
        zip_uint64_t df_comp_size, df_uncomp_size;
613
0
        if (zip_source_seek(src, central_compressed_size, SEEK_CUR) != 0 || (buffer = _zip_buffer_new_from_source(src, MAX_DATA_DESCRIPTOR_LENGTH, buf, error)) == NULL) {
614
0
            return -1;
615
0
        }
616
0
        if (memcmp(_zip_buffer_peek(buffer, MAGIC_LEN), DATADES_MAGIC, MAGIC_LEN) == 0) {
617
0
            _zip_buffer_skip(buffer, MAGIC_LEN);
618
0
        }
619
0
        df_crc = _zip_buffer_get_32(buffer);
620
0
        df_comp_size = is_zip64 ? _zip_buffer_get_64(buffer) : _zip_buffer_get_32(buffer);
621
0
        df_uncomp_size = is_zip64 ? _zip_buffer_get_64(buffer) : _zip_buffer_get_32(buffer);
622
623
0
        if (!_zip_buffer_ok(buffer)) {
624
0
            zip_error_set(error, ZIP_ER_INTERNAL, 0);
625
0
            _zip_buffer_free(buffer);
626
0
            return -1;
627
0
        }
628
0
        _zip_buffer_free(buffer);
629
630
0
        if ((zde->crc != 0 && zde->crc != df_crc) || (zde->comp_size != 0 && zde->comp_size != df_comp_size) || (zde->uncomp_size != 0 && zde->uncomp_size != df_uncomp_size)) {
631
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_DATA_DESCRIPTOR_MISMATCH);
632
0
            return -1;
633
0
        }
634
0
        zde->crc = df_crc;
635
0
        zde->comp_size = df_comp_size;
636
0
        zde->uncomp_size = df_uncomp_size;
637
0
    }
638
639
    /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
640
0
    if (zde->offset > ZIP_INT64_MAX) {
641
0
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
642
0
        return -1;
643
0
    }
644
645
0
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
646
0
        return -1;
647
0
    }
648
649
0
    zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
650
651
0
    return (zip_int64_t)size + (zip_int64_t)variable_size;
652
0
}
653
654
0
bool zip_dirent_process_ef_zip64(zip_dirent_t *zde, const zip_uint8_t *ef, zip_uint64_t got_len, bool local, zip_error_t *error) {
655
0
    zip_buffer_t *ef_buffer;
656
657
0
    if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
658
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
659
0
        return false;
660
0
    }
661
662
0
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
663
0
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
664
0
    }
665
0
    else if (local) {
666
        /* From appnote.txt: This entry in the Local header MUST
667
           include BOTH original and compressed file size fields. */
668
0
        (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
669
0
    }
670
0
    if (zde->comp_size == ZIP_UINT32_MAX) {
671
0
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
672
0
    }
673
0
    if (!local) {
674
0
        if (zde->offset == ZIP_UINT32_MAX) {
675
0
            zde->offset = _zip_buffer_get_64(ef_buffer);
676
0
        }
677
0
        if (zde->disk_number == ZIP_UINT16_MAX) {
678
0
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
679
0
        }
680
0
    }
681
682
0
    if (!_zip_buffer_eof(ef_buffer)) {
683
        /* accept additional fields if values match */
684
0
        bool ok = true;
685
0
        switch (got_len) {
686
0
        case 28:
687
0
            _zip_buffer_set_offset(ef_buffer, 24);
688
0
            if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
689
0
                ok = false;
690
0
            }
691
            /* fallthrough */
692
0
        case 24:
693
0
            _zip_buffer_set_offset(ef_buffer, 0);
694
0
            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))) {
695
0
                ok = false;
696
0
            }
697
0
            break;
698
699
0
        default:
700
0
            ok = false;
701
0
        }
702
0
        if (!ok) {
703
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
704
0
            _zip_buffer_free(ef_buffer);
705
0
            return false;
706
0
        }
707
0
    }
708
0
    _zip_buffer_free(ef_buffer);
709
710
0
    return true;
711
0
}
712
713
714
0
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency) {
715
0
    zip_uint16_t ef_len;
716
0
    zip_uint32_t ef_crc;
717
0
    zip_buffer_t *buffer;
718
719
0
    const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
720
721
0
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
722
0
        return str;
723
0
    }
724
725
0
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
726
0
        return str;
727
0
    }
728
729
0
    _zip_buffer_get_8(buffer);
730
0
    ef_crc = _zip_buffer_get_32(buffer);
731
732
0
    if (_zip_string_crc32(str) == ef_crc) {
733
0
        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
734
0
        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
735
736
0
        if (ef_str != NULL) {
737
0
            if (check_consistency) {
738
0
                if (!_zip_string_equal(str, ef_str) && _zip_string_is_ascii(ef_str)) {
739
0
                    _zip_string_free(ef_str);
740
0
                    _zip_buffer_free(buffer);
741
0
                    return NULL;
742
0
                }
743
0
            }
744
745
0
            _zip_string_free(str);
746
0
            str = ef_str;
747
0
        }
748
0
    }
749
750
0
    _zip_buffer_free(buffer);
751
752
0
    return str;
753
0
}
754
755
756
0
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
757
0
    zip_uint16_t ef_len;
758
0
    zip_buffer_t *buffer;
759
0
    const zip_uint8_t *ef;
760
0
    bool crc_valid;
761
0
    zip_uint16_t enc_method;
762
763
764
0
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
765
0
        return true;
766
0
    }
767
768
0
    ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
769
770
0
    if (ef == NULL || ef_len < 7) {
771
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
772
0
        return false;
773
0
    }
774
775
0
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
776
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
777
0
        return false;
778
0
    }
779
780
    /* version */
781
782
0
    crc_valid = true;
783
0
    switch (_zip_buffer_get_16(buffer)) {
784
0
    case 1:
785
0
        break;
786
787
0
    case 2:
788
0
        crc_valid = false;
789
        /* TODO: When checking consistency, check that crc is 0. */
790
0
        break;
791
792
0
    default:
793
0
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
794
0
        _zip_buffer_free(buffer);
795
0
        return false;
796
0
    }
797
798
    /* vendor */
799
0
    if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
800
0
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
801
0
        _zip_buffer_free(buffer);
802
0
        return false;
803
0
    }
804
805
    /* mode */
806
0
    switch (_zip_buffer_get_8(buffer)) {
807
0
    case 1:
808
0
        enc_method = ZIP_EM_AES_128;
809
0
        break;
810
0
    case 2:
811
0
        enc_method = ZIP_EM_AES_192;
812
0
        break;
813
0
    case 3:
814
0
        enc_method = ZIP_EM_AES_256;
815
0
        break;
816
0
    default:
817
0
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
818
0
        _zip_buffer_free(buffer);
819
0
        return false;
820
0
    }
821
822
0
    if (ef_len != 7) {
823
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
824
0
        _zip_buffer_free(buffer);
825
0
        return false;
826
0
    }
827
828
0
    de->crc_valid = crc_valid;
829
0
    de->encryption_method = enc_method;
830
0
    de->comp_method = _zip_buffer_get_16(buffer);
831
832
0
    _zip_buffer_free(buffer);
833
0
    return true;
834
0
}
835
836
837
0
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
838
0
    zip_int32_t size;
839
0
    bool local = (flags & ZIP_EF_LOCAL) != 0;
840
0
    int i;
841
0
    zip_uint8_t b[6];
842
0
    zip_buffer_t *buffer;
843
844
0
    size = local ? LENTRYSIZE : CDENTRYSIZE;
845
846
0
    if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
847
0
        zip_error_set_from_source(error, src);
848
0
        return -1;
849
0
    }
850
851
0
    if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
852
0
        return -1;
853
0
    }
854
855
0
    for (i = 0; i < (local ? 2 : 3); i++) {
856
0
        size += _zip_buffer_get_16(buffer);
857
0
    }
858
859
0
    if (!_zip_buffer_eof(buffer)) {
860
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
861
0
        _zip_buffer_free(buffer);
862
0
        return -1;
863
0
    }
864
865
0
    _zip_buffer_free(buffer);
866
0
    return size;
867
0
}
868
869
870
/* _zip_dirent_write
871
   Writes zip directory entry.
872
873
   If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
874
   directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
875
876
   Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
877
   returned.
878
*/
879
880
0
int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
881
0
    zip_dostime_t dostime;
882
0
    zip_encoding_type_t com_enc, name_enc;
883
0
    zip_extra_field_t *ef;
884
0
    zip_extra_field_t *ef64;
885
0
    zip_uint32_t ef_total_size;
886
0
    bool is_zip64;
887
0
    bool is_really_zip64;
888
0
    bool is_winzip_aes;
889
0
    zip_uint8_t buf[CDENTRYSIZE];
890
0
    zip_buffer_t *buffer;
891
892
0
    ef = NULL;
893
894
0
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
895
0
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
896
897
0
    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)) {
898
0
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
899
0
    }
900
0
    else {
901
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
902
0
        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
903
0
            ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
904
0
            if (ef == NULL) {
905
0
                return -1;
906
0
            }
907
0
        }
908
0
        if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
909
0
            zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
910
0
            if (ef2 == NULL) {
911
0
                _zip_ef_free(ef);
912
0
                return -1;
913
0
            }
914
0
            ef2->next = ef;
915
0
            ef = ef2;
916
0
        }
917
0
    }
918
919
0
    if (de->encryption_method == ZIP_EM_NONE) {
920
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
921
0
    }
922
0
    else {
923
0
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
924
0
    }
925
926
0
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
927
0
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
928
0
    is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
929
930
0
    if (is_zip64) {
931
0
        zip_uint8_t ef_zip64[EFZIP64SIZE];
932
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
933
0
        if (ef_buffer == NULL) {
934
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
935
0
            _zip_ef_free(ef);
936
0
            return -1;
937
0
        }
938
939
0
        if (flags & ZIP_FL_LOCAL) {
940
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
941
0
                _zip_buffer_put_64(ef_buffer, de->uncomp_size);
942
0
                _zip_buffer_put_64(ef_buffer, de->comp_size);
943
0
            }
944
0
        }
945
0
        else {
946
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
947
0
                if (de->uncomp_size >= ZIP_UINT32_MAX) {
948
0
                    _zip_buffer_put_64(ef_buffer, de->uncomp_size);
949
0
                }
950
0
                if (de->comp_size >= ZIP_UINT32_MAX) {
951
0
                    _zip_buffer_put_64(ef_buffer, de->comp_size);
952
0
                }
953
0
                if (de->offset >= ZIP_UINT32_MAX) {
954
0
                    _zip_buffer_put_64(ef_buffer, de->offset);
955
0
                }
956
0
            }
957
0
        }
958
959
0
        if (!_zip_buffer_ok(ef_buffer)) {
960
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
961
0
            _zip_buffer_free(ef_buffer);
962
0
            _zip_ef_free(ef);
963
0
            return -1;
964
0
        }
965
966
0
        ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
967
0
        _zip_buffer_free(ef_buffer);
968
0
        if (ef64 == NULL) {
969
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
970
0
            _zip_ef_free(ef);
971
0
            return -1;
972
0
        }
973
0
        ef64->next = ef;
974
0
        ef = ef64;
975
0
    }
976
977
0
    if (is_winzip_aes) {
978
0
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
979
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
980
0
        zip_extra_field_t *ef_winzip;
981
982
0
        if (ef_buffer == NULL) {
983
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
984
0
            _zip_ef_free(ef);
985
0
            return -1;
986
0
        }
987
988
0
        _zip_buffer_put_16(ef_buffer, 2);
989
0
        _zip_buffer_put(ef_buffer, "AE", 2);
990
0
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
991
0
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
992
993
0
        if (!_zip_buffer_ok(ef_buffer)) {
994
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
995
0
            _zip_buffer_free(ef_buffer);
996
0
            _zip_ef_free(ef);
997
0
            return -1;
998
0
        }
999
1000
0
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
1001
0
        _zip_buffer_free(ef_buffer);
1002
0
        if (ef_winzip == NULL) {
1003
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1004
0
            _zip_ef_free(ef);
1005
0
            return -1;
1006
0
        }
1007
0
        ef_winzip->next = ef;
1008
0
        ef = ef_winzip;
1009
0
    }
1010
1011
0
    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
1012
0
        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1013
0
        _zip_ef_free(ef);
1014
0
        return -1;
1015
0
    }
1016
1017
0
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
1018
1019
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1020
0
        _zip_buffer_put_16(buffer, de->version_madeby);
1021
0
    }
1022
0
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1023
0
    _zip_buffer_put_16(buffer, de->bitflags);
1024
0
    if (is_winzip_aes) {
1025
0
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1026
0
    }
1027
0
    else {
1028
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1029
0
    }
1030
1031
0
    if (ZIP_WANT_TORRENTZIP(za)) {
1032
0
        dostime.time = 0xbc00;
1033
0
        dostime.date = 0x2198;
1034
0
    }
1035
0
    else {
1036
0
        dostime = de->last_mod;
1037
0
    }
1038
0
    _zip_buffer_put_16(buffer, dostime.time);
1039
0
    _zip_buffer_put_16(buffer, dostime.date);
1040
1041
0
    if (is_winzip_aes && de->uncomp_size < 20) {
1042
0
        _zip_buffer_put_32(buffer, 0);
1043
0
    }
1044
0
    else {
1045
0
        _zip_buffer_put_32(buffer, de->crc);
1046
0
    }
1047
1048
0
    if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
1049
        /* In local headers, if a ZIP64 EF is written, it MUST contain
1050
         * both compressed and uncompressed sizes (even if one of the
1051
         * two is smaller than 0xFFFFFFFF); on the other hand, those
1052
         * may only appear when the corresponding standard entry is
1053
         * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
1054
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1055
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1056
0
    }
1057
0
    else {
1058
0
        if (de->comp_size < ZIP_UINT32_MAX) {
1059
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1060
0
        }
1061
0
        else {
1062
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1063
0
        }
1064
0
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1065
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1066
0
        }
1067
0
        else {
1068
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1069
0
        }
1070
0
    }
1071
1072
0
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1073
0
    ef_total_size = (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
1074
0
    if (!ZIP_WANT_TORRENTZIP(za)) {
1075
        /* TODO: check for overflow */
1076
0
        ef_total_size += (zip_uint32_t)_zip_ef_size(de->extra_fields, flags);
1077
0
    }
1078
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
1079
1080
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1081
0
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1082
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1083
0
        _zip_buffer_put_16(buffer, de->int_attrib);
1084
0
        _zip_buffer_put_32(buffer, de->ext_attrib);
1085
0
        if (de->offset < ZIP_UINT32_MAX) {
1086
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1087
0
        }
1088
0
        else {
1089
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1090
0
        }
1091
0
    }
1092
1093
0
    if (!_zip_buffer_ok(buffer)) {
1094
0
        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
1095
0
        _zip_buffer_free(buffer);
1096
0
        _zip_ef_free(ef);
1097
0
        return -1;
1098
0
    }
1099
1100
0
    if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
1101
0
        _zip_buffer_free(buffer);
1102
0
        _zip_ef_free(ef);
1103
0
        return -1;
1104
0
    }
1105
1106
0
    _zip_buffer_free(buffer);
1107
1108
0
    if (de->filename) {
1109
0
        if (_zip_string_write(za, de->filename) < 0) {
1110
0
            _zip_ef_free(ef);
1111
0
            return -1;
1112
0
        }
1113
0
    }
1114
1115
0
    if (ef) {
1116
0
        if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
1117
0
            _zip_ef_free(ef);
1118
0
            return -1;
1119
0
        }
1120
0
    }
1121
0
    _zip_ef_free(ef);
1122
0
    if (de->extra_fields && !ZIP_WANT_TORRENTZIP(za)) {
1123
0
        if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
1124
0
            return -1;
1125
0
        }
1126
0
    }
1127
1128
0
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1129
0
        if (de->comment) {
1130
0
            if (_zip_string_write(za, de->comment) < 0) {
1131
0
                return -1;
1132
0
            }
1133
0
        }
1134
0
    }
1135
1136
1137
0
    return is_zip64;
1138
0
}
1139
1140
1141
0
time_t _zip_d2u_time(const zip_dostime_t *dtime) {
1142
0
    struct tm tm;
1143
1144
0
    memset(&tm, 0, sizeof(tm));
1145
1146
    /* let mktime decide if DST is in effect */
1147
0
    tm.tm_isdst = -1;
1148
1149
0
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1150
0
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1151
0
    tm.tm_mday = dtime->date & 31;
1152
1153
0
    tm.tm_hour = (dtime->time >> 11) & 31;
1154
0
    tm.tm_min = (dtime->time >> 5) & 63;
1155
0
    tm.tm_sec = (dtime->time << 1) & 62;
1156
1157
0
    return mktime(&tm);
1158
0
}
1159
1160
1161
0
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
1162
0
    const zip_uint8_t *raw;
1163
0
    zip_uint32_t len;
1164
0
    zip_buffer_t *buffer;
1165
0
    zip_extra_field_t *ef;
1166
1167
0
    if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
1168
        /* error already set */
1169
0
        return NULL;
1170
0
    }
1171
1172
0
    if (len + 5 > ZIP_UINT16_MAX) {
1173
0
        zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
1174
0
        return NULL;
1175
0
    }
1176
1177
0
    if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
1178
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
1179
0
        return NULL;
1180
0
    }
1181
1182
0
    _zip_buffer_put_8(buffer, 1);
1183
0
    _zip_buffer_put_32(buffer, _zip_string_crc32(str));
1184
0
    _zip_buffer_put(buffer, raw, len);
1185
1186
0
    if (!_zip_buffer_ok(buffer)) {
1187
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
1188
0
        _zip_buffer_free(buffer);
1189
0
        return NULL;
1190
0
    }
1191
1192
0
    ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
1193
0
    _zip_buffer_free(buffer);
1194
1195
0
    return ef;
1196
0
}
1197
1198
1199
0
zip_dirent_t *_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1200
0
    if (error == NULL) {
1201
0
        error = &za->error;
1202
0
    }
1203
1204
0
    if (idx >= za->nentry) {
1205
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1206
0
        return NULL;
1207
0
    }
1208
1209
0
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1210
0
        if (za->entry[idx].orig == NULL) {
1211
0
            zip_error_set(error, ZIP_ER_INVAL, 0);
1212
0
            return NULL;
1213
0
        }
1214
0
        if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
1215
0
            zip_error_set(error, ZIP_ER_DELETED, 0);
1216
0
            return NULL;
1217
0
        }
1218
0
        return za->entry[idx].orig;
1219
0
    }
1220
0
    else {
1221
0
        return za->entry[idx].changes;
1222
0
    }
1223
0
}
1224
1225
1226
0
int _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1227
0
    struct tm *tpm;
1228
0
    struct tm tm;
1229
0
    tpm = zip_localtime(&intime, &tm);
1230
0
    if (tpm == NULL) {
1231
        /* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */
1232
0
        dtime->date = (1 << 5) + 1;
1233
0
        dtime->time = 0;
1234
0
        if (ze) {
1235
0
            zip_error_set(ze, ZIP_ER_INVAL, errno);
1236
0
        }
1237
0
        return -1;
1238
0
    }
1239
0
    if (tpm->tm_year < 80) {
1240
0
        tpm->tm_year = 80;
1241
0
    }
1242
1243
0
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1244
0
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1245
1246
0
    return 0;
1247
0
}
1248
1249
1250
0
bool _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1251
0
    zip_uint16_t length;
1252
0
    bool has_changed = false;
1253
0
    zip_uint16_t version_madeby, version_needed;
1254
1255
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1256
0
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1257
0
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1258
0
        if (de->bitflags != bitflags) {
1259
0
            de->bitflags = bitflags;
1260
0
            has_changed = true;
1261
0
        }
1262
0
    }
1263
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
1264
0
        zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
1265
0
        if (de->int_attrib != int_attrib) {
1266
0
            de->int_attrib = int_attrib;
1267
0
            has_changed = true;
1268
0
        }
1269
0
    }
1270
    /* manually set attributes are preferred over attributes provided by source */
1271
0
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
1272
0
        if (de->ext_attrib != attributes->external_file_attributes) {
1273
0
            de->ext_attrib = attributes->external_file_attributes;
1274
0
            has_changed = true;
1275
0
        }
1276
0
    }
1277
1278
0
    if (de->comp_method == ZIP_CM_LZMA) {
1279
0
        version_needed = 63;
1280
0
    }
1281
0
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1282
0
        version_needed = 51;
1283
0
    }
1284
0
    else if (de->comp_method == ZIP_CM_BZIP2) {
1285
0
        version_needed = 46;
1286
0
    }
1287
0
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1288
0
        version_needed = 45;
1289
0
    }
1290
0
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1291
0
        version_needed = 20;
1292
0
    }
1293
0
    else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
1294
0
        version_needed = 20;
1295
0
    }
1296
0
    else {
1297
0
        version_needed = 10;
1298
0
    }
1299
1300
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1301
0
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1302
0
    }
1303
1304
0
    if (de->version_needed != version_needed) {
1305
0
        de->version_needed = version_needed;
1306
0
        has_changed = true;
1307
0
    }
1308
1309
0
    version_madeby = 63 | (de->version_madeby & 0xff00);
1310
0
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
1311
0
        version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
1312
0
    }
1313
0
    if (de->version_madeby != version_madeby) {
1314
0
        de->version_madeby = version_madeby;
1315
0
        has_changed = true;
1316
0
    }
1317
1318
0
    return has_changed;
1319
0
}
1320
1321
1322
/* _zip_dirent_torrent_normalize(de);
1323
   Set values suitable for torrentzip.
1324
*/
1325
1326
0
void zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
1327
0
    de->version_madeby = 0;
1328
0
    de->version_needed = 20; /* 2.0 */
1329
0
    de->bitflags = 2;        /* maximum compression */
1330
0
    de->comp_method = ZIP_CM_DEFLATE;
1331
0
    de->compression_level = TORRENTZIP_COMPRESSION_FLAGS;
1332
0
    de->disk_number = 0;
1333
0
    de->int_attrib = 0;
1334
0
    de->ext_attrib = 0;
1335
1336
    /* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */
1337
0
}
1338
1339
0
int zip_dirent_check_consistency(zip_dirent_t *dirent) {
1340
0
    if (dirent->comp_method == ZIP_CM_STORE) {
1341
0
        zip_uint64_t header_size = 0;
1342
0
        switch (dirent->encryption_method) {
1343
0
        case ZIP_EM_NONE:
1344
0
            break;
1345
0
        case ZIP_EM_TRAD_PKWARE:
1346
0
            header_size = 12;
1347
0
            break;
1348
0
        case ZIP_EM_AES_128:
1349
0
            header_size = 20;
1350
0
            break;
1351
0
        case ZIP_EM_AES_192:
1352
0
            header_size = 24;
1353
0
            break;
1354
0
        case ZIP_EM_AES_256:
1355
0
            header_size = 28;
1356
0
            break;
1357
1358
0
        default:
1359
0
            return 0;
1360
0
        }
1361
0
        if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
1362
0
            return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
1363
0
        }
1364
0
    }
1365
0
    return 0;
1366
0
}
1367
1368
0
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1369
0
    if (!de->last_mod_mtime_valid) {
1370
0
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1371
0
        de->last_mod_mtime_valid = true;
1372
0
    }
1373
1374
0
    return de->last_mod_mtime;
1375
0
}