Imported Upstream version 1.1.3
[platform/upstream/libzip.git] / lib / zip_dirent.c
1 /*
2   zip_dirent.c -- read directory entry (local or central), clean dirent
3   Copyright (C) 1999-2016 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 <libzip@nih.at>
7
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions
10   are met:
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in
15      the documentation and/or other materials provided with the
16      distribution.
17   3. The names of the authors may not be used to endorse or promote
18      products derived from this software without specific prior
19      written permission.
20
21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <time.h>
41
42 #include "zipint.h"
43
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
48
49 void
50 _zip_cdir_free(zip_cdir_t *cd)
51 {
52     zip_uint64_t i;
53
54     if (!cd)
55         return;
56
57     for (i=0; i<cd->nentry; i++)
58         _zip_entry_finalize(cd->entry+i);
59     free(cd->entry);
60     _zip_string_free(cd->comment);
61     free(cd);
62 }
63
64
65 zip_cdir_t *
66 _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
67 {
68     zip_cdir_t *cd;
69     zip_uint64_t i;
70
71     if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
72         zip_error_set(error, ZIP_ER_MEMORY, 0);
73         return NULL;
74     }
75
76     if (nentry == 0)
77         cd->entry = NULL;
78     else if ((nentry > SIZE_MAX/sizeof(*(cd->entry))) || (cd->entry=(zip_entry_t *)malloc(sizeof(*(cd->entry))*(size_t)nentry)) == NULL) {
79         zip_error_set(error, ZIP_ER_MEMORY, 0);
80         free(cd);
81         return NULL;
82     }
83
84     for (i=0; i<nentry; i++)
85         _zip_entry_init(cd->entry+i);
86
87     cd->nentry = cd->nentry_alloc = nentry;
88     cd->size = cd->offset = 0;
89     cd->comment = NULL;
90
91     return cd;
92 }
93
94
95 zip_int64_t
96 _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
97 {
98     zip_uint64_t offset, size;
99     zip_string_t *comment;
100     zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
101     zip_buffer_t *buffer;
102     zip_int64_t off;
103     zip_uint64_t i;
104     bool is_zip64;
105     int ret;
106
107     if ((off = zip_source_tell_write(za->src)) < 0) {
108         _zip_error_set_from_source(&za->error, za->src);
109         return -1;
110     }
111     offset = (zip_uint64_t)off;
112
113     is_zip64 = false;
114
115     for (i=0; i<survivors; i++) {
116         zip_entry_t *entry = za->entry+filelist[i].idx;
117
118         if ((ret=_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0)
119             return -1;
120         if (ret)
121             is_zip64 = true;
122     }
123
124     if ((off = zip_source_tell_write(za->src)) < 0) {
125         _zip_error_set_from_source(&za->error, za->src);
126         return -1;
127     }
128     size = (zip_uint64_t)off - offset;
129
130     if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
131         is_zip64 = true;
132
133
134     if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
135         zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
136         return -1;
137     }
138
139     if (is_zip64) {
140         _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
141         _zip_buffer_put_64(buffer, EOCD64LEN-12);
142         _zip_buffer_put_16(buffer, 45);
143         _zip_buffer_put_16(buffer, 45);
144         _zip_buffer_put_32(buffer, 0);
145         _zip_buffer_put_32(buffer, 0);
146         _zip_buffer_put_64(buffer, survivors);
147         _zip_buffer_put_64(buffer, survivors);
148         _zip_buffer_put_64(buffer, size);
149         _zip_buffer_put_64(buffer, offset);
150         _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
151         _zip_buffer_put_32(buffer, 0);
152         _zip_buffer_put_64(buffer, offset+size);
153         _zip_buffer_put_32(buffer, 1);
154     }
155
156     _zip_buffer_put(buffer, EOCD_MAGIC, 4);
157     _zip_buffer_put_32(buffer, 0);
158     _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
159     _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
160     _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
161     _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
162
163     comment = za->comment_changed ? za->comment_changes : za->comment_orig;
164
165     _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
166
167     if (!_zip_buffer_ok(buffer)) {
168         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
169         _zip_buffer_free(buffer);
170         return -1;
171     }
172
173     if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
174         _zip_buffer_free(buffer);
175         return -1;
176     }
177
178     _zip_buffer_free(buffer);
179
180     if (comment) {
181         if (_zip_write(za, comment->raw, comment->length) < 0) {
182             return -1;
183         }
184     }
185
186     return (zip_int64_t)size;
187 }
188
189
190 zip_dirent_t *
191 _zip_dirent_clone(const zip_dirent_t *sde)
192 {
193     zip_dirent_t *tde;
194
195     if ((tde=(zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
196         return NULL;
197
198     if (sde)
199         memcpy(tde, sde, sizeof(*sde));
200     else
201         _zip_dirent_init(tde);
202
203     tde->changed = 0;
204     tde->cloned = 1;
205
206     return tde;
207 }
208
209
210 void
211 _zip_dirent_finalize(zip_dirent_t *zde)
212 {
213     if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
214         _zip_string_free(zde->filename);
215         zde->filename = NULL;
216     }
217     if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
218         _zip_ef_free(zde->extra_fields);
219         zde->extra_fields = NULL;
220     }
221     if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
222         _zip_string_free(zde->comment);
223         zde->comment = NULL;
224     }
225 }
226
227
228 void
229 _zip_dirent_free(zip_dirent_t *zde)
230 {
231     if (zde == NULL)
232         return;
233
234     _zip_dirent_finalize(zde);
235     free(zde);
236 }
237
238
239 void
240 _zip_dirent_init(zip_dirent_t *de)
241 {
242     de->changed = 0;
243     de->local_extra_fields_read = 0;
244     de->cloned = 0;
245
246     de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8);
247     de->version_needed = 20; /* 2.0 */
248     de->bitflags = 0;
249     de->comp_method = ZIP_CM_DEFAULT;
250     de->last_mod = 0;
251     de->crc = 0;
252     de->comp_size = 0;
253     de->uncomp_size = 0;
254     de->filename = NULL;
255     de->extra_fields = NULL;
256     de->comment = NULL;
257     de->disk_number = 0;
258     de->int_attrib = 0;
259     de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
260     de->offset = 0;
261 }
262
263
264 bool
265 _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags)
266 {
267     if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX
268         || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
269         return true;
270
271     return false;
272 }
273
274
275 zip_dirent_t *
276 _zip_dirent_new(void)
277 {
278     zip_dirent_t *de;
279
280     if ((de=(zip_dirent_t *)malloc(sizeof(*de))) == NULL)
281         return NULL;
282
283     _zip_dirent_init(de);
284     return de;
285 }
286
287
288 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
289    Fills the zip directory entry zde.
290
291    If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
292
293    If local is true, it reads a local header instead of a central directory entry.
294
295    Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
296 */
297
298 zip_int64_t
299 _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error)
300 {
301     zip_uint8_t buf[CDENTRYSIZE];
302     zip_uint16_t dostime, dosdate;
303     zip_uint32_t size, variable_size;
304     zip_uint16_t filename_len, comment_len, ef_len;
305
306     bool from_buffer = (buffer != NULL);
307
308     size = local ? LENTRYSIZE : CDENTRYSIZE;
309
310     if (buffer) {
311         if (_zip_buffer_left(buffer) < size) {
312             zip_error_set(error, ZIP_ER_NOZIP, 0);
313             return -1;
314         }
315     }
316     else {
317         if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
318             return -1;
319         }
320     }
321
322     if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
323         zip_error_set(error, ZIP_ER_NOZIP, 0);
324         if (!from_buffer) {
325             _zip_buffer_free(buffer);
326         }
327         return -1;
328     }
329
330     /* convert buffercontents to zip_dirent */
331
332     _zip_dirent_init(zde);
333     if (!local)
334         zde->version_madeby = _zip_buffer_get_16(buffer);
335     else
336         zde->version_madeby = 0;
337     zde->version_needed = _zip_buffer_get_16(buffer);
338     zde->bitflags = _zip_buffer_get_16(buffer);
339     zde->comp_method = _zip_buffer_get_16(buffer);
340
341     /* convert to time_t */
342     dostime = _zip_buffer_get_16(buffer);
343     dosdate = _zip_buffer_get_16(buffer);
344     zde->last_mod = _zip_d2u_time(dostime, dosdate);
345
346     zde->crc = _zip_buffer_get_32(buffer);
347     zde->comp_size = _zip_buffer_get_32(buffer);
348     zde->uncomp_size = _zip_buffer_get_32(buffer);
349
350     filename_len = _zip_buffer_get_16(buffer);
351     ef_len = _zip_buffer_get_16(buffer);
352
353     if (local) {
354         comment_len = 0;
355         zde->disk_number = 0;
356         zde->int_attrib = 0;
357         zde->ext_attrib = 0;
358         zde->offset = 0;
359     } else {
360         comment_len = _zip_buffer_get_16(buffer);
361         zde->disk_number = _zip_buffer_get_16(buffer);
362         zde->int_attrib = _zip_buffer_get_16(buffer);
363         zde->ext_attrib = _zip_buffer_get_32(buffer);
364         zde->offset = _zip_buffer_get_32(buffer);
365     }
366
367     if (!_zip_buffer_ok(buffer)) {
368         zip_error_set(error, ZIP_ER_INTERNAL, 0);
369         if (!from_buffer) {
370             _zip_buffer_free(buffer);
371         }
372         return -1;
373     }
374
375     zde->filename = NULL;
376     zde->extra_fields = NULL;
377     zde->comment = NULL;
378
379     variable_size = (zip_uint32_t)filename_len+(zip_uint32_t)ef_len+(zip_uint32_t)comment_len;
380
381     if (from_buffer) {
382         if (_zip_buffer_left(buffer) < variable_size) {
383             zip_error_set(error, ZIP_ER_INCONS, 0);
384             return -1;
385         }
386     }
387     else {
388         _zip_buffer_free(buffer);
389
390         if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
391             return -1;
392         }
393     }
394
395     if (filename_len) {
396         zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
397         if (!zde->filename) {
398             if (zip_error_code_zip(error) == ZIP_ER_EOF) {
399                 zip_error_set(error, ZIP_ER_INCONS, 0);
400             }
401             if (!from_buffer) {
402                 _zip_buffer_free(buffer);
403             }
404             return -1;
405         }
406
407         if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
408             if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
409                 zip_error_set(error, ZIP_ER_INCONS, 0);
410                 if (!from_buffer) {
411                     _zip_buffer_free(buffer);
412                 }
413                 return -1;
414             }
415         }
416     }
417
418     if (ef_len) {
419         zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
420
421         if (ef == NULL) {
422             if (!from_buffer) {
423                 _zip_buffer_free(buffer);
424             }
425             return -1;
426         }
427         if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
428             free(ef);
429             if (!from_buffer) {
430                 _zip_buffer_free(buffer);
431             }
432             return -1;
433         }
434         free(ef);
435         if (local)
436             zde->local_extra_fields_read = 1;
437     }
438
439     if (comment_len) {
440         zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
441         if (!zde->comment) {
442             if (!from_buffer) {
443                 _zip_buffer_free(buffer);
444             }
445             return -1;
446         }
447         if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
448             if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
449                 zip_error_set(error, ZIP_ER_INCONS, 0);
450                 if (!from_buffer) {
451                     _zip_buffer_free(buffer);
452                 }
453                 return -1;
454             }
455         }
456     }
457
458     zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename);
459     zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment);
460
461     /* Zip64 */
462
463     if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
464         zip_uint16_t got_len;
465         zip_buffer_t *ef_buffer;
466         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);
467         /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
468         if (ef == NULL) {
469             if (!from_buffer) {
470                 _zip_buffer_free(buffer);
471             }
472             return -1;
473         }
474
475         if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
476             zip_error_set(error, ZIP_ER_MEMORY, 0);
477             if (!from_buffer) {
478                 _zip_buffer_free(buffer);
479             }
480             return -1;
481         }
482
483         if (zde->uncomp_size == ZIP_UINT32_MAX)
484             zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
485         else if (local) {
486             /* From appnote.txt: This entry in the Local header MUST
487                include BOTH original and compressed file size fields. */
488             (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
489         }
490         if (zde->comp_size == ZIP_UINT32_MAX)
491             zde->comp_size = _zip_buffer_get_64(ef_buffer);
492         if (!local) {
493             if (zde->offset == ZIP_UINT32_MAX)
494                 zde->offset = _zip_buffer_get_64(ef_buffer);
495             if (zde->disk_number == ZIP_UINT16_MAX)
496                 zde->disk_number = _zip_buffer_get_32(buffer);
497         }
498
499         if (!_zip_buffer_eof(ef_buffer)) {
500             zip_error_set(error, ZIP_ER_INCONS, 0);
501             _zip_buffer_free(ef_buffer);
502             if (!from_buffer) {
503                 _zip_buffer_free(buffer);
504             }
505             return -1;
506         }
507         _zip_buffer_free(ef_buffer);
508     }
509
510     if (!_zip_buffer_ok(buffer)) {
511         zip_error_set(error, ZIP_ER_INTERNAL, 0);
512         if (!from_buffer) {
513             _zip_buffer_free(buffer);
514         }
515         return -1;
516     }
517     if (!from_buffer) {
518         _zip_buffer_free(buffer);
519     }
520
521     /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
522     if (zde->offset > ZIP_INT64_MAX) {
523         zip_error_set(error, ZIP_ER_SEEK, EFBIG);
524         return -1;
525     }
526
527     zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
528
529     return (zip_int64_t)(size + variable_size);
530 }
531
532
533 static zip_string_t *
534 _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str)
535 {
536     zip_uint16_t ef_len;
537     zip_uint32_t ef_crc;
538     zip_buffer_t *buffer;
539
540     const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
541
542     if (ef == NULL || ef_len < 5 || ef[0] != 1) {
543         return str;
544     }
545
546     if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
547         return str;
548     }
549
550     _zip_buffer_get_8(buffer);
551     ef_crc = _zip_buffer_get_32(buffer);
552
553     if (_zip_string_crc32(str) == ef_crc) {
554         zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
555         zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
556
557         if (ef_str != NULL) {
558             _zip_string_free(str);
559             str = ef_str;
560         }
561     }
562
563     _zip_buffer_free(buffer);
564
565     return str;
566 }
567
568
569 zip_int32_t
570 _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
571 {
572     zip_int32_t size;
573     bool local = (flags & ZIP_EF_LOCAL) != 0;
574     int i;
575     zip_uint8_t b[6];
576     zip_buffer_t *buffer;
577
578     size = local ? LENTRYSIZE : CDENTRYSIZE;
579
580     if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
581         _zip_error_set_from_source(error, src);
582         return -1;
583     }
584
585     if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
586         return -1;
587     }
588
589     for (i=0; i<(local ? 2 : 3); i++) {
590         size += _zip_buffer_get_16(buffer);
591     }
592
593     if (!_zip_buffer_eof(buffer)) {
594         zip_error_set(error, ZIP_ER_INTERNAL, 0);
595         _zip_buffer_free(buffer);
596         return -1;
597     }
598
599     _zip_buffer_free(buffer);
600     return size;
601 }
602
603
604 /* _zip_dirent_write
605    Writes zip directory entry.
606
607    If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
608    directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
609
610    Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
611    returned.
612 */
613
614 int
615 _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
616 {
617     zip_uint16_t dostime, dosdate;
618     zip_encoding_type_t com_enc, name_enc;
619     zip_extra_field_t *ef;
620     zip_extra_field_t *ef64;
621     zip_uint32_t ef_total_size;
622     bool is_zip64;
623     bool is_really_zip64;
624     zip_uint8_t buf[CDENTRYSIZE];
625     zip_buffer_t *buffer;
626
627     ef = NULL;
628
629     name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
630     com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
631
632     if ((name_enc == ZIP_ENCODING_UTF8_KNOWN  && com_enc == ZIP_ENCODING_ASCII) ||
633         (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) ||
634         (name_enc == ZIP_ENCODING_UTF8_KNOWN  && com_enc == ZIP_ENCODING_UTF8_KNOWN))
635         de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
636     else {
637         de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
638         if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
639             ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
640             if (ef == NULL)
641                 return -1;
642         }
643         if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){
644             zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
645             if (ef2 == NULL) {
646                 _zip_ef_free(ef);
647                 return -1;
648             }
649             ef2->next = ef;
650             ef = ef2;
651         }
652     }
653
654     is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
655     is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
656
657     if (is_zip64) {
658         zip_uint8_t ef_zip64[EFZIP64SIZE];
659         zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
660         if (ef_buffer == NULL) {
661             zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
662             _zip_ef_free(ef);
663             return -1;
664         }
665
666         if (flags & ZIP_FL_LOCAL) {
667             if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
668                 _zip_buffer_put_64(ef_buffer, de->uncomp_size);
669                 _zip_buffer_put_64(ef_buffer, de->comp_size);
670             }
671         }
672         else {
673             if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
674                 if (de->uncomp_size >= ZIP_UINT32_MAX) {
675                     _zip_buffer_put_64(ef_buffer, de->uncomp_size);
676                 }
677                 if (de->comp_size >= ZIP_UINT32_MAX) {
678                     _zip_buffer_put_64(ef_buffer, de->comp_size);
679                 }
680                 if (de->offset >= ZIP_UINT32_MAX) {
681                     _zip_buffer_put_64(ef_buffer, de->offset);
682                 }
683             }
684         }
685
686         if (!_zip_buffer_ok(ef_buffer)) {
687             zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
688             _zip_buffer_free(ef_buffer);
689             _zip_ef_free(ef);
690             return -1;
691         }
692
693         ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
694         _zip_buffer_free(ef_buffer);
695         ef64->next = ef;
696         ef = ef64;
697     }
698
699     if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
700         zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
701         _zip_ef_free(ef);
702         return -1;
703     }
704
705     _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
706
707     if ((flags & ZIP_FL_LOCAL) == 0) {
708         _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
709     }
710     _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
711     _zip_buffer_put_16(buffer, de->bitflags&0xfff9); /* clear compression method specific flags */
712     _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
713
714     _zip_u2d_time(de->last_mod, &dostime, &dosdate);
715     _zip_buffer_put_16(buffer, dostime);
716     _zip_buffer_put_16(buffer, dosdate);
717
718     _zip_buffer_put_32(buffer, de->crc);
719
720     if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
721         /* In local headers, if a ZIP64 EF is written, it MUST contain
722          * both compressed and uncompressed sizes (even if one of the
723          * two is smaller than 0xFFFFFFFF); on the other hand, those
724          * may only appear when the corresponding standard entry is
725          * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
726         _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
727         _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
728     }
729     else {
730         if (de->comp_size < ZIP_UINT32_MAX) {
731             _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
732         }
733         else {
734             _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
735         }
736         if (de->uncomp_size < ZIP_UINT32_MAX) {
737             _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
738         }
739         else {
740             _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
741         }
742     }
743
744     _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
745     /* TODO: check for overflow */
746     ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
747     _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
748
749     if ((flags & ZIP_FL_LOCAL) == 0) {
750         _zip_buffer_put_16(buffer, _zip_string_length(de->comment));
751         _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
752         _zip_buffer_put_16(buffer, de->int_attrib);
753         _zip_buffer_put_32(buffer, de->ext_attrib);
754         if (de->offset < ZIP_UINT32_MAX)
755             _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
756         else
757             _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
758     }
759
760     if (!_zip_buffer_ok(buffer)) {
761         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
762         _zip_buffer_free(buffer);
763         _zip_ef_free(ef);
764         return -1;
765     }
766
767     if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
768         _zip_buffer_free(buffer);
769         _zip_ef_free(ef);
770         return -1;
771     }
772
773     _zip_buffer_free(buffer);
774
775     if (de->filename) {
776         if (_zip_string_write(za, de->filename) < 0) {
777             _zip_ef_free(ef);
778             return -1;
779         }
780     }
781
782     if (ef) {
783         if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
784             _zip_ef_free(ef);
785             return -1;
786         }
787     }
788     _zip_ef_free(ef);
789     if (de->extra_fields) {
790         if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
791             return -1;
792         }
793     }
794
795     if ((flags & ZIP_FL_LOCAL) == 0) {
796         if (de->comment) {
797             if (_zip_string_write(za, de->comment) < 0) {
798                 return -1;
799             }
800         }
801     }
802
803
804     return is_zip64;
805 }
806
807
808 static time_t
809 _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
810 {
811     struct tm tm;
812
813     memset(&tm, 0, sizeof(tm));
814
815     /* let mktime decide if DST is in effect */
816     tm.tm_isdst = -1;
817
818     tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
819     tm.tm_mon = ((ddate>>5)&15) - 1;
820     tm.tm_mday = ddate&31;
821
822     tm.tm_hour = (dtime>>11)&31;
823     tm.tm_min = (dtime>>5)&63;
824     tm.tm_sec = (dtime<<1)&62;
825
826     return mktime(&tm);
827 }
828
829
830 static zip_extra_field_t *
831 _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
832 {
833     const zip_uint8_t *raw;
834     zip_uint32_t len;
835     zip_buffer_t *buffer;
836     zip_extra_field_t *ef;
837
838     if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
839         /* error already set */
840         return NULL;
841     }
842
843     if (len+5 > ZIP_UINT16_MAX) {
844         zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
845         return NULL;
846     }
847
848     if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
849         zip_error_set(error, ZIP_ER_MEMORY, 0);
850         return NULL;
851     }
852
853     _zip_buffer_put_8(buffer, 1);
854     _zip_buffer_put_32(buffer, _zip_string_crc32(str));
855     _zip_buffer_put(buffer, raw, len);
856
857     if (!_zip_buffer_ok(buffer)) {
858         zip_error_set(error, ZIP_ER_INTERNAL, 0);
859         _zip_buffer_free(buffer);
860         return NULL;
861     }
862
863     ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
864     _zip_buffer_free(buffer);
865
866     return ef;
867 }
868
869
870 zip_dirent_t *
871 _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error)
872 {
873     if (error == NULL)
874         error = &za->error;
875
876     if (idx >= za->nentry) {
877         zip_error_set(error, ZIP_ER_INVAL, 0);
878         return NULL;
879     }
880
881     if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
882         if (za->entry[idx].orig == NULL) {
883             zip_error_set(error, ZIP_ER_INVAL, 0);
884             return NULL;
885         }
886         if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
887             zip_error_set(error, ZIP_ER_DELETED, 0);
888             return NULL;
889         }
890         return za->entry[idx].orig;
891     }
892     else
893         return za->entry[idx].changes;
894 }
895
896
897
898
899 void
900 _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
901 {
902     struct tm *tm;
903
904     tm = localtime(&intime);
905     if (tm->tm_year < 80) {
906         tm->tm_year = 80;
907     }
908
909     *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
910     *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
911
912     return;
913 }