root/ext/zip/lib/zip_dirent.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _zip_cdir_free
  2. _zip_cdir_new
  3. _zip_cdir_write
  4. _zip_dirent_clone
  5. _zip_dirent_finalize
  6. _zip_dirent_free
  7. _zip_dirent_init
  8. _zip_dirent_needs_zip64
  9. _zip_dirent_new
  10. _zip_dirent_read
  11. _zip_dirent_process_ef_utf_8
  12. _zip_dirent_size
  13. _zip_dirent_write
  14. _zip_d2u_time
  15. _zip_ef_utf8
  16. _zip_get_dirent
  17. _zip_u2d_time

   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 }

/* [<][>][^][v][top][bottom][index][help] */