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