comparison modules/zip/libzip/lib/zip_dirent.c @ 527:8f8c32f102f1

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