2 zip_dirent.c -- read directory entry (local or central), clean dirent
3 Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
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
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
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.
38 #include <sys/types.h>
44 static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
45 static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str);
46 static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
47 static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
51 _zip_cdir_free(zip_cdir_t *cd)
58 for (i=0; i<cd->nentry; i++)
59 _zip_entry_finalize(cd->entry+i);
61 _zip_string_free(cd->comment);
67 _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
71 if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
72 zip_error_set(error, ZIP_ER_MEMORY, 0);
77 cd->nentry = cd->nentry_alloc = 0;
78 cd->size = cd->offset = 0;
82 if (!_zip_cdir_grow(cd, nentry, error)) {
92 _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error)
94 zip_uint64_t i, new_alloc;
95 zip_entry_t *new_entry;
97 if (additional_entries == 0) {
101 new_alloc = cd->nentry_alloc + additional_entries;
103 if (new_alloc < additional_entries || new_alloc > SIZE_MAX/sizeof(*(cd->entry))) {
104 zip_error_set(error, ZIP_ER_MEMORY, 0);
108 if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry))*(size_t)new_alloc)) == NULL) {
109 zip_error_set(error, ZIP_ER_MEMORY, 0);
113 cd->entry = new_entry;
115 for (i = cd->nentry; i < new_alloc; i++) {
116 _zip_entry_init(cd->entry+i);
119 cd->nentry = cd->nentry_alloc = new_alloc;
126 _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
128 zip_uint64_t offset, size;
129 zip_string_t *comment;
130 zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
131 zip_buffer_t *buffer;
137 if ((off = zip_source_tell_write(za->src)) < 0) {
138 _zip_error_set_from_source(&za->error, za->src);
141 offset = (zip_uint64_t)off;
145 for (i=0; i<survivors; i++) {
146 zip_entry_t *entry = za->entry+filelist[i].idx;
148 if ((ret=_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
154 if ((off = zip_source_tell_write(za->src)) < 0) {
155 _zip_error_set_from_source(&za->error, za->src);
158 size = (zip_uint64_t)off - offset;
160 if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
164 if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
165 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
170 _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
171 _zip_buffer_put_64(buffer, EOCD64LEN-12);
172 _zip_buffer_put_16(buffer, 45);
173 _zip_buffer_put_16(buffer, 45);
174 _zip_buffer_put_32(buffer, 0);
175 _zip_buffer_put_32(buffer, 0);
176 _zip_buffer_put_64(buffer, survivors);
177 _zip_buffer_put_64(buffer, survivors);
178 _zip_buffer_put_64(buffer, size);
179 _zip_buffer_put_64(buffer, offset);
180 _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
181 _zip_buffer_put_32(buffer, 0);
182 _zip_buffer_put_64(buffer, offset+size);
183 _zip_buffer_put_32(buffer, 1);
186 _zip_buffer_put(buffer, EOCD_MAGIC, 4);
187 _zip_buffer_put_32(buffer, 0);
188 _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
189 _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
190 _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
191 _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
193 comment = za->comment_changed ? za->comment_changes : za->comment_orig;
195 _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
197 if (!_zip_buffer_ok(buffer)) {
198 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
199 _zip_buffer_free(buffer);
203 if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
204 _zip_buffer_free(buffer);
208 _zip_buffer_free(buffer);
211 if (_zip_write(za, comment->raw, comment->length) < 0) {
216 return (zip_int64_t)size;
221 _zip_dirent_clone(const zip_dirent_t *sde)
225 if ((tde=(zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
229 memcpy(tde, sde, sizeof(*sde));
231 _zip_dirent_init(tde);
241 _zip_dirent_finalize(zip_dirent_t *zde)
243 if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
244 _zip_string_free(zde->filename);
245 zde->filename = NULL;
247 if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
248 _zip_ef_free(zde->extra_fields);
249 zde->extra_fields = NULL;
251 if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
252 _zip_string_free(zde->comment);
255 if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
257 _zip_crypto_clear(zde->password, strlen(zde->password));
260 zde->password = NULL;
266 _zip_dirent_free(zip_dirent_t *zde)
271 _zip_dirent_finalize(zde);
277 _zip_dirent_init(zip_dirent_t *de)
280 de->local_extra_fields_read = 0;
283 de->crc_valid = true;
284 de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
285 de->version_needed = 10; /* 1.0 */
287 de->comp_method = ZIP_CM_DEFAULT;
293 de->extra_fields = NULL;
297 de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
299 de->compression_level = 0;
300 de->encryption_method = ZIP_EM_NONE;
306 _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags)
308 if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX
309 || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
317 _zip_dirent_new(void)
321 if ((de=(zip_dirent_t *)malloc(sizeof(*de))) == NULL)
324 _zip_dirent_init(de);
329 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
330 Fills the zip directory entry zde.
332 If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
334 If local is true, it reads a local header instead of a central directory entry.
336 Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
340 _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error)
342 zip_uint8_t buf[CDENTRYSIZE];
343 zip_uint16_t dostime, dosdate;
344 zip_uint32_t size, variable_size;
345 zip_uint16_t filename_len, comment_len, ef_len;
347 bool from_buffer = (buffer != NULL);
349 size = local ? LENTRYSIZE : CDENTRYSIZE;
352 if (_zip_buffer_left(buffer) < size) {
353 zip_error_set(error, ZIP_ER_NOZIP, 0);
358 if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
363 if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
364 zip_error_set(error, ZIP_ER_NOZIP, 0);
366 _zip_buffer_free(buffer);
371 /* convert buffercontents to zip_dirent */
373 _zip_dirent_init(zde);
375 zde->version_madeby = _zip_buffer_get_16(buffer);
377 zde->version_madeby = 0;
378 zde->version_needed = _zip_buffer_get_16(buffer);
379 zde->bitflags = _zip_buffer_get_16(buffer);
380 zde->comp_method = _zip_buffer_get_16(buffer);
382 /* convert to time_t */
383 dostime = _zip_buffer_get_16(buffer);
384 dosdate = _zip_buffer_get_16(buffer);
385 zde->last_mod = _zip_d2u_time(dostime, dosdate);
387 zde->crc = _zip_buffer_get_32(buffer);
388 zde->comp_size = _zip_buffer_get_32(buffer);
389 zde->uncomp_size = _zip_buffer_get_32(buffer);
391 filename_len = _zip_buffer_get_16(buffer);
392 ef_len = _zip_buffer_get_16(buffer);
396 zde->disk_number = 0;
401 comment_len = _zip_buffer_get_16(buffer);
402 zde->disk_number = _zip_buffer_get_16(buffer);
403 zde->int_attrib = _zip_buffer_get_16(buffer);
404 zde->ext_attrib = _zip_buffer_get_32(buffer);
405 zde->offset = _zip_buffer_get_32(buffer);
408 if (!_zip_buffer_ok(buffer)) {
409 zip_error_set(error, ZIP_ER_INTERNAL, 0);
411 _zip_buffer_free(buffer);
416 if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
417 if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
419 zde->encryption_method = ZIP_EM_UNKNOWN;
422 zde->encryption_method = ZIP_EM_TRAD_PKWARE;
426 zde->encryption_method = ZIP_EM_NONE;
429 zde->filename = NULL;
430 zde->extra_fields = NULL;
433 variable_size = (zip_uint32_t)filename_len+(zip_uint32_t)ef_len+(zip_uint32_t)comment_len;
436 if (_zip_buffer_left(buffer) < variable_size) {
437 zip_error_set(error, ZIP_ER_INCONS, 0);
442 _zip_buffer_free(buffer);
444 if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
450 zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
451 if (!zde->filename) {
452 if (zip_error_code_zip(error) == ZIP_ER_EOF) {
453 zip_error_set(error, ZIP_ER_INCONS, 0);
456 _zip_buffer_free(buffer);
461 if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
462 if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
463 zip_error_set(error, ZIP_ER_INCONS, 0);
465 _zip_buffer_free(buffer);
473 zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
477 _zip_buffer_free(buffer);
481 if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
484 _zip_buffer_free(buffer);
490 zde->local_extra_fields_read = 1;
494 zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
497 _zip_buffer_free(buffer);
501 if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
502 if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
503 zip_error_set(error, ZIP_ER_INCONS, 0);
505 _zip_buffer_free(buffer);
512 zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename);
513 zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment);
517 if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
518 zip_uint16_t got_len;
519 zip_buffer_t *ef_buffer;
520 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);
521 /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
524 _zip_buffer_free(buffer);
529 if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
530 zip_error_set(error, ZIP_ER_MEMORY, 0);
532 _zip_buffer_free(buffer);
537 if (zde->uncomp_size == ZIP_UINT32_MAX)
538 zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
540 /* From appnote.txt: This entry in the Local header MUST
541 include BOTH original and compressed file size fields. */
542 (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
544 if (zde->comp_size == ZIP_UINT32_MAX)
545 zde->comp_size = _zip_buffer_get_64(ef_buffer);
547 if (zde->offset == ZIP_UINT32_MAX)
548 zde->offset = _zip_buffer_get_64(ef_buffer);
549 if (zde->disk_number == ZIP_UINT16_MAX)
550 zde->disk_number = _zip_buffer_get_32(buffer);
553 if (!_zip_buffer_eof(ef_buffer)) {
554 zip_error_set(error, ZIP_ER_INCONS, 0);
555 _zip_buffer_free(ef_buffer);
557 _zip_buffer_free(buffer);
561 _zip_buffer_free(ef_buffer);
564 if (!_zip_buffer_ok(buffer)) {
565 zip_error_set(error, ZIP_ER_INTERNAL, 0);
567 _zip_buffer_free(buffer);
572 _zip_buffer_free(buffer);
575 /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
576 if (zde->offset > ZIP_INT64_MAX) {
577 zip_error_set(error, ZIP_ER_SEEK, EFBIG);
581 if (!_zip_dirent_process_winzip_aes(zde, error)) {
585 zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
587 return (zip_int64_t)(size + variable_size);
591 static zip_string_t *
592 _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str)
596 zip_buffer_t *buffer;
598 const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
600 if (ef == NULL || ef_len < 5 || ef[0] != 1) {
604 if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
608 _zip_buffer_get_8(buffer);
609 ef_crc = _zip_buffer_get_32(buffer);
611 if (_zip_string_crc32(str) == ef_crc) {
612 zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
613 zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
615 if (ef_str != NULL) {
616 _zip_string_free(str);
621 _zip_buffer_free(buffer);
628 _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error)
631 zip_buffer_t *buffer;
632 const zip_uint8_t *ef;
634 zip_uint16_t enc_method;
637 if (de->comp_method != ZIP_CM_WINZIP_AES) {
641 ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
643 if (ef == NULL || ef_len < 7) {
644 zip_error_set(error, ZIP_ER_INCONS, 0);
648 if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
649 zip_error_set(error, ZIP_ER_INTERNAL, 0);
656 switch (_zip_buffer_get_16(buffer)) {
661 if (de->uncomp_size < 20 /* TODO: constant */) {
667 zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
668 _zip_buffer_free(buffer);
673 if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
674 zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
675 _zip_buffer_free(buffer);
680 switch (_zip_buffer_get_8(buffer)) {
682 enc_method = ZIP_EM_AES_128;
685 enc_method = ZIP_EM_AES_192;
688 enc_method = ZIP_EM_AES_256;
691 zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
692 _zip_buffer_free(buffer);
697 zip_error_set(error, ZIP_ER_INCONS, 0);
698 _zip_buffer_free(buffer);
702 de->crc_valid = crc_valid;
703 de->encryption_method = enc_method;
704 de->comp_method = _zip_buffer_get_16(buffer);
706 _zip_buffer_free(buffer);
712 _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
715 bool local = (flags & ZIP_EF_LOCAL) != 0;
718 zip_buffer_t *buffer;
720 size = local ? LENTRYSIZE : CDENTRYSIZE;
722 if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
723 _zip_error_set_from_source(error, src);
727 if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
731 for (i=0; i<(local ? 2 : 3); i++) {
732 size += _zip_buffer_get_16(buffer);
735 if (!_zip_buffer_eof(buffer)) {
736 zip_error_set(error, ZIP_ER_INTERNAL, 0);
737 _zip_buffer_free(buffer);
741 _zip_buffer_free(buffer);
747 Writes zip directory entry.
749 If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
750 directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
752 Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
757 _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
759 zip_uint16_t dostime, dosdate;
760 zip_encoding_type_t com_enc, name_enc;
761 zip_extra_field_t *ef;
762 zip_extra_field_t *ef64;
763 zip_uint32_t ef_total_size;
765 bool is_really_zip64;
767 zip_uint8_t buf[CDENTRYSIZE];
768 zip_buffer_t *buffer;
772 name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
773 com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
775 if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) ||
776 (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) ||
777 (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
778 de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
780 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
781 if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
782 ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
786 if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){
787 zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
797 if (de->encryption_method == ZIP_EM_NONE) {
798 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
801 de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
804 is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
805 is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
806 is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
809 zip_uint8_t ef_zip64[EFZIP64SIZE];
810 zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
811 if (ef_buffer == NULL) {
812 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
817 if (flags & ZIP_FL_LOCAL) {
818 if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
819 _zip_buffer_put_64(ef_buffer, de->uncomp_size);
820 _zip_buffer_put_64(ef_buffer, de->comp_size);
824 if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
825 if (de->uncomp_size >= ZIP_UINT32_MAX) {
826 _zip_buffer_put_64(ef_buffer, de->uncomp_size);
828 if (de->comp_size >= ZIP_UINT32_MAX) {
829 _zip_buffer_put_64(ef_buffer, de->comp_size);
831 if (de->offset >= ZIP_UINT32_MAX) {
832 _zip_buffer_put_64(ef_buffer, de->offset);
837 if (!_zip_buffer_ok(ef_buffer)) {
838 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
839 _zip_buffer_free(ef_buffer);
844 ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
845 _zip_buffer_free(ef_buffer);
851 zip_uint8_t data[EF_WINZIP_AES_SIZE];
852 zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
853 zip_extra_field_t *ef_winzip;
855 if (ef_buffer == NULL) {
856 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
861 _zip_buffer_put_16(ef_buffer, 2);
862 _zip_buffer_put(ef_buffer, "AE", 2);
863 _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
864 _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
866 if (!_zip_buffer_ok(ef_buffer)) {
867 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
868 _zip_buffer_free(ef_buffer);
873 ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
874 _zip_buffer_free(ef_buffer);
875 ef_winzip->next = ef;
879 if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
880 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
885 _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
887 if ((flags & ZIP_FL_LOCAL) == 0) {
888 _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
890 _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
891 _zip_buffer_put_16(buffer, de->bitflags);
893 _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
896 _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
899 _zip_u2d_time(de->last_mod, &dostime, &dosdate);
900 _zip_buffer_put_16(buffer, dostime);
901 _zip_buffer_put_16(buffer, dosdate);
903 if (is_winzip_aes && de->uncomp_size < 20) {
904 _zip_buffer_put_32(buffer, 0);
907 _zip_buffer_put_32(buffer, de->crc);
910 if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
911 /* In local headers, if a ZIP64 EF is written, it MUST contain
912 * both compressed and uncompressed sizes (even if one of the
913 * two is smaller than 0xFFFFFFFF); on the other hand, those
914 * may only appear when the corresponding standard entry is
915 * 0xFFFFFFFF. (appnote.txt 4.5.3) */
916 _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
917 _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
920 if (de->comp_size < ZIP_UINT32_MAX) {
921 _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
924 _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
926 if (de->uncomp_size < ZIP_UINT32_MAX) {
927 _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
930 _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
934 _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
935 /* TODO: check for overflow */
936 ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
937 _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
939 if ((flags & ZIP_FL_LOCAL) == 0) {
940 _zip_buffer_put_16(buffer, _zip_string_length(de->comment));
941 _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
942 _zip_buffer_put_16(buffer, de->int_attrib);
943 _zip_buffer_put_32(buffer, de->ext_attrib);
944 if (de->offset < ZIP_UINT32_MAX)
945 _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
947 _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
950 if (!_zip_buffer_ok(buffer)) {
951 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
952 _zip_buffer_free(buffer);
957 if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
958 _zip_buffer_free(buffer);
963 _zip_buffer_free(buffer);
966 if (_zip_string_write(za, de->filename) < 0) {
973 if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
979 if (de->extra_fields) {
980 if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
985 if ((flags & ZIP_FL_LOCAL) == 0) {
987 if (_zip_string_write(za, de->comment) < 0) {
999 _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
1003 memset(&tm, 0, sizeof(tm));
1005 /* let mktime decide if DST is in effect */
1008 tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
1009 tm.tm_mon = ((ddate>>5)&15) - 1;
1010 tm.tm_mday = ddate&31;
1012 tm.tm_hour = (dtime>>11)&31;
1013 tm.tm_min = (dtime>>5)&63;
1014 tm.tm_sec = (dtime<<1)&62;
1020 static zip_extra_field_t *
1021 _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
1023 const zip_uint8_t *raw;
1025 zip_buffer_t *buffer;
1026 zip_extra_field_t *ef;
1028 if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
1029 /* error already set */
1033 if (len+5 > ZIP_UINT16_MAX) {
1034 zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
1038 if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
1039 zip_error_set(error, ZIP_ER_MEMORY, 0);
1043 _zip_buffer_put_8(buffer, 1);
1044 _zip_buffer_put_32(buffer, _zip_string_crc32(str));
1045 _zip_buffer_put(buffer, raw, len);
1047 if (!_zip_buffer_ok(buffer)) {
1048 zip_error_set(error, ZIP_ER_INTERNAL, 0);
1049 _zip_buffer_free(buffer);
1053 ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
1054 _zip_buffer_free(buffer);
1061 _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
1066 if (idx >= za->nentry) {
1067 zip_error_set(error, ZIP_ER_INVAL, 0);
1071 if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1072 if (za->entry[idx].orig == NULL) {
1073 zip_error_set(error, ZIP_ER_INVAL, 0);
1076 if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
1077 zip_error_set(error, ZIP_ER_DELETED, 0);
1080 return za->entry[idx].orig;
1083 return za->entry[idx].changes;
1090 _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
1094 tm = localtime(&intime);
1095 if (tm->tm_year < 80) {
1099 *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
1100 *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
1107 _zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) {
1108 zip_uint16_t length;
1110 if (de->comp_method == ZIP_CM_LZMA) {
1111 de->version_needed = 63;
1115 if (de->comp_method == ZIP_CM_BZIP2) {
1116 de->version_needed = 46;
1120 if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1121 de->version_needed = 45;
1125 if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1126 de->version_needed = 20;
1131 if ((length = _zip_string_length(de->filename)) > 0) {
1132 if (de->filename->raw[length-1] == '/') {
1133 de->version_needed = 20;
1138 de->version_needed = 10;