/* zipAlreadyThere() set functions for a set of zero-terminated strings, and // a block_t type for reading the central directory datablocks. */ typedefchar*set_key_t; #defineset_cmp(a,b)strcmp(a,b) #defineset_drop(s,k)set_free(s,k) #include"skipset.h" typedefstruct{
unsigned char *next; /* next byte in datablock data */
size_t left; /* number of bytes left in data (at least) */
linkedlist_datablock_internal *node; /* current datablock */
} block_t;
int stream_initialised; /* 1 is stream is initialised */
uInt pos_in_buffered_data; /* last written byte in buffered_data */
ZPOS64_T pos_local_header; /* offset of the local header of the file
currently writing */ char* central_header; /* central header data for the current file */
uLong size_centralExtra;
uLong size_centralheader; /* size of the central header for cur file */
uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
uLong flag; /* flag of the file currently writing */
int method; /* compression method of file currently wr.*/ int raw; /* 1 for directly writing raw data */
Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
uLong dosDate;
uLong crc32; int encrypt; int zip64; /* Add ZIP64 extended information in the extra field */
ZPOS64_T pos_zip64extrainfo;
ZPOS64_T totalCompressedData;
ZPOS64_T totalUncompressedData; #ifndef NOCRYPT unsignedlong keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; unsigned crypt_header_size; #endif
} curfile64_info;
typedefstruct
{
zlib_filefunc64_32_def z_filefunc;
voidpf filestream; /* io structure of the zipfile */
linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
curfile64_info ci; /* info on the file currently writing */
ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
ZPOS64_T add_position_when_writing_offset;
ZPOS64_T number_entry;
/* zipAlreadyThere() operations. "set" in the zip internal structure keeps the // set of names that are in the under-construction central directory so far. A // skipset provides ~O(log n) time insertion and searching. Central directory // records, stored in a linked list of allocated memory datablocks, is read // through "block" in the zip internal structure.
// The block_*() functions support extracting the central directory file names // from the datablocks. They are designed to support a growing directory by // automatically continuing once more data has been appended to the linked // datablocks.
// Initialize *block to the head of list. This should only be called once the // list has at least some data in it, i.e. list->first_block is not NULL. */ localvoidblock_init(block_t*block,linkedlist_data*list){ block->node=list->first_block; block->next=block->node->data; block->left=block->node->filled_in_this_block; }
/* Mark *block as bad, with all subsequent reads returning end, even if more // data is added to the datablocks. This is invoked if the central directory is // invalid, so there is no longer any point in attempting to interpret it. */ localvoidblock_stop(block_t*block){ block->left=0; block->next=NULL; }
/* Return true if *block has reached the end of the data in the datablocks. */
local int block_end(block_t *block) {
linkedlist_datablock_internal *node = block->node; if (node == NULL) /* This block was previously terminated with extreme prejudice. */ return1; if (block->next < node->data + node->filled_in_this_block) /* There are more bytes to read in the current datablock. */ return0; while (node->next_datablock != NULL) { if (node->filled_in_this_block != 0) /* There are some bytes in a later datablock. */ return0;
node = node->next_datablock;
} /* Reached the end of the list of datablocks. There's nothing. */ return1;
}
/* Return one byte from *block, or -1 if the end is reached. */
local int block_get(block_t *block) { while (block->left == 0) { if (block->node == NULL) /* We've been marked bad. Return end. */ return -1; /* Update left in case more was filled in since we were last here. */
block->left = block->node->filled_in_this_block -
(size_t)(block->next - block->node->data); if (block->left != 0) /* There was indeed more data appended in the current datablock. */ break; if (block->node->next_datablock == NULL) /* No more data here, and there is no next datablock. At the end. */ return -1; /* Try the next datablock for more data. */
block->node = block->node->next_datablock;
block->next = block->node->data;
block->left = block->node->filled_in_this_block;
} /* We have a byte to return. */
block->left--; return *block->next++;
}
/* Return a 16-bit unsigned little-endian value from block, or a negative value // if the end is reached. */ locallongblock_get2(block_t*block){ intlow=block_get(block); inthigh=block_get(block); returnlow<0||high<0?-1:low|((long)high<<8); }
/* Read up to len bytes from block into buf. Return the number of bytes read. */
local size_t block_read(block_t *block, unsignedchar *buf, size_t len) {
size_t need = len; while (need) { if (block->left == 0) { /* Get a byte to update and step through the linked list as needed. */ int got = block_get(block); if (got == -1) /* Reached the end. */ break;
*buf++ = (unsignedchar)got;
need--; continue;
}
size_t take = need > block->left ? block->left : need;
memcpy(buf, block->next, take);
block->next += take;
block->left -= take;
buf += take;
need -= take;
} return len - need; /* return the number of bytes copied */
}
/* Skip n bytes in block. Return 0 on success or -1 if there are less than n // bytes to the end. */ localintblock_skip(block_t*block,size_tn){ while(n>block->left){ n-=block->left; block->next+=block->left; block->left=0; if(block_get(block)==-1) return-1; n--; } block->next+=n; block->left-=n; return0; }
/* Process the next central directory record at *block. Return the allocated, // zero-terminated file name, or NULL for end of input or invalid data. If // invalid, *block is marked bad. This uses *set for the allocation of memory. */ localchar*block_central_name(block_t*block,set_t*set){ char*name=NULL; for(;;){ if(block_end(block))
/* At the end of the central directory (so far). */ return NULL;
/* Check for a central directory record signature. */ if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) ||
block_get2(block) != (CENTRALHEADERMAGIC >> 16)) /* Incorrect signature. */ break;
/* Go through the remaining fixed-length portion of the record,
// extracting the lengths of the three variable-length fields. */
block_skip(block, 24); unsigned flen = (unsigned)block_get2(block); /* file name length */ unsigned xlen = (unsigned)block_get2(block); /* extra length */ unsigned clen = (unsigned)block_get2(block); /* comment length */ if (block_skip(block, 12) == -1) /* Premature end of the record. */ break;
/* Extract the name and skip over the extra and comment fields. */
name = set_alloc(set, NULL, flen + 1); if (block_read(block, (unsignedchar *)name, flen) < flen ||
block_skip(block, xlen + clen) == -1) /* Premature end of the record. */ break;
/* Check for embedded nuls in the name. */ if (memchr(name, 0, flen) != NULL) { /* This name can never match the zero-terminated name provided to // zipAlreadyThere(), so we discard it and go back to get another // name. (Who the heck is putting nuls inside their zip file entry
// names anyway?) */
set_free(set, name); continue;
}
/* All good. Return the zero-terminated file name. */
name[flen] = 0; return name;
}
/* Invalid signature or premature end of the central directory record.
// Abandon trying to process the central directory. */
set_free(set, name);
block_stop(block); return NULL;
}
/* Return 0 if name is not in the central directory so far, 1 if it is, -1 if // the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if // file is NULL. */ externintZEXPORTzipAlreadyThere(zipFilefile,charconst*name){ zip64_internal*zip=file; if(zip==NULL) returnZIP_PARAMERROR; if(zip->central_dir.first_block==NULL)
/* No central directory yet, so no, name isn't there. */ return0; if (setjmp(zip->set.env)) { /* Memory allocation failure. */
set_end(&zip->set); return -2;
} if (!set_ok(&zip->set)) { /* This is the first time here with some central directory content. We
// construct this set of names only on demand. Prepare set and block. */
set_start(&zip->set);
block_init(&zip->block, &zip->central_dir);
}
/* Update the set of names from the current central directory contents. // This reads any new central directory records since the last time we were
// here. */ for (;;) { char *there = block_central_name(&zip->block, &zip->set); if (there == NULL) { if (zip->block.next == NULL) /* The central directory is invalid. */ return -1; break;
}
/* Add there to the set. */ if (set_insert(&zip->set, there)) /* There's already a duplicate in the central directory! We'll just
// let this be and carry on. */
set_free(&zip->set, there);
}
/* Return true if name is in the central directory. */
size_t len = strlen(name); char *copy = set_alloc(&zip->set, NULL, len + 1);
memcpy(copy, name, len + 1); int found = set_found(&zip->set, copy);
set_free(&zip->set, copy); return found;
}
local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { unsignedchar c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1)
{
*pi = (int)c; return ZIP_OK;
} else
{ if (ZERROR64(*pzlib_filefunc_def,filestream)) return ZIP_ERRNO; else return ZIP_EOF;
}
}
/* =========================================================================== ReadsalonginLSBorderfromthegivengz_stream.Sets
*/
local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
uLong x ; int i = 0; int err;
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
x = (uLong)i;
if (err==ZIP_OK)
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
x += ((uLong)i)<<8;
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break;
for (i=(int)uReadSize-3; (i--)>0;)
{ /* Signature "0x07064b50" Zip64 end of central directory locator */ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
{
uPosFound = uReadPos+(unsigned)i; break;
}
}
if (uPosFound!=0) break;
}
free(buf); if (uPosFound == 0) return0;
/* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) return0;
/* the signature, already checked */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return0;
/* number of the disk with the start of the zip64 end of central directory */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return0; if (uL != 0) return0;
/* relative offset of the zip64 end of central directory record */ if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) return0;
/* total number of disks */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return0; if (uL != 1) return0;
/* Goto Zip64 end of central directory record */ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) return0;
/* the signature */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return0;
if (uL != 0x06064b50) /* signature of 'Zip64 end of central directory' */ return0;
return relativeOffset;
}
local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK;
ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
ZPOS64_T size_central_dir; /* size of the central directory */
ZPOS64_T offset_central_dir; /* offset of start of central directory */
ZPOS64_T central_pos;
uLong uL;
uLong number_disk; /* number of the current disk, used for
spanning ZIP, unsupported, always 0*/
uLong number_disk_with_CD; /* number of the disk with central dir, used
for spanning ZIP, unsupported, always 0*/
ZPOS64_T number_entry;
ZPOS64_T number_entry_CD; /* total number of entries in thecentraldir
(same than number_entry on nospan) */
uLong VersionMadeBy;
uLong VersionNeeded;
uLong size_comment;
int hasZIP64Record = 0;
/* check first if we find a ZIP64 record */
central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); if(central_pos > 0)
{
hasZIP64Record = 1;
} elseif(central_pos == 0)
{
central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
}
/* disable to allow appending to empty ZIP archive if(central_pos==0) err=ZIP_ERRNO;
*/
/* the signature, already checked */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
err=ZIP_ERRNO;
/* size of zip64 end of central directory record */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)
err=ZIP_ERRNO;
/* version made by */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)
err=ZIP_ERRNO;
/* version needed to extract */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)
err=ZIP_ERRNO;
/* number of this disk */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
err=ZIP_ERRNO;
/* number of the disk with the start of the central directory */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
err=ZIP_ERRNO;
/* total number of entries in the central directory on this disk */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)
err=ZIP_ERRNO;
/* total number of entries in the central directory */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->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 (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)
err=ZIP_ERRNO;
/* offset of start of central directory with respect to the
starting disk number */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)
err=ZIP_ERRNO;
/* TODO..
// read the comment from the standard central header. */
size_comment = 0;
} else
{ /* Read End of central Directory info */ if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
err=ZIP_ERRNO;
/* the signature, already checked */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
err=ZIP_ERRNO;
/* number of this disk */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
err=ZIP_ERRNO;
/* number of the disk with the start of the central directory */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
err=ZIP_ERRNO;
/* total number of entries in the central dir on this disk */
number_entry = 0; if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
err=ZIP_ERRNO; else
number_entry = uL;
/* total number of entries in the central dir */
number_entry_CD = 0; if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
err=ZIP_ERRNO; else
number_entry_CD = uL;
if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
err=ZIP_BADZIPFILE;
/* size of the central directory */
size_central_dir = 0; if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
err=ZIP_ERRNO; else
size_central_dir = uL;
/* offset of start of central directory with respect to the starting disk number */
offset_central_dir = 0; if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
err=ZIP_ERRNO; else
offset_central_dir = uL;
/* zipfile global comment length */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->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)
{
ZCLOSE64(pziinit->z_filefunc, pziinit->filestream); return ZIP_ERRNO;
}
if (size_comment>0)
{
pziinit->globalcomment = (char*)ALLOC(size_comment+1); if (pziinit->globalcomment)
{
size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
pziinit->globalcomment[size_comment]=0;
}
}
/* now we add file in a zipfile */ # ifndef NO_ADDFILEINEXISTINGZIP
zi->globalcomment = NULL; if (append == APPEND_STATUS_ADDINZIP)
{ /* Read and Cache Central Directory Records */
err = LoadCentralDirectoryRecord(zi);
}
if (err==ZIP_OK)
{ if(zi->ci.zip64)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
}
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
/* CRC / Compressed size / Uncompressed size will be filled in later and rewritten later */ if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ if (err==ZIP_OK)
{ if(zi->ci.zip64)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
} if (err==ZIP_OK)
{ if(zi->ci.zip64)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
}
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
if(zi->ci.zip64)
{
size_extrafield += 20;
}
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
if ((err==ZIP_OK) && (size_filename > 0))
{ if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
err = ZIP_ERRNO;
}
if ((err==ZIP_OK) && (size_extrafield_local > 0))
{ if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
err = ZIP_ERRNO;
}
if ((err==ZIP_OK) && (zi->ci.zip64))
{ /* write the Zip64 extended info */ short HeaderID = 1; short DataSize = 16;
ZPOS64_T CompressedSize = 0;
ZPOS64_T UncompressedSize = 0;
/* Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) */
zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
/* Return the length of the UTF-8 code at str[0..len-1] in [1..4], or negative ifthereisnovalidUTF-8codethere.Ifnegative,itisminusthenumber ofbytesexaminedinordertodetermineitwasbad.Orifminusthereturn codeisonelessthanlen,thenatleastonemorebytethanprovidedwould
be needed to complete the code. */
local int utf8len(unsignedcharconst *str, size_t len) { return
len == 0 ? -1 : /* empty input */
str[0] < 0x80 ? 1 : /* good one-byte */
str[0] < 0xc0 ? -1 : /* bad first byte */
len < 2 || (str[1] >> 6) != 2 ? -2 : /* missing or bad 2nd byte */
str[0] < 0xc2 ? -2 : /* overlong code */
str[0] < 0xe0 ? 2 : /* good two-byte */
len < 3 || (str[2] >> 6) != 2 ? -3 : /* missing or bad 3rd byte */
str[0] == 0xe0 && str[1] < 0xa0 ? -3 : /* overlong code */
str[0] < 0xf0 ? 3 : /* good three-byte */
len < 4 || (str[3] >> 6) != 2 ? -4 : /* missing or bad 4th byte */
str[0] == 0xf0 && str[1] < 0x90 ? -4 : /* overlong code */
str[0] < 0xf4 ||
(str[0] == 0xf4 && str[1] < 0x90) ? 4 : /* good four-byte */
-4; /* code > 0x10ffff */
}
/* Return true if str[0..len-1] is valid UTF-8 *and* it contains at least one codeoftwoormorebytes.Thisisusedtodeterminewhetherornottoset
bit 11 in the zip header flags. */
local int isutf8(charconst *str, size_t len) { int utf8 = 0; while (len) { int code = utf8len((unsignedcharconst *)str, len); if (code < 0) return0; if (code > 1)
utf8 = 1;
str += code;
len -= (unsigned)code;
} return utf8;
}
#ifdef HAVE_BZIP2 if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) return ZIP_PARAMERROR; #else if ((method!=0) && (method!=Z_DEFLATED)) return ZIP_PARAMERROR; #endif
/* The filename and comment length must fit in 16 bits. */ if ((filename!=NULL) && (strlen(filename)>0xffff)) return ZIP_PARAMERROR; if ((comment!=NULL) && (strlen(comment)>0xffff)) return ZIP_PARAMERROR; /* The extra field length must fit in 16 bits. If the member also requires // a Zip64 extra block, that will also need to fit within that 16-bit
// length, but that will be checked for later. */ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff)) return ZIP_PARAMERROR;
zi = (zip64_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);
zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
zi->ci.size_centralExtraFree = 32; /* Extra space we have reserved in case we need to add ZIP64 extra info data */
if (zipfi==NULL)
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); else
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
if (zipfi==NULL)
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); else
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
/* set internal file attributes field */ if (zi->ci.stream.data_type == Z_ASCII)
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
/* Add ZIP64 extra info field for uncompressed size */ if(uncompressed_size >= 0xffffffff)
datasize += 8;
/* Add ZIP64 extra info field for compressed size */ if(compressed_size >= 0xffffffff)
datasize += 8;
/* Add ZIP64 extra info field for relative offset to local file header of current file */ if(zi->ci.pos_local_header >= 0xffffffff)
datasize += 8;
if(datasize > 0)
{ char* p = NULL;
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
{ /* we cannot write more data to the buffer that we have room for. */ return ZIP_BADZIPFILE;
}
p = zi->ci.central_header + zi->ci.size_centralheader;
/* Add Extra Information Header for 'ZIP64 information' */
zip64local_putValue_inmemory(p, 0x0001, 2); /* HeaderID */
p += 2;
zip64local_putValue_inmemory(p, datasize, 2); /* DataSize */
p += 2;
/* Update how much extra free space we got in the memory buffer // and increase the centralheader size so the new ZIP64 fields are included
// ( 4 below is the size of HeaderID and DataSize field ) */
zi->ci.size_centralExtraFree -= datasize + 4;
zi->ci.size_centralheader += datasize + 4;
/* Update the extra info size field */
zi->ci.size_centralExtra += datasize + 4;
zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
}
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)
{ /* Update the LocalFileHeader with the new values. */
/*num disks*/ if (err==ZIP_OK) /* number of the disk with the start of the central directory */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
/*relative offset*/ if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
/*total disks*/ /* Do not support spawning of disk so always say 1 here*/ if (err==ZIP_OK) /* number of the disk with the start of the central directory */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
return err;
}
local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK;
if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); /* why ZPOS64_T of this ? */
if (err==ZIP_OK) /* version made by */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
if (err==ZIP_OK) /* version needed */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
if (err==ZIP_OK) /* number of this disk */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
if (err==ZIP_OK) /* total number of entries in the central dir */
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
if (err==ZIP_OK) /* size of the central directory */
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
{
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
} return err;
}
local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK;
if (err==ZIP_OK) /* number of this disk */
err = zip64local_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 = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
{
{ if(zi->number_entry >= 0xFFFF)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
}
}
if (err==ZIP_OK) /* total number of entries in the central dir */
{ if(zi->number_entry >= 0xFFFF)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
}
if (err==ZIP_OK) /* size of the central directory */
err = zip64local_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 */
{
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff)
{
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
} else
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
}
return err;
}
local int Write_GlobalComment(zip64_internal* zi, constchar* global_comment) { int err = ZIP_OK;
uInt size_global_comment = 0;
externint ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; char* pTmp; short header; short dataSize;
if( header == sHeader ) /* Header found. */
{
p += dataSize + 4; /* skip it. do not copy to temp buffer */
} else
{ /* Extra Info block should not be removed, So copy it to the temp buffer. */
memcpy(pTmp, p, dataSize + 4);
p += dataSize + 4;
size += dataSize + 4;
}
}
if(size < *dataLen)
{ /* clean old extra info block. */
memset(pData,0, *dataLen);
/* copy the new extra info block over the old */ if(size > 0)
memcpy(pData, pNewHeader, size);
/* set the new extra info size */
*dataLen = size;
retVal = ZIP_OK;
} else
retVal = ZIP_ERRNO;
free(pNewHeader);
return retVal;
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.68Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.