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