/* zip.c -- IO on .zip files using zlib Version 1.01, May 8th, 2004 Slightly modified by StatMat to expose internal data 28th March, 2005 Copyright (C) 1998-2004 Gilles Vollant Read zip.h for more info */ #include #include #include #include #include "zlib.h" #include "zip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY # define VERSIONMADEBY (0x0) /* platform depedent */ #endif #ifndef Z_MAXFILENAMEINZIP #define Z_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif /* #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef DEF_MEM_LEVEL #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif #endif const char zip_copyright[] = " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; #ifndef NOCRYPT #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED #include "crypt.h" #endif local linkedlist_datablock_internal * allocate_new_datablock () { linkedlist_datablock_internal *ldi; ldi = (linkedlist_datablock_internal *) ALLOC (sizeof (linkedlist_datablock_internal)); if (ldi != NULL) { ldi->next_datablock = NULL; ldi->filled_in_this_block = 0; ldi->avail_in_this_block = SIZEDATA_INDATABLOCK; } return ldi; } local void free_datablock (ldi) linkedlist_datablock_internal *ldi; { while (ldi != NULL) { linkedlist_datablock_internal *ldinext = ldi->next_datablock; TRYFREE (ldi); ldi = ldinext; } } local void init_linkedlist (ll) linkedlist_data *ll; { ll->first_block = ll->last_block = NULL; } local void free_linkedlist (ll) linkedlist_data *ll; { free_datablock (ll->first_block); ll->first_block = ll->last_block = NULL; } local int add_data_in_datablock (ll, buf, len) linkedlist_data *ll; const void *buf; uLong len; { linkedlist_datablock_internal *ldi; const unsigned char *from_copy; if (ll == NULL) return ZIP_INTERNALERROR; if (ll->last_block == NULL) { ll->first_block = ll->last_block = allocate_new_datablock (); if (ll->first_block == NULL) return ZIP_INTERNALERROR; } ldi = ll->last_block; from_copy = (unsigned char *) buf; while (len > 0) { uInt copy_this; uInt i; unsigned char *to_copy; if (ldi->avail_in_this_block == 0) { ldi->next_datablock = allocate_new_datablock (); if (ldi->next_datablock == NULL) return ZIP_INTERNALERROR; ldi = ldi->next_datablock; ll->last_block = ldi; } if (ldi->avail_in_this_block < len) copy_this = (uInt) ldi->avail_in_this_block; else copy_this = (uInt) len; to_copy = &(ldi->data[ldi->filled_in_this_block]); for (i = 0; i < copy_this; i++) *(to_copy + i) = *(from_copy + i); ldi->filled_in_this_block += copy_this; ldi->avail_in_this_block -= copy_this; from_copy += copy_this; len -= copy_this; } return ZIP_OK; } /****************************************************************************/ #ifndef NO_ADDFILEINEXISTINGZIP /* =========================================================================== Inputs a long in LSB order to the given file nbByte == 1, 2 or 4 (byte, short or long) */ local int ziplocal_putValue OF ((const zlib_filefunc_def * pzlib_filefunc_def, voidpf filestream, uLong x, int nbByte)); local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) const zlib_filefunc_def *pzlib_filefunc_def; voidpf filestream; uLong x; int nbByte; { unsigned char buf[4]; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char) (x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 (X Roche) */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } if (ZWRITE (*pzlib_filefunc_def, filestream, buf, nbByte) != (uLong) nbByte) return ZIP_ERRNO; else return ZIP_OK; } local void ziplocal_putValue_inmemory OF ((void *dest, uLong x, int nbByte)); local void ziplocal_putValue_inmemory (dest, x, nbByte) void *dest; uLong x; int nbByte; { unsigned char *buf = (unsigned char *) dest; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char) (x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } } /****************************************************************************/ local uLong ziplocal_TmzDateToDosDate (ptm, dosDate) const tm_zip *ptm; uLong dosDate; { uLong year = (uLong) ptm->tm_year; if (year > 1980) year -= 1980; else if (year > 80) year -= 80; return (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon + 1)) + (512 * year)) << 16) | ((ptm->tm_sec / 2) + (32 * ptm->tm_min) + (2048 * (uLong) ptm->tm_hour)); } /****************************************************************************/ local int ziplocal_getByte OF ((const zlib_filefunc_def * pzlib_filefunc_def, voidpf filestream, int *pi)); local int ziplocal_getByte (pzlib_filefunc_def, filestream, pi) const zlib_filefunc_def *pzlib_filefunc_def; voidpf filestream; int *pi; { unsigned char c; int err = (int) ZREAD (*pzlib_filefunc_def, filestream, &c, 1); if (err == 1) { *pi = (int) c; return ZIP_OK; } else { if (ZERROR (*pzlib_filefunc_def, filestream)) return ZIP_ERRNO; else return ZIP_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int ziplocal_getShort OF ((const zlib_filefunc_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); local int ziplocal_getShort (pzlib_filefunc_def, filestream, pX) const zlib_filefunc_def *pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x; int i; int err; err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x = (uLong) i; if (err == ZIP_OK) err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x += ((uLong) i) << 8; if (err == ZIP_OK) *pX = x; else *pX = 0; return err; } local int ziplocal_getLong OF ((const zlib_filefunc_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); local int ziplocal_getLong (pzlib_filefunc_def, filestream, pX) const zlib_filefunc_def *pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x; int i; int err; err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x = (uLong) i; if (err == ZIP_OK) err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x += ((uLong) i) << 8; if (err == ZIP_OK) err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x += ((uLong) i) << 16; if (err == ZIP_OK) err = ziplocal_getByte (pzlib_filefunc_def, filestream, &i); x += ((uLong) i) << 24; if (err == ZIP_OK) *pX = x; else *pX = 0; return err; } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local uLong ziplocal_SearchCentralDir OF ((const zlib_filefunc_def * pzlib_filefunc_def, voidpf filestream)); local uLong ziplocal_SearchCentralDir (pzlib_filefunc_def, filestream) const zlib_filefunc_def *pzlib_filefunc_def; voidpf filestream; { unsigned char *buf; uLong uSizeFile; uLong uBackRead; uLong uMaxBack = 0xffff; /* maximum size of global comment */ uLong uPosFound = 0; if (ZSEEK (*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL (*pzlib_filefunc_def, filestream); if (uMaxBack > uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char *) ALLOC (BUFREADCOMMENT + 4); if (buf == NULL) return 0; uBackRead = 4; while (uBackRead < uMaxBack) { uLong uReadSize, uReadPos; int i; if (uBackRead + BUFREADCOMMENT > uMaxBack) uBackRead = uMaxBack; else uBackRead += BUFREADCOMMENT; uReadPos = uSizeFile - uBackRead; uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uSizeFile - uReadPos); if (ZSEEK (*pzlib_filefunc_def, filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0) break; if (ZREAD (*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize) break; for (i = (int) uReadSize - 3; (i--) > 0;) if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06)) { uPosFound = uReadPos + i; break; } if (uPosFound != 0) break; } TRYFREE (buf); return uPosFound; } #endif /* !NO_ADDFILEINEXISTINGZIP */ /************************************************************/ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) const char *pathname; int append; zipcharpc *globalcomment; zlib_filefunc_def *pzlib_filefunc_def; { zip_internal ziinit; zip_internal *zi; int err = ZIP_OK; if (pzlib_filefunc_def == NULL) fill_fopen_filefunc (&ziinit.z_filefunc); else ziinit.z_filefunc = *pzlib_filefunc_def; ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) (ziinit.z_filefunc.opaque, pathname, (append == APPEND_STATUS_CREATE) ? (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); if (ziinit.filestream == NULL) return NULL; ziinit.begin_pos = ZTELL (ziinit.z_filefunc, ziinit.filestream); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; ziinit.add_position_when_writting_offset = 0; init_linkedlist (&(ziinit.central_dir)); zi = (zip_internal *) ALLOC (sizeof (zip_internal)); if (zi == NULL) { ZCLOSE (ziinit.z_filefunc, ziinit.filestream); return NULL; } /* now we add file in a zipfile */ # ifndef NO_ADDFILEINEXISTINGZIP if (append == APPEND_STATUS_ADDINZIP) { uLong byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */ uLong size_central_dir; /* size of the central directory */ uLong offset_central_dir; /* offset of start of central directory */ uLong central_pos, uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0 */ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0 */ uLong number_entry; uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ uLong size_comment; central_pos = ziplocal_SearchCentralDir (&ziinit.z_filefunc, ziinit.filestream); if (central_pos == 0) err = ZIP_ERRNO; if (ZSEEK (ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) err = ZIP_ERRNO; /* the signature, already checked */ if (ziplocal_getLong (&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) err = ZIP_ERRNO; /* number of this disk */ if (ziplocal_getShort (&ziinit.z_filefunc, ziinit.filestream, &number_disk) != ZIP_OK) err = ZIP_ERRNO; /* number of the disk with the start of the central directory */ if (ziplocal_getShort (&ziinit.z_filefunc, ziinit.filestream, &number_disk_with_CD) != ZIP_OK) err = ZIP_ERRNO; /* total number of entries in the central dir on this disk */ if (ziplocal_getShort (&ziinit.z_filefunc, ziinit.filestream, &number_entry) != ZIP_OK) err = ZIP_ERRNO; /* total number of entries in the central dir */ if (ziplocal_getShort (&ziinit.z_filefunc, ziinit.filestream, &number_entry_CD) != ZIP_OK) err = ZIP_ERRNO; if ((number_entry_CD != number_entry) || (number_disk_with_CD != 0) || (number_disk != 0)) err = ZIP_BADZIPFILE; /* size of the central directory */ if (ziplocal_getLong (&ziinit.z_filefunc, ziinit.filestream, &size_central_dir) != ZIP_OK) err = ZIP_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (ziplocal_getLong (&ziinit.z_filefunc, ziinit.filestream, &offset_central_dir) != ZIP_OK) err = ZIP_ERRNO; /* zipfile comment length */ if (ziplocal_getShort (&ziinit.z_filefunc, ziinit.filestream, &size_comment) != ZIP_OK) err = ZIP_ERRNO; if ((central_pos < offset_central_dir + size_central_dir) && (err == ZIP_OK)) err = ZIP_BADZIPFILE; if (err != ZIP_OK) { ZCLOSE (ziinit.z_filefunc, ziinit.filestream); return NULL; } byte_before_the_zipfile = central_pos - (offset_central_dir + size_central_dir); ziinit.add_position_when_writting_offset = byte_before_the_zipfile; { uLong size_central_dir_to_read = size_central_dir; size_t buf_size = SIZEDATA_INDATABLOCK; void *buf_read = (void *) ALLOC (buf_size); if (ZSEEK (ziinit.z_filefunc, ziinit.filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) err = ZIP_ERRNO; while ((size_central_dir_to_read > 0) && (err == ZIP_OK)) { uLong read_this = SIZEDATA_INDATABLOCK; if (read_this > size_central_dir_to_read) read_this = size_central_dir_to_read; if (ZREAD (ziinit.z_filefunc, ziinit.filestream, buf_read, read_this) != read_this) err = ZIP_ERRNO; if (err == ZIP_OK) err = add_data_in_datablock (&ziinit.central_dir, buf_read, (uLong) read_this); size_central_dir_to_read -= read_this; } TRYFREE (buf_read); } ziinit.begin_pos = byte_before_the_zipfile; ziinit.number_entry = number_entry_CD; if (ZSEEK (ziinit.z_filefunc, ziinit.filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) err = ZIP_ERRNO; } # endif /* !NO_ADDFILEINEXISTINGZIP */ if (err != ZIP_OK) { TRYFREE (zi); return NULL; } else { *zi = ziinit; return (zipFile) zi; } } extern zipFile ZEXPORT zipOpen (pathname, append) const char *pathname; int append; { return zipOpen2 (pathname, append, NULL, NULL); } extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting) zipFile file; const char *filename; const zip_fileinfo *zipfi; const void *extrafield_local; uInt size_extrafield_local; const void *extrafield_global; uInt size_extrafield_global; const char *comment; int method; int level; int raw; int windowBits; int memLevel; int strategy; const char *password; uLong crcForCrypting; { zip_internal *zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; # ifdef NOCRYPT if (password != NULL) return ZIP_PARAMERROR; # endif if (file == NULL) return ZIP_PARAMERROR; if ((method != 0) && (method != Z_DEFLATED)) return ZIP_PARAMERROR; zi = (zip_internal *) file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); if (err != ZIP_OK) return err; } if (filename == NULL) filename = "-"; if (comment == NULL) size_comment = 0; else size_comment = (uInt) strlen (comment); size_filename = (uInt) strlen (filename); if (zipfi == NULL) zi->ci.dosDate = 0; else { if (zipfi->dosDate != 0) zi->ci.dosDate = zipfi->dosDate; else zi->ci.dosDate = ziplocal_TmzDateToDosDate (&zipfi->tmz_date, zipfi->dosDate); } zi->ci.flag = 0; if ((level == 8) || (level == 9)) zi->ci.flag |= 2; if ((level == 2)) zi->ci.flag |= 4; if ((level == 1)) zi->ci.flag |= 6; if (password != NULL) zi->ci.flag |= 1; zi->ci.crc32 = 0; zi->ci.method = method; zi->ci.encrypt = 0; zi->ci.stream_initialised = 0; zi->ci.pos_in_buffered_data = 0; zi->ci.raw = raw; zi->ci.pos_local_header = ZTELL (zi->z_filefunc, zi->filestream); zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; zi->ci.central_header = (char *) ALLOC ((uInt) zi->ci.size_centralheader); ziplocal_putValue_inmemory (zi->ci.central_header, (uLong) CENTRALHEADERMAGIC, 4); /* version info */ ziplocal_putValue_inmemory (zi->ci.central_header + 4, (uLong) VERSIONMADEBY, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 6, (uLong) 20, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 8, (uLong) zi->ci.flag, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 10, (uLong) zi->ci.method, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 12, (uLong) zi->ci.dosDate, 4); ziplocal_putValue_inmemory (zi->ci.central_header + 16, (uLong) 0, 4); /* crc */ ziplocal_putValue_inmemory (zi->ci.central_header + 20, (uLong) 0, 4); /* compr size */ ziplocal_putValue_inmemory (zi->ci.central_header + 24, (uLong) 0, 4); /* uncompr size */ ziplocal_putValue_inmemory (zi->ci.central_header + 28, (uLong) size_filename, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 30, (uLong) size_extrafield_global, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 32, (uLong) size_comment, 2); ziplocal_putValue_inmemory (zi->ci.central_header + 34, (uLong) 0, 2); /* disk nm start */ if (zipfi == NULL) ziplocal_putValue_inmemory (zi->ci.central_header + 36, (uLong) 0, 2); else ziplocal_putValue_inmemory (zi->ci.central_header + 36, (uLong) zipfi->internal_fa, 2); if (zipfi == NULL) ziplocal_putValue_inmemory (zi->ci.central_header + 38, (uLong) 0, 4); else ziplocal_putValue_inmemory (zi->ci.central_header + 38, (uLong) zipfi->external_fa, 4); ziplocal_putValue_inmemory (zi->ci.central_header + 42, (uLong) zi->ci.pos_local_header - zi->add_position_when_writting_offset, 4); for (i = 0; i < size_filename; i++) *(zi->ci.central_header + SIZECENTRALHEADER + i) = *(filename + i); for (i = 0; i < size_extrafield_global; i++) *(zi->ci.central_header + SIZECENTRALHEADER + size_filename + i) = *(((const char *) extrafield_global) + i); for (i = 0; i < size_comment; i++) *(zi->ci.central_header + SIZECENTRALHEADER + size_filename + size_extrafield_global + i) = *(comment + i); if (zi->ci.central_header == NULL) return ZIP_INTERNALERROR; /* write the local header */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) LOCALHEADERMAGIC, 4); if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 20, 2); /* version needed to extract */ if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) zi->ci.flag, 2); if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) zi->ci.method, 2); if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) zi->ci.dosDate, 4); if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 0, 4); /* crc 32, unknown */ if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 0, 4); /* compressed size, unknown */ if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 0, 4); /* uncompressed size, unknown */ if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) size_filename, 2); if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) size_extrafield_local, 2); if ((err == ZIP_OK) && (size_filename > 0)) if (ZWRITE (zi->z_filefunc, zi->filestream, filename, size_filename) != size_filename) err = ZIP_ERRNO; if ((err == ZIP_OK) && (size_extrafield_local > 0)) if (ZWRITE (zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) err = ZIP_ERRNO; zi->ci.stream.avail_in = (uInt) 0; zi->ci.stream.avail_out = (uInt) Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; zi->ci.stream.total_in = 0; zi->ci.stream.total_out = 0; if ((err == ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { zi->ci.stream.zalloc = (alloc_func) 0; zi->ci.stream.zfree = (free_func) 0; zi->ci.stream.opaque = (voidpf) 0; if (windowBits > 0) windowBits = -windowBits; err = deflateInit2 (&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); if (err == Z_OK) zi->ci.stream_initialised = 1; } # ifndef NOCRYPT zi->ci.crypt_header_size = 0; if ((err == Z_OK) && (password != NULL)) { unsigned char bufHead[RAND_HEAD_LEN]; unsigned int sizeHead; zi->ci.encrypt = 1; zi->ci.pcrc_32_tab = get_crc_table (); /* init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab); */ sizeHead = crypthead (password, bufHead, RAND_HEAD_LEN, zi->ci.keys, zi->ci.pcrc_32_tab, crcForCrypting); zi->ci.crypt_header_size = sizeHead; if (ZWRITE (zi->z_filefunc, zi->filestream, bufHead, sizeHead) != sizeHead) err = ZIP_ERRNO; } # endif if (err == Z_OK) zi->in_opened_file_inzip = 1; return err; } extern int ZEXPORT zipOpenNewFileInZip2 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw) zipFile file; const char *filename; const zip_fileinfo *zipfi; const void *extrafield_local; uInt size_extrafield_local; const void *extrafield_global; uInt size_extrafield_global; const char *comment; int method; int level; int raw; { return zipOpenNewFileInZip3 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0); } extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level) zipFile file; const char *filename; const zip_fileinfo *zipfi; const void *extrafield_local; uInt size_extrafield_local; const void *extrafield_global; uInt size_extrafield_global; const char *comment; int method; int level; { return zipOpenNewFileInZip2 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, 0); } local int zipFlushWriteBuffer (zi) zip_internal *zi; { int err = ZIP_OK; if (zi->ci.encrypt != 0) { #ifndef NOCRYPT uInt i; int t; for (i = 0; i < zi->ci.pos_in_buffered_data; i++) zi->ci.buffered_data[i] = zencode (zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i], t); #endif } if (ZWRITE (zi->z_filefunc, zi->filestream, zi->ci.buffered_data, zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) err = ZIP_ERRNO; zi->ci.pos_in_buffered_data = 0; return err; } extern int ZEXPORT zipWriteInFileInZip (file, buf, len) zipFile file; const void *buf; unsigned len; { zip_internal *zi; int err = ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal *) file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.next_in = (void *) buf; zi->ci.stream.avail_in = len; zi->ci.crc32 = crc32 (zi->ci.crc32, buf, len); while ((err == ZIP_OK) && (zi->ci.stream.avail_in > 0)) { if (zi->ci.stream.avail_out == 0) { if (zipFlushWriteBuffer (zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt) Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } if (err != ZIP_OK) break; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { uLong uTotalOutBefore = zi->ci.stream.total_out; err = deflate (&zi->ci.stream, Z_NO_FLUSH); zi->ci.pos_in_buffered_data += (uInt) (zi->ci.stream.total_out - uTotalOutBefore); } else { uInt copy_this, i; if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) copy_this = zi->ci.stream.avail_in; else copy_this = zi->ci.stream.avail_out; for (i = 0; i < copy_this; i++) *(((char *) zi->ci.stream.next_out) + i) = *(((const char *) zi->ci.stream.next_in) + i); { zi->ci.stream.avail_in -= copy_this; zi->ci.stream.avail_out -= copy_this; zi->ci.stream.next_in += copy_this; zi->ci.stream.next_out += copy_this; zi->ci.stream.total_in += copy_this; zi->ci.stream.total_out += copy_this; zi->ci.pos_in_buffered_data += copy_this; } } } return err; } extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) zipFile file; uLong uncompressed_size; uLong crc32; { zip_internal *zi; uLong compressed_size; int err = ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal *) file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.avail_in = 0; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) while (err == ZIP_OK) { uLong uTotalOutBefore; if (zi->ci.stream.avail_out == 0) { if (zipFlushWriteBuffer (zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt) Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } uTotalOutBefore = zi->ci.stream.total_out; err = deflate (&zi->ci.stream, Z_FINISH); zi->ci.pos_in_buffered_data += (uInt) (zi->ci.stream.total_out - uTotalOutBefore); } if (err == Z_STREAM_END) err = ZIP_OK; /* this is normal */ if ((zi->ci.pos_in_buffered_data > 0) && (err == ZIP_OK)) if (zipFlushWriteBuffer (zi) == ZIP_ERRNO) err = ZIP_ERRNO; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { err = deflateEnd (&zi->ci.stream); zi->ci.stream_initialised = 0; } if (!zi->ci.raw) { crc32 = (uLong) zi->ci.crc32; uncompressed_size = (uLong) zi->ci.stream.total_in; } compressed_size = (uLong) zi->ci.stream.total_out; # ifndef NOCRYPT compressed_size += zi->ci.crypt_header_size; # endif ziplocal_putValue_inmemory (zi->ci.central_header + 16, crc32, 4); /* crc */ ziplocal_putValue_inmemory (zi->ci.central_header + 20, compressed_size, 4); /* compr size */ // FIX STATMAT - 09/04/05 // Had to comment out this setting of ASCII file type. Results // differed on different platforms. Windows would sometimes set // this and SuSE Linux wouldn't. Rather than investigate // further, just simply removed it. // if (zi->ci.stream.data_type == Z_ASCII) // ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); // FIX STATMAT - 09/04/05 ziplocal_putValue_inmemory (zi->ci.central_header + 24, uncompressed_size, 4); /* uncompr size */ if (err == ZIP_OK) err = add_data_in_datablock (&zi->central_dir, zi->ci.central_header, (uLong) zi->ci.size_centralheader); free (zi->ci.central_header); if (err == ZIP_OK) { long cur_pos_inzip = ZTELL (zi->z_filefunc, zi->filestream); if (ZSEEK (zi->z_filefunc, zi->filestream, zi->ci.pos_local_header + 14, ZLIB_FILEFUNC_SEEK_SET) != 0) err = ZIP_ERRNO; if (err == ZIP_OK) err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, crc32, 4); /* crc 32, unknown */ if (err == ZIP_OK) /* compressed size, unknown */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, compressed_size, 4); if (err == ZIP_OK) /* uncompressed size, unknown */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, uncompressed_size, 4); if (ZSEEK (zi->z_filefunc, zi->filestream, cur_pos_inzip, ZLIB_FILEFUNC_SEEK_SET) != 0) err = ZIP_ERRNO; } zi->number_entry++; zi->in_opened_file_inzip = 0; return err; } extern int ZEXPORT zipCloseFileInZip (file) zipFile file; { return zipCloseFileInZipRaw (file, 0, 0); } extern int ZEXPORT zipClose (file, global_comment) zipFile file; const char *global_comment; { zip_internal *zi; int err = 0; uLong size_centraldir = 0; uLong centraldir_pos_inzip; uInt size_global_comment; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal *) file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); } if (global_comment == NULL) size_global_comment = 0; else size_global_comment = (uInt) strlen (global_comment); centraldir_pos_inzip = ZTELL (zi->z_filefunc, zi->filestream); if (err == ZIP_OK) { linkedlist_datablock_internal *ldi = zi->central_dir.first_block; while (ldi != NULL) { if ((err == ZIP_OK) && (ldi->filled_in_this_block > 0)) if (ZWRITE (zi->z_filefunc, zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) err = ZIP_ERRNO; size_centraldir += ldi->filled_in_this_block; ldi = ldi->next_datablock; } } free_datablock (zi->central_dir.first_block); if (err == ZIP_OK) /* Magic End */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) ENDHEADERMAGIC, 4); if (err == ZIP_OK) /* number of this disk */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 0, 2); if (err == ZIP_OK) /* number of the disk with the start of the central directory */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) 0, 2); if (err == ZIP_OK) /* total number of entries in the central dir on this disk */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) zi->number_entry, 2); if (err == ZIP_OK) /* total number of entries in the central dir */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) zi->number_entry, 2); if (err == ZIP_OK) /* size of the central directory */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) size_centraldir, 4); if (err == ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) (centraldir_pos_inzip - zi->add_position_when_writting_offset), 4); if (err == ZIP_OK) /* zipfile comment length */ err = ziplocal_putValue (&zi->z_filefunc, zi->filestream, (uLong) size_global_comment, 2); if ((err == ZIP_OK) && (size_global_comment > 0)) if (ZWRITE (zi->z_filefunc, zi->filestream, global_comment, size_global_comment) != size_global_comment) err = ZIP_ERRNO; if (ZCLOSE (zi->z_filefunc, zi->filestream) != 0) if (err == ZIP_OK) err = ZIP_ERRNO; TRYFREE (zi); return err; }