Coverage Report

Created: 2026-10-28 07:26

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