1 /* zip.c -- IO on .zip files using zlib 2 Version 1.01e, February 12th, 2005 3 4 27 Dec 2004 Rolf Kalbermatter 5 Modification to zipOpen2 to support globalComment retrieval. 6 7 Copyright (C) 1998-2005 Gilles Vollant 8 9 Read zip.h for more info 10 */ 11 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <time.h> 17 #if defined(USE_SYSTEM_ZLIB) 18 #include <zlib.h> 19 #else 20 #include "third_party/zlib/zlib.h" 21 #endif 22 #include "zip.h" 23 24 #ifdef STDC 25 # include <stddef.h> 26 # include <string.h> 27 # include <stdlib.h> 28 #endif 29 #ifdef NO_ERRNO_H 30 extern int errno; 31 #else 32 # include <errno.h> 33 #endif 34 35 36 #ifndef local 37 # define local static 38 #endif 39 /* compile with -Dlocal if your debugger can't find static symbols */ 40 41 #ifndef VERSIONMADEBY 42 # define VERSIONMADEBY (0x0) /* platform depedent */ 43 #endif 44 45 #ifndef Z_BUFSIZE 46 #define Z_BUFSIZE (16384) 47 #endif 48 49 #ifndef Z_MAXFILENAMEINZIP 50 #define Z_MAXFILENAMEINZIP (256) 51 #endif 52 53 #ifndef ALLOC 54 # define ALLOC(size) (malloc(size)) 55 #endif 56 #ifndef TRYFREE 57 # define TRYFREE(p) {if (p) free(p);} 58 #endif 59 60 /* 61 #define SIZECENTRALDIRITEM (0x2e) 62 #define SIZEZIPLOCALHEADER (0x1e) 63 */ 64 65 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ 66 67 #ifndef SEEK_CUR 68 #define SEEK_CUR 1 69 #endif 70 71 #ifndef SEEK_END 72 #define SEEK_END 2 73 #endif 74 75 #ifndef SEEK_SET 76 #define SEEK_SET 0 77 #endif 78 79 #ifndef DEF_MEM_LEVEL 80 #if MAX_MEM_LEVEL >= 8 81 # define DEF_MEM_LEVEL 8 82 #else 83 # define DEF_MEM_LEVEL MAX_MEM_LEVEL 84 #endif 85 #endif 86 const char zip_copyright[] = 87 " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; 88 89 90 #define SIZEDATA_INDATABLOCK (4096-(4*4)) 91 92 #define LOCALHEADERMAGIC (0x04034b50) 93 #define CENTRALHEADERMAGIC (0x02014b50) 94 #define ENDHEADERMAGIC (0x06054b50) 95 96 #define FLAG_LOCALHEADER_OFFSET (0x06) 97 #define CRC_LOCALHEADER_OFFSET (0x0e) 98 99 #define SIZECENTRALHEADER (0x2e) /* 46 */ 100 101 typedef struct linkedlist_datablock_internal_s 102 { 103 struct linkedlist_datablock_internal_s* next_datablock; 104 uLong avail_in_this_block; 105 uLong filled_in_this_block; 106 uLong unused; /* for future use and alignement */ 107 unsigned char data[SIZEDATA_INDATABLOCK]; 108 } linkedlist_datablock_internal; 109 110 typedef struct linkedlist_data_s 111 { 112 linkedlist_datablock_internal* first_block; 113 linkedlist_datablock_internal* last_block; 114 } linkedlist_data; 115 116 117 typedef struct 118 { 119 z_stream stream; /* zLib stream structure for inflate */ 120 int stream_initialised; /* 1 is stream is initialised */ 121 uInt pos_in_buffered_data; /* last written byte in buffered_data */ 122 123 uLong pos_local_header; /* offset of the local header of the file 124 currenty writing */ 125 char* central_header; /* central header data for the current file */ 126 uLong size_centralheader; /* size of the central header for cur file */ 127 uLong flag; /* flag of the file currently writing */ 128 129 int method; /* compression method of file currenty wr.*/ 130 int raw; /* 1 for directly writing raw data */ 131 Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ 132 uLong dosDate; 133 uLong crc32; 134 int encrypt; 135 #ifndef NOCRYPT 136 unsigned long keys[3]; /* keys defining the pseudo-random sequence */ 137 const unsigned long* pcrc_32_tab; 138 int crypt_header_size; 139 #endif 140 } curfile_info; 141 142 typedef struct 143 { 144 zlib_filefunc_def z_filefunc; 145 voidpf filestream; /* io structore of the zipfile */ 146 linkedlist_data central_dir;/* datablock with central dir in construction*/ 147 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ 148 curfile_info ci; /* info on the file curretly writing */ 149 150 uLong begin_pos; /* position of the beginning of the zipfile */ 151 uLong add_position_when_writting_offset; 152 uLong number_entry; 153 #ifndef NO_ADDFILEINEXISTINGZIP 154 char *globalcomment; 155 #endif 156 } zip_internal; 157 158 159 160 #ifndef NOCRYPT 161 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED 162 #include "crypt.h" 163 #endif 164 165 local linkedlist_datablock_internal* allocate_new_datablock() 166 { 167 linkedlist_datablock_internal* ldi; 168 ldi = (linkedlist_datablock_internal*) 169 ALLOC(sizeof(linkedlist_datablock_internal)); 170 if (ldi!=NULL) 171 { 172 ldi->next_datablock = NULL ; 173 ldi->filled_in_this_block = 0 ; 174 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; 175 } 176 return ldi; 177 } 178 179 local void free_datablock(ldi) 180 linkedlist_datablock_internal* ldi; 181 { 182 while (ldi!=NULL) 183 { 184 linkedlist_datablock_internal* ldinext = ldi->next_datablock; 185 TRYFREE(ldi); 186 ldi = ldinext; 187 } 188 } 189 190 local void init_linkedlist(ll) 191 linkedlist_data* ll; 192 { 193 ll->first_block = ll->last_block = NULL; 194 } 195 196 local void free_linkedlist(ll) 197 linkedlist_data* ll; 198 { 199 free_datablock(ll->first_block); 200 ll->first_block = ll->last_block = NULL; 201 } 202 203 204 local int add_data_in_datablock(ll,buf,len) 205 linkedlist_data* ll; 206 const void* buf; 207 uLong len; 208 { 209 linkedlist_datablock_internal* ldi; 210 const unsigned char* from_copy; 211 212 if (ll==NULL) 213 return ZIP_INTERNALERROR; 214 215 if (ll->last_block == NULL) 216 { 217 ll->first_block = ll->last_block = allocate_new_datablock(); 218 if (ll->first_block == NULL) 219 return ZIP_INTERNALERROR; 220 } 221 222 ldi = ll->last_block; 223 from_copy = (unsigned char*)buf; 224 225 while (len>0) 226 { 227 uInt copy_this; 228 uInt i; 229 unsigned char* to_copy; 230 231 if (ldi->avail_in_this_block==0) 232 { 233 ldi->next_datablock = allocate_new_datablock(); 234 if (ldi->next_datablock == NULL) 235 return ZIP_INTERNALERROR; 236 ldi = ldi->next_datablock ; 237 ll->last_block = ldi; 238 } 239 240 if (ldi->avail_in_this_block < len) 241 copy_this = (uInt)ldi->avail_in_this_block; 242 else 243 copy_this = (uInt)len; 244 245 to_copy = &(ldi->data[ldi->filled_in_this_block]); 246 247 for (i=0;i<copy_this;i++) 248 *(to_copy+i)=*(from_copy+i); 249 250 ldi->filled_in_this_block += copy_this; 251 ldi->avail_in_this_block -= copy_this; 252 from_copy += copy_this ; 253 len -= copy_this; 254 } 255 return ZIP_OK; 256 } 257 258 259 260 /****************************************************************************/ 261 262 #ifndef NO_ADDFILEINEXISTINGZIP 263 /* =========================================================================== 264 Inputs a long in LSB order to the given file 265 nbByte == 1, 2 or 4 (byte, short or long) 266 */ 267 268 local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, 269 voidpf filestream, uLong x, int nbByte)); 270 local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) 271 const zlib_filefunc_def* pzlib_filefunc_def; 272 voidpf filestream; 273 uLong x; 274 int nbByte; 275 { 276 unsigned char buf[4]; 277 int n; 278 for (n = 0; n < nbByte; n++) 279 { 280 buf[n] = (unsigned char)(x & 0xff); 281 x >>= 8; 282 } 283 if (x != 0) 284 { /* data overflow - hack for ZIP64 (X Roche) */ 285 for (n = 0; n < nbByte; n++) 286 { 287 buf[n] = 0xff; 288 } 289 } 290 291 if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) 292 return ZIP_ERRNO; 293 else 294 return ZIP_OK; 295 } 296 297 local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); 298 local void ziplocal_putValue_inmemory (dest, x, nbByte) 299 void* dest; 300 uLong x; 301 int nbByte; 302 { 303 unsigned char* buf=(unsigned char*)dest; 304 int n; 305 for (n = 0; n < nbByte; n++) { 306 buf[n] = (unsigned char)(x & 0xff); 307 x >>= 8; 308 } 309 310 if (x != 0) 311 { /* data overflow - hack for ZIP64 */ 312 for (n = 0; n < nbByte; n++) 313 { 314 buf[n] = 0xff; 315 } 316 } 317 } 318 319 /****************************************************************************/ 320 321 322 local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) 323 const tm_zip* ptm; 324 uLong dosDate; 325 { 326 uLong year = (uLong)ptm->tm_year; 327 if (year>1980) 328 year-=1980; 329 else if (year>80) 330 year-=80; 331 return 332 (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | 333 ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); 334 } 335 336 337 /****************************************************************************/ 338 339 local int ziplocal_getByte OF(( 340 const zlib_filefunc_def* pzlib_filefunc_def, 341 voidpf filestream, 342 int *pi)); 343 344 local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) 345 const zlib_filefunc_def* pzlib_filefunc_def; 346 voidpf filestream; 347 int *pi; 348 { 349 unsigned char c; 350 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); 351 if (err==1) 352 { 353 *pi = (int)c; 354 return ZIP_OK; 355 } 356 else 357 { 358 if (ZERROR(*pzlib_filefunc_def,filestream)) 359 return ZIP_ERRNO; 360 else 361 return ZIP_EOF; 362 } 363 } 364 365 366 /* =========================================================================== 367 Reads a long in LSB order from the given gz_stream. Sets 368 */ 369 local int ziplocal_getShort OF(( 370 const zlib_filefunc_def* pzlib_filefunc_def, 371 voidpf filestream, 372 uLong *pX)); 373 374 local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) 375 const zlib_filefunc_def* pzlib_filefunc_def; 376 voidpf filestream; 377 uLong *pX; 378 { 379 uLong x ; 380 int i; 381 int err; 382 383 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 384 x = (uLong)i; 385 386 if (err==ZIP_OK) 387 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 388 x += ((uLong)i)<<8; 389 390 if (err==ZIP_OK) 391 *pX = x; 392 else 393 *pX = 0; 394 return err; 395 } 396 397 local int ziplocal_getLong OF(( 398 const zlib_filefunc_def* pzlib_filefunc_def, 399 voidpf filestream, 400 uLong *pX)); 401 402 local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) 403 const zlib_filefunc_def* pzlib_filefunc_def; 404 voidpf filestream; 405 uLong *pX; 406 { 407 uLong x ; 408 int i; 409 int err; 410 411 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 412 x = (uLong)i; 413 414 if (err==ZIP_OK) 415 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 416 x += ((uLong)i)<<8; 417 418 if (err==ZIP_OK) 419 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 420 x += ((uLong)i)<<16; 421 422 if (err==ZIP_OK) 423 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); 424 x += ((uLong)i)<<24; 425 426 if (err==ZIP_OK) 427 *pX = x; 428 else 429 *pX = 0; 430 return err; 431 } 432 433 #ifndef BUFREADCOMMENT 434 #define BUFREADCOMMENT (0x400) 435 #endif 436 /* 437 Locate the Central directory of a zipfile (at the end, just before 438 the global comment) 439 */ 440 local uLong ziplocal_SearchCentralDir OF(( 441 const zlib_filefunc_def* pzlib_filefunc_def, 442 voidpf filestream)); 443 444 local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) 445 const zlib_filefunc_def* pzlib_filefunc_def; 446 voidpf filestream; 447 { 448 unsigned char* buf; 449 uLong uSizeFile; 450 uLong uBackRead; 451 uLong uMaxBack=0xffff; /* maximum size of global comment */ 452 uLong uPosFound=0; 453 454 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) 455 return 0; 456 457 458 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); 459 460 if (uMaxBack>uSizeFile) 461 uMaxBack = uSizeFile; 462 463 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); 464 if (buf==NULL) 465 return 0; 466 467 uBackRead = 4; 468 while (uBackRead<uMaxBack) 469 { 470 uLong uReadSize,uReadPos ; 471 int i; 472 if (uBackRead+BUFREADCOMMENT>uMaxBack) 473 uBackRead = uMaxBack; 474 else 475 uBackRead+=BUFREADCOMMENT; 476 uReadPos = uSizeFile-uBackRead ; 477 478 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 479 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); 480 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) 481 break; 482 483 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) 484 break; 485 486 for (i=(int)uReadSize-3; (i--)>0;) 487 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 488 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) 489 { 490 uPosFound = uReadPos+i; 491 break; 492 } 493 494 if (uPosFound!=0) 495 break; 496 } 497 TRYFREE(buf); 498 return uPosFound; 499 } 500 #endif /* !NO_ADDFILEINEXISTINGZIP*/ 501 502 /************************************************************/ 503 extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) 504 const char *pathname; 505 int append; 506 zipcharpc* globalcomment; 507 zlib_filefunc_def* pzlib_filefunc_def; 508 { 509 zip_internal ziinit; 510 zip_internal* zi; 511 int err=ZIP_OK; 512 513 514 if (pzlib_filefunc_def==NULL) 515 fill_fopen_filefunc(&ziinit.z_filefunc); 516 else 517 ziinit.z_filefunc = *pzlib_filefunc_def; 518 519 ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) 520 (ziinit.z_filefunc.opaque, 521 pathname, 522 (append == APPEND_STATUS_CREATE) ? 523 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : 524 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); 525 526 if (ziinit.filestream == NULL) 527 return NULL; 528 ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); 529 ziinit.in_opened_file_inzip = 0; 530 ziinit.ci.stream_initialised = 0; 531 ziinit.number_entry = 0; 532 ziinit.add_position_when_writting_offset = 0; 533 init_linkedlist(&(ziinit.central_dir)); 534 535 536 zi = (zip_internal*)ALLOC(sizeof(zip_internal)); 537 if (zi==NULL) 538 { 539 ZCLOSE(ziinit.z_filefunc,ziinit.filestream); 540 return NULL; 541 } 542 543 /* now we add file in a zipfile */ 544 # ifndef NO_ADDFILEINEXISTINGZIP 545 ziinit.globalcomment = NULL; 546 if (append == APPEND_STATUS_ADDINZIP) 547 { 548 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ 549 550 uLong size_central_dir; /* size of the central directory */ 551 uLong offset_central_dir; /* offset of start of central directory */ 552 uLong central_pos,uL; 553 554 uLong number_disk; /* number of the current dist, used for 555 spaning ZIP, unsupported, always 0*/ 556 uLong number_disk_with_CD; /* number the the disk with central dir, used 557 for spaning ZIP, unsupported, always 0*/ 558 uLong number_entry; 559 uLong number_entry_CD; /* total number of entries in 560 the central dir 561 (same than number_entry on nospan) */ 562 uLong size_comment; 563 564 central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); 565 if (central_pos==0) 566 err=ZIP_ERRNO; 567 568 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, 569 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) 570 err=ZIP_ERRNO; 571 572 /* the signature, already checked */ 573 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) 574 err=ZIP_ERRNO; 575 576 /* number of this disk */ 577 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) 578 err=ZIP_ERRNO; 579 580 /* number of the disk with the start of the central directory */ 581 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) 582 err=ZIP_ERRNO; 583 584 /* total number of entries in the central dir on this disk */ 585 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) 586 err=ZIP_ERRNO; 587 588 /* total number of entries in the central dir */ 589 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) 590 err=ZIP_ERRNO; 591 592 if ((number_entry_CD!=number_entry) || 593 (number_disk_with_CD!=0) || 594 (number_disk!=0)) 595 err=ZIP_BADZIPFILE; 596 597 /* size of the central directory */ 598 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) 599 err=ZIP_ERRNO; 600 601 /* offset of start of central directory with respect to the 602 starting disk number */ 603 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) 604 err=ZIP_ERRNO; 605 606 /* zipfile global comment length */ 607 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) 608 err=ZIP_ERRNO; 609 610 if ((central_pos<offset_central_dir+size_central_dir) && 611 (err==ZIP_OK)) 612 err=ZIP_BADZIPFILE; 613 614 if (err!=ZIP_OK) 615 { 616 ZCLOSE(ziinit.z_filefunc, ziinit.filestream); 617 return NULL; 618 } 619 620 if (size_comment>0) 621 { 622 ziinit.globalcomment = ALLOC(size_comment+1); 623 if (ziinit.globalcomment) 624 { 625 size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); 626 ziinit.globalcomment[size_comment]=0; 627 } 628 } 629 630 byte_before_the_zipfile = central_pos - 631 (offset_central_dir+size_central_dir); 632 ziinit.add_position_when_writting_offset = byte_before_the_zipfile; 633 634 { 635 uLong size_central_dir_to_read = size_central_dir; 636 size_t buf_size = SIZEDATA_INDATABLOCK; 637 void* buf_read = (void*)ALLOC(buf_size); 638 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, 639 offset_central_dir + byte_before_the_zipfile, 640 ZLIB_FILEFUNC_SEEK_SET) != 0) 641 err=ZIP_ERRNO; 642 643 while ((size_central_dir_to_read>0) && (err==ZIP_OK)) 644 { 645 uLong read_this = SIZEDATA_INDATABLOCK; 646 if (read_this > size_central_dir_to_read) 647 read_this = size_central_dir_to_read; 648 if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) 649 err=ZIP_ERRNO; 650 651 if (err==ZIP_OK) 652 err = add_data_in_datablock(&ziinit.central_dir,buf_read, 653 (uLong)read_this); 654 size_central_dir_to_read-=read_this; 655 } 656 TRYFREE(buf_read); 657 } 658 ziinit.begin_pos = byte_before_the_zipfile; 659 ziinit.number_entry = number_entry_CD; 660 661 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, 662 offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) 663 err=ZIP_ERRNO; 664 } 665 666 if (globalcomment) 667 { 668 *globalcomment = ziinit.globalcomment; 669 } 670 # endif /* !NO_ADDFILEINEXISTINGZIP*/ 671 672 if (err != ZIP_OK) 673 { 674 # ifndef NO_ADDFILEINEXISTINGZIP 675 TRYFREE(ziinit.globalcomment); 676 # endif /* !NO_ADDFILEINEXISTINGZIP*/ 677 TRYFREE(zi); 678 return NULL; 679 } 680 else 681 { 682 *zi = ziinit; 683 return (zipFile)zi; 684 } 685 } 686 687 extern zipFile ZEXPORT zipOpen (pathname, append) 688 const char *pathname; 689 int append; 690 { 691 return zipOpen2(pathname,append,NULL,NULL); 692 } 693 694 extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, 695 extrafield_local, size_extrafield_local, 696 extrafield_global, size_extrafield_global, 697 comment, method, level, raw, 698 windowBits, memLevel, strategy, 699 password, crcForCrypting) 700 zipFile file; 701 const char* filename; 702 const zip_fileinfo* zipfi; 703 const void* extrafield_local; 704 uInt size_extrafield_local; 705 const void* extrafield_global; 706 uInt size_extrafield_global; 707 const char* comment; 708 int method; 709 int level; 710 int raw; 711 int windowBits; 712 int memLevel; 713 int strategy; 714 const char* password; 715 uLong crcForCrypting; 716 { 717 zip_internal* zi; 718 uInt size_filename; 719 uInt size_comment; 720 uInt i; 721 int err = ZIP_OK; 722 723 # ifdef NOCRYPT 724 if (password != NULL) 725 return ZIP_PARAMERROR; 726 # endif 727 728 if (file == NULL) 729 return ZIP_PARAMERROR; 730 if ((method!=0) && (method!=Z_DEFLATED)) 731 return ZIP_PARAMERROR; 732 733 zi = (zip_internal*)file; 734 735 if (zi->in_opened_file_inzip == 1) 736 { 737 err = zipCloseFileInZip (file); 738 if (err != ZIP_OK) 739 return err; 740 } 741 742 743 if (filename==NULL) 744 filename="-"; 745 746 if (comment==NULL) 747 size_comment = 0; 748 else 749 size_comment = (uInt)strlen(comment); 750 751 size_filename = (uInt)strlen(filename); 752 753 if (zipfi == NULL) 754 zi->ci.dosDate = 0; 755 else 756 { 757 if (zipfi->dosDate != 0) 758 zi->ci.dosDate = zipfi->dosDate; 759 else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); 760 } 761 762 zi->ci.flag = 0; 763 if ((level==8) || (level==9)) 764 zi->ci.flag |= 2; 765 if ((level==2)) 766 zi->ci.flag |= 4; 767 if ((level==1)) 768 zi->ci.flag |= 6; 769 if (password != NULL) 770 zi->ci.flag |= 1; 771 772 zi->ci.crc32 = 0; 773 zi->ci.method = method; 774 zi->ci.encrypt = 0; 775 zi->ci.stream_initialised = 0; 776 zi->ci.pos_in_buffered_data = 0; 777 zi->ci.raw = raw; 778 zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; 779 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 780 size_extrafield_global + size_comment; 781 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); 782 783 ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); 784 /* version info */ 785 ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); 786 ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); 787 ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); 788 ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); 789 ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); 790 ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ 791 ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ 792 ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ 793 ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); 794 ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); 795 ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); 796 ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ 797 798 if (zipfi==NULL) 799 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 800 else 801 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 802 803 if (zipfi==NULL) 804 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 805 else 806 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); 807 808 ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); 809 810 for (i=0;i<size_filename;i++) 811 *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); 812 813 for (i=0;i<size_extrafield_global;i++) 814 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) = 815 *(((const char*)extrafield_global)+i); 816 817 for (i=0;i<size_comment;i++) 818 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+ 819 size_extrafield_global+i) = *(comment+i); 820 if (zi->ci.central_header == NULL) 821 return ZIP_INTERNALERROR; 822 823 /* write the local header */ 824 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); 825 826 if (err==ZIP_OK) 827 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ 828 if (err==ZIP_OK) 829 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); 830 831 if (err==ZIP_OK) 832 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); 833 834 if (err==ZIP_OK) 835 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); 836 837 if (err==ZIP_OK) 838 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ 839 if (err==ZIP_OK) 840 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ 841 if (err==ZIP_OK) 842 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ 843 844 if (err==ZIP_OK) 845 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); 846 847 if (err==ZIP_OK) 848 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); 849 850 if ((err==ZIP_OK) && (size_filename>0)) 851 if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) 852 err = ZIP_ERRNO; 853 854 if ((err==ZIP_OK) && (size_extrafield_local>0)) 855 if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) 856 !=size_extrafield_local) 857 err = ZIP_ERRNO; 858 859 zi->ci.stream.avail_in = (uInt)0; 860 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 861 zi->ci.stream.next_out = zi->ci.buffered_data; 862 zi->ci.stream.total_in = 0; 863 zi->ci.stream.total_out = 0; 864 865 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 866 { 867 zi->ci.stream.zalloc = (alloc_func)0; 868 zi->ci.stream.zfree = (free_func)0; 869 zi->ci.stream.opaque = (voidpf)0; 870 871 if (windowBits>0) 872 windowBits = -windowBits; 873 874 err = deflateInit2(&zi->ci.stream, level, 875 Z_DEFLATED, windowBits, memLevel, strategy); 876 877 if (err==Z_OK) 878 zi->ci.stream_initialised = 1; 879 } 880 # ifndef NOCRYPT 881 zi->ci.crypt_header_size = 0; 882 if ((err==Z_OK) && (password != NULL)) 883 { 884 unsigned char bufHead[RAND_HEAD_LEN]; 885 unsigned int sizeHead; 886 zi->ci.encrypt = 1; 887 zi->ci.pcrc_32_tab = get_crc_table(); 888 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ 889 890 sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); 891 zi->ci.crypt_header_size = sizeHead; 892 893 if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) 894 err = ZIP_ERRNO; 895 } 896 # endif 897 898 if (err==Z_OK) 899 zi->in_opened_file_inzip = 1; 900 return err; 901 } 902 903 extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, 904 extrafield_local, size_extrafield_local, 905 extrafield_global, size_extrafield_global, 906 comment, method, level, raw) 907 zipFile file; 908 const char* filename; 909 const zip_fileinfo* zipfi; 910 const void* extrafield_local; 911 uInt size_extrafield_local; 912 const void* extrafield_global; 913 uInt size_extrafield_global; 914 const char* comment; 915 int method; 916 int level; 917 int raw; 918 { 919 return zipOpenNewFileInZip3 (file, filename, zipfi, 920 extrafield_local, size_extrafield_local, 921 extrafield_global, size_extrafield_global, 922 comment, method, level, raw, 923 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 924 NULL, 0); 925 } 926 927 extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, 928 extrafield_local, size_extrafield_local, 929 extrafield_global, size_extrafield_global, 930 comment, method, level) 931 zipFile file; 932 const char* filename; 933 const zip_fileinfo* zipfi; 934 const void* extrafield_local; 935 uInt size_extrafield_local; 936 const void* extrafield_global; 937 uInt size_extrafield_global; 938 const char* comment; 939 int method; 940 int level; 941 { 942 return zipOpenNewFileInZip2 (file, filename, zipfi, 943 extrafield_local, size_extrafield_local, 944 extrafield_global, size_extrafield_global, 945 comment, method, level, 0); 946 } 947 948 local int zipFlushWriteBuffer(zi) 949 zip_internal* zi; 950 { 951 int err=ZIP_OK; 952 953 if (zi->ci.encrypt != 0) 954 { 955 #ifndef NOCRYPT 956 uInt i; 957 int t; 958 for (i=0;i<zi->ci.pos_in_buffered_data;i++) 959 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, 960 zi->ci.buffered_data[i],t); 961 #endif 962 } 963 if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) 964 !=zi->ci.pos_in_buffered_data) 965 err = ZIP_ERRNO; 966 zi->ci.pos_in_buffered_data = 0; 967 return err; 968 } 969 970 extern int ZEXPORT zipWriteInFileInZip (file, buf, len) 971 zipFile file; 972 const void* buf; 973 unsigned len; 974 { 975 zip_internal* zi; 976 int err=ZIP_OK; 977 978 if (file == NULL) 979 return ZIP_PARAMERROR; 980 zi = (zip_internal*)file; 981 982 if (zi->in_opened_file_inzip == 0) 983 return ZIP_PARAMERROR; 984 985 zi->ci.stream.next_in = (void*)buf; 986 zi->ci.stream.avail_in = len; 987 zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); 988 989 while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) 990 { 991 if (zi->ci.stream.avail_out == 0) 992 { 993 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) 994 err = ZIP_ERRNO; 995 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 996 zi->ci.stream.next_out = zi->ci.buffered_data; 997 } 998 999 1000 if(err != ZIP_OK) 1001 break; 1002 1003 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1004 { 1005 uLong uTotalOutBefore = zi->ci.stream.total_out; 1006 err=deflate(&zi->ci.stream, Z_NO_FLUSH); 1007 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; 1008 1009 } 1010 else 1011 { 1012 uInt copy_this,i; 1013 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) 1014 copy_this = zi->ci.stream.avail_in; 1015 else 1016 copy_this = zi->ci.stream.avail_out; 1017 for (i=0;i<copy_this;i++) 1018 *(((char*)zi->ci.stream.next_out)+i) = 1019 *(((const char*)zi->ci.stream.next_in)+i); 1020 { 1021 zi->ci.stream.avail_in -= copy_this; 1022 zi->ci.stream.avail_out-= copy_this; 1023 zi->ci.stream.next_in+= copy_this; 1024 zi->ci.stream.next_out+= copy_this; 1025 zi->ci.stream.total_in+= copy_this; 1026 zi->ci.stream.total_out+= copy_this; 1027 zi->ci.pos_in_buffered_data += copy_this; 1028 } 1029 } 1030 } 1031 1032 return err; 1033 } 1034 1035 extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) 1036 zipFile file; 1037 uLong uncompressed_size; 1038 uLong crc32; 1039 { 1040 zip_internal* zi; 1041 uLong compressed_size; 1042 int err=ZIP_OK; 1043 1044 if (file == NULL) 1045 return ZIP_PARAMERROR; 1046 zi = (zip_internal*)file; 1047 1048 if (zi->in_opened_file_inzip == 0) 1049 return ZIP_PARAMERROR; 1050 zi->ci.stream.avail_in = 0; 1051 1052 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1053 while (err==ZIP_OK) 1054 { 1055 uLong uTotalOutBefore; 1056 if (zi->ci.stream.avail_out == 0) 1057 { 1058 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) 1059 err = ZIP_ERRNO; 1060 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; 1061 zi->ci.stream.next_out = zi->ci.buffered_data; 1062 } 1063 uTotalOutBefore = zi->ci.stream.total_out; 1064 err=deflate(&zi->ci.stream, Z_FINISH); 1065 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; 1066 } 1067 1068 if (err==Z_STREAM_END) 1069 err=ZIP_OK; /* this is normal */ 1070 1071 if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) 1072 if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) 1073 err = ZIP_ERRNO; 1074 1075 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) 1076 { 1077 err=deflateEnd(&zi->ci.stream); 1078 zi->ci.stream_initialised = 0; 1079 } 1080 1081 if (!zi->ci.raw) 1082 { 1083 crc32 = (uLong)zi->ci.crc32; 1084 uncompressed_size = (uLong)zi->ci.stream.total_in; 1085 } 1086 compressed_size = (uLong)zi->ci.stream.total_out; 1087 # ifndef NOCRYPT 1088 compressed_size += zi->ci.crypt_header_size; 1089 # endif 1090 1091 ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ 1092 ziplocal_putValue_inmemory(zi->ci.central_header+20, 1093 compressed_size,4); /*compr size*/ 1094 if (zi->ci.stream.data_type == Z_ASCII) 1095 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); 1096 ziplocal_putValue_inmemory(zi->ci.central_header+24, 1097 uncompressed_size,4); /*uncompr size*/ 1098 1099 if (err==ZIP_OK) 1100 err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, 1101 (uLong)zi->ci.size_centralheader); 1102 free(zi->ci.central_header); 1103 1104 if (err==ZIP_OK) 1105 { 1106 long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); 1107 if (ZSEEK(zi->z_filefunc,zi->filestream, 1108 zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) 1109 err = ZIP_ERRNO; 1110 1111 if (err==ZIP_OK) 1112 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ 1113 1114 if (err==ZIP_OK) /* compressed size, unknown */ 1115 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); 1116 1117 if (err==ZIP_OK) /* uncompressed size, unknown */ 1118 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); 1119 1120 if (ZSEEK(zi->z_filefunc,zi->filestream, 1121 cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) 1122 err = ZIP_ERRNO; 1123 } 1124 1125 zi->number_entry ++; 1126 zi->in_opened_file_inzip = 0; 1127 1128 return err; 1129 } 1130 1131 extern int ZEXPORT zipCloseFileInZip (file) 1132 zipFile file; 1133 { 1134 return zipCloseFileInZipRaw (file,0,0); 1135 } 1136 1137 extern int ZEXPORT zipClose (file, global_comment) 1138 zipFile file; 1139 const char* global_comment; 1140 { 1141 zip_internal* zi; 1142 int err = 0; 1143 uLong size_centraldir = 0; 1144 uLong centraldir_pos_inzip; 1145 uInt size_global_comment; 1146 if (file == NULL) 1147 return ZIP_PARAMERROR; 1148 zi = (zip_internal*)file; 1149 1150 if (zi->in_opened_file_inzip == 1) 1151 { 1152 err = zipCloseFileInZip (file); 1153 } 1154 1155 #ifndef NO_ADDFILEINEXISTINGZIP 1156 if (global_comment==NULL) 1157 global_comment = zi->globalcomment; 1158 #endif 1159 if (global_comment==NULL) 1160 size_global_comment = 0; 1161 else 1162 size_global_comment = (uInt)strlen(global_comment); 1163 1164 centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); 1165 if (err==ZIP_OK) 1166 { 1167 linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; 1168 while (ldi!=NULL) 1169 { 1170 if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) 1171 if (ZWRITE(zi->z_filefunc,zi->filestream, 1172 ldi->data,ldi->filled_in_this_block) 1173 !=ldi->filled_in_this_block ) 1174 err = ZIP_ERRNO; 1175 1176 size_centraldir += ldi->filled_in_this_block; 1177 ldi = ldi->next_datablock; 1178 } 1179 } 1180 free_datablock(zi->central_dir.first_block); 1181 1182 if (err==ZIP_OK) /* Magic End */ 1183 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); 1184 1185 if (err==ZIP_OK) /* number of this disk */ 1186 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); 1187 1188 if (err==ZIP_OK) /* number of the disk with the start of the central directory */ 1189 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); 1190 1191 if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ 1192 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); 1193 1194 if (err==ZIP_OK) /* total number of entries in the central dir */ 1195 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); 1196 1197 if (err==ZIP_OK) /* size of the central directory */ 1198 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); 1199 1200 if (err==ZIP_OK) /* offset of start of central directory with respect to the 1201 starting disk number */ 1202 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, 1203 (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); 1204 1205 if (err==ZIP_OK) /* zipfile comment length */ 1206 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); 1207 1208 if ((err==ZIP_OK) && (size_global_comment>0)) 1209 if (ZWRITE(zi->z_filefunc,zi->filestream, 1210 global_comment,size_global_comment) != size_global_comment) 1211 err = ZIP_ERRNO; 1212 1213 if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) 1214 if (err == ZIP_OK) 1215 err = ZIP_ERRNO; 1216 1217 #ifndef NO_ADDFILEINEXISTINGZIP 1218 TRYFREE(zi->globalcomment); 1219 #endif 1220 TRYFREE(zi); 1221 1222 return err; 1223 } 1224