unzip.c (44242B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2004, 2008, 2012 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @file common/unzip.c 22 * @brief API to access ZIP archives 23 * @author Christian Grothoff 24 * 25 * This code is based in part on 26 * unzip 1.00 Copyright 1998-2003 Gilles Vollant 27 * http://www.winimage.com/zLibDll" 28 * 29 * 30 * The filenames for each file in a zipfile are stored in two locations. 31 * There is one at the start of each entry, just before the compressed data, 32 * and another at the end in a 'central directory structure'. 33 * 34 * In order to catch self-extracting executables, we scan backwards from the end 35 * of the file looking for the central directory structure. The previous version 36 * of this went forewards through the local headers, but that only works for plain 37 * vanilla zip's and I don't feel like writing a special case for each of the dozen 38 * self-extracting executable stubs. 39 * 40 * This assumes that the zip file is considered to be non-corrupt/non-truncated. 41 * If it is truncated then it's not considered to be a zip and skipped. 42 * 43 * ZIP format description from appnote.iz and appnote.txt (more or less): 44 * 45 * (this is why you always need to put in the last floppy if you span disks) 46 * 47 * 0- 3 end of central dir signature 4 bytes (0x06054b50) P K ^E ^F 48 * 4- 5 number of this disk 2 bytes 49 * 6- 7 number of the disk with the 50 * start of the central directory 2 bytes 51 * 8- 9 total number of entries in 52 * the central dir on this disk 2 bytes 53 * 10-11 total number of entries in 54 * the central dir 2 bytes 55 * 12-15 size of the central directory 4 bytes 56 * 16-19 offset of start of central 57 * directory with respect to 58 * the starting disk number 4 bytes 59 * 20-21 zipfile comment length 2 bytes 60 * 22-?? zipfile comment (variable size) max length 65536 bytes 61 */ 62 #include "platform.h" 63 #include <ctype.h> 64 #include "extractor.h" 65 #include "unzip.h" 66 67 #define CASESENSITIVITY (0) 68 #define MAXFILENAME (256) 69 70 #ifndef UNZ_BUFSIZE 71 #define UNZ_BUFSIZE (16384) 72 #endif 73 74 #ifndef UNZ_MAXFILENAMEINZIP 75 #define UNZ_MAXFILENAMEINZIP (256) 76 #endif 77 78 #define SIZECENTRALDIRITEM (0x2e) 79 #define SIZEZIPLOCALHEADER (0x1e) 80 81 82 /** 83 * IO callbacks for access to the ZIP data. 84 */ 85 struct FileFuncDefs 86 { 87 /** 88 * Callback for reading 'size' bytes from the ZIP archive into buf. 89 */ 90 uLong (*zread_file) (voidpf opaque, void*buf, uLong size); 91 92 /** 93 * Callback to obtain the current read offset in the ZIP archive. 94 */ 95 long (*ztell_file) (voidpf opaque); 96 97 /** 98 * Callback for seeking to a different position in the ZIP archive. 99 */ 100 long (*zseek_file) (voidpf opaque, uLong offset, int origin); 101 102 /** 103 * Opaque argument to pass to all IO functions. 104 */ 105 voidpf opaque; 106 }; 107 108 109 /** 110 * Macro to read using filefunc API. 111 * 112 * @param filefunc filefunc struct 113 * @param buf where to write data 114 * @param size number of bytes to read 115 * @return number of bytes copied to buf 116 */ 117 #define ZREAD(filefunc,buf,size) ((*((filefunc).zread_file))((filefunc).opaque, \ 118 buf, size)) 119 120 /** 121 * Macro to obtain current offset in file using filefunc API. 122 * 123 * @param filefunc filefunc struct 124 * @return current offset in file 125 */ 126 #define ZTELL(filefunc) ((*((filefunc).ztell_file))((filefunc).opaque)) 127 128 /** 129 * Macro to seek using filefunc API. 130 * 131 * @param filefunc filefunc struct 132 * @param pos position to seek 133 * @param mode seek mode 134 * @return 0 on success 135 */ 136 #define ZSEEK(filefunc,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque, \ 137 pos, mode)) 138 139 140 /** 141 * Global data about the ZIPfile 142 * These data comes from the end of central dir 143 */ 144 struct GlobalInfo 145 { 146 147 /** 148 * total number of entries in 149 * the central dir on this disk 150 */ 151 uLong number_entry; 152 153 /** 154 * size of the global comment of the zipfile 155 */ 156 uLong size_comment; 157 158 /** 159 * offset of the global comment in the zipfile 160 */ 161 uLong offset_comment; 162 }; 163 164 165 /** 166 * internal info about a file in zipfile 167 */ 168 struct UnzipFileInfoInternal 169 { 170 171 /** 172 * relative offset of local header 4 bytes 173 */ 174 uLong offset_curfile; 175 176 }; 177 178 179 /** 180 * Information about a file in zipfile, when reading and 181 * decompressing it 182 */ 183 struct FileInZipReadInfo 184 { 185 /** 186 * internal buffer for compressed data 187 */ 188 char *read_buffer; 189 190 /** 191 * zLib stream structure for inflate 192 */ 193 z_stream stream; 194 195 /** 196 * position in byte on the zipfile, for fseek 197 */ 198 uLong pos_in_zipfile; 199 200 /** 201 * flag set if stream structure is initialised 202 */ 203 uLong stream_initialised; 204 205 /** 206 * offset of the local extra field 207 */ 208 uLong offset_local_extrafield; 209 210 /** 211 * size of the local extra field 212 */ 213 uInt size_local_extrafield; 214 215 /** 216 * position in the local extra field in read 217 */ 218 uLong pos_local_extrafield; 219 220 /** 221 * crc32 of all data uncompressed so far 222 */ 223 uLong crc32; 224 225 /** 226 * crc32 we must obtain after decompress all 227 */ 228 uLong crc32_wait; 229 230 /** 231 * number of bytes to be decompressed 232 */ 233 uLong rest_read_compressed; 234 235 /** 236 * number of bytes to be obtained after decomp 237 */ 238 uLong rest_read_uncompressed; 239 240 /** 241 * IO functions. 242 */ 243 struct FileFuncDefs z_filefunc; 244 245 /** 246 * compression method (0==store) 247 */ 248 uLong compression_method; 249 250 /** 251 * byte before the zipfile, (>0 for sfx) 252 */ 253 uLong byte_before_the_zipfile; 254 }; 255 256 257 /** 258 * Handle for a ZIP archive. 259 * contains internal information about the zipfile 260 */ 261 struct EXTRACTOR_UnzipFile 262 { 263 /** 264 * io structore of the zipfile 265 */ 266 struct FileFuncDefs z_filefunc; 267 268 /** 269 * public global information 270 */ 271 struct GlobalInfo gi; 272 273 /** 274 * byte before the zipfile, (>0 for sfx) 275 */ 276 uLong byte_before_the_zipfile; 277 278 /** 279 * number of the current file in the zipfile 280 */ 281 uLong num_file; 282 283 /** 284 * pos of the current file in the central dir 285 */ 286 uLong pos_in_central_dir; 287 288 /** 289 * flag about the usability of the current file 290 */ 291 uLong current_file_ok; 292 293 /** 294 * position of the beginning of the central dir 295 */ 296 uLong central_pos; 297 298 /** 299 * size of the central directory 300 */ 301 uLong size_central_dir; 302 303 /** 304 * offset of start of central directory with respect to the starting 305 * disk number 306 */ 307 uLong offset_central_dir; 308 309 /** 310 * public info about the current file in zip 311 */ 312 struct EXTRACTOR_UnzipFileInfo cur_file_info; 313 314 /** 315 * private info about it 316 */ 317 struct UnzipFileInfoInternal cur_file_info_internal; 318 319 /** 320 * structure about the current file if we are decompressing it 321 */ 322 struct FileInZipReadInfo *pfile_in_zip_read; 323 324 /** 325 * Is the file encrypted? 326 */ 327 int encrypted; 328 }; 329 330 331 /** 332 * Read a byte from a gz_stream; update next_in and avail_in. Return EOF 333 * for end of file. 334 * IN assertion: the stream s has been successfully opened for reading. 335 * 336 * @param ffd functions for performing IO operations 337 * @param pi where to store the byte that was read 338 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF 339 */ 340 static int 341 read_byte_from_ffd (const struct FileFuncDefs *ffd, 342 int *pi) 343 { 344 unsigned char c; 345 346 if (1 != ZREAD (*ffd, &c, 1)) 347 return EXTRACTOR_UNZIP_EOF; 348 *pi = (int) c; 349 return EXTRACTOR_UNZIP_OK; 350 } 351 352 353 /** 354 * Read a short (2 bytes) from a gz_stream; update next_in and avail_in. Return EOF 355 * for end of file. 356 * IN assertion: the stream s has been successfully opened for reading. 357 * 358 * @param ffd functions for performing IO operations 359 * @param pi where to store the short that was read 360 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF 361 */ 362 static int 363 read_short_from_ffd (const struct FileFuncDefs *ffd, 364 uLong *pX) 365 { 366 uLong x; 367 int i; 368 int err; 369 370 *pX = 0; 371 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 372 return err; 373 x = (uLong) i; 374 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 375 return err; 376 x += ((uLong) i) << 8; 377 *pX = x; 378 return err; 379 } 380 381 382 /** 383 * Read a 'long' (4 bytes) from a gz_stream; update next_in and avail_in. Return EOF 384 * for end of file. 385 * IN assertion: the stream s has been successfully opened for reading. 386 * 387 * @param ffd functions for performing IO operations 388 * @param pi where to store the long that was read 389 * @return #EXTRACTOR_UNZIP_OK on success, or #EXTRACTOR_UNZIP_EOF 390 */ 391 static int 392 read_long_from_ffd (const struct FileFuncDefs *ffd, 393 uLong *pX) 394 { 395 uLong x; 396 int i; 397 int err; 398 399 *pX = 0; 400 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 401 return err; 402 x = (uLong) i; 403 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 404 return err; 405 x += ((uLong) i) << 8; 406 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 407 return err; 408 x += ((uLong) i) << 16; 409 if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) 410 return err; 411 x += ((uLong) i) << 24; 412 *pX = x; 413 return err; 414 } 415 416 417 #ifndef CASESENSITIVITYDEFAULT_NO 418 #if ! defined(unix) && ! defined(CASESENSITIVITYDEFAULT_YES) 419 #define CASESENSITIVITYDEFAULT_NO 420 #endif 421 #endif 422 423 #ifdef CASESENSITIVITYDEFAULT_NO 424 #define CASESENSITIVITYDEFAULTVALUE 2 425 #else 426 #define CASESENSITIVITYDEFAULTVALUE 1 427 #endif 428 429 430 /** 431 * Compare two filenames (fileName1, fileName2). 432 * 433 * @param filename1 name of first file 434 * @param filename2 name of second file 435 * @param iCaseSensitivity, use 1 for case sensitivity (like strcmp); 436 * 2 for no case sensitivity (like strcmpi or strcasecmp); or 437 * 0 for default of your operating system (like 1 on Unix, 2 on Windows) 438 * @return 0 if names are equal 439 */ 440 static int 441 EXTRACTOR_common_unzip_string_file_name_compare (const char*fileName1, 442 const char*fileName2, 443 int iCaseSensitivity) 444 { 445 if (0 == iCaseSensitivity) 446 iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE; 447 if (1 == iCaseSensitivity) 448 return strcmp (fileName1, fileName2); 449 return strcasecmp (fileName1, fileName2); 450 } 451 452 453 #ifndef BUFREADCOMMENT 454 #define BUFREADCOMMENT (0x400) 455 #endif 456 457 458 /** 459 * Locate the central directory in the ZIP file. 460 * 461 * @param ffd IO functions 462 * @return offset of central directory, 0 on error 463 */ 464 static uLong 465 locate_central_directory (const struct FileFuncDefs *ffd) 466 { 467 unsigned char buf[BUFREADCOMMENT + 4]; 468 uLong uSizeFile; 469 uLong uBackRead; 470 uLong uMaxBack = 0xffff; /* maximum size of global comment */ 471 472 if (0 != ZSEEK (*ffd, 0, SEEK_END)) 473 return 0; 474 uSizeFile = ZTELL (*ffd); 475 if (uMaxBack > uSizeFile) 476 uMaxBack = uSizeFile; 477 uBackRead = 4; 478 while (uBackRead < uMaxBack) 479 { 480 uLong uReadSize; 481 uLong uReadPos; 482 int i; 483 484 if (uBackRead + BUFREADCOMMENT > uMaxBack) 485 uBackRead = uMaxBack; 486 else 487 uBackRead += BUFREADCOMMENT; 488 uReadPos = uSizeFile - uBackRead; 489 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) 490 ? (BUFREADCOMMENT + 4) 491 : (uSizeFile - uReadPos); 492 if (0 != ZSEEK (*ffd, uReadPos, SEEK_SET)) 493 break; 494 if (ZREAD (*ffd, buf, uReadSize) != uReadSize) 495 break; 496 i = (int) uReadSize - 3; 497 while (i-- > 0) 498 if ( (0x50 == (*(buf + i))) && 499 (0x4b == (*(buf + i + 1))) && 500 (0x05 == (*(buf + i + 2))) && 501 (0x06 == (*(buf + i + 3))) ) 502 return uReadPos + i; 503 } 504 return 0; 505 } 506 507 508 /** 509 * Translate date/time from Dos format to `struct 510 * EXTRACTOR_UnzipDateTimeInfo` (readable more easilty) 511 * 512 * @param ulDosDate time in DOS format (input) 513 * @param ptm where to write time in readable format 514 */ 515 static void 516 dos_date_to_tmu_date (uLong ulDosDate, 517 struct EXTRACTOR_UnzipDateTimeInfo*ptm) 518 { 519 uLong uDate; 520 521 uDate = (uLong) (ulDosDate >> 16); 522 ptm->tm_mday = (uInt) (uDate & 0x1f); 523 ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1); 524 ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980); 525 ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800); 526 ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20); 527 ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f)); 528 } 529 530 531 /** 532 * Write info about the ZipFile in the *pglobal_info structure. 533 * No preparation of the structure is needed. 534 * 535 * @param file zipfile to manipulate 536 * @param pfile_info file information to initialize 537 * @param pfile_info_internal internal file information to initialize 538 * @param szFileName where to write the name of the current file 539 * @param fileNameBufferSize number of bytes available in @a szFileName 540 * @param extraField where to write extra data 541 * @param extraFieldBufferSize number of bytes available in extraField 542 * @param szComment where to write the comment on the current file 543 * @param commentBufferSize number of bytes available in @a szComment 544 * @return #EXTRACTOR_UNZIP_OK if there is no problem. 545 */ 546 static int 547 get_current_file_info (struct EXTRACTOR_UnzipFile *file, 548 struct EXTRACTOR_UnzipFileInfo *pfile_info, 549 struct UnzipFileInfoInternal *pfile_info_internal, 550 char *szFileName, 551 uLong fileNameBufferSize, 552 void *extraField, 553 uLong extraFieldBufferSize, 554 char *szComment, 555 uLong commentBufferSize) 556 { 557 struct EXTRACTOR_UnzipFileInfo file_info; 558 struct UnzipFileInfoInternal file_info_internal; 559 uLong uMagic; 560 long lSeek = 0; 561 562 if (NULL == file) 563 return EXTRACTOR_UNZIP_PARAMERROR; 564 if (0 != ZSEEK (file->z_filefunc, 565 file->pos_in_central_dir + file->byte_before_the_zipfile, 566 SEEK_SET)) 567 return EXTRACTOR_UNZIP_ERRNO; 568 569 /* we check the magic */ 570 if (EXTRACTOR_UNZIP_OK != 571 read_long_from_ffd (&file->z_filefunc, &uMagic)) 572 return EXTRACTOR_UNZIP_ERRNO; 573 if (0x02014b50 != uMagic) 574 return EXTRACTOR_UNZIP_BADZIPFILE; 575 576 if ( (EXTRACTOR_UNZIP_OK != 577 read_short_from_ffd (&file->z_filefunc, &file_info.version)) || 578 (EXTRACTOR_UNZIP_OK != 579 read_short_from_ffd (&file->z_filefunc, &file_info.version_needed)) || 580 (EXTRACTOR_UNZIP_OK != 581 read_short_from_ffd (&file->z_filefunc, &file_info.flag)) || 582 (EXTRACTOR_UNZIP_OK != 583 read_short_from_ffd (&file->z_filefunc, 584 &file_info.compression_method)) || 585 (EXTRACTOR_UNZIP_OK != 586 read_long_from_ffd (&file->z_filefunc, &file_info.dosDate)) ) 587 return EXTRACTOR_UNZIP_ERRNO; 588 dos_date_to_tmu_date (file_info.dosDate, 589 &file_info.tmu_date); 590 if ( (EXTRACTOR_UNZIP_OK != 591 read_long_from_ffd (&file->z_filefunc, &file_info.crc)) || 592 (EXTRACTOR_UNZIP_OK != 593 read_long_from_ffd (&file->z_filefunc, &file_info.compressed_size)) || 594 (EXTRACTOR_UNZIP_OK != 595 read_long_from_ffd (&file->z_filefunc, &file_info.uncompressed_size)) || 596 (EXTRACTOR_UNZIP_OK != 597 read_short_from_ffd (&file->z_filefunc, &file_info.size_filename)) || 598 (EXTRACTOR_UNZIP_OK != 599 read_short_from_ffd (&file->z_filefunc, &file_info.size_file_extra)) || 600 (EXTRACTOR_UNZIP_OK != 601 read_short_from_ffd (&file->z_filefunc, 602 &file_info.size_file_comment)) || 603 (EXTRACTOR_UNZIP_OK != 604 read_short_from_ffd (&file->z_filefunc, &file_info.disk_num_start)) || 605 (EXTRACTOR_UNZIP_OK != 606 read_short_from_ffd (&file->z_filefunc, &file_info.internal_fa)) || 607 (EXTRACTOR_UNZIP_OK != 608 read_long_from_ffd (&file->z_filefunc, &file_info.external_fa)) || 609 (EXTRACTOR_UNZIP_OK != 610 read_long_from_ffd (&file->z_filefunc, 611 &file_info_internal.offset_curfile)) ) 612 return EXTRACTOR_UNZIP_ERRNO; 613 614 lSeek += file_info.size_filename; 615 if (NULL != szFileName) 616 { 617 uLong uSizeRead; 618 619 if (file_info.size_filename < fileNameBufferSize) 620 { 621 *(szFileName + file_info.size_filename) = '\0'; 622 uSizeRead = file_info.size_filename; 623 } 624 else 625 uSizeRead = fileNameBufferSize; 626 627 if ( (file_info.size_filename > 0) && 628 (fileNameBufferSize > 0) ) 629 if (ZREAD (file->z_filefunc, szFileName, uSizeRead) != uSizeRead) 630 return EXTRACTOR_UNZIP_ERRNO; 631 lSeek -= uSizeRead; 632 } 633 634 if (NULL != extraField) 635 { 636 uLong uSizeRead; 637 638 if (file_info.size_file_extra<extraFieldBufferSize) 639 uSizeRead = file_info.size_file_extra; 640 else 641 uSizeRead = extraFieldBufferSize; 642 643 if (0 != lSeek) 644 { 645 if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR)) 646 lSeek = 0; 647 else 648 return EXTRACTOR_UNZIP_ERRNO; 649 } 650 if ( (file_info.size_file_extra > 0) && 651 (extraFieldBufferSize > 0) && 652 (ZREAD (file->z_filefunc, 653 extraField, 654 uSizeRead) != uSizeRead) ) 655 return EXTRACTOR_UNZIP_ERRNO; 656 lSeek += file_info.size_file_extra - uSizeRead; 657 } 658 else 659 lSeek += file_info.size_file_extra; 660 661 if (NULL != szComment) 662 { 663 uLong uSizeRead; 664 665 if (file_info.size_file_comment < commentBufferSize) 666 { 667 *(szComment + file_info.size_file_comment) = '\0'; 668 uSizeRead = file_info.size_file_comment; 669 } 670 else 671 { 672 *(szComment + commentBufferSize - 1) = '\0'; 673 uSizeRead = commentBufferSize - 1; 674 } 675 676 if (0 != lSeek) 677 { 678 if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR)) 679 lSeek = 0; 680 else 681 return EXTRACTOR_UNZIP_ERRNO; 682 } 683 if ( (file_info.size_file_comment > 0) && 684 (commentBufferSize > 0) && 685 (ZREAD (file->z_filefunc, szComment, uSizeRead) != uSizeRead) ) 686 return EXTRACTOR_UNZIP_ERRNO; 687 lSeek += file_info.size_file_comment - uSizeRead; 688 } 689 else 690 lSeek += file_info.size_file_comment; 691 692 if (NULL != pfile_info) 693 *pfile_info = file_info; 694 if (NULL != pfile_info_internal) 695 *pfile_info_internal = file_info_internal; 696 return EXTRACTOR_UNZIP_OK; 697 } 698 699 700 /** 701 * Set the current file of the zipfile to the first file. 702 * 703 * @param file zipfile to manipulate 704 * @return UNZ_OK if there is no problem 705 */ 706 int 707 EXTRACTOR_common_unzip_go_to_first_file (struct EXTRACTOR_UnzipFile *file) 708 { 709 int err; 710 711 if (NULL == file) 712 return EXTRACTOR_UNZIP_PARAMERROR; 713 file->pos_in_central_dir = file->offset_central_dir; 714 file->num_file = 0; 715 err = get_current_file_info (file, 716 &file->cur_file_info, 717 &file->cur_file_info_internal, 718 NULL, 0, NULL, 0, NULL, 0); 719 file->current_file_ok = (EXTRACTOR_UNZIP_OK == err); 720 return err; 721 } 722 723 724 /** 725 * Open a Zip file. 726 * 727 * @param ffd IO functions 728 * @return NULL on error 729 */ 730 static struct EXTRACTOR_UnzipFile * 731 unzip_open_using_ffd (struct FileFuncDefs *ffd) 732 { 733 struct EXTRACTOR_UnzipFile us; 734 struct EXTRACTOR_UnzipFile *file; 735 uLong central_pos; 736 uLong uL; 737 uLong number_disk; /* number of the current dist, used for 738 spanning ZIP, unsupported, always 0*/ 739 uLong number_disk_with_CD; /* number of the disk with central dir, used 740 for spanning ZIP, unsupported, always 0*/ 741 uLong number_entry_CD; /* total number of entries in 742 the central dir 743 (same than number_entry on nospan) */ 744 745 memset (&us, 0, sizeof(us)); 746 us.z_filefunc = *ffd; 747 central_pos = locate_central_directory (&us.z_filefunc); 748 if (0 == central_pos) 749 return NULL; 750 if (0 != ZSEEK (us.z_filefunc, 751 central_pos, SEEK_SET)) 752 return NULL; 753 754 /* the signature, already checked */ 755 if (EXTRACTOR_UNZIP_OK != 756 read_long_from_ffd (&us.z_filefunc, &uL)) 757 return NULL; 758 759 /* number of this disk */ 760 if (EXTRACTOR_UNZIP_OK != 761 read_short_from_ffd (&us.z_filefunc, &number_disk)) 762 return NULL; 763 764 /* number of the disk with the start of the central directory */ 765 if (EXTRACTOR_UNZIP_OK != 766 read_short_from_ffd (&us.z_filefunc, &number_disk_with_CD)) 767 return NULL; 768 769 /* total number of entries in the central dir on this disk */ 770 if (EXTRACTOR_UNZIP_OK != 771 read_short_from_ffd (&us.z_filefunc, &us.gi.number_entry)) 772 return NULL; 773 774 /* total number of entries in the central dir */ 775 if (EXTRACTOR_UNZIP_OK != 776 read_short_from_ffd (&us.z_filefunc, &number_entry_CD)) 777 return NULL; 778 779 if ( (number_entry_CD != us.gi.number_entry) || 780 (0 != number_disk_with_CD) || 781 (0 != number_disk) ) 782 return NULL; 783 784 /* size of the central directory */ 785 if (EXTRACTOR_UNZIP_OK != 786 read_long_from_ffd (&us.z_filefunc, &us.size_central_dir)) 787 return NULL; 788 789 /* offset of start of central directory with respect to the 790 starting disk number */ 791 if (EXTRACTOR_UNZIP_OK != 792 read_long_from_ffd (&us.z_filefunc, &us.offset_central_dir)) 793 return NULL; 794 795 /* zipfile comment length */ 796 if (EXTRACTOR_UNZIP_OK != 797 read_short_from_ffd (&us.z_filefunc, &us.gi.size_comment)) 798 return NULL; 799 us.gi.offset_comment = ZTELL (us.z_filefunc); 800 if ((central_pos < us.offset_central_dir + us.size_central_dir)) 801 return NULL; 802 803 us.byte_before_the_zipfile = central_pos 804 - (us.offset_central_dir + us.size_central_dir); 805 us.central_pos = central_pos; 806 us.pfile_in_zip_read = NULL; 807 us.encrypted = 0; 808 809 if (NULL == (file = malloc (sizeof(struct EXTRACTOR_UnzipFile)))) 810 return NULL; 811 *file = us; 812 EXTRACTOR_common_unzip_go_to_first_file (file); 813 return file; 814 } 815 816 817 /** 818 * Close the file in zip opened with #EXTRACTOR_common_unzip_open_current_file(). 819 * 820 * @return #EXTRACTOR_UNZIP_CRCERROR if all the file was read but the CRC is not good 821 */ 822 int 823 EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile *file) 824 { 825 struct FileInZipReadInfo*pfile_in_zip_read_info; 826 int err = EXTRACTOR_UNZIP_OK; 827 828 if (NULL == file) 829 return EXTRACTOR_UNZIP_PARAMERROR; 830 if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read)) 831 return EXTRACTOR_UNZIP_PARAMERROR; 832 if ( (0 == pfile_in_zip_read_info->rest_read_uncompressed) && 833 (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) ) 834 err = EXTRACTOR_UNZIP_CRCERROR; 835 if (NULL != pfile_in_zip_read_info->read_buffer) 836 free (pfile_in_zip_read_info->read_buffer); 837 pfile_in_zip_read_info->read_buffer = NULL; 838 if (pfile_in_zip_read_info->stream_initialised) 839 inflateEnd (&pfile_in_zip_read_info->stream); 840 pfile_in_zip_read_info->stream_initialised = 0; 841 free (pfile_in_zip_read_info); 842 file->pfile_in_zip_read = NULL; 843 return err; 844 } 845 846 847 /** 848 * Close a ZipFile. 849 * 850 * @param file zip file to close 851 * @return #EXTRACTOR_UNZIP_OK if there is no problem. 852 */ 853 int 854 EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file) 855 { 856 if (NULL == file) 857 return EXTRACTOR_UNZIP_PARAMERROR; 858 if (NULL != file->pfile_in_zip_read) 859 EXTRACTOR_common_unzip_close_current_file (file); 860 free (file); 861 return EXTRACTOR_UNZIP_OK; 862 } 863 864 865 /** 866 * Obtain the global comment from a ZIP file. 867 * 868 * @param file unzip file to inspect 869 * @param comment where to copy the comment 870 * @param comment_len maximum number of bytes available in comment 871 * @return #EXTRACTOR_UNZIP_OK on success 872 */ 873 int 874 EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file, 875 char *comment, 876 size_t comment_len) 877 { 878 if (NULL == file) 879 return EXTRACTOR_UNZIP_PARAMERROR; 880 if (comment_len > file->gi.size_comment) 881 comment_len = file->gi.size_comment + 1; 882 if (0 != 883 ZSEEK (file->z_filefunc, file->gi.offset_comment, SEEK_SET)) 884 return EXTRACTOR_UNZIP_ERRNO; 885 if (comment_len - 1 != 886 ZREAD (file->z_filefunc, comment, comment_len - 1)) 887 return EXTRACTOR_UNZIP_ERRNO; 888 comment[comment_len - 1] = '\0'; 889 return EXTRACTOR_UNZIP_OK; 890 } 891 892 893 /** 894 * Write info about the ZipFile in the *pglobal_info structure. 895 * No preparation of the structure is needed. 896 * 897 * @param file zipfile to manipulate 898 * @param pfile_info file information to initialize 899 * @param szFileName where to write the name of the current file 900 * @param fileNameBufferSize number of bytes available in szFileName 901 * @param extraField where to write extra data 902 * @param extraFieldBufferSize number of bytes available in extraField 903 * @param szComment where to write the comment on the current file 904 * @param commentBufferSize number of bytes available in szComment 905 * @return #EXTRACTOR_UNZIP_OK if there is no problem. 906 */ 907 int 908 EXTRACTOR_common_unzip_get_current_file_info (struct EXTRACTOR_UnzipFile *file, 909 struct EXTRACTOR_UnzipFileInfo * 910 pfile_info, 911 char *szFileName, 912 uLong fileNameBufferSize, 913 void *extraField, 914 uLong extraFieldBufferSize, 915 char *szComment, 916 uLong commentBufferSize) 917 { 918 return get_current_file_info (file, pfile_info, NULL, 919 szFileName, fileNameBufferSize, 920 extraField, extraFieldBufferSize, 921 szComment, commentBufferSize); 922 } 923 924 925 /** 926 * Set the current file of the zipfile to the next file. 927 * 928 * @param file zipfile to manipulate 929 * @return #EXTRACTOR_UNZIP_OK if there is no problem, 930 * #EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the actual file was the latest. 931 */ 932 int 933 EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile *file) 934 { 935 int err; 936 937 if (NULL == file) 938 return EXTRACTOR_UNZIP_PARAMERROR; 939 if (! file->current_file_ok) 940 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; 941 if (file->num_file + 1 == file->gi.number_entry) 942 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; 943 file->pos_in_central_dir += SIZECENTRALDIRITEM 944 + file->cur_file_info.size_filename 945 + file->cur_file_info.size_file_extra 946 + file->cur_file_info.size_file_comment; 947 file->num_file++; 948 err = get_current_file_info (file, 949 &file->cur_file_info, 950 &file->cur_file_info_internal, 951 NULL, 0, NULL, 0, NULL, 0); 952 file->current_file_ok = (EXTRACTOR_UNZIP_OK == err); 953 return err; 954 } 955 956 957 /** 958 * Try locate the file szFileName in the zipfile. 959 * 960 * @param file zipfile to manipulate 961 * @param szFileName name to find 962 * @param iCaseSensitivity, use 1 for case sensitivity (like strcmp); 963 * 2 for no case sensitivity (like strcmpi or strcasecmp); or 964 * 0 for default of your operating system (like 1 on Unix, 2 on Windows) 965 * @return #EXTRACTOR_UNZIP_OK if the file is found. It becomes the current file. 966 * #EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the file is not found 967 */ 968 int 969 EXTRACTOR_common_unzip_go_find_local_file (struct EXTRACTOR_UnzipFile *file, 970 const char *szFileName, 971 int iCaseSensitivity) 972 { 973 int err; 974 /* We remember the 'current' position in the file so that we can jump 975 * back there if we fail. 976 */ 977 struct EXTRACTOR_UnzipFileInfo cur_file_infoSaved; 978 struct UnzipFileInfoInternal cur_file_info_internalSaved; 979 uLong num_fileSaved; 980 uLong pos_in_central_dirSaved; 981 982 if (NULL == file) 983 return EXTRACTOR_UNZIP_PARAMERROR; 984 if (strlen (szFileName) >= UNZ_MAXFILENAMEINZIP) 985 return EXTRACTOR_UNZIP_PARAMERROR; 986 if (! file->current_file_ok) 987 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; 988 989 /* Save the current state */ 990 num_fileSaved = file->num_file; 991 pos_in_central_dirSaved = file->pos_in_central_dir; 992 cur_file_infoSaved = file->cur_file_info; 993 cur_file_info_internalSaved = file->cur_file_info_internal; 994 err = EXTRACTOR_common_unzip_go_to_first_file (file); 995 996 while (EXTRACTOR_UNZIP_OK == err) 997 { 998 char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1]; 999 1000 if (EXTRACTOR_UNZIP_OK != 1001 (err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL, 1002 szCurrentFileName, 1003 sizeof ( 1004 szCurrentFileName) 1005 - 1, 1006 NULL, 0, NULL, 0))) 1007 break; 1008 if (0 == 1009 EXTRACTOR_common_unzip_string_file_name_compare (szCurrentFileName, 1010 szFileName, 1011 iCaseSensitivity)) 1012 return EXTRACTOR_UNZIP_OK; 1013 err = EXTRACTOR_common_unzip_go_to_next_file (file); 1014 } 1015 1016 /* We failed, so restore the state of the 'current file' to where we 1017 * were. 1018 */ 1019 file->num_file = num_fileSaved; 1020 file->pos_in_central_dir = pos_in_central_dirSaved; 1021 file->cur_file_info = cur_file_infoSaved; 1022 file->cur_file_info_internal = cur_file_info_internalSaved; 1023 return err; 1024 } 1025 1026 1027 /** 1028 * Read bytes from the current file (must have been opened). 1029 * 1030 * @param buf contain buffer where data must be copied 1031 * @param len the size of buf. 1032 * @return the number of byte copied if some bytes are copied 1033 * 0 if the end of file was reached 1034 * <0 with error code if there is an error 1035 * (#EXTRACTOR_UNZIP_ERRNO for IO error, or zLib error for uncompress error) 1036 */ 1037 ssize_t 1038 EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, 1039 void *buf, 1040 size_t len) 1041 { 1042 int err = EXTRACTOR_UNZIP_OK; 1043 uInt iRead = 0; 1044 struct FileInZipReadInfo *pfile_in_zip_read_info; 1045 1046 if (NULL == file) 1047 return EXTRACTOR_UNZIP_PARAMERROR; 1048 if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read)) 1049 return EXTRACTOR_UNZIP_PARAMERROR; 1050 if (NULL == pfile_in_zip_read_info->read_buffer) 1051 return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; 1052 if (0 == len) 1053 return 0; 1054 1055 pfile_in_zip_read_info->stream.next_out = (Bytef *) buf; 1056 pfile_in_zip_read_info->stream.avail_out = (uInt) len; 1057 if (len > pfile_in_zip_read_info->rest_read_uncompressed) 1058 pfile_in_zip_read_info->stream.avail_out = 1059 (uInt) pfile_in_zip_read_info->rest_read_uncompressed; 1060 1061 while (pfile_in_zip_read_info->stream.avail_out > 0) 1062 { 1063 if ( (0 == pfile_in_zip_read_info->stream.avail_in) && 1064 (pfile_in_zip_read_info->rest_read_compressed > 0) ) 1065 { 1066 uInt uReadThis = UNZ_BUFSIZE; 1067 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) 1068 uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed; 1069 if (0 == uReadThis) 1070 return EXTRACTOR_UNZIP_EOF; 1071 if (0 != 1072 ZSEEK (pfile_in_zip_read_info->z_filefunc, 1073 pfile_in_zip_read_info->pos_in_zipfile 1074 + pfile_in_zip_read_info->byte_before_the_zipfile, 1075 SEEK_SET)) 1076 return EXTRACTOR_UNZIP_ERRNO; 1077 if (ZREAD (pfile_in_zip_read_info->z_filefunc, 1078 pfile_in_zip_read_info->read_buffer, 1079 uReadThis) != uReadThis) 1080 return EXTRACTOR_UNZIP_ERRNO; 1081 1082 pfile_in_zip_read_info->pos_in_zipfile += uReadThis; 1083 pfile_in_zip_read_info->rest_read_compressed -= uReadThis; 1084 pfile_in_zip_read_info->stream.next_in = 1085 (Bytef *) pfile_in_zip_read_info->read_buffer; 1086 pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis; 1087 } 1088 1089 if (0 == pfile_in_zip_read_info->compression_method) 1090 { 1091 uInt uDoCopy; 1092 1093 if ( (0 == pfile_in_zip_read_info->stream.avail_in) && 1094 (0 == pfile_in_zip_read_info->rest_read_compressed) ) 1095 return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead; 1096 1097 if (pfile_in_zip_read_info->stream.avail_out < 1098 pfile_in_zip_read_info->stream.avail_in) 1099 uDoCopy = pfile_in_zip_read_info->stream.avail_out; 1100 else 1101 uDoCopy = pfile_in_zip_read_info->stream.avail_in; 1102 memcpy (pfile_in_zip_read_info->stream.next_out, 1103 pfile_in_zip_read_info->stream.next_in, 1104 uDoCopy); 1105 pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, 1106 pfile_in_zip_read_info->stream. 1107 next_out, 1108 uDoCopy); 1109 pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy; 1110 pfile_in_zip_read_info->stream.avail_in -= uDoCopy; 1111 pfile_in_zip_read_info->stream.avail_out -= uDoCopy; 1112 pfile_in_zip_read_info->stream.next_out += uDoCopy; 1113 pfile_in_zip_read_info->stream.next_in += uDoCopy; 1114 pfile_in_zip_read_info->stream.total_out += uDoCopy; 1115 iRead += uDoCopy; 1116 } 1117 else 1118 { 1119 uLong uTotalOutBefore; 1120 uLong uTotalOutAfter; 1121 const Bytef *bufBefore; 1122 uLong uOutThis; 1123 int flush = Z_SYNC_FLUSH; 1124 1125 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; 1126 bufBefore = pfile_in_zip_read_info->stream.next_out; 1127 1128 /* 1129 if ((pfile_in_zip_read_info->rest_read_uncompressed == 1130 pfile_in_zip_read_info->stream.avail_out) && 1131 (pfile_in_zip_read_info->rest_read_compressed == 0)) 1132 flush = Z_FINISH; 1133 */err = inflate (&pfile_in_zip_read_info->stream, flush); 1134 1135 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; 1136 uOutThis = uTotalOutAfter - uTotalOutBefore; 1137 1138 pfile_in_zip_read_info->crc32 = 1139 crc32 (pfile_in_zip_read_info->crc32, bufBefore, 1140 (uInt) (uOutThis)); 1141 1142 pfile_in_zip_read_info->rest_read_uncompressed -= 1143 uOutThis; 1144 1145 iRead += (uInt) (uTotalOutAfter - uTotalOutBefore); 1146 1147 if (Z_STREAM_END == err) 1148 return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead; 1149 if (Z_OK != err) 1150 break; 1151 } 1152 } 1153 1154 if (Z_OK == err) 1155 return iRead; 1156 return err; 1157 } 1158 1159 1160 /** 1161 * Read the local header of the current zipfile. Check the coherency of 1162 * the local header and info in the end of central directory about 1163 * this file. Store in *piSizeVar the size of extra info in local 1164 * header (filename and size of extra field data) 1165 * 1166 * @param file zipfile to process 1167 * @param piSizeVar where to store the size of the extra info 1168 * @param poffset_local_extrafield where to store the offset of the local extrafield 1169 * @param psoze_local_extrafield where to store the size of the local extrafield 1170 * @return #EXTRACTOR_UNZIP_OK on success 1171 */ 1172 static int 1173 parse_current_file_coherency_header (struct EXTRACTOR_UnzipFile *file, 1174 uInt *piSizeVar, 1175 uLong *poffset_local_extrafield, 1176 uInt *psize_local_extrafield) 1177 { 1178 uLong uMagic; 1179 uLong uData; 1180 uLong uFlags; 1181 uLong size_filename; 1182 uLong size_extra_field; 1183 1184 *piSizeVar = 0; 1185 *poffset_local_extrafield = 0; 1186 *psize_local_extrafield = 0; 1187 1188 if (0 != ZSEEK (file->z_filefunc, 1189 file->cur_file_info_internal.offset_curfile 1190 + file->byte_before_the_zipfile, 1191 SEEK_SET)) 1192 return EXTRACTOR_UNZIP_ERRNO; 1193 if (EXTRACTOR_UNZIP_OK != 1194 read_long_from_ffd (&file->z_filefunc, 1195 &uMagic)) 1196 return EXTRACTOR_UNZIP_ERRNO; 1197 if (0x04034b50 != uMagic) 1198 return EXTRACTOR_UNZIP_BADZIPFILE; 1199 if ( (EXTRACTOR_UNZIP_OK != 1200 read_short_from_ffd (&file->z_filefunc, &uData)) || 1201 (EXTRACTOR_UNZIP_OK != 1202 read_short_from_ffd (&file->z_filefunc, &uFlags)) ) 1203 return EXTRACTOR_UNZIP_ERRNO; 1204 if (EXTRACTOR_UNZIP_OK != read_short_from_ffd (&file->z_filefunc, &uData)) 1205 return EXTRACTOR_UNZIP_ERRNO; 1206 if (uData != file->cur_file_info.compression_method) 1207 return EXTRACTOR_UNZIP_BADZIPFILE; 1208 if ( (0 != file->cur_file_info.compression_method) && 1209 (Z_DEFLATED != file->cur_file_info.compression_method) ) 1210 return EXTRACTOR_UNZIP_BADZIPFILE; 1211 if (EXTRACTOR_UNZIP_OK != 1212 read_long_from_ffd (&file->z_filefunc, &uData)) /* date/time */ 1213 return EXTRACTOR_UNZIP_ERRNO; 1214 if (EXTRACTOR_UNZIP_OK != 1215 read_long_from_ffd (&file->z_filefunc, &uData)) /* crc */ 1216 return EXTRACTOR_UNZIP_ERRNO; 1217 if ( (uData != file->cur_file_info.crc) && 1218 (0 == (uFlags & 8)) ) 1219 return EXTRACTOR_UNZIP_BADZIPFILE; 1220 if (EXTRACTOR_UNZIP_OK != 1221 read_long_from_ffd (&file->z_filefunc, &uData)) /* size compr */ 1222 return EXTRACTOR_UNZIP_ERRNO; 1223 if ( (uData != file->cur_file_info.compressed_size) && 1224 (0 == (uFlags & 8)) ) 1225 return EXTRACTOR_UNZIP_BADZIPFILE; 1226 if (EXTRACTOR_UNZIP_OK != 1227 read_long_from_ffd (&file->z_filefunc, 1228 &uData)) /* size uncompr */ 1229 return EXTRACTOR_UNZIP_ERRNO; 1230 if ( (uData != file->cur_file_info.uncompressed_size) && 1231 (0 == (uFlags & 8))) 1232 return EXTRACTOR_UNZIP_BADZIPFILE; 1233 if (EXTRACTOR_UNZIP_OK != 1234 read_short_from_ffd (&file->z_filefunc, &size_filename)) 1235 return EXTRACTOR_UNZIP_ERRNO; 1236 if (size_filename != file->cur_file_info.size_filename) 1237 return EXTRACTOR_UNZIP_BADZIPFILE; 1238 *piSizeVar += (uInt) size_filename; 1239 if (EXTRACTOR_UNZIP_OK != 1240 read_short_from_ffd (&file->z_filefunc, 1241 &size_extra_field)) 1242 return EXTRACTOR_UNZIP_ERRNO; 1243 *poffset_local_extrafield = file->cur_file_info_internal.offset_curfile 1244 + SIZEZIPLOCALHEADER + size_filename; 1245 *psize_local_extrafield = (uInt) size_extra_field; 1246 *piSizeVar += (uInt) size_extra_field; 1247 1248 return EXTRACTOR_UNZIP_OK; 1249 } 1250 1251 1252 /** 1253 * Open for reading data the current file in the zipfile. 1254 * 1255 * @param file zipfile to manipulate 1256 * @return #EXTRACTOR_UNZIP_OK on success 1257 */ 1258 int 1259 EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) 1260 { 1261 int err; 1262 uInt iSizeVar; 1263 struct FileInZipReadInfo *pfile_in_zip_read_info; 1264 uLong offset_local_extrafield; /* offset of the local extra field */ 1265 uInt size_local_extrafield; /* size of the local extra field */ 1266 1267 if (NULL == file) 1268 return EXTRACTOR_UNZIP_PARAMERROR; 1269 if (! file->current_file_ok) 1270 return EXTRACTOR_UNZIP_PARAMERROR; 1271 if (NULL != file->pfile_in_zip_read) 1272 EXTRACTOR_common_unzip_close_current_file (file); 1273 if (EXTRACTOR_UNZIP_OK != 1274 parse_current_file_coherency_header (file, 1275 &iSizeVar, 1276 &offset_local_extrafield, 1277 &size_local_extrafield)) 1278 return EXTRACTOR_UNZIP_BADZIPFILE; 1279 if (NULL == (pfile_in_zip_read_info = malloc (sizeof(struct 1280 FileInZipReadInfo)))) 1281 return EXTRACTOR_UNZIP_INTERNALERROR; 1282 if (NULL == (pfile_in_zip_read_info->read_buffer = malloc (UNZ_BUFSIZE))) 1283 { 1284 free (pfile_in_zip_read_info); 1285 return EXTRACTOR_UNZIP_INTERNALERROR; 1286 } 1287 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; 1288 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; 1289 pfile_in_zip_read_info->pos_local_extrafield = 0; 1290 pfile_in_zip_read_info->stream_initialised = 0; 1291 1292 if ( (0 != file->cur_file_info.compression_method) && 1293 (Z_DEFLATED != file->cur_file_info.compression_method) ) 1294 { 1295 // err = EXTRACTOR_UNZIP_BADZIPFILE; 1296 // FIXME: we don't do anything with this 'err' code. 1297 // Can this happen? Should we abort in this case? 1298 } 1299 1300 pfile_in_zip_read_info->crc32_wait = file->cur_file_info.crc; 1301 pfile_in_zip_read_info->crc32 = 0; 1302 pfile_in_zip_read_info->compression_method = 1303 file->cur_file_info.compression_method; 1304 pfile_in_zip_read_info->z_filefunc = file->z_filefunc; 1305 pfile_in_zip_read_info->byte_before_the_zipfile = 1306 file->byte_before_the_zipfile; 1307 pfile_in_zip_read_info->stream.total_out = 0; 1308 if (Z_DEFLATED == file->cur_file_info.compression_method) 1309 { 1310 pfile_in_zip_read_info->stream.zalloc = (alloc_func) NULL; 1311 pfile_in_zip_read_info->stream.zfree = (free_func) NULL; 1312 pfile_in_zip_read_info->stream.opaque = NULL; 1313 pfile_in_zip_read_info->stream.next_in = NULL; 1314 pfile_in_zip_read_info->stream.avail_in = 0; 1315 if (Z_OK != (err = inflateInit2 (&pfile_in_zip_read_info->stream, 1316 -MAX_WBITS))) 1317 { 1318 free (pfile_in_zip_read_info->read_buffer); 1319 free (pfile_in_zip_read_info); 1320 return err; 1321 } 1322 pfile_in_zip_read_info->stream_initialised = 1; 1323 /* windowBits is passed < 0 to tell that there is no zlib header. 1324 * Note that in this case inflate *requires* an extra "dummy" byte 1325 * after the compressed stream in order to complete decompression and 1326 * return Z_STREAM_END. 1327 * In unzip, i don't wait absolutely Z_STREAM_END because I known the 1328 * size of both compressed and uncompressed data 1329 */} 1330 pfile_in_zip_read_info->rest_read_compressed = 1331 file->cur_file_info.compressed_size; 1332 pfile_in_zip_read_info->rest_read_uncompressed = 1333 file->cur_file_info.uncompressed_size; 1334 pfile_in_zip_read_info->pos_in_zipfile = 1335 file->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER 1336 + iSizeVar; 1337 pfile_in_zip_read_info->stream.avail_in = 0; 1338 file->pfile_in_zip_read = pfile_in_zip_read_info; 1339 return EXTRACTOR_UNZIP_OK; 1340 } 1341 1342 1343 /** 1344 * Callback to perform read operation using LE API. 1345 * Note that partial reads are not allowed. 1346 * 1347 * @param opaque the 'struct EXTRACTOR_ExtractContext' 1348 * @param buf where to write bytes read 1349 * @param size number of bytes desired 1350 * @return number of bytes copied to buf 1351 */ 1352 static uLong 1353 ec_read_file_func (voidpf opaque, 1354 void*buf, 1355 uLong size) 1356 { 1357 struct EXTRACTOR_ExtractContext *ec = opaque; 1358 void *ptr; 1359 ssize_t ret; 1360 uLong done; 1361 1362 done = 0; 1363 while (done < size) 1364 { 1365 ret = ec->read (ec->cls, 1366 &ptr, 1367 size - done); 1368 if (ret <= 0) 1369 return done; 1370 memcpy (buf + done, ptr, ret); 1371 done += ret; 1372 } 1373 return done; 1374 } 1375 1376 1377 /** 1378 * Callback to obtain current offset in file using LE API. 1379 * 1380 * @param opaque the 'struct EXTRACTOR_ExtractContext' 1381 * @return current offset in file, -1 on error 1382 */ 1383 static long 1384 ec_tell_file_func (voidpf opaque) 1385 { 1386 struct EXTRACTOR_ExtractContext *ec = opaque; 1387 1388 return ec->seek (ec->cls, 0, SEEK_CUR); 1389 } 1390 1391 1392 /** 1393 * Callback to perform seek operation using LE API. 1394 * 1395 * @param opaque the 'struct EXTRACTOR_ExtractContext' 1396 * @param offset where to seek 1397 * @param origin relative to where should we seek 1398 * @return #EXTRACTOR_UNZIP_OK on success 1399 */ 1400 static long 1401 ec_seek_file_func (voidpf opaque, 1402 uLong offset, 1403 int origin) 1404 { 1405 struct EXTRACTOR_ExtractContext *ec = opaque; 1406 1407 if (-1 == ec->seek (ec->cls, offset, origin)) 1408 return EXTRACTOR_UNZIP_INTERNALERROR; 1409 return EXTRACTOR_UNZIP_OK; 1410 } 1411 1412 1413 /** 1414 * Open a zip file for processing using the data access 1415 * functions from the extract context. 1416 * 1417 * @param ec extract context to use 1418 * @return handle to zip data, NULL on error 1419 */ 1420 struct EXTRACTOR_UnzipFile * 1421 EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec) 1422 { 1423 struct FileFuncDefs ffd; 1424 1425 ffd.zread_file = &ec_read_file_func; 1426 ffd.ztell_file = &ec_tell_file_func; 1427 ffd.zseek_file = &ec_seek_file_func; 1428 ffd.opaque = ec; 1429 1430 return unzip_open_using_ffd (&ffd); 1431 } 1432 1433 1434 /* end of unzip.c */