1 /* zip.c -- IO on .zip files using zlib 2 part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) 3 4 Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) 5 6 Modifications for Zip64 support 7 Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) 8 9 For more info read MiniZip_info.txt 10 11 Changes 12 Oct-2009 - Mathias Svensson - Remove old C style function prototypes 13 Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives 14 Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. 15 Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data 16 It is used when recreating zip archive with RAW when deleting items from a zip. 17 ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. 18 Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) 19 Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer 20 21 */ 22 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <time.h> 28 #ifndef ZLIB_CONST 29 # define ZLIB_CONST 30 #endif 31 #ifdef ZLIB_DLL 32 # undef ZLIB_DLL 33 #endif 34 #include "zlib.h" 35 #include "zip.h" 36 37 #ifdef STDC 38 # include <stddef.h> 39 #endif 40 #ifdef NO_ERRNO_H 41 extern int errno; 42 #else 43 # include <errno.h> 44 #endif 45 46 47 #ifndef local 48 # define local static 49 #endif 50 /* compile with -Dlocal if your debugger can't find static symbols */ 51 52 #ifndef VERSIONMADEBY 53 # define VERSIONMADEBY (0x0) /* platform dependent */ 54 #endif 55 56 #ifndef Z_BUFSIZE 57 #define Z_BUFSIZE (64*1024) /* (16384) */ 58 #endif 59 60 #ifndef Z_MAXFILENAMEINZIP 61 #define Z_MAXFILENAMEINZIP (256) 62 #endif 63 64 #ifndef ALLOC 65 # define ALLOC(size) (malloc(size)) 66 #endif 67 68 /* 69 #define SIZECENTRALDIRITEM (0x2e) 70 #define SIZEZIPLOCALHEADER (0x1e) 71 */ 72 73 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ 74 75 76 /* NOT sure that this work on ALL platform */ 77 #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) 78 79 #ifndef SEEK_CUR 80 #define SEEK_CUR 1 81 #endif 82 83 #ifndef SEEK_END 84 #define SEEK_END 2 85 #endif 86 87 #ifndef SEEK_SET 88 #define SEEK_SET 0 89 #endif 90 91 #ifndef DEF_MEM_LEVEL 92 #if MAX_MEM_LEVEL >= 8 93 # define DEF_MEM_LEVEL 8 94 #else 95 # define DEF_MEM_LEVEL MAX_MEM_LEVEL 96 #endif 97 #endif 98 const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - https://www.winimage.com/zLibDll/minizip.html"; 99 100 101 #define SIZEDATA_INDATABLOCK (4096-(4*4)) 102 103 #define LOCALHEADERMAGIC (0x04034b50) 104 #define CENTRALHEADERMAGIC (0x02014b50) 105 #define ENDHEADERMAGIC (0x06054b50) 106 #define ZIP64ENDHEADERMAGIC (0x6064b50) 107 #define ZIP64ENDLOCHEADERMAGIC (0x7064b50) 108 109 #define FLAG_LOCALHEADER_OFFSET (0x06) 110 #define CRC_LOCALHEADER_OFFSET (0x0e) 111 112 #define SIZECENTRALHEADER (0x2e) /* 46 */ 113 114 typedef struct linkedlist_datablock_internal_s 115 { 116 struct linkedlist_datablock_internal_s* next_datablock; 117 uLong avail_in_this_block; 118 uLong filled_in_this_block; 119 uLong unused; /* for future use and alignment */ 120 unsigned char data[SIZEDATA_INDATABLOCK]; 121 } linkedlist_datablock_internal; 122 123 typedef struct linkedlist_data_s 124 { 125 linkedlist_datablock_internal* first_block; 126 linkedlist_datablock_internal* last_block; 127 } linkedlist_data; 128 129 130 /* zipAlreadyThere() set functions for a set of zero-terminated strings, and 131 // a block_t type for reading the central directory datablocks. */ 132 typedef char *set_key_t; 133 #define set_cmp(a, b) strcmp(a, b) 134 #define set_drop(s, k) set_free(s, k) 135 #include "skipset.h" 136 typedef struct { 137 unsigned char *next; /* next byte in datablock data */ 138 size_t left; /* number of bytes left in data (at least) */ 139 linkedlist_datablock_internal *node; /* current datablock */ 140 } block_t; 141 142 143 typedef struct 144 { 145 z_stream stream; /* zLib stream structure for inflate */ 146 #ifdef HAVE_BZIP2 147 bz_stream bstream; /* bzLib stream structure for bziped */ 148 #endif 149 150 int stream_initialised; /* 1 is stream is initialised */ 151 uInt pos_in_buffered_data; /* last written byte in buffered_data */ 152 153 ZPOS64_T pos_local_header; /* offset of the local header of the file 154 currently writing */ 155 char* central_header; /* central header data for the current file */ 156 uLong size_centralExtra; 157 uLong size_centralheader; /* size of the central header for cur file */ 158 uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ 159 uLong flag; /* flag of the file currently writing */ 160 161 int method; /* compression method of file currently wr.*/ 162 int raw; /* 1 for directly writing raw data */ 163 Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ 164 uLong dosDate; 165 uLong crc32; 166 int encrypt; 167 int zip64; /* Add ZIP64 extended information in the extra field */ 168 ZPOS64_T pos_zip64extrainfo; 169 ZPOS64_T totalCompressedData; 170 ZPOS64_T totalUncompressedData; 171 #ifndef NOCRYPT 172 unsigned long keys[3]; /* keys defining the pseudo-random sequence */ 173 const z_crc_t* pcrc_32_tab; 174 unsigned crypt_header_size; 175 #endif 176 } curfile64_info; 177 178 typedef struct 179 { 180 zlib_filefunc64_32_def z_filefunc; 181 voidpf filestream; /* io structure of the zipfile */ 182 linkedlist_data central_dir;/* datablock with central dir in construction*/ 183 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ 184 curfile64_info ci; /* info on the file currently writing */ 185 186 ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ 187 ZPOS64_T add_position_when_writing_offset; 188 ZPOS64_T number_entry; 189 190 #ifndef NO_ADDFILEINEXISTINGZIP 191 char *globalcomment; 192 #endif 193 194 /* Support for zipAlreadyThere(). */ 195 set_t set; /* set for detecting name collisions */ 196 block_t block; /* block for reading the central directory */ 197 198 } zip64_internal; 199 200 201 #ifndef NOCRYPT 202 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED 203 #include "crypt.h" 204 #endif 205 206 local linkedlist_datablock_internal* allocate_new_datablock(void) { 207 linkedlist_datablock_internal* ldi; 208 ldi = (linkedlist_datablock_internal*) 209 ALLOC(sizeof(linkedlist_datablock_internal)); 210 if (ldi!=NULL) 211 { 212 ldi->next_datablock = NULL ; 213 ldi->filled_in_this_block = 0 ; 214 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; 215 } 216 return ldi; 217 } 218 219 local void free_datablock(linkedlist_datablock_internal* ldi) { 220 while (ldi!=NULL) 221 { 222 linkedlist_datablock_internal* ldinext = ldi->next_datablock; 223 free(ldi); 224 ldi = ldinext; 225 } 226 } 227 228 local void init_linkedlist(linkedlist_data* ll) { 229 ll->first_block = ll->last_block = NULL; 230 } 231 232 local void free_linkedlist(linkedlist_data* ll) { 233 free_datablock(ll->first_block); 234 ll->first_block = ll->last_block = NULL; 235 } 236 237 238 local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { 239 linkedlist_datablock_internal* ldi; 240 const unsigned char* from_copy; 241 242 if (ll==NULL) 243 return ZIP_INTERNALERROR; 244 245 if (ll->last_block == NULL) 246 { 247 ll->first_block = ll->last_block = allocate_new_datablock(); 248 if (ll->first_block == NULL) 249 return ZIP_INTERNALERROR; 250 } 251 252 ldi = ll->last_block; 253 from_copy = (const unsigned char*)buf; 254 255 while (len>0) 256 { 257 uInt copy_this; 258 uInt i; 259 unsigned char* to_copy; 260 261 if (ldi->avail_in_this_block==0) 262 { 263 ldi->next_datablock = allocate_new_datablock(); 264 if (ldi->next_datablock == NULL) 265 return ZIP_INTERNALERROR; 266 ldi = ldi->next_datablock ; 267 ll->last_block = ldi; 268 } 269 270 if (ldi->avail_in_this_block < len) 271 copy_this = (uInt)ldi->avail_in_this_block; 272 else 273 copy_this = (uInt)len; 274 275 to_copy = &(ldi->data[ldi->filled_in_this_block]); 276 277 for (i=0;i<copy_this;i++) 278 *(to_copy+i)=*(from_copy+i); 279 280 ldi->filled_in_this_block += copy_this; 281 ldi->avail_in_this_block -= copy_this; 282 from_copy += copy_this ; 283 len -= copy_this; 284 } 285 return ZIP_OK; 286 } 287 288 /* zipAlreadyThere() operations. "set" in the zip internal structure keeps the 289 // set of names that are in the under-construction central directory so far. A 290 // skipset provides ~O(log n) time insertion and searching. Central directory 291 // records, stored in a linked list of allocated memory datablocks, is read 292 // through "block" in the zip internal structure. 293 294 // The block_*() functions support extracting the central directory file names 295 // from the datablocks. They are designed to support a growing directory by 296 // automatically continuing once more data has been appended to the linked 297 // datablocks. 298 299 // Initialize *block to the head of list. This should only be called once the 300 // list has at least some data in it, i.e. list->first_block is not NULL. */ 301 local void block_init(block_t *block, linkedlist_data *list) { 302 block->node = list->first_block; 303 block->next = block->node->data; 304 block->left = block->node->filled_in_this_block; 305 } 306 307 /* Mark *block as bad, with all subsequent reads returning end, even if more 308 // data is added to the datablocks. This is invoked if the central directory is 309 // invalid, so there is no longer any point in attempting to interpret it. */ 310 local void block_stop(block_t *block) { 311 block->left = 0; 312 block->next = NULL; 313 } 314 315 /* Return true if *block has reached the end of the data in the datablocks. */ 316 local int block_end(block_t *block) { 317 linkedlist_datablock_internal *node = block->node; 318 if (node == NULL) 319 /* This block was previously terminated with extreme prejudice. */ 320 return 1; 321 if (block->next < node->data + node->filled_in_this_block) 322 /* There are more bytes to read in the current datablock. */ 323 return 0; 324 while (node->next_datablock != NULL) { 325 if (node->filled_in_this_block != 0) 326 /* There are some bytes in a later datablock. */ 327 return 0; 328 node = node->next_datablock; 329 } 330 /* Reached the end of the list of datablocks. There's nothing. */ 331 return 1; 332 } 333 334 /* Return one byte from *block, or -1 if the end is reached. */ 335 local int block_get(block_t *block) { 336 while (block->left == 0) { 337 if (block->node == NULL) 338 /* We've been marked bad. Return end. */ 339 return -1; 340 /* Update left in case more was filled in since we were last here. */ 341 block->left = block->node->filled_in_this_block - 342 (size_t)(block->next - block->node->data); 343 if (block->left != 0) 344 /* There was indeed more data appended in the current datablock. */ 345 break; 346 if (block->node->next_datablock == NULL) 347 /* No more data here, and there is no next datablock. At the end. */ 348 return -1; 349 /* Try the next datablock for more data. */ 350 block->node = block->node->next_datablock; 351 block->next = block->node->data; 352 block->left = block->node->filled_in_this_block; 353 } 354 /* We have a byte to return. */ 355 block->left--; 356 return *block->next++; 357 } 358 359 /* Return a 16-bit unsigned little-endian value from block, or a negative value 360 // if the end is reached. */ 361 local long block_get2(block_t *block) { 362 int low = block_get(block); 363 int high = block_get(block); 364 return low < 0 || high < 0 ? -1 : low | ((long)high << 8); 365 } 366 367 /* Read up to len bytes from block into buf. Return the number of bytes read. */ 368 local size_t block_read(block_t *block, unsigned char *buf, size_t len) { 369 size_t need = len; 370 while (need) { 371 if (block->left == 0) { 372 /* Get a byte to update and step through the linked list as needed. */ 373 int got = block_get(block); 374 if (got == -1) 375 /* Reached the end. */ 376 break; 377 *buf++ = (unsigned char)got; 378 need--; 379 continue; 380 } 381 size_t take = need > block->left ? block->left : need; 382 memcpy(buf, block->next, take); 383 block->next += take; 384 block->left -= take; 385 buf += take; 386 need -= take; 387 } 388 return len - need; /* return the number of bytes copied */ 389 } 390 391 /* Skip n bytes in block. Return 0 on success or -1 if there are less than n 392 // bytes to the end. */ 393 local int block_skip(block_t *block, size_t n) { 394 while (n > block->left) { 395 n -= block->left; 396 block->next += block->left; 397 block->left = 0; 398 if (block_get(block) == -1) 399 return -1; 400 n--; 401 } 402 block->next += n; 403 block->left -= n; 404 return 0; 405 } 406 407 /* Process the next central directory record at *block. Return the allocated, 408 // zero-terminated file name, or NULL for end of input or invalid data. If 409 // invalid, *block is marked bad. This uses *set for the allocation of memory. */ 410 local char *block_central_name(block_t *block, set_t *set) { 411 char *name = NULL; 412 for (;;) { 413 if (block_end(block)) 414 /* At the end of the central directory (so far). */ 415 return NULL; 416 417 /* Check for a central directory record signature. */ 418 if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) || 419 block_get2(block) != (CENTRALHEADERMAGIC >> 16)) 420 /* Incorrect signature. */ 421 break; 422 423 /* Go through the remaining fixed-length portion of the record, 424 // extracting the lengths of the three variable-length fields. */ 425 block_skip(block, 24); 426 unsigned flen = (unsigned)block_get2(block); /* file name length */ 427 unsigned xlen = (unsigned)block_get2(block); /* extra length */ 428 unsigned clen = (unsigned)block_get2(block); /* comment length */ 429 if (block_skip(block, 12) == -1) 430 /* Premature end of the record. */ 431 break; 432 433 /* Extract the name and skip over the extra and comment fields. */ 434 name = set_alloc(set, NULL, flen + 1); 435 if (block_read(block, (unsigned char *)name, flen) < flen || 436 block_skip(block, xlen + clen) == -1) 437 /* Premature end of the record. */ 438 break; 439 440 /* Check for embedded nuls in the name. */ 441 if (memchr(name, 0, flen) != NULL) { 442 /* This name can never match the zero-terminated name provided to 443 // zipAlreadyThere(), so we discard it and go back to get another 444 // name. (Who the heck is putting nuls inside their zip file entry 445 // names anyway?) */ 446 set_free(set, name); 447 continue; 448 } 449 450 /* All good. Return the zero-terminated file name. */ 451 name[flen] = 0; 452 return name; 453 } 454 455 /* Invalid signature or premature end of the central directory record. 456 // Abandon trying to process the central directory. */ 457 set_free(set, name); 458 block_stop(block); 459 return NULL; 460 } 461 462 /* Return 0 if name is not in the central directory so far, 1 if it is, -1 if 463 // the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if 464 // file is NULL. */ 465 extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) { 466 zip64_internal *zip = file; 467 if (zip == NULL) 468 return ZIP_PARAMERROR; 469 if (zip->central_dir.first_block == NULL) 470 /* No central directory yet, so no, name isn't there. */ 471 return 0; 472 if (setjmp(zip->set.env)) { 473 /* Memory allocation failure. */ 474 set_end(&zip->set); 475 return -2; 476 } 477 if (!set_ok(&zip->set)) { 478 /* This is the first time here with some central directory content. We 479 // construct this set of names only on demand. Prepare set and block. */ 480 set_start(&zip->set); 481 block_init(&zip->block, &zip->central_dir); 482 } 483 484 /* Update the set of names from the current central directory contents. 485 // This reads any new central directory records since the last time we were 486 // here. */ 487 for (;;) { 488 char *there = block_central_name(&zip->block, &zip->set); 489 if (there == NULL) { 490 if (zip->block.next == NULL) 491 /* The central directory is invalid. */ 492 return -1; 493 break; 494 } 495 496 /* Add there to the set. */ 497 if (set_insert(&zip->set, there)) 498 /* There's already a duplicate in the central directory! We'll just 499 // let this be and carry on. */ 500 set_free(&zip->set, there); 501 } 502 503 /* Return true if name is in the central directory. */ 504 size_t len = strlen(name); 505 char *copy = set_alloc(&zip->set, NULL, len + 1); 506 memcpy(copy, name, len + 1); 507 int found = set_found(&zip->set, copy); 508 set_free(&zip->set, copy); 509 return found; 510 } 511 512 513 /****************************************************************************/ 514 515 #ifndef NO_ADDFILEINEXISTINGZIP 516 /* =========================================================================== 517 Inputs a long in LSB order to the given file 518 nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) 519 */ 520 521 local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { 522 unsigned char buf[8]; 523 int n; 524 for (n = 0; n < nbByte; n++) 525 { 526 buf[n] = (unsigned char)(x & 0xff); 527 x >>= 8; 528 } 529 if (x != 0) 530 { /* data overflow - hack for ZIP64 (X Roche) */ 531 for (n = 0; n < nbByte; n++) 532 { 533 buf[n] = 0xff; 534 } 535 } 536 537 if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte) 538 return ZIP_ERRNO; 539 else 540 return ZIP_OK; 541 } 542 543 local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { 544 unsigned char* buf=(unsigned char*)dest; 545 int n; 546 for (n = 0; n < nbByte; n++) { 547 buf[n] = (unsigned char)(x & 0xff); 548 x >>= 8; 549 } 550 551 if (x != 0) 552 { /* data overflow - hack for ZIP64 */ 553 for (n = 0; n < nbByte; n++) 554 { 555 buf[n] = 0xff; 556 } 557 } 558 } 559 560 /****************************************************************************/ 561 562 563 local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { 564 uLong year = (uLong)ptm->tm_year; 565 if (year>=1980) 566 year-=1980; 567 else if (year>=80) 568 year-=80; 569 return 570 (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) | 571 (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); 572 } 573 574 575 /****************************************************************************/ 576 577 local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { 578 unsigned char c; 579 int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); 580 if (err==1) 581 { 582 *pi = (int)c; 583 return ZIP_OK; 584 } 585 else 586 { 587 if (ZERROR64(*pzlib_filefunc_def,filestream)) 588 return ZIP_ERRNO; 589 else 590 return ZIP_EOF; 591 } 592 } 593 594 595 /* =========================================================================== 596 Reads a long in LSB order from the given gz_stream. Sets 597 */ 598 local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { 599 uLong x ; 600 int i = 0; 601 int err; 602 603 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 604 x = (uLong)i; 605 606 if (err==ZIP_OK) 607 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 608 x += ((uLong)i)<<8; 609 610 if (err==ZIP_OK) 611 *pX = x; 612 else 613 *pX = 0; 614 return err; 615 } 616 617 local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { 618 uLong x ; 619 int i = 0; 620 int err; 621 622 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 623 x = (uLong)i; 624 625 if (err==ZIP_OK) 626 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 627 x += ((uLong)i)<<8; 628 629 if (err==ZIP_OK) 630 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 631 x += ((uLong)i)<<16; 632 633 if (err==ZIP_OK) 634 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 635 x += ((uLong)i)<<24; 636 637 if (err==ZIP_OK) 638 *pX = x; 639 else 640 *pX = 0; 641 return err; 642 } 643 644 645 local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { 646 ZPOS64_T x; 647 int i = 0; 648 int err; 649 650 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 651 x = (ZPOS64_T)i; 652 653 if (err==ZIP_OK) 654 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 655 x += ((ZPOS64_T)i)<<8; 656 657 if (err==ZIP_OK) 658 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 659 x += ((ZPOS64_T)i)<<16; 660 661 if (err==ZIP_OK) 662 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 663 x += ((ZPOS64_T)i)<<24; 664 665 if (err==ZIP_OK) 666 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 667 x += ((ZPOS64_T)i)<<32; 668 669 if (err==ZIP_OK) 670 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 671 x += ((ZPOS64_T)i)<<40; 672 673 if (err==ZIP_OK) 674 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 675 x += ((ZPOS64_T)i)<<48; 676 677 if (err==ZIP_OK) 678 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); 679 x += ((ZPOS64_T)i)<<56; 680 681 if (err==ZIP_OK) 682 *pX = x; 683 else 684 *pX = 0; 685 686 return err; 687 } 688 689 #ifndef BUFREADCOMMENT 690 #define BUFREADCOMMENT (0x400) 691 #endif 692 /* 693 Locate the Central directory of a zipfile (at the end, just before 694 the global comment) 695 */ 696 local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { 697 unsigned char* buf; 698 ZPOS64_T uSizeFile; 699 ZPOS64_T uBackRead; 700 ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ 701 ZPOS64_T uPosFound=0; 702 703 if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) 704 return 0; 705 706 707 uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); 708 709 if (uMaxBack>uSizeFile) 710 uMaxBack = uSizeFile; 711 712 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); 713 if (buf==NULL) 714 return 0; 715 716 uBackRead = 4; 717 while (uBackRead<uMaxBack) 718 { 719 uLong uReadSize; 720 ZPOS64_T uReadPos ; 721 int i; 722 if (uBackRead+BUFREADCOMMENT>uMaxBack) 723 uBackRead = uMaxBack; 724 else 725 uBackRead+=BUFREADCOMMENT; 726 uReadPos = uSizeFile-uBackRead ; 727 728 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 729 (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); 730 if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) 731 break; 732 733 if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) 734 break; 735 736 for (i=(int)uReadSize-3; (i--)>0;) 737 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 738 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) 739 { 740 uPosFound = uReadPos+(unsigned)i; 741 break; 742 } 743 744 if (uPosFound!=0) 745 break; 746 } 747 free(buf); 748 return uPosFound; 749 } 750 751 /* 752 Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before 753 the global comment) 754 */ 755 local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { 756 unsigned char* buf; 757 ZPOS64_T uSizeFile; 758 ZPOS64_T uBackRead; 759 ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ 760 ZPOS64_T uPosFound=0; 761 uLong uL; 762 ZPOS64_T relativeOffset; 763 764 if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) 765 return 0; 766 767 uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); 768 769 if (uMaxBack>uSizeFile) 770 uMaxBack = uSizeFile; 771 772 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); 773 if (buf==NULL) 774 return 0; 775 776 uBackRead = 4; 777 while (uBackRead<uMaxBack) 778 { 779 uLong uReadSize; 780 ZPOS64_T uReadPos; 781 int i; 782 if (uBackRead+BUFREADCOMMENT>uMaxBack) 783 uBackRead = uMaxBack; 784 else 785 uBackRead+=BUFREADCOMMENT; 786 uReadPos = uSizeFile-uBackRead ; 787 788 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 789 (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); 790 if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) 791 break; 792 793 if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) 794 break; 795 796 for (i=(int)uReadSize-3; (i--)>0;) 797 { 798 /* Signature "0x07064b50" Zip64 end of central directory locator */ 799 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) 800 { 801 uPosFound = uReadPos+(unsigned)i; 802 break; 803 } 804 } 805 806 if (uPosFound!=0) 807 break; 808 } 809 810 free(buf); 811 if (uPosFound == 0) 812 return 0; 813 814 /* Zip64 end of central directory locator */ 815 if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) 816 return 0; 817 818 /* the signature, already checked */ 819 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) 820 return 0; 821 822 /* number of the disk with the start of the zip64 end of central directory */ 823 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) 824 return 0; 825 if (uL != 0) 826 return 0; 827 828 /* relative offset of the zip64 end of central directory record */ 829 if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) 830 return 0; 831 832 /* total number of disks */ 833 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) 834 return 0; 835 if (uL != 1) 836 return 0; 837 838 /* Goto Zip64 end of central directory record */ 839 if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) 840 return 0; 841 842 /* the signature */ 843 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) 844 return 0; 845 846 if (uL != 0x06064b50) /* signature of 'Zip64 end of central directory' */ 847 return 0; 848 849 return relativeOffset; 850 } 851 852 local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { 853 int err=ZIP_OK; 854 ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ 855 856 ZPOS64_T size_central_dir; /* size of the central directory */ 857 ZPOS64_T offset_central_dir; /* offset of start of central directory */ 858 ZPOS64_T central_pos; 859 uLong uL; 860 861 uLong number_disk; /* number of the current disk, used for 862 spanning ZIP, unsupported, always 0*/ 863 uLong number_disk_with_CD; /* number of the disk with central dir, used 864 for spanning ZIP, unsupported, always 0*/ 865 ZPOS64_T number_entry; 866 ZPOS64_T number_entry_CD; /* total number of entries in 867 the central dir 868 (same than number_entry on nospan) */ 869 uLong VersionMadeBy; 870 uLong VersionNeeded; 871 uLong size_comment; 872 873 int hasZIP64Record = 0; 874 875 /* check first if we find a ZIP64 record */ 876 central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); 877 if(central_pos > 0) 878 { 879 hasZIP64Record = 1; 880 } 881 else if(central_pos == 0) 882 { 883 central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); 884 } 885 886 /* disable to allow appending to empty ZIP archive 887 if (central_pos==0) 888 err=ZIP_ERRNO; 889 */ 890 891 if(hasZIP64Record) 892 { 893 ZPOS64_T sizeEndOfCentralDirectory; 894 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) 895 err=ZIP_ERRNO; 896 897 /* the signature, already checked */ 898 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) 899 err=ZIP_ERRNO; 900 901 /* size of zip64 end of central directory record */ 902 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) 903 err=ZIP_ERRNO; 904 905 /* version made by */ 906 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) 907 err=ZIP_ERRNO; 908 909 /* version needed to extract */ 910 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) 911 err=ZIP_ERRNO; 912 913 /* number of this disk */ 914 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) 915 err=ZIP_ERRNO; 916 917 /* number of the disk with the start of the central directory */ 918 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) 919 err=ZIP_ERRNO; 920 921 /* total number of entries in the central directory on this disk */ 922 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) 923 err=ZIP_ERRNO; 924 925 /* total number of entries in the central directory */ 926 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) 927 err=ZIP_ERRNO; 928 929 if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) 930 err=ZIP_BADZIPFILE; 931 932 /* size of the central directory */ 933 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) 934 err=ZIP_ERRNO; 935 936 /* offset of start of central directory with respect to the 937 starting disk number */ 938 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) 939 err=ZIP_ERRNO; 940 941 /* TODO.. 942 // read the comment from the standard central header. */ 943 size_comment = 0; 944 } 945 else 946 { 947 /* Read End of central Directory info */ 948 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) 949 err=ZIP_ERRNO; 950 951 /* the signature, already checked */ 952 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) 953 err=ZIP_ERRNO; 954 955 /* number of this disk */ 956 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) 957 err=ZIP_ERRNO; 958 959 /* number of the disk with the start of the central directory */ 960 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) 961 err=ZIP_ERRNO; 962 963 /* total number of entries in the central dir on this disk */ 964 number_entry = 0; 965 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) 966 err=ZIP_ERRNO; 967 else 968 number_entry = uL; 969 970 /* total number of entries in the central dir */ 971 number_entry_CD = 0; 972 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) 973 err=ZIP_ERRNO; 974 else 975 number_entry_CD = uL; 976 977 if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) 978 err=ZIP_BADZIPFILE; 979 980 /* size of the central directory */ 981 size_central_dir = 0; 982 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) 983 err=ZIP_ERRNO; 984 else 985 size_central_dir = uL; 986 987 /* offset of start of central directory with respect to the starting disk number */ 988 offset_central_dir = 0; 989 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) 990 err=ZIP_ERRNO; 991 else 992 offset_central_dir = uL; 993 994 995 /* zipfile global comment length */ 996 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) 997 err=ZIP_ERRNO; 998 } 999 1000 if ((central_pos<offset_central_dir+size_central_dir) && 1001 (err==ZIP_OK)) 1002 err=ZIP_BADZIPFILE; 1003 1004 if (err!=ZIP_OK) 1005 { 1006 ZCLOSE64(pziinit->z_filefunc, pziinit->filestream); 1007 return ZIP_ERRNO; 1008 } 1009 1010 if (size_comment>0) 1011 { 1012 pziinit->globalcomment = (char*)ALLOC(size_comment+1); 1013 if (pziinit->globalcomment) 1014 { 1015 size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); 1016 pziinit->globalcomment[size_comment]=0; 1017 } 1018 } 1019 1020 byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); 1021 pziinit->add_position_when_writing_offset = byte_before_the_zipfile; 1022 1023 { 1024 ZPOS64_T size_central_dir_to_read = size_central_dir; 1025 size_t buf_size = SIZEDATA_INDATABLOCK; 1026 void* buf_read = (void*)ALLOC(buf_size); 1027 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) 1028 err=ZIP_ERRNO; 1029 1030 while ((size_central_dir_to_read>0) && (err==ZIP_OK)) 1031 { 1032 ZPOS64_T read_this = SIZEDATA_INDATABLOCK; 1033 if (read_this > size_central_dir_to_read) 1034 read_this = size_central_dir_to_read; 1035 1036 if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) 1037 err=ZIP_ERRNO; 1038 1039 if (err==ZIP_OK) 1040 err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); 1041 1042 size_central_dir_to_read-=read_this; 1043 } 1044 free(buf_read); 1045 } 1046 pziinit->begin_pos = byte_before_the_zipfile; 1047 pziinit->number_entry = number_entry_CD; 1048 1049 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) 1050 err=ZIP_ERRNO; 1051 1052 return err; 1053 } 1054 1055 1056 #endif /* !NO_ADDFILEINEXISTINGZIP*/ 1057 1058 1059 /************************************************************/ 1060 extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { 1061 zip64_internal ziinit; 1062 zip64_internal* zi; 1063 int err=ZIP_OK; 1064 1065 ziinit.z_filefunc.zseek32_file = NULL; 1066 ziinit.z_filefunc.ztell32_file = NULL; 1067 if (pzlib_filefunc64_32_def==NULL) 1068 fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); 1069 else 1070 ziinit.z_filefunc = *pzlib_filefunc64_32_def; 1071 1072 ziinit.filestream = ZOPEN64(ziinit.z_filefunc, 1073 pathname, 1074 (append == APPEND_STATUS_CREATE) ? 1075 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : 1076 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); 1077 1078 if (ziinit.filestream == NULL) 1079 return NULL; 1080 1081 if (append == APPEND_STATUS_CREATEAFTER) 1082 ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); 1083 1084 ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); 1085 ziinit.in_opened_file_inzip = 0; 1086 ziinit.ci.stream_initialised = 0; 1087 ziinit.number_entry = 0; 1088 ziinit.add_position_when_writing_offset = 0; 1089 init_linkedlist(&(ziinit.central_dir)); 1090 memset(&ziinit.set, 0, sizeof(set_t)); /* make sure set appears dormant */ 1091 1092 1093 1094 zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); 1095 if (zi==NULL) 1096 { 1097 ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); 1098 return NULL; 1099 } 1100 1101 /* now we add file in a zipfile */ 1102 # ifndef NO_ADDFILEINEXISTINGZIP 1103 ziinit.globalcomment = NULL; 1104 if (append == APPEND_STATUS_ADDINZIP) 1105 { 1106 /* Read and Cache Central Directory Records */ 1107 err = LoadCentralDirectoryRecord(&ziinit); 1108 } 1109 1110 if (globalcomment) 1111 { 1112 *globalcomment = ziinit.globalcomment; 1113 } 1114 # endif /* !NO_ADDFILEINEXISTINGZIP*/ 1115 1116 if (err != ZIP_OK) 1117 { 1118 # ifndef NO_ADDFILEINEXISTINGZIP 1119 free(ziinit.globalcomment); 1120 # endif /* !NO_ADDFILEINEXISTINGZIP*/ 1121 free(zi); 1122 return NULL; 1123 } 1124 else 1125 { 1126 *zi = ziinit; 1127 return (zipFile)zi; 1128 } 1129 } 1130 1131 extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { 1132 if (pzlib_filefunc32_def != NULL) 1133 { 1134 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; 1135 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); 1136 return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); 1137 } 1138 else 1139 return zipOpen3(pathname, append, globalcomment, NULL); 1140 } 1141 1142 extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { 1143 if (pzlib_filefunc_def != NULL) 1144 { 1145 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; 1146 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; 1147 zlib_filefunc64_32_def_fill.zopen32_file = NULL; 1148 zlib_filefunc64_32_def_fill.ztell32_file = NULL; 1149 zlib_filefunc64_32_def_fill.zseek32_file = NULL; 1150 return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); 1151 } 1152 else 1153 return zipOpen3(pathname, append, globalcomment, NULL); 1154 } 1155 1156 1157 1158 extern zipFile ZEXPORT zipOpen(const char* pathname, int append) { 1159 return zipOpen3((const void*)pathname,append,NULL,NULL); 1160 } 1161 1162 extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) { 1163 return zipOpen3(pathname,append,NULL,NULL); 1164 } 1165 1166 local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { 1167 /* write the local header */ 1168 int err; 1169 uInt size_filename = (uInt)strlen(filename); 1170 uInt size_extrafield = size_extrafield_local; 1171 1172 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); 1173 1174 if (err==ZIP_OK) 1175 { 1176 if(zi->ci.zip64) 1177 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ 1178 else 1179 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ 1180 } 1181 1182 if (err==ZIP_OK) 1183 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); 1184 1185 if (err==ZIP_OK) 1186 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); 1187 1188 if (err==ZIP_OK) 1189 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); 1190 1191 /* CRC / Compressed size / Uncompressed size will be filled in later and rewritten later */ 1192 if (err==ZIP_OK) 1193 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ 1194 if (err==ZIP_OK) 1195 { 1196 if(zi->ci.zip64) 1197 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ 1198 else 1199 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ 1200 } 1201 if (err==ZIP_OK) 1202 { 1203 if(zi->ci.zip64) 1204 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ 1205 else 1206 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ 1207 } 1208 1209 if (err==ZIP_OK) 1210 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); 1211 1212 if(zi->ci.zip64) 1213 { 1214 size_extrafield += 20; 1215 } 1216 1217 if (err==ZIP_OK) 1218 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); 1219 1220 if ((err==ZIP_OK) && (size_filename > 0)) 1221 { 1222 if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) 1223 err = ZIP_ERRNO; 1224 } 1225 1226 if ((err==ZIP_OK) && (size_extrafield_local > 0)) 1227 { 1228 if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) 1229 err = ZIP_ERRNO; 1230 } 1231 1232 1233 if ((err==ZIP_OK) && (zi->ci.zip64)) 1234 { 1235 /* write the Zip64 extended info */ 1236 short HeaderID = 1; 1237 short DataSize = 16; 1238 ZPOS64_T CompressedSize = 0; 1239 ZPOS64_T UncompressedSize = 0; 1240 1241 /* Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) */ 1242 zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); 1243 1244 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2); 1245 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2); 1246 1247 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); 1248 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); 1249 } 1250 1251 return err; 1252 } 1253 1254 /* Return the length of the UTF-8 code at str[0..len-1] in [1..4], or negative 1255 if there is no valid UTF-8 code there. If negative, it is minus the number 1256 of bytes examined in order to determine it was bad. Or if minus the return 1257 code is one less than len, then at least one more byte than provided would 1258 be needed to complete the code. */ 1259 local int utf8len(unsigned char const *str, size_t len) { 1260 return 1261 len == 0 ? -1 : /* empty input */ 1262 str[0] < 0x80 ? 1 : /* good one-byte */ 1263 str[0] < 0xc0 ? -1 : /* bad first byte */ 1264 len < 2 || (str[1] >> 6) != 2 ? -2 : /* missing or bad 2nd byte */ 1265 str[0] < 0xc2 ? -2 : /* overlong code */ 1266 str[0] < 0xe0 ? 2 : /* good two-byte */ 1267 len < 3 || (str[2] >> 6) != 2 ? -3 : /* missing or bad 3rd byte */ 1268 str[0] == 0xe0 && str[1] < 0xa0 ? -3 : /* overlong code */ 1269 str[0] < 0xf0 ? 3 : /* good three-byte */ 1270 len < 4 || (str[3] >> 6) != 2 ? -4 : /* missing or bad 4th byte */ 1271 str[0] == 0xf0 && str[1] < 0x90 ? -4 : /* overlong code */ 1272 str[0] < 0xf4 || 1273 (str[0] == 0xf4 && str[1] < 0x90) ? 4 : /* good four-byte */ 1274 -4; /* code > 0x10ffff */ 1275 } 1276 1277 /* Return true if str[0..len-1] is valid UTF-8 *and* it contains at least one 1278 code of two or more bytes. This is used to determine whether or not to set 1279 bit 11 in the zip header flags. */ 1280 local int isutf8(char const *str, size_t len) { 1281 int utf8 = 0; 1282 while (len) { 1283 int code = utf8len((unsigned char const *)str, len); 1284 if (code < 0) 1285 return 0; 1286 if (code > 1) 1287 utf8 = 1; 1288 str += code; 1289 len -= (unsigned)code; 1290 } 1291 return utf8; 1292 } 1293 1294 /* 1295 NOTE. 1296 When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped 1297 before calling this function it can be done with zipRemoveExtraInfoBlock 1298 1299 It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize 1300 unnecessary allocations. 1301 */ 1302 extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1303 const void* extrafield_local, uInt size_extrafield_local, 1304 const void* extrafield_global, uInt size_extrafield_global, 1305 const char* comment, int method, int level, int raw, 1306 int windowBits,int memLevel, int strategy, 1307 const char* password, uLong crcForCrypting, 1308 uLong versionMadeBy, uLong flagBase, int zip64) { 1309 zip64_internal* zi; 1310 uInt size_filename; 1311 uInt size_comment; 1312 uInt i; 1313 int err = ZIP_OK; 1314 1315 # ifdef NOCRYPT 1316 if (password != NULL) 1317 return ZIP_PARAMERROR; 1318 # endif 1319 1320 if (file == NULL) 1321 return ZIP_PARAMERROR; 1322 1323 #ifdef HAVE_BZIP2 1324 if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) 1325 return ZIP_PARAMERROR; 1326 #else 1327 if ((method!=0) && (method!=Z_DEFLATED)) 1328 return ZIP_PARAMERROR; 1329 #endif 1330 1331 /* The filename and comment length must fit in 16 bits. */ 1332 if ((filename!=NULL) && (strlen(filename)>0xffff)) 1333 return ZIP_PARAMERROR; 1334 if ((comment!=NULL) && (strlen(comment)>0xffff)) 1335 return ZIP_PARAMERROR; 1336 /* The extra field length must fit in 16 bits. If the member also requires 1337 // a Zip64 extra block, that will also need to fit within that 16-bit 1338 // length, but that will be checked for later. */ 1339 if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff)) 1340 return ZIP_PARAMERROR; 1341 1342 zi = (zip64_internal*)file; 1343 1344 if (zi->in_opened_file_inzip == 1) 1345 { 1346 err = zipCloseFileInZip (file); 1347 if (err != ZIP_OK) 1348 return err; 1349 } 1350 1351 if (filename==NULL) 1352 filename="-"; 1353 1354 if (comment==NULL) 1355 size_comment = 0; 1356 else 1357 size_comment = (uInt)strlen(comment); 1358 1359 size_filename = (uInt)strlen(filename); 1360 1361 if (zipfi == NULL) 1362 zi->ci.dosDate = 0; 1363 else 1364 { 1365 if (zipfi->dosDate != 0) 1366 zi->ci.dosDate = zipfi->dosDate; 1367 else 1368 zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); 1369 } 1370 1371 zi->ci.flag = flagBase; 1372 if ((level==8) || (level==9)) 1373 zi->ci.flag |= 2; 1374 if (level==2) 1375 zi->ci.flag |= 4; 1376 if (level==1) 1377 zi->ci.flag |= 6; 1378 if (password != NULL) 1379 zi->ci.flag |= 1; 1380 if (isutf8(filename, size_filename) && 1381 (size_comment == 0 || isutf8(comment, size_comment))) 1382 zi->ci.flag |= (1 << 11); 1383 1384 zi->ci.crc32 = 0; 1385 zi->ci.method = method; 1386 zi->ci.encrypt = 0; 1387 zi->ci.stream_initialised = 0; 1388 zi->ci.pos_in_buffered_data = 0; 1389 zi->ci.raw = raw; 1390 zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); 1391 1392 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; 1393 zi->ci.size_centralExtraFree = 32; /* Extra space we have reserved in case we need to add ZIP64 extra info data */ 1394 1395 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); 1396 1397 zi->ci.size_centralExtra = size_extrafield_global; 1398 zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); 1399 /* version info */ 1400 zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); 1401 zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); 1402 zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); 1403 zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); 1404 zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); 1405 zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ 1406 zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ 1407 zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ 1408 zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); 1409 zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); 1410 zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); 1411 zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ 1412 1413 if (zipfi==NULL) 1414 zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 1415 else 1416 zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 1417 1418 if (zipfi==NULL) 1419 zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 1420 else 1421 zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); 1422 1423 if(zi->ci.pos_local_header >= 0xffffffff) 1424 zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); 1425 else 1426 zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); 1427 1428 for (i=0;i<size_filename;i++) 1429 *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); 1430 1431 for (i=0;i<size_extrafield_global;i++) 1432 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) = 1433 *(((const char*)extrafield_global)+i); 1434 1435 for (i=0;i<size_comment;i++) 1436 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+ 1437 size_extrafield_global+i) = *(comment+i); 1438 if (zi->ci.central_header == NULL) 1439 return ZIP_INTERNALERROR; 1440 1441 zi->ci.zip64 = zip64; 1442 zi->ci.totalCompressedData = 0; 1443 zi->ci.totalUncompressedData = 0; 1444 zi->ci.pos_zip64extrainfo = 0; 1445 1446 err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); 1447 1448 #ifdef HAVE_BZIP2 1449 zi->ci.bstream.avail_in = (uInt)0; 1450 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; 1451 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; 1452 zi->ci.bstream.total_in_hi32 = 0; 1453 zi->ci.bstream.total_in_lo32 = 0; 1454 zi->ci.bstream.total_out_hi32 = 0; 1455 zi->ci.bstream.total_out_lo32 = 0; 1456 #endif 1457 1458 zi->ci.stream.avail_in = (uInt)0; 1459 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 1460 zi->ci.stream.next_out = zi->ci.buffered_data; 1461 zi->ci.stream.total_in = 0; 1462 zi->ci.stream.total_out = 0; 1463 zi->ci.stream.data_type = Z_BINARY; 1464 1465 #ifdef HAVE_BZIP2 1466 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) 1467 #else 1468 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1469 #endif 1470 { 1471 if(zi->ci.method == Z_DEFLATED) 1472 { 1473 zi->ci.stream.zalloc = (alloc_func)0; 1474 zi->ci.stream.zfree = (free_func)0; 1475 zi->ci.stream.opaque = (voidpf)0; 1476 1477 if (windowBits>0) 1478 windowBits = -windowBits; 1479 1480 err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); 1481 1482 if (err==Z_OK) 1483 zi->ci.stream_initialised = Z_DEFLATED; 1484 } 1485 else if(zi->ci.method == Z_BZIP2ED) 1486 { 1487 #ifdef HAVE_BZIP2 1488 /* Init BZip stuff here */ 1489 zi->ci.bstream.bzalloc = 0; 1490 zi->ci.bstream.bzfree = 0; 1491 zi->ci.bstream.opaque = (voidpf)0; 1492 1493 err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); 1494 if(err == BZ_OK) 1495 zi->ci.stream_initialised = Z_BZIP2ED; 1496 #endif 1497 } 1498 1499 } 1500 1501 # ifndef NOCRYPT 1502 zi->ci.crypt_header_size = 0; 1503 if ((err==Z_OK) && (password != NULL)) 1504 { 1505 unsigned char bufHead[RAND_HEAD_LEN]; 1506 unsigned int sizeHead; 1507 zi->ci.encrypt = 1; 1508 zi->ci.pcrc_32_tab = get_crc_table(); 1509 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ 1510 1511 sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); 1512 zi->ci.crypt_header_size = sizeHead; 1513 1514 if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) 1515 err = ZIP_ERRNO; 1516 } 1517 # endif 1518 1519 if (err==Z_OK) 1520 zi->in_opened_file_inzip = 1; 1521 return err; 1522 } 1523 1524 extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1525 const void* extrafield_local, uInt size_extrafield_local, 1526 const void* extrafield_global, uInt size_extrafield_global, 1527 const char* comment, int method, int level, int raw, 1528 int windowBits,int memLevel, int strategy, 1529 const char* password, uLong crcForCrypting, 1530 uLong versionMadeBy, uLong flagBase) { 1531 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1532 extrafield_local, size_extrafield_local, 1533 extrafield_global, size_extrafield_global, 1534 comment, method, level, raw, 1535 windowBits, memLevel, strategy, 1536 password, crcForCrypting, versionMadeBy, flagBase, 0); 1537 } 1538 1539 extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1540 const void* extrafield_local, uInt size_extrafield_local, 1541 const void* extrafield_global, uInt size_extrafield_global, 1542 const char* comment, int method, int level, int raw, 1543 int windowBits,int memLevel, int strategy, 1544 const char* password, uLong crcForCrypting) { 1545 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1546 extrafield_local, size_extrafield_local, 1547 extrafield_global, size_extrafield_global, 1548 comment, method, level, raw, 1549 windowBits, memLevel, strategy, 1550 password, crcForCrypting, VERSIONMADEBY, 0, 0); 1551 } 1552 1553 extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1554 const void* extrafield_local, uInt size_extrafield_local, 1555 const void* extrafield_global, uInt size_extrafield_global, 1556 const char* comment, int method, int level, int raw, 1557 int windowBits,int memLevel, int strategy, 1558 const char* password, uLong crcForCrypting, int zip64) { 1559 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1560 extrafield_local, size_extrafield_local, 1561 extrafield_global, size_extrafield_global, 1562 comment, method, level, raw, 1563 windowBits, memLevel, strategy, 1564 password, crcForCrypting, VERSIONMADEBY, 0, zip64); 1565 } 1566 1567 extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1568 const void* extrafield_local, uInt size_extrafield_local, 1569 const void* extrafield_global, uInt size_extrafield_global, 1570 const char* comment, int method, int level, int raw) { 1571 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1572 extrafield_local, size_extrafield_local, 1573 extrafield_global, size_extrafield_global, 1574 comment, method, level, raw, 1575 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 1576 NULL, 0, VERSIONMADEBY, 0, 0); 1577 } 1578 1579 extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1580 const void* extrafield_local, uInt size_extrafield_local, 1581 const void* extrafield_global, uInt size_extrafield_global, 1582 const char* comment, int method, int level, int raw, int zip64) { 1583 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1584 extrafield_local, size_extrafield_local, 1585 extrafield_global, size_extrafield_global, 1586 comment, method, level, raw, 1587 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 1588 NULL, 0, VERSIONMADEBY, 0, zip64); 1589 } 1590 1591 extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1592 const void* extrafield_local, uInt size_extrafield_local, 1593 const void*extrafield_global, uInt size_extrafield_global, 1594 const char* comment, int method, int level, int zip64) { 1595 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1596 extrafield_local, size_extrafield_local, 1597 extrafield_global, size_extrafield_global, 1598 comment, method, level, 0, 1599 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 1600 NULL, 0, VERSIONMADEBY, 0, zip64); 1601 } 1602 1603 extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi, 1604 const void* extrafield_local, uInt size_extrafield_local, 1605 const void*extrafield_global, uInt size_extrafield_global, 1606 const char* comment, int method, int level) { 1607 return zipOpenNewFileInZip4_64(file, filename, zipfi, 1608 extrafield_local, size_extrafield_local, 1609 extrafield_global, size_extrafield_global, 1610 comment, method, level, 0, 1611 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 1612 NULL, 0, VERSIONMADEBY, 0, 0); 1613 } 1614 1615 local int zip64FlushWriteBuffer(zip64_internal* zi) { 1616 int err=ZIP_OK; 1617 1618 if (zi->ci.encrypt != 0) 1619 { 1620 #ifndef NOCRYPT 1621 uInt i; 1622 int t; 1623 for (i=0;i<zi->ci.pos_in_buffered_data;i++) 1624 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); 1625 #endif 1626 } 1627 1628 if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) 1629 err = ZIP_ERRNO; 1630 1631 zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; 1632 1633 #ifdef HAVE_BZIP2 1634 if(zi->ci.method == Z_BZIP2ED) 1635 { 1636 zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; 1637 zi->ci.bstream.total_in_lo32 = 0; 1638 zi->ci.bstream.total_in_hi32 = 0; 1639 } 1640 else 1641 #endif 1642 { 1643 zi->ci.totalUncompressedData += zi->ci.stream.total_in; 1644 zi->ci.stream.total_in = 0; 1645 } 1646 1647 1648 zi->ci.pos_in_buffered_data = 0; 1649 1650 return err; 1651 } 1652 1653 extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) { 1654 zip64_internal* zi; 1655 int err=ZIP_OK; 1656 1657 if (file == NULL) 1658 return ZIP_PARAMERROR; 1659 zi = (zip64_internal*)file; 1660 1661 if (zi->in_opened_file_inzip == 0) 1662 return ZIP_PARAMERROR; 1663 1664 zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); 1665 1666 #ifdef HAVE_BZIP2 1667 if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) 1668 { 1669 zi->ci.bstream.next_in = (void*)buf; 1670 zi->ci.bstream.avail_in = len; 1671 err = BZ_RUN_OK; 1672 1673 while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) 1674 { 1675 if (zi->ci.bstream.avail_out == 0) 1676 { 1677 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) 1678 err = ZIP_ERRNO; 1679 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; 1680 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; 1681 } 1682 1683 1684 if(err != BZ_RUN_OK) 1685 break; 1686 1687 if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) 1688 { 1689 uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; 1690 /* uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; */ 1691 err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); 1692 1693 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; 1694 } 1695 } 1696 1697 if(err == BZ_RUN_OK) 1698 err = ZIP_OK; 1699 } 1700 else 1701 #endif 1702 { 1703 zi->ci.stream.next_in = buf; 1704 zi->ci.stream.avail_in = len; 1705 1706 while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) 1707 { 1708 if (zi->ci.stream.avail_out == 0) 1709 { 1710 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) 1711 err = ZIP_ERRNO; 1712 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 1713 zi->ci.stream.next_out = zi->ci.buffered_data; 1714 } 1715 1716 1717 if(err != ZIP_OK) 1718 break; 1719 1720 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1721 { 1722 uLong uTotalOutBefore = zi->ci.stream.total_out; 1723 err=deflate(&zi->ci.stream, Z_NO_FLUSH); 1724 1725 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; 1726 } 1727 else 1728 { 1729 uInt copy_this,i; 1730 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) 1731 copy_this = zi->ci.stream.avail_in; 1732 else 1733 copy_this = zi->ci.stream.avail_out; 1734 1735 for (i = 0; i < copy_this; i++) 1736 *(((char*)zi->ci.stream.next_out)+i) = 1737 *(((const char*)zi->ci.stream.next_in)+i); 1738 { 1739 zi->ci.stream.avail_in -= copy_this; 1740 zi->ci.stream.avail_out-= copy_this; 1741 zi->ci.stream.next_in+= copy_this; 1742 zi->ci.stream.next_out+= copy_this; 1743 zi->ci.stream.total_in+= copy_this; 1744 zi->ci.stream.total_out+= copy_this; 1745 zi->ci.pos_in_buffered_data += copy_this; 1746 } 1747 } 1748 }/* while(...) */ 1749 } 1750 1751 return err; 1752 } 1753 1754 extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) { 1755 return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); 1756 } 1757 1758 extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { 1759 zip64_internal* zi; 1760 ZPOS64_T compressed_size; 1761 uLong invalidValue = 0xffffffff; 1762 unsigned datasize = 0; 1763 int err=ZIP_OK; 1764 1765 if (file == NULL) 1766 return ZIP_PARAMERROR; 1767 zi = (zip64_internal*)file; 1768 1769 if (zi->in_opened_file_inzip == 0) 1770 return ZIP_PARAMERROR; 1771 zi->ci.stream.avail_in = 0; 1772 1773 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1774 { 1775 while (err==ZIP_OK) 1776 { 1777 uLong uTotalOutBefore; 1778 if (zi->ci.stream.avail_out == 0) 1779 { 1780 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) 1781 err = ZIP_ERRNO; 1782 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 1783 zi->ci.stream.next_out = zi->ci.buffered_data; 1784 } 1785 uTotalOutBefore = zi->ci.stream.total_out; 1786 err=deflate(&zi->ci.stream, Z_FINISH); 1787 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; 1788 } 1789 } 1790 else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) 1791 { 1792 #ifdef HAVE_BZIP2 1793 err = BZ_FINISH_OK; 1794 while (err==BZ_FINISH_OK) 1795 { 1796 uLong uTotalOutBefore; 1797 if (zi->ci.bstream.avail_out == 0) 1798 { 1799 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) 1800 err = ZIP_ERRNO; 1801 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; 1802 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; 1803 } 1804 uTotalOutBefore = zi->ci.bstream.total_out_lo32; 1805 err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); 1806 if(err == BZ_STREAM_END) 1807 err = Z_STREAM_END; 1808 1809 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); 1810 } 1811 1812 if(err == BZ_FINISH_OK) 1813 err = ZIP_OK; 1814 #endif 1815 } 1816 1817 if (err==Z_STREAM_END) 1818 err=ZIP_OK; /* this is normal */ 1819 1820 if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) 1821 { 1822 if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) 1823 err = ZIP_ERRNO; 1824 } 1825 1826 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1827 { 1828 int tmp_err = deflateEnd(&zi->ci.stream); 1829 if (err == ZIP_OK) 1830 err = tmp_err; 1831 zi->ci.stream_initialised = 0; 1832 } 1833 #ifdef HAVE_BZIP2 1834 else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) 1835 { 1836 int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); 1837 if (err==ZIP_OK) 1838 err = tmperr; 1839 zi->ci.stream_initialised = 0; 1840 } 1841 #endif 1842 1843 if (!zi->ci.raw) 1844 { 1845 crc32 = (uLong)zi->ci.crc32; 1846 uncompressed_size = zi->ci.totalUncompressedData; 1847 } 1848 compressed_size = zi->ci.totalCompressedData; 1849 1850 # ifndef NOCRYPT 1851 compressed_size += zi->ci.crypt_header_size; 1852 # endif 1853 1854 /* update Current Item crc and sizes, */ 1855 if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) 1856 { 1857 /*version Made by*/ 1858 zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); 1859 /*version needed*/ 1860 zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); 1861 1862 } 1863 1864 zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ 1865 1866 1867 if(compressed_size >= 0xffffffff) 1868 zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ 1869 else 1870 zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ 1871 1872 /* set internal file attributes field */ 1873 if (zi->ci.stream.data_type == Z_ASCII) 1874 zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); 1875 1876 if(uncompressed_size >= 0xffffffff) 1877 zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ 1878 else 1879 zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ 1880 1881 /* Add ZIP64 extra info field for uncompressed size */ 1882 if(uncompressed_size >= 0xffffffff) 1883 datasize += 8; 1884 1885 /* Add ZIP64 extra info field for compressed size */ 1886 if(compressed_size >= 0xffffffff) 1887 datasize += 8; 1888 1889 /* Add ZIP64 extra info field for relative offset to local file header of current file */ 1890 if(zi->ci.pos_local_header >= 0xffffffff) 1891 datasize += 8; 1892 1893 if(datasize > 0) 1894 { 1895 char* p = NULL; 1896 1897 if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) 1898 { 1899 /* we cannot write more data to the buffer that we have room for. */ 1900 return ZIP_BADZIPFILE; 1901 } 1902 1903 p = zi->ci.central_header + zi->ci.size_centralheader; 1904 1905 /* Add Extra Information Header for 'ZIP64 information' */ 1906 zip64local_putValue_inmemory(p, 0x0001, 2); /* HeaderID */ 1907 p += 2; 1908 zip64local_putValue_inmemory(p, datasize, 2); /* DataSize */ 1909 p += 2; 1910 1911 if(uncompressed_size >= 0xffffffff) 1912 { 1913 zip64local_putValue_inmemory(p, uncompressed_size, 8); 1914 p += 8; 1915 } 1916 1917 if(compressed_size >= 0xffffffff) 1918 { 1919 zip64local_putValue_inmemory(p, compressed_size, 8); 1920 p += 8; 1921 } 1922 1923 if(zi->ci.pos_local_header >= 0xffffffff) 1924 { 1925 zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); 1926 p += 8; 1927 } 1928 1929 /* Update how much extra free space we got in the memory buffer 1930 // and increase the centralheader size so the new ZIP64 fields are included 1931 // ( 4 below is the size of HeaderID and DataSize field ) */ 1932 zi->ci.size_centralExtraFree -= datasize + 4; 1933 zi->ci.size_centralheader += datasize + 4; 1934 1935 /* Update the extra info size field */ 1936 zi->ci.size_centralExtra += datasize + 4; 1937 zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); 1938 } 1939 1940 if (err==ZIP_OK) 1941 err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); 1942 1943 free(zi->ci.central_header); 1944 1945 if (err==ZIP_OK) 1946 { 1947 /* Update the LocalFileHeader with the new values. */ 1948 1949 ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); 1950 1951 if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) 1952 err = ZIP_ERRNO; 1953 1954 if (err==ZIP_OK) 1955 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ 1956 1957 if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) 1958 { 1959 if(zi->ci.pos_zip64extrainfo > 0) 1960 { 1961 /* Update the size in the ZIP64 extended field. */ 1962 if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) 1963 err = ZIP_ERRNO; 1964 1965 if (err==ZIP_OK) /* compressed size, unknown */ 1966 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); 1967 1968 if (err==ZIP_OK) /* uncompressed size, unknown */ 1969 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); 1970 } 1971 else 1972 err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */ 1973 } 1974 else 1975 { 1976 if (err==ZIP_OK) /* compressed size, unknown */ 1977 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); 1978 1979 if (err==ZIP_OK) /* uncompressed size, unknown */ 1980 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); 1981 } 1982 1983 if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) 1984 err = ZIP_ERRNO; 1985 } 1986 1987 zi->number_entry ++; 1988 zi->in_opened_file_inzip = 0; 1989 1990 return err; 1991 } 1992 1993 extern int ZEXPORT zipCloseFileInZip(zipFile file) { 1994 return zipCloseFileInZipRaw (file,0,0); 1995 } 1996 1997 local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { 1998 int err = ZIP_OK; 1999 ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; 2000 2001 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); 2002 2003 /*num disks*/ 2004 if (err==ZIP_OK) /* number of the disk with the start of the central directory */ 2005 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); 2006 2007 /*relative offset*/ 2008 if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ 2009 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); 2010 2011 /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ 2012 if (err==ZIP_OK) /* number of the disk with the start of the central directory */ 2013 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); 2014 2015 return err; 2016 } 2017 2018 local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { 2019 int err = ZIP_OK; 2020 2021 uLong Zip64DataSize = 44; 2022 2023 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); 2024 2025 if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ 2026 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); /* why ZPOS64_T of this ? */ 2027 2028 if (err==ZIP_OK) /* version made by */ 2029 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); 2030 2031 if (err==ZIP_OK) /* version needed */ 2032 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); 2033 2034 if (err==ZIP_OK) /* number of this disk */ 2035 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); 2036 2037 if (err==ZIP_OK) /* number of the disk with the start of the central directory */ 2038 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); 2039 2040 if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ 2041 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); 2042 2043 if (err==ZIP_OK) /* total number of entries in the central dir */ 2044 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); 2045 2046 if (err==ZIP_OK) /* size of the central directory */ 2047 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); 2048 2049 if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ 2050 { 2051 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; 2052 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); 2053 } 2054 return err; 2055 } 2056 2057 local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { 2058 int err = ZIP_OK; 2059 2060 /*signature*/ 2061 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); 2062 2063 if (err==ZIP_OK) /* number of this disk */ 2064 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); 2065 2066 if (err==ZIP_OK) /* number of the disk with the start of the central directory */ 2067 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); 2068 2069 if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ 2070 { 2071 { 2072 if(zi->number_entry >= 0xFFFF) 2073 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ 2074 else 2075 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); 2076 } 2077 } 2078 2079 if (err==ZIP_OK) /* total number of entries in the central dir */ 2080 { 2081 if(zi->number_entry >= 0xFFFF) 2082 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ 2083 else 2084 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); 2085 } 2086 2087 if (err==ZIP_OK) /* size of the central directory */ 2088 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); 2089 2090 if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ 2091 { 2092 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; 2093 if(pos >= 0xffffffff) 2094 { 2095 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); 2096 } 2097 else 2098 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); 2099 } 2100 2101 return err; 2102 } 2103 2104 local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { 2105 int err = ZIP_OK; 2106 uInt size_global_comment = 0; 2107 2108 if(global_comment != NULL) 2109 size_global_comment = (uInt)strlen(global_comment); 2110 2111 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); 2112 2113 if (err == ZIP_OK && size_global_comment > 0) 2114 { 2115 if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) 2116 err = ZIP_ERRNO; 2117 } 2118 return err; 2119 } 2120 2121 extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { 2122 zip64_internal* zi; 2123 int err = 0; 2124 uLong size_centraldir = 0; 2125 ZPOS64_T centraldir_pos_inzip; 2126 ZPOS64_T pos; 2127 2128 if (file == NULL) 2129 return ZIP_PARAMERROR; 2130 2131 zi = (zip64_internal*)file; 2132 2133 if (zi->in_opened_file_inzip == 1) 2134 { 2135 err = zipCloseFileInZip (file); 2136 } 2137 2138 #ifndef NO_ADDFILEINEXISTINGZIP 2139 if (global_comment==NULL) 2140 global_comment = zi->globalcomment; 2141 #endif 2142 2143 centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); 2144 2145 if (err==ZIP_OK) 2146 { 2147 linkedlist_datablock_internal* ldi = zi->central_dir.first_block; 2148 while (ldi!=NULL) 2149 { 2150 if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) 2151 { 2152 if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) 2153 err = ZIP_ERRNO; 2154 } 2155 2156 size_centraldir += ldi->filled_in_this_block; 2157 ldi = ldi->next_datablock; 2158 } 2159 } 2160 free_linkedlist(&(zi->central_dir)); 2161 2162 set_end(&zi->set); /* set was zeroed, so this is safe */ 2163 2164 pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; 2165 if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF) 2166 { 2167 ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); 2168 Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); 2169 2170 Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); 2171 } 2172 2173 if (err==ZIP_OK) 2174 err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); 2175 2176 if(err == ZIP_OK) 2177 err = Write_GlobalComment(zi, global_comment); 2178 2179 if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) 2180 if (err == ZIP_OK) 2181 err = ZIP_ERRNO; 2182 2183 #ifndef NO_ADDFILEINEXISTINGZIP 2184 free(zi->globalcomment); 2185 #endif 2186 free(zi); 2187 2188 return err; 2189 } 2190 2191 extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { 2192 char* p = pData; 2193 int size = 0; 2194 char* pNewHeader; 2195 char* pTmp; 2196 short header; 2197 short dataSize; 2198 2199 int retVal = ZIP_OK; 2200 2201 if(pData == NULL || dataLen == NULL || *dataLen < 4) 2202 return ZIP_PARAMERROR; 2203 2204 pNewHeader = (char*)ALLOC((unsigned)*dataLen); 2205 pTmp = pNewHeader; 2206 2207 while(p < (pData + *dataLen)) 2208 { 2209 header = *(short*)p; 2210 dataSize = *(((short*)p)+1); 2211 2212 if( header == sHeader ) /* Header found. */ 2213 { 2214 p += dataSize + 4; /* skip it. do not copy to temp buffer */ 2215 } 2216 else 2217 { 2218 /* Extra Info block should not be removed, So copy it to the temp buffer. */ 2219 memcpy(pTmp, p, dataSize + 4); 2220 p += dataSize + 4; 2221 size += dataSize + 4; 2222 } 2223 2224 } 2225 2226 if(size < *dataLen) 2227 { 2228 /* clean old extra info block. */ 2229 memset(pData,0, *dataLen); 2230 2231 /* copy the new extra info block over the old */ 2232 if(size > 0) 2233 memcpy(pData, pNewHeader, size); 2234 2235 /* set the new extra info size */ 2236 *dataLen = size; 2237 2238 retVal = ZIP_OK; 2239 } 2240 else 2241 retVal = ZIP_ERRNO; 2242 2243 free(pNewHeader); 2244 2245 return retVal; 2246 } 2247