Fossil SCM

Blame History Raw 2247 lines
1
/* zip.c -- IO on .zip files using zlib
2
part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html )
3
4
Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html )
5
6
Modifications for Zip64 support
7
Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com )
8
9
For more info read MiniZip_info.txt
10
11
Changes
12
Oct-2009 - Mathias Svensson - Remove old C style function prototypes
13
Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
14
Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
15
Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
16
It is used when recreating zip archive with RAW when deleting items from a zip.
17
ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
18
Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
19
Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
20
21
*/
22
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <time.h>
28
#ifndef ZLIB_CONST
29
# define ZLIB_CONST
30
#endif
31
#ifdef ZLIB_DLL
32
# undef ZLIB_DLL
33
#endif
34
#include "zlib.h"
35
#include "zip.h"
36
37
#ifdef STDC
38
# include <stddef.h>
39
#endif
40
#ifdef NO_ERRNO_H
41
extern int errno;
42
#else
43
# include <errno.h>
44
#endif
45
46
47
#ifndef local
48
# define local static
49
#endif
50
/* compile with -Dlocal if your debugger can't find static symbols */
51
52
#ifndef VERSIONMADEBY
53
# define VERSIONMADEBY (0x0) /* platform dependent */
54
#endif
55
56
#ifndef Z_BUFSIZE
57
#define Z_BUFSIZE (64*1024) /* (16384) */
58
#endif
59
60
#ifndef Z_MAXFILENAMEINZIP
61
#define Z_MAXFILENAMEINZIP (256)
62
#endif
63
64
#ifndef ALLOC
65
# define ALLOC(size) (malloc(size))
66
#endif
67
68
/*
69
#define SIZECENTRALDIRITEM (0x2e)
70
#define SIZEZIPLOCALHEADER (0x1e)
71
*/
72
73
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
74
75
76
/* NOT sure that this work on ALL platform */
77
#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
78
79
#ifndef SEEK_CUR
80
#define SEEK_CUR 1
81
#endif
82
83
#ifndef SEEK_END
84
#define SEEK_END 2
85
#endif
86
87
#ifndef SEEK_SET
88
#define SEEK_SET 0
89
#endif
90
91
#ifndef DEF_MEM_LEVEL
92
#if MAX_MEM_LEVEL >= 8
93
# define DEF_MEM_LEVEL 8
94
#else
95
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
96
#endif
97
#endif
98
const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - https://www.winimage.com/zLibDll/minizip.html";
99
100
101
#define SIZEDATA_INDATABLOCK (4096-(4*4))
102
103
#define LOCALHEADERMAGIC (0x04034b50)
104
#define CENTRALHEADERMAGIC (0x02014b50)
105
#define ENDHEADERMAGIC (0x06054b50)
106
#define ZIP64ENDHEADERMAGIC (0x6064b50)
107
#define ZIP64ENDLOCHEADERMAGIC (0x7064b50)
108
109
#define FLAG_LOCALHEADER_OFFSET (0x06)
110
#define CRC_LOCALHEADER_OFFSET (0x0e)
111
112
#define SIZECENTRALHEADER (0x2e) /* 46 */
113
114
typedef struct linkedlist_datablock_internal_s
115
{
116
struct linkedlist_datablock_internal_s* next_datablock;
117
uLong avail_in_this_block;
118
uLong filled_in_this_block;
119
uLong unused; /* for future use and alignment */
120
unsigned char data[SIZEDATA_INDATABLOCK];
121
} linkedlist_datablock_internal;
122
123
typedef struct linkedlist_data_s
124
{
125
linkedlist_datablock_internal* first_block;
126
linkedlist_datablock_internal* last_block;
127
} linkedlist_data;
128
129
130
/* zipAlreadyThere() set functions for a set of zero-terminated strings, and
131
// a block_t type for reading the central directory datablocks. */
132
typedef char *set_key_t;
133
#define set_cmp(a, b) strcmp(a, b)
134
#define set_drop(s, k) set_free(s, k)
135
#include "skipset.h"
136
typedef struct {
137
unsigned char *next; /* next byte in datablock data */
138
size_t left; /* number of bytes left in data (at least) */
139
linkedlist_datablock_internal *node; /* current datablock */
140
} block_t;
141
142
143
typedef struct
144
{
145
z_stream stream; /* zLib stream structure for inflate */
146
#ifdef HAVE_BZIP2
147
bz_stream bstream; /* bzLib stream structure for bziped */
148
#endif
149
150
int stream_initialised; /* 1 is stream is initialised */
151
uInt pos_in_buffered_data; /* last written byte in buffered_data */
152
153
ZPOS64_T pos_local_header; /* offset of the local header of the file
154
currently writing */
155
char* central_header; /* central header data for the current file */
156
uLong size_centralExtra;
157
uLong size_centralheader; /* size of the central header for cur file */
158
uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
159
uLong flag; /* flag of the file currently writing */
160
161
int method; /* compression method of file currently wr.*/
162
int raw; /* 1 for directly writing raw data */
163
Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
164
uLong dosDate;
165
uLong crc32;
166
int encrypt;
167
int zip64; /* Add ZIP64 extended information in the extra field */
168
ZPOS64_T pos_zip64extrainfo;
169
ZPOS64_T totalCompressedData;
170
ZPOS64_T totalUncompressedData;
171
#ifndef NOCRYPT
172
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
173
const z_crc_t* pcrc_32_tab;
174
unsigned crypt_header_size;
175
#endif
176
} curfile64_info;
177
178
typedef struct
179
{
180
zlib_filefunc64_32_def z_filefunc;
181
voidpf filestream; /* io structure of the zipfile */
182
linkedlist_data central_dir;/* datablock with central dir in construction*/
183
int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
184
curfile64_info ci; /* info on the file currently writing */
185
186
ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
187
ZPOS64_T add_position_when_writing_offset;
188
ZPOS64_T number_entry;
189
190
#ifndef NO_ADDFILEINEXISTINGZIP
191
char *globalcomment;
192
#endif
193
194
/* Support for zipAlreadyThere(). */
195
set_t set; /* set for detecting name collisions */
196
block_t block; /* block for reading the central directory */
197
198
} zip64_internal;
199
200
201
#ifndef NOCRYPT
202
#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
203
#include "crypt.h"
204
#endif
205
206
local linkedlist_datablock_internal* allocate_new_datablock(void) {
207
linkedlist_datablock_internal* ldi;
208
ldi = (linkedlist_datablock_internal*)
209
ALLOC(sizeof(linkedlist_datablock_internal));
210
if (ldi!=NULL)
211
{
212
ldi->next_datablock = NULL ;
213
ldi->filled_in_this_block = 0 ;
214
ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
215
}
216
return ldi;
217
}
218
219
local void free_datablock(linkedlist_datablock_internal* ldi) {
220
while (ldi!=NULL)
221
{
222
linkedlist_datablock_internal* ldinext = ldi->next_datablock;
223
free(ldi);
224
ldi = ldinext;
225
}
226
}
227
228
local void init_linkedlist(linkedlist_data* ll) {
229
ll->first_block = ll->last_block = NULL;
230
}
231
232
local void free_linkedlist(linkedlist_data* ll) {
233
free_datablock(ll->first_block);
234
ll->first_block = ll->last_block = NULL;
235
}
236
237
238
local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) {
239
linkedlist_datablock_internal* ldi;
240
const unsigned char* from_copy;
241
242
if (ll==NULL)
243
return ZIP_INTERNALERROR;
244
245
if (ll->last_block == NULL)
246
{
247
ll->first_block = ll->last_block = allocate_new_datablock();
248
if (ll->first_block == NULL)
249
return ZIP_INTERNALERROR;
250
}
251
252
ldi = ll->last_block;
253
from_copy = (const unsigned char*)buf;
254
255
while (len>0)
256
{
257
uInt copy_this;
258
uInt i;
259
unsigned char* to_copy;
260
261
if (ldi->avail_in_this_block==0)
262
{
263
ldi->next_datablock = allocate_new_datablock();
264
if (ldi->next_datablock == NULL)
265
return ZIP_INTERNALERROR;
266
ldi = ldi->next_datablock ;
267
ll->last_block = ldi;
268
}
269
270
if (ldi->avail_in_this_block < len)
271
copy_this = (uInt)ldi->avail_in_this_block;
272
else
273
copy_this = (uInt)len;
274
275
to_copy = &(ldi->data[ldi->filled_in_this_block]);
276
277
for (i=0;i<copy_this;i++)
278
*(to_copy+i)=*(from_copy+i);
279
280
ldi->filled_in_this_block += copy_this;
281
ldi->avail_in_this_block -= copy_this;
282
from_copy += copy_this ;
283
len -= copy_this;
284
}
285
return ZIP_OK;
286
}
287
288
/* zipAlreadyThere() operations. "set" in the zip internal structure keeps the
289
// set of names that are in the under-construction central directory so far. A
290
// skipset provides ~O(log n) time insertion and searching. Central directory
291
// records, stored in a linked list of allocated memory datablocks, is read
292
// through "block" in the zip internal structure.
293
294
// The block_*() functions support extracting the central directory file names
295
// from the datablocks. They are designed to support a growing directory by
296
// automatically continuing once more data has been appended to the linked
297
// datablocks.
298
299
// Initialize *block to the head of list. This should only be called once the
300
// list has at least some data in it, i.e. list->first_block is not NULL. */
301
local void block_init(block_t *block, linkedlist_data *list) {
302
block->node = list->first_block;
303
block->next = block->node->data;
304
block->left = block->node->filled_in_this_block;
305
}
306
307
/* Mark *block as bad, with all subsequent reads returning end, even if more
308
// data is added to the datablocks. This is invoked if the central directory is
309
// invalid, so there is no longer any point in attempting to interpret it. */
310
local void block_stop(block_t *block) {
311
block->left = 0;
312
block->next = NULL;
313
}
314
315
/* Return true if *block has reached the end of the data in the datablocks. */
316
local int block_end(block_t *block) {
317
linkedlist_datablock_internal *node = block->node;
318
if (node == NULL)
319
/* This block was previously terminated with extreme prejudice. */
320
return 1;
321
if (block->next < node->data + node->filled_in_this_block)
322
/* There are more bytes to read in the current datablock. */
323
return 0;
324
while (node->next_datablock != NULL) {
325
if (node->filled_in_this_block != 0)
326
/* There are some bytes in a later datablock. */
327
return 0;
328
node = node->next_datablock;
329
}
330
/* Reached the end of the list of datablocks. There's nothing. */
331
return 1;
332
}
333
334
/* Return one byte from *block, or -1 if the end is reached. */
335
local int block_get(block_t *block) {
336
while (block->left == 0) {
337
if (block->node == NULL)
338
/* We've been marked bad. Return end. */
339
return -1;
340
/* Update left in case more was filled in since we were last here. */
341
block->left = block->node->filled_in_this_block -
342
(size_t)(block->next - block->node->data);
343
if (block->left != 0)
344
/* There was indeed more data appended in the current datablock. */
345
break;
346
if (block->node->next_datablock == NULL)
347
/* No more data here, and there is no next datablock. At the end. */
348
return -1;
349
/* Try the next datablock for more data. */
350
block->node = block->node->next_datablock;
351
block->next = block->node->data;
352
block->left = block->node->filled_in_this_block;
353
}
354
/* We have a byte to return. */
355
block->left--;
356
return *block->next++;
357
}
358
359
/* Return a 16-bit unsigned little-endian value from block, or a negative value
360
// if the end is reached. */
361
local long block_get2(block_t *block) {
362
int low = block_get(block);
363
int high = block_get(block);
364
return low < 0 || high < 0 ? -1 : low | ((long)high << 8);
365
}
366
367
/* Read up to len bytes from block into buf. Return the number of bytes read. */
368
local size_t block_read(block_t *block, unsigned char *buf, size_t len) {
369
size_t need = len;
370
while (need) {
371
if (block->left == 0) {
372
/* Get a byte to update and step through the linked list as needed. */
373
int got = block_get(block);
374
if (got == -1)
375
/* Reached the end. */
376
break;
377
*buf++ = (unsigned char)got;
378
need--;
379
continue;
380
}
381
size_t take = need > block->left ? block->left : need;
382
memcpy(buf, block->next, take);
383
block->next += take;
384
block->left -= take;
385
buf += take;
386
need -= take;
387
}
388
return len - need; /* return the number of bytes copied */
389
}
390
391
/* Skip n bytes in block. Return 0 on success or -1 if there are less than n
392
// bytes to the end. */
393
local int block_skip(block_t *block, size_t n) {
394
while (n > block->left) {
395
n -= block->left;
396
block->next += block->left;
397
block->left = 0;
398
if (block_get(block) == -1)
399
return -1;
400
n--;
401
}
402
block->next += n;
403
block->left -= n;
404
return 0;
405
}
406
407
/* Process the next central directory record at *block. Return the allocated,
408
// zero-terminated file name, or NULL for end of input or invalid data. If
409
// invalid, *block is marked bad. This uses *set for the allocation of memory. */
410
local char *block_central_name(block_t *block, set_t *set) {
411
char *name = NULL;
412
for (;;) {
413
if (block_end(block))
414
/* At the end of the central directory (so far). */
415
return NULL;
416
417
/* Check for a central directory record signature. */
418
if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) ||
419
block_get2(block) != (CENTRALHEADERMAGIC >> 16))
420
/* Incorrect signature. */
421
break;
422
423
/* Go through the remaining fixed-length portion of the record,
424
// extracting the lengths of the three variable-length fields. */
425
block_skip(block, 24);
426
unsigned flen = (unsigned)block_get2(block); /* file name length */
427
unsigned xlen = (unsigned)block_get2(block); /* extra length */
428
unsigned clen = (unsigned)block_get2(block); /* comment length */
429
if (block_skip(block, 12) == -1)
430
/* Premature end of the record. */
431
break;
432
433
/* Extract the name and skip over the extra and comment fields. */
434
name = set_alloc(set, NULL, flen + 1);
435
if (block_read(block, (unsigned char *)name, flen) < flen ||
436
block_skip(block, xlen + clen) == -1)
437
/* Premature end of the record. */
438
break;
439
440
/* Check for embedded nuls in the name. */
441
if (memchr(name, 0, flen) != NULL) {
442
/* This name can never match the zero-terminated name provided to
443
// zipAlreadyThere(), so we discard it and go back to get another
444
// name. (Who the heck is putting nuls inside their zip file entry
445
// names anyway?) */
446
set_free(set, name);
447
continue;
448
}
449
450
/* All good. Return the zero-terminated file name. */
451
name[flen] = 0;
452
return name;
453
}
454
455
/* Invalid signature or premature end of the central directory record.
456
// Abandon trying to process the central directory. */
457
set_free(set, name);
458
block_stop(block);
459
return NULL;
460
}
461
462
/* Return 0 if name is not in the central directory so far, 1 if it is, -1 if
463
// the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if
464
// file is NULL. */
465
extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) {
466
zip64_internal *zip = file;
467
if (zip == NULL)
468
return ZIP_PARAMERROR;
469
if (zip->central_dir.first_block == NULL)
470
/* No central directory yet, so no, name isn't there. */
471
return 0;
472
if (setjmp(zip->set.env)) {
473
/* Memory allocation failure. */
474
set_end(&zip->set);
475
return -2;
476
}
477
if (!set_ok(&zip->set)) {
478
/* This is the first time here with some central directory content. We
479
// construct this set of names only on demand. Prepare set and block. */
480
set_start(&zip->set);
481
block_init(&zip->block, &zip->central_dir);
482
}
483
484
/* Update the set of names from the current central directory contents.
485
// This reads any new central directory records since the last time we were
486
// here. */
487
for (;;) {
488
char *there = block_central_name(&zip->block, &zip->set);
489
if (there == NULL) {
490
if (zip->block.next == NULL)
491
/* The central directory is invalid. */
492
return -1;
493
break;
494
}
495
496
/* Add there to the set. */
497
if (set_insert(&zip->set, there))
498
/* There's already a duplicate in the central directory! We'll just
499
// let this be and carry on. */
500
set_free(&zip->set, there);
501
}
502
503
/* Return true if name is in the central directory. */
504
size_t len = strlen(name);
505
char *copy = set_alloc(&zip->set, NULL, len + 1);
506
memcpy(copy, name, len + 1);
507
int found = set_found(&zip->set, copy);
508
set_free(&zip->set, copy);
509
return found;
510
}
511
512
513
/****************************************************************************/
514
515
#ifndef NO_ADDFILEINEXISTINGZIP
516
/* ===========================================================================
517
Inputs a long in LSB order to the given file
518
nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
519
*/
520
521
local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) {
522
unsigned char buf[8];
523
int n;
524
for (n = 0; n < nbByte; n++)
525
{
526
buf[n] = (unsigned char)(x & 0xff);
527
x >>= 8;
528
}
529
if (x != 0)
530
{ /* data overflow - hack for ZIP64 (X Roche) */
531
for (n = 0; n < nbByte; n++)
532
{
533
buf[n] = 0xff;
534
}
535
}
536
537
if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte)
538
return ZIP_ERRNO;
539
else
540
return ZIP_OK;
541
}
542
543
local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) {
544
unsigned char* buf=(unsigned char*)dest;
545
int n;
546
for (n = 0; n < nbByte; n++) {
547
buf[n] = (unsigned char)(x & 0xff);
548
x >>= 8;
549
}
550
551
if (x != 0)
552
{ /* data overflow - hack for ZIP64 */
553
for (n = 0; n < nbByte; n++)
554
{
555
buf[n] = 0xff;
556
}
557
}
558
}
559
560
/****************************************************************************/
561
562
563
local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) {
564
uLong year = (uLong)ptm->tm_year;
565
if (year>=1980)
566
year-=1980;
567
else if (year>=80)
568
year-=80;
569
return
570
(uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) |
571
(((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
572
}
573
574
575
/****************************************************************************/
576
577
local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) {
578
unsigned char c;
579
int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
580
if (err==1)
581
{
582
*pi = (int)c;
583
return ZIP_OK;
584
}
585
else
586
{
587
if (ZERROR64(*pzlib_filefunc_def,filestream))
588
return ZIP_ERRNO;
589
else
590
return ZIP_EOF;
591
}
592
}
593
594
595
/* ===========================================================================
596
Reads a long in LSB order from the given gz_stream. Sets
597
*/
598
local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
599
uLong x ;
600
int i = 0;
601
int err;
602
603
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
604
x = (uLong)i;
605
606
if (err==ZIP_OK)
607
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
608
x += ((uLong)i)<<8;
609
610
if (err==ZIP_OK)
611
*pX = x;
612
else
613
*pX = 0;
614
return err;
615
}
616
617
local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
618
uLong x ;
619
int i = 0;
620
int err;
621
622
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
623
x = (uLong)i;
624
625
if (err==ZIP_OK)
626
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
627
x += ((uLong)i)<<8;
628
629
if (err==ZIP_OK)
630
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
631
x += ((uLong)i)<<16;
632
633
if (err==ZIP_OK)
634
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
635
x += ((uLong)i)<<24;
636
637
if (err==ZIP_OK)
638
*pX = x;
639
else
640
*pX = 0;
641
return err;
642
}
643
644
645
local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) {
646
ZPOS64_T x;
647
int i = 0;
648
int err;
649
650
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
651
x = (ZPOS64_T)i;
652
653
if (err==ZIP_OK)
654
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
655
x += ((ZPOS64_T)i)<<8;
656
657
if (err==ZIP_OK)
658
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
659
x += ((ZPOS64_T)i)<<16;
660
661
if (err==ZIP_OK)
662
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
663
x += ((ZPOS64_T)i)<<24;
664
665
if (err==ZIP_OK)
666
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
667
x += ((ZPOS64_T)i)<<32;
668
669
if (err==ZIP_OK)
670
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
671
x += ((ZPOS64_T)i)<<40;
672
673
if (err==ZIP_OK)
674
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
675
x += ((ZPOS64_T)i)<<48;
676
677
if (err==ZIP_OK)
678
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
679
x += ((ZPOS64_T)i)<<56;
680
681
if (err==ZIP_OK)
682
*pX = x;
683
else
684
*pX = 0;
685
686
return err;
687
}
688
689
#ifndef BUFREADCOMMENT
690
#define BUFREADCOMMENT (0x400)
691
#endif
692
/*
693
Locate the Central directory of a zipfile (at the end, just before
694
the global comment)
695
*/
696
local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
697
unsigned char* buf;
698
ZPOS64_T uSizeFile;
699
ZPOS64_T uBackRead;
700
ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
701
ZPOS64_T uPosFound=0;
702
703
if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
704
return 0;
705
706
707
uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
708
709
if (uMaxBack>uSizeFile)
710
uMaxBack = uSizeFile;
711
712
buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
713
if (buf==NULL)
714
return 0;
715
716
uBackRead = 4;
717
while (uBackRead<uMaxBack)
718
{
719
uLong uReadSize;
720
ZPOS64_T uReadPos ;
721
int i;
722
if (uBackRead+BUFREADCOMMENT>uMaxBack)
723
uBackRead = uMaxBack;
724
else
725
uBackRead+=BUFREADCOMMENT;
726
uReadPos = uSizeFile-uBackRead ;
727
728
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
729
(BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
730
if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
731
break;
732
733
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
734
break;
735
736
for (i=(int)uReadSize-3; (i--)>0;)
737
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
738
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
739
{
740
uPosFound = uReadPos+(unsigned)i;
741
break;
742
}
743
744
if (uPosFound!=0)
745
break;
746
}
747
free(buf);
748
return uPosFound;
749
}
750
751
/*
752
Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
753
the global comment)
754
*/
755
local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
756
unsigned char* buf;
757
ZPOS64_T uSizeFile;
758
ZPOS64_T uBackRead;
759
ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
760
ZPOS64_T uPosFound=0;
761
uLong uL;
762
ZPOS64_T relativeOffset;
763
764
if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
765
return 0;
766
767
uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
768
769
if (uMaxBack>uSizeFile)
770
uMaxBack = uSizeFile;
771
772
buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
773
if (buf==NULL)
774
return 0;
775
776
uBackRead = 4;
777
while (uBackRead<uMaxBack)
778
{
779
uLong uReadSize;
780
ZPOS64_T uReadPos;
781
int i;
782
if (uBackRead+BUFREADCOMMENT>uMaxBack)
783
uBackRead = uMaxBack;
784
else
785
uBackRead+=BUFREADCOMMENT;
786
uReadPos = uSizeFile-uBackRead ;
787
788
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
789
(BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
790
if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
791
break;
792
793
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
794
break;
795
796
for (i=(int)uReadSize-3; (i--)>0;)
797
{
798
/* Signature "0x07064b50" Zip64 end of central directory locator */
799
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
800
{
801
uPosFound = uReadPos+(unsigned)i;
802
break;
803
}
804
}
805
806
if (uPosFound!=0)
807
break;
808
}
809
810
free(buf);
811
if (uPosFound == 0)
812
return 0;
813
814
/* Zip64 end of central directory locator */
815
if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
816
return 0;
817
818
/* the signature, already checked */
819
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
820
return 0;
821
822
/* number of the disk with the start of the zip64 end of central directory */
823
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
824
return 0;
825
if (uL != 0)
826
return 0;
827
828
/* relative offset of the zip64 end of central directory record */
829
if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)
830
return 0;
831
832
/* total number of disks */
833
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
834
return 0;
835
if (uL != 1)
836
return 0;
837
838
/* Goto Zip64 end of central directory record */
839
if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
840
return 0;
841
842
/* the signature */
843
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
844
return 0;
845
846
if (uL != 0x06064b50) /* signature of 'Zip64 end of central directory' */
847
return 0;
848
849
return relativeOffset;
850
}
851
852
local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
853
int err=ZIP_OK;
854
ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
855
856
ZPOS64_T size_central_dir; /* size of the central directory */
857
ZPOS64_T offset_central_dir; /* offset of start of central directory */
858
ZPOS64_T central_pos;
859
uLong uL;
860
861
uLong number_disk; /* number of the current disk, used for
862
spanning ZIP, unsupported, always 0*/
863
uLong number_disk_with_CD; /* number of the disk with central dir, used
864
for spanning ZIP, unsupported, always 0*/
865
ZPOS64_T number_entry;
866
ZPOS64_T number_entry_CD; /* total number of entries in
867
the central dir
868
(same than number_entry on nospan) */
869
uLong VersionMadeBy;
870
uLong VersionNeeded;
871
uLong size_comment;
872
873
int hasZIP64Record = 0;
874
875
/* check first if we find a ZIP64 record */
876
central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);
877
if(central_pos > 0)
878
{
879
hasZIP64Record = 1;
880
}
881
else if(central_pos == 0)
882
{
883
central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
884
}
885
886
/* disable to allow appending to empty ZIP archive
887
if (central_pos==0)
888
err=ZIP_ERRNO;
889
*/
890
891
if(hasZIP64Record)
892
{
893
ZPOS64_T sizeEndOfCentralDirectory;
894
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
895
err=ZIP_ERRNO;
896
897
/* the signature, already checked */
898
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
899
err=ZIP_ERRNO;
900
901
/* size of zip64 end of central directory record */
902
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)
903
err=ZIP_ERRNO;
904
905
/* version made by */
906
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)
907
err=ZIP_ERRNO;
908
909
/* version needed to extract */
910
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)
911
err=ZIP_ERRNO;
912
913
/* number of this disk */
914
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
915
err=ZIP_ERRNO;
916
917
/* number of the disk with the start of the central directory */
918
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
919
err=ZIP_ERRNO;
920
921
/* total number of entries in the central directory on this disk */
922
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)
923
err=ZIP_ERRNO;
924
925
/* total number of entries in the central directory */
926
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK)
927
err=ZIP_ERRNO;
928
929
if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
930
err=ZIP_BADZIPFILE;
931
932
/* size of the central directory */
933
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)
934
err=ZIP_ERRNO;
935
936
/* offset of start of central directory with respect to the
937
starting disk number */
938
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)
939
err=ZIP_ERRNO;
940
941
/* TODO..
942
// read the comment from the standard central header. */
943
size_comment = 0;
944
}
945
else
946
{
947
/* Read End of central Directory info */
948
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
949
err=ZIP_ERRNO;
950
951
/* the signature, already checked */
952
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
953
err=ZIP_ERRNO;
954
955
/* number of this disk */
956
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
957
err=ZIP_ERRNO;
958
959
/* number of the disk with the start of the central directory */
960
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
961
err=ZIP_ERRNO;
962
963
/* total number of entries in the central dir on this disk */
964
number_entry = 0;
965
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
966
err=ZIP_ERRNO;
967
else
968
number_entry = uL;
969
970
/* total number of entries in the central dir */
971
number_entry_CD = 0;
972
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
973
err=ZIP_ERRNO;
974
else
975
number_entry_CD = uL;
976
977
if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
978
err=ZIP_BADZIPFILE;
979
980
/* size of the central directory */
981
size_central_dir = 0;
982
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
983
err=ZIP_ERRNO;
984
else
985
size_central_dir = uL;
986
987
/* offset of start of central directory with respect to the starting disk number */
988
offset_central_dir = 0;
989
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
990
err=ZIP_ERRNO;
991
else
992
offset_central_dir = uL;
993
994
995
/* zipfile global comment length */
996
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK)
997
err=ZIP_ERRNO;
998
}
999
1000
if ((central_pos<offset_central_dir+size_central_dir) &&
1001
(err==ZIP_OK))
1002
err=ZIP_BADZIPFILE;
1003
1004
if (err!=ZIP_OK)
1005
{
1006
ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);
1007
return ZIP_ERRNO;
1008
}
1009
1010
if (size_comment>0)
1011
{
1012
pziinit->globalcomment = (char*)ALLOC(size_comment+1);
1013
if (pziinit->globalcomment)
1014
{
1015
size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
1016
pziinit->globalcomment[size_comment]=0;
1017
}
1018
}
1019
1020
byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
1021
pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
1022
1023
{
1024
ZPOS64_T size_central_dir_to_read = size_central_dir;
1025
size_t buf_size = SIZEDATA_INDATABLOCK;
1026
void* buf_read = (void*)ALLOC(buf_size);
1027
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
1028
err=ZIP_ERRNO;
1029
1030
while ((size_central_dir_to_read>0) && (err==ZIP_OK))
1031
{
1032
ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
1033
if (read_this > size_central_dir_to_read)
1034
read_this = size_central_dir_to_read;
1035
1036
if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)
1037
err=ZIP_ERRNO;
1038
1039
if (err==ZIP_OK)
1040
err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);
1041
1042
size_central_dir_to_read-=read_this;
1043
}
1044
free(buf_read);
1045
}
1046
pziinit->begin_pos = byte_before_the_zipfile;
1047
pziinit->number_entry = number_entry_CD;
1048
1049
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
1050
err=ZIP_ERRNO;
1051
1052
return err;
1053
}
1054
1055
1056
#endif /* !NO_ADDFILEINEXISTINGZIP*/
1057
1058
1059
/************************************************************/
1060
extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) {
1061
zip64_internal ziinit;
1062
zip64_internal* zi;
1063
int err=ZIP_OK;
1064
1065
ziinit.z_filefunc.zseek32_file = NULL;
1066
ziinit.z_filefunc.ztell32_file = NULL;
1067
if (pzlib_filefunc64_32_def==NULL)
1068
fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
1069
else
1070
ziinit.z_filefunc = *pzlib_filefunc64_32_def;
1071
1072
ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
1073
pathname,
1074
(append == APPEND_STATUS_CREATE) ?
1075
(ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
1076
(ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
1077
1078
if (ziinit.filestream == NULL)
1079
return NULL;
1080
1081
if (append == APPEND_STATUS_CREATEAFTER)
1082
ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
1083
1084
ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
1085
ziinit.in_opened_file_inzip = 0;
1086
ziinit.ci.stream_initialised = 0;
1087
ziinit.number_entry = 0;
1088
ziinit.add_position_when_writing_offset = 0;
1089
init_linkedlist(&(ziinit.central_dir));
1090
memset(&ziinit.set, 0, sizeof(set_t)); /* make sure set appears dormant */
1091
1092
1093
1094
zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
1095
if (zi==NULL)
1096
{
1097
ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
1098
return NULL;
1099
}
1100
1101
/* now we add file in a zipfile */
1102
# ifndef NO_ADDFILEINEXISTINGZIP
1103
ziinit.globalcomment = NULL;
1104
if (append == APPEND_STATUS_ADDINZIP)
1105
{
1106
/* Read and Cache Central Directory Records */
1107
err = LoadCentralDirectoryRecord(&ziinit);
1108
}
1109
1110
if (globalcomment)
1111
{
1112
*globalcomment = ziinit.globalcomment;
1113
}
1114
# endif /* !NO_ADDFILEINEXISTINGZIP*/
1115
1116
if (err != ZIP_OK)
1117
{
1118
# ifndef NO_ADDFILEINEXISTINGZIP
1119
free(ziinit.globalcomment);
1120
# endif /* !NO_ADDFILEINEXISTINGZIP*/
1121
free(zi);
1122
return NULL;
1123
}
1124
else
1125
{
1126
*zi = ziinit;
1127
return (zipFile)zi;
1128
}
1129
}
1130
1131
extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) {
1132
if (pzlib_filefunc32_def != NULL)
1133
{
1134
zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1135
fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
1136
return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1137
}
1138
else
1139
return zipOpen3(pathname, append, globalcomment, NULL);
1140
}
1141
1142
extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) {
1143
if (pzlib_filefunc_def != NULL)
1144
{
1145
zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1146
zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
1147
zlib_filefunc64_32_def_fill.zopen32_file = NULL;
1148
zlib_filefunc64_32_def_fill.ztell32_file = NULL;
1149
zlib_filefunc64_32_def_fill.zseek32_file = NULL;
1150
return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1151
}
1152
else
1153
return zipOpen3(pathname, append, globalcomment, NULL);
1154
}
1155
1156
1157
1158
extern zipFile ZEXPORT zipOpen(const char* pathname, int append) {
1159
return zipOpen3((const void*)pathname,append,NULL,NULL);
1160
}
1161
1162
extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) {
1163
return zipOpen3(pathname,append,NULL,NULL);
1164
}
1165
1166
local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) {
1167
/* write the local header */
1168
int err;
1169
uInt size_filename = (uInt)strlen(filename);
1170
uInt size_extrafield = size_extrafield_local;
1171
1172
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);
1173
1174
if (err==ZIP_OK)
1175
{
1176
if(zi->ci.zip64)
1177
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */
1178
else
1179
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
1180
}
1181
1182
if (err==ZIP_OK)
1183
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
1184
1185
if (err==ZIP_OK)
1186
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
1187
1188
if (err==ZIP_OK)
1189
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
1190
1191
/* CRC / Compressed size / Uncompressed size will be filled in later and rewritten later */
1192
if (err==ZIP_OK)
1193
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
1194
if (err==ZIP_OK)
1195
{
1196
if(zi->ci.zip64)
1197
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */
1198
else
1199
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
1200
}
1201
if (err==ZIP_OK)
1202
{
1203
if(zi->ci.zip64)
1204
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */
1205
else
1206
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
1207
}
1208
1209
if (err==ZIP_OK)
1210
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
1211
1212
if(zi->ci.zip64)
1213
{
1214
size_extrafield += 20;
1215
}
1216
1217
if (err==ZIP_OK)
1218
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
1219
1220
if ((err==ZIP_OK) && (size_filename > 0))
1221
{
1222
if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
1223
err = ZIP_ERRNO;
1224
}
1225
1226
if ((err==ZIP_OK) && (size_extrafield_local > 0))
1227
{
1228
if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
1229
err = ZIP_ERRNO;
1230
}
1231
1232
1233
if ((err==ZIP_OK) && (zi->ci.zip64))
1234
{
1235
/* write the Zip64 extended info */
1236
short HeaderID = 1;
1237
short DataSize = 16;
1238
ZPOS64_T CompressedSize = 0;
1239
ZPOS64_T UncompressedSize = 0;
1240
1241
/* Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) */
1242
zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
1243
1244
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
1245
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);
1246
1247
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
1248
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
1249
}
1250
1251
return err;
1252
}
1253
1254
/* Return the length of the UTF-8 code at str[0..len-1] in [1..4], or negative
1255
if there is no valid UTF-8 code there. If negative, it is minus the number
1256
of bytes examined in order to determine it was bad. Or if minus the return
1257
code is one less than len, then at least one more byte than provided would
1258
be needed to complete the code. */
1259
local int utf8len(unsigned char const *str, size_t len) {
1260
return
1261
len == 0 ? -1 : /* empty input */
1262
str[0] < 0x80 ? 1 : /* good one-byte */
1263
str[0] < 0xc0 ? -1 : /* bad first byte */
1264
len < 2 || (str[1] >> 6) != 2 ? -2 : /* missing or bad 2nd byte */
1265
str[0] < 0xc2 ? -2 : /* overlong code */
1266
str[0] < 0xe0 ? 2 : /* good two-byte */
1267
len < 3 || (str[2] >> 6) != 2 ? -3 : /* missing or bad 3rd byte */
1268
str[0] == 0xe0 && str[1] < 0xa0 ? -3 : /* overlong code */
1269
str[0] < 0xf0 ? 3 : /* good three-byte */
1270
len < 4 || (str[3] >> 6) != 2 ? -4 : /* missing or bad 4th byte */
1271
str[0] == 0xf0 && str[1] < 0x90 ? -4 : /* overlong code */
1272
str[0] < 0xf4 ||
1273
(str[0] == 0xf4 && str[1] < 0x90) ? 4 : /* good four-byte */
1274
-4; /* code > 0x10ffff */
1275
}
1276
1277
/* Return true if str[0..len-1] is valid UTF-8 *and* it contains at least one
1278
code of two or more bytes. This is used to determine whether or not to set
1279
bit 11 in the zip header flags. */
1280
local int isutf8(char const *str, size_t len) {
1281
int utf8 = 0;
1282
while (len) {
1283
int code = utf8len((unsigned char const *)str, len);
1284
if (code < 0)
1285
return 0;
1286
if (code > 1)
1287
utf8 = 1;
1288
str += code;
1289
len -= (unsigned)code;
1290
}
1291
return utf8;
1292
}
1293
1294
/*
1295
NOTE.
1296
When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
1297
before calling this function it can be done with zipRemoveExtraInfoBlock
1298
1299
It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
1300
unnecessary allocations.
1301
*/
1302
extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1303
const void* extrafield_local, uInt size_extrafield_local,
1304
const void* extrafield_global, uInt size_extrafield_global,
1305
const char* comment, int method, int level, int raw,
1306
int windowBits,int memLevel, int strategy,
1307
const char* password, uLong crcForCrypting,
1308
uLong versionMadeBy, uLong flagBase, int zip64) {
1309
zip64_internal* zi;
1310
uInt size_filename;
1311
uInt size_comment;
1312
uInt i;
1313
int err = ZIP_OK;
1314
1315
# ifdef NOCRYPT
1316
if (password != NULL)
1317
return ZIP_PARAMERROR;
1318
# endif
1319
1320
if (file == NULL)
1321
return ZIP_PARAMERROR;
1322
1323
#ifdef HAVE_BZIP2
1324
if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))
1325
return ZIP_PARAMERROR;
1326
#else
1327
if ((method!=0) && (method!=Z_DEFLATED))
1328
return ZIP_PARAMERROR;
1329
#endif
1330
1331
/* The filename and comment length must fit in 16 bits. */
1332
if ((filename!=NULL) && (strlen(filename)>0xffff))
1333
return ZIP_PARAMERROR;
1334
if ((comment!=NULL) && (strlen(comment)>0xffff))
1335
return ZIP_PARAMERROR;
1336
/* The extra field length must fit in 16 bits. If the member also requires
1337
// a Zip64 extra block, that will also need to fit within that 16-bit
1338
// length, but that will be checked for later. */
1339
if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
1340
return ZIP_PARAMERROR;
1341
1342
zi = (zip64_internal*)file;
1343
1344
if (zi->in_opened_file_inzip == 1)
1345
{
1346
err = zipCloseFileInZip (file);
1347
if (err != ZIP_OK)
1348
return err;
1349
}
1350
1351
if (filename==NULL)
1352
filename="-";
1353
1354
if (comment==NULL)
1355
size_comment = 0;
1356
else
1357
size_comment = (uInt)strlen(comment);
1358
1359
size_filename = (uInt)strlen(filename);
1360
1361
if (zipfi == NULL)
1362
zi->ci.dosDate = 0;
1363
else
1364
{
1365
if (zipfi->dosDate != 0)
1366
zi->ci.dosDate = zipfi->dosDate;
1367
else
1368
zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
1369
}
1370
1371
zi->ci.flag = flagBase;
1372
if ((level==8) || (level==9))
1373
zi->ci.flag |= 2;
1374
if (level==2)
1375
zi->ci.flag |= 4;
1376
if (level==1)
1377
zi->ci.flag |= 6;
1378
if (password != NULL)
1379
zi->ci.flag |= 1;
1380
if (isutf8(filename, size_filename) &&
1381
(size_comment == 0 || isutf8(comment, size_comment)))
1382
zi->ci.flag |= (1 << 11);
1383
1384
zi->ci.crc32 = 0;
1385
zi->ci.method = method;
1386
zi->ci.encrypt = 0;
1387
zi->ci.stream_initialised = 0;
1388
zi->ci.pos_in_buffered_data = 0;
1389
zi->ci.raw = raw;
1390
zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
1391
1392
zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
1393
zi->ci.size_centralExtraFree = 32; /* Extra space we have reserved in case we need to add ZIP64 extra info data */
1394
1395
zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
1396
1397
zi->ci.size_centralExtra = size_extrafield_global;
1398
zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
1399
/* version info */
1400
zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);
1401
zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
1402
zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
1403
zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
1404
zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
1405
zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
1406
zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
1407
zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
1408
zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
1409
zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
1410
zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
1411
zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
1412
1413
if (zipfi==NULL)
1414
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
1415
else
1416
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
1417
1418
if (zipfi==NULL)
1419
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
1420
else
1421
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
1422
1423
if(zi->ci.pos_local_header >= 0xffffffff)
1424
zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
1425
else
1426
zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4);
1427
1428
for (i=0;i<size_filename;i++)
1429
*(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
1430
1431
for (i=0;i<size_extrafield_global;i++)
1432
*(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
1433
*(((const char*)extrafield_global)+i);
1434
1435
for (i=0;i<size_comment;i++)
1436
*(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
1437
size_extrafield_global+i) = *(comment+i);
1438
if (zi->ci.central_header == NULL)
1439
return ZIP_INTERNALERROR;
1440
1441
zi->ci.zip64 = zip64;
1442
zi->ci.totalCompressedData = 0;
1443
zi->ci.totalUncompressedData = 0;
1444
zi->ci.pos_zip64extrainfo = 0;
1445
1446
err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);
1447
1448
#ifdef HAVE_BZIP2
1449
zi->ci.bstream.avail_in = (uInt)0;
1450
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1451
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1452
zi->ci.bstream.total_in_hi32 = 0;
1453
zi->ci.bstream.total_in_lo32 = 0;
1454
zi->ci.bstream.total_out_hi32 = 0;
1455
zi->ci.bstream.total_out_lo32 = 0;
1456
#endif
1457
1458
zi->ci.stream.avail_in = (uInt)0;
1459
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1460
zi->ci.stream.next_out = zi->ci.buffered_data;
1461
zi->ci.stream.total_in = 0;
1462
zi->ci.stream.total_out = 0;
1463
zi->ci.stream.data_type = Z_BINARY;
1464
1465
#ifdef HAVE_BZIP2
1466
if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1467
#else
1468
if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1469
#endif
1470
{
1471
if(zi->ci.method == Z_DEFLATED)
1472
{
1473
zi->ci.stream.zalloc = (alloc_func)0;
1474
zi->ci.stream.zfree = (free_func)0;
1475
zi->ci.stream.opaque = (voidpf)0;
1476
1477
if (windowBits>0)
1478
windowBits = -windowBits;
1479
1480
err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
1481
1482
if (err==Z_OK)
1483
zi->ci.stream_initialised = Z_DEFLATED;
1484
}
1485
else if(zi->ci.method == Z_BZIP2ED)
1486
{
1487
#ifdef HAVE_BZIP2
1488
/* Init BZip stuff here */
1489
zi->ci.bstream.bzalloc = 0;
1490
zi->ci.bstream.bzfree = 0;
1491
zi->ci.bstream.opaque = (voidpf)0;
1492
1493
err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);
1494
if(err == BZ_OK)
1495
zi->ci.stream_initialised = Z_BZIP2ED;
1496
#endif
1497
}
1498
1499
}
1500
1501
# ifndef NOCRYPT
1502
zi->ci.crypt_header_size = 0;
1503
if ((err==Z_OK) && (password != NULL))
1504
{
1505
unsigned char bufHead[RAND_HEAD_LEN];
1506
unsigned int sizeHead;
1507
zi->ci.encrypt = 1;
1508
zi->ci.pcrc_32_tab = get_crc_table();
1509
/*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
1510
1511
sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
1512
zi->ci.crypt_header_size = sizeHead;
1513
1514
if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
1515
err = ZIP_ERRNO;
1516
}
1517
# endif
1518
1519
if (err==Z_OK)
1520
zi->in_opened_file_inzip = 1;
1521
return err;
1522
}
1523
1524
extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1525
const void* extrafield_local, uInt size_extrafield_local,
1526
const void* extrafield_global, uInt size_extrafield_global,
1527
const char* comment, int method, int level, int raw,
1528
int windowBits,int memLevel, int strategy,
1529
const char* password, uLong crcForCrypting,
1530
uLong versionMadeBy, uLong flagBase) {
1531
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1532
extrafield_local, size_extrafield_local,
1533
extrafield_global, size_extrafield_global,
1534
comment, method, level, raw,
1535
windowBits, memLevel, strategy,
1536
password, crcForCrypting, versionMadeBy, flagBase, 0);
1537
}
1538
1539
extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1540
const void* extrafield_local, uInt size_extrafield_local,
1541
const void* extrafield_global, uInt size_extrafield_global,
1542
const char* comment, int method, int level, int raw,
1543
int windowBits,int memLevel, int strategy,
1544
const char* password, uLong crcForCrypting) {
1545
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1546
extrafield_local, size_extrafield_local,
1547
extrafield_global, size_extrafield_global,
1548
comment, method, level, raw,
1549
windowBits, memLevel, strategy,
1550
password, crcForCrypting, VERSIONMADEBY, 0, 0);
1551
}
1552
1553
extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1554
const void* extrafield_local, uInt size_extrafield_local,
1555
const void* extrafield_global, uInt size_extrafield_global,
1556
const char* comment, int method, int level, int raw,
1557
int windowBits,int memLevel, int strategy,
1558
const char* password, uLong crcForCrypting, int zip64) {
1559
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1560
extrafield_local, size_extrafield_local,
1561
extrafield_global, size_extrafield_global,
1562
comment, method, level, raw,
1563
windowBits, memLevel, strategy,
1564
password, crcForCrypting, VERSIONMADEBY, 0, zip64);
1565
}
1566
1567
extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1568
const void* extrafield_local, uInt size_extrafield_local,
1569
const void* extrafield_global, uInt size_extrafield_global,
1570
const char* comment, int method, int level, int raw) {
1571
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1572
extrafield_local, size_extrafield_local,
1573
extrafield_global, size_extrafield_global,
1574
comment, method, level, raw,
1575
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1576
NULL, 0, VERSIONMADEBY, 0, 0);
1577
}
1578
1579
extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1580
const void* extrafield_local, uInt size_extrafield_local,
1581
const void* extrafield_global, uInt size_extrafield_global,
1582
const char* comment, int method, int level, int raw, int zip64) {
1583
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1584
extrafield_local, size_extrafield_local,
1585
extrafield_global, size_extrafield_global,
1586
comment, method, level, raw,
1587
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1588
NULL, 0, VERSIONMADEBY, 0, zip64);
1589
}
1590
1591
extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1592
const void* extrafield_local, uInt size_extrafield_local,
1593
const void*extrafield_global, uInt size_extrafield_global,
1594
const char* comment, int method, int level, int zip64) {
1595
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1596
extrafield_local, size_extrafield_local,
1597
extrafield_global, size_extrafield_global,
1598
comment, method, level, 0,
1599
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1600
NULL, 0, VERSIONMADEBY, 0, zip64);
1601
}
1602
1603
extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1604
const void* extrafield_local, uInt size_extrafield_local,
1605
const void*extrafield_global, uInt size_extrafield_global,
1606
const char* comment, int method, int level) {
1607
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1608
extrafield_local, size_extrafield_local,
1609
extrafield_global, size_extrafield_global,
1610
comment, method, level, 0,
1611
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1612
NULL, 0, VERSIONMADEBY, 0, 0);
1613
}
1614
1615
local int zip64FlushWriteBuffer(zip64_internal* zi) {
1616
int err=ZIP_OK;
1617
1618
if (zi->ci.encrypt != 0)
1619
{
1620
#ifndef NOCRYPT
1621
uInt i;
1622
int t;
1623
for (i=0;i<zi->ci.pos_in_buffered_data;i++)
1624
zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
1625
#endif
1626
}
1627
1628
if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
1629
err = ZIP_ERRNO;
1630
1631
zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
1632
1633
#ifdef HAVE_BZIP2
1634
if(zi->ci.method == Z_BZIP2ED)
1635
{
1636
zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
1637
zi->ci.bstream.total_in_lo32 = 0;
1638
zi->ci.bstream.total_in_hi32 = 0;
1639
}
1640
else
1641
#endif
1642
{
1643
zi->ci.totalUncompressedData += zi->ci.stream.total_in;
1644
zi->ci.stream.total_in = 0;
1645
}
1646
1647
1648
zi->ci.pos_in_buffered_data = 0;
1649
1650
return err;
1651
}
1652
1653
extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) {
1654
zip64_internal* zi;
1655
int err=ZIP_OK;
1656
1657
if (file == NULL)
1658
return ZIP_PARAMERROR;
1659
zi = (zip64_internal*)file;
1660
1661
if (zi->in_opened_file_inzip == 0)
1662
return ZIP_PARAMERROR;
1663
1664
zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
1665
1666
#ifdef HAVE_BZIP2
1667
if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))
1668
{
1669
zi->ci.bstream.next_in = (void*)buf;
1670
zi->ci.bstream.avail_in = len;
1671
err = BZ_RUN_OK;
1672
1673
while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0))
1674
{
1675
if (zi->ci.bstream.avail_out == 0)
1676
{
1677
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1678
err = ZIP_ERRNO;
1679
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1680
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1681
}
1682
1683
1684
if(err != BZ_RUN_OK)
1685
break;
1686
1687
if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1688
{
1689
uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
1690
/* uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; */
1691
err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN);
1692
1693
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;
1694
}
1695
}
1696
1697
if(err == BZ_RUN_OK)
1698
err = ZIP_OK;
1699
}
1700
else
1701
#endif
1702
{
1703
zi->ci.stream.next_in = buf;
1704
zi->ci.stream.avail_in = len;
1705
1706
while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
1707
{
1708
if (zi->ci.stream.avail_out == 0)
1709
{
1710
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1711
err = ZIP_ERRNO;
1712
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1713
zi->ci.stream.next_out = zi->ci.buffered_data;
1714
}
1715
1716
1717
if(err != ZIP_OK)
1718
break;
1719
1720
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1721
{
1722
uLong uTotalOutBefore = zi->ci.stream.total_out;
1723
err=deflate(&zi->ci.stream, Z_NO_FLUSH);
1724
1725
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1726
}
1727
else
1728
{
1729
uInt copy_this,i;
1730
if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1731
copy_this = zi->ci.stream.avail_in;
1732
else
1733
copy_this = zi->ci.stream.avail_out;
1734
1735
for (i = 0; i < copy_this; i++)
1736
*(((char*)zi->ci.stream.next_out)+i) =
1737
*(((const char*)zi->ci.stream.next_in)+i);
1738
{
1739
zi->ci.stream.avail_in -= copy_this;
1740
zi->ci.stream.avail_out-= copy_this;
1741
zi->ci.stream.next_in+= copy_this;
1742
zi->ci.stream.next_out+= copy_this;
1743
zi->ci.stream.total_in+= copy_this;
1744
zi->ci.stream.total_out+= copy_this;
1745
zi->ci.pos_in_buffered_data += copy_this;
1746
}
1747
}
1748
}/* while(...) */
1749
}
1750
1751
return err;
1752
}
1753
1754
extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) {
1755
return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
1756
}
1757
1758
extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) {
1759
zip64_internal* zi;
1760
ZPOS64_T compressed_size;
1761
uLong invalidValue = 0xffffffff;
1762
unsigned datasize = 0;
1763
int err=ZIP_OK;
1764
1765
if (file == NULL)
1766
return ZIP_PARAMERROR;
1767
zi = (zip64_internal*)file;
1768
1769
if (zi->in_opened_file_inzip == 0)
1770
return ZIP_PARAMERROR;
1771
zi->ci.stream.avail_in = 0;
1772
1773
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1774
{
1775
while (err==ZIP_OK)
1776
{
1777
uLong uTotalOutBefore;
1778
if (zi->ci.stream.avail_out == 0)
1779
{
1780
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1781
err = ZIP_ERRNO;
1782
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1783
zi->ci.stream.next_out = zi->ci.buffered_data;
1784
}
1785
uTotalOutBefore = zi->ci.stream.total_out;
1786
err=deflate(&zi->ci.stream, Z_FINISH);
1787
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1788
}
1789
}
1790
else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1791
{
1792
#ifdef HAVE_BZIP2
1793
err = BZ_FINISH_OK;
1794
while (err==BZ_FINISH_OK)
1795
{
1796
uLong uTotalOutBefore;
1797
if (zi->ci.bstream.avail_out == 0)
1798
{
1799
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1800
err = ZIP_ERRNO;
1801
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1802
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1803
}
1804
uTotalOutBefore = zi->ci.bstream.total_out_lo32;
1805
err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH);
1806
if(err == BZ_STREAM_END)
1807
err = Z_STREAM_END;
1808
1809
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
1810
}
1811
1812
if(err == BZ_FINISH_OK)
1813
err = ZIP_OK;
1814
#endif
1815
}
1816
1817
if (err==Z_STREAM_END)
1818
err=ZIP_OK; /* this is normal */
1819
1820
if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
1821
{
1822
if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO)
1823
err = ZIP_ERRNO;
1824
}
1825
1826
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1827
{
1828
int tmp_err = deflateEnd(&zi->ci.stream);
1829
if (err == ZIP_OK)
1830
err = tmp_err;
1831
zi->ci.stream_initialised = 0;
1832
}
1833
#ifdef HAVE_BZIP2
1834
else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1835
{
1836
int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
1837
if (err==ZIP_OK)
1838
err = tmperr;
1839
zi->ci.stream_initialised = 0;
1840
}
1841
#endif
1842
1843
if (!zi->ci.raw)
1844
{
1845
crc32 = (uLong)zi->ci.crc32;
1846
uncompressed_size = zi->ci.totalUncompressedData;
1847
}
1848
compressed_size = zi->ci.totalCompressedData;
1849
1850
# ifndef NOCRYPT
1851
compressed_size += zi->ci.crypt_header_size;
1852
# endif
1853
1854
/* update Current Item crc and sizes, */
1855
if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
1856
{
1857
/*version Made by*/
1858
zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);
1859
/*version needed*/
1860
zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);
1861
1862
}
1863
1864
zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
1865
1866
1867
if(compressed_size >= 0xffffffff)
1868
zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/
1869
else
1870
zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/
1871
1872
/* set internal file attributes field */
1873
if (zi->ci.stream.data_type == Z_ASCII)
1874
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
1875
1876
if(uncompressed_size >= 0xffffffff)
1877
zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/
1878
else
1879
zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/
1880
1881
/* Add ZIP64 extra info field for uncompressed size */
1882
if(uncompressed_size >= 0xffffffff)
1883
datasize += 8;
1884
1885
/* Add ZIP64 extra info field for compressed size */
1886
if(compressed_size >= 0xffffffff)
1887
datasize += 8;
1888
1889
/* Add ZIP64 extra info field for relative offset to local file header of current file */
1890
if(zi->ci.pos_local_header >= 0xffffffff)
1891
datasize += 8;
1892
1893
if(datasize > 0)
1894
{
1895
char* p = NULL;
1896
1897
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1898
{
1899
/* we cannot write more data to the buffer that we have room for. */
1900
return ZIP_BADZIPFILE;
1901
}
1902
1903
p = zi->ci.central_header + zi->ci.size_centralheader;
1904
1905
/* Add Extra Information Header for 'ZIP64 information' */
1906
zip64local_putValue_inmemory(p, 0x0001, 2); /* HeaderID */
1907
p += 2;
1908
zip64local_putValue_inmemory(p, datasize, 2); /* DataSize */
1909
p += 2;
1910
1911
if(uncompressed_size >= 0xffffffff)
1912
{
1913
zip64local_putValue_inmemory(p, uncompressed_size, 8);
1914
p += 8;
1915
}
1916
1917
if(compressed_size >= 0xffffffff)
1918
{
1919
zip64local_putValue_inmemory(p, compressed_size, 8);
1920
p += 8;
1921
}
1922
1923
if(zi->ci.pos_local_header >= 0xffffffff)
1924
{
1925
zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
1926
p += 8;
1927
}
1928
1929
/* Update how much extra free space we got in the memory buffer
1930
// and increase the centralheader size so the new ZIP64 fields are included
1931
// ( 4 below is the size of HeaderID and DataSize field ) */
1932
zi->ci.size_centralExtraFree -= datasize + 4;
1933
zi->ci.size_centralheader += datasize + 4;
1934
1935
/* Update the extra info size field */
1936
zi->ci.size_centralExtra += datasize + 4;
1937
zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
1938
}
1939
1940
if (err==ZIP_OK)
1941
err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
1942
1943
free(zi->ci.central_header);
1944
1945
if (err==ZIP_OK)
1946
{
1947
/* Update the LocalFileHeader with the new values. */
1948
1949
ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
1950
1951
if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
1952
err = ZIP_ERRNO;
1953
1954
if (err==ZIP_OK)
1955
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
1956
1957
if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
1958
{
1959
if(zi->ci.pos_zip64extrainfo > 0)
1960
{
1961
/* Update the size in the ZIP64 extended field. */
1962
if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)
1963
err = ZIP_ERRNO;
1964
1965
if (err==ZIP_OK) /* compressed size, unknown */
1966
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
1967
1968
if (err==ZIP_OK) /* uncompressed size, unknown */
1969
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
1970
}
1971
else
1972
err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */
1973
}
1974
else
1975
{
1976
if (err==ZIP_OK) /* compressed size, unknown */
1977
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
1978
1979
if (err==ZIP_OK) /* uncompressed size, unknown */
1980
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
1981
}
1982
1983
if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
1984
err = ZIP_ERRNO;
1985
}
1986
1987
zi->number_entry ++;
1988
zi->in_opened_file_inzip = 0;
1989
1990
return err;
1991
}
1992
1993
extern int ZEXPORT zipCloseFileInZip(zipFile file) {
1994
return zipCloseFileInZipRaw (file,0,0);
1995
}
1996
1997
local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) {
1998
int err = ZIP_OK;
1999
ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
2000
2001
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
2002
2003
/*num disks*/
2004
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
2005
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2006
2007
/*relative offset*/
2008
if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
2009
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
2010
2011
/*total disks*/ /* Do not support spawning of disk so always say 1 here*/
2012
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
2013
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
2014
2015
return err;
2016
}
2017
2018
local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
2019
int err = ZIP_OK;
2020
2021
uLong Zip64DataSize = 44;
2022
2023
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);
2024
2025
if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
2026
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); /* why ZPOS64_T of this ? */
2027
2028
if (err==ZIP_OK) /* version made by */
2029
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
2030
2031
if (err==ZIP_OK) /* version needed */
2032
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
2033
2034
if (err==ZIP_OK) /* number of this disk */
2035
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2036
2037
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
2038
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2039
2040
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
2041
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
2042
2043
if (err==ZIP_OK) /* total number of entries in the central dir */
2044
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
2045
2046
if (err==ZIP_OK) /* size of the central directory */
2047
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
2048
2049
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2050
{
2051
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2052
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
2053
}
2054
return err;
2055
}
2056
2057
local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
2058
int err = ZIP_OK;
2059
2060
/*signature*/
2061
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
2062
2063
if (err==ZIP_OK) /* number of this disk */
2064
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2065
2066
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
2067
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2068
2069
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
2070
{
2071
{
2072
if(zi->number_entry >= 0xFFFF)
2073
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */
2074
else
2075
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2076
}
2077
}
2078
2079
if (err==ZIP_OK) /* total number of entries in the central dir */
2080
{
2081
if(zi->number_entry >= 0xFFFF)
2082
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */
2083
else
2084
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2085
}
2086
2087
if (err==ZIP_OK) /* size of the central directory */
2088
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
2089
2090
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2091
{
2092
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2093
if(pos >= 0xffffffff)
2094
{
2095
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
2096
}
2097
else
2098
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
2099
}
2100
2101
return err;
2102
}
2103
2104
local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) {
2105
int err = ZIP_OK;
2106
uInt size_global_comment = 0;
2107
2108
if(global_comment != NULL)
2109
size_global_comment = (uInt)strlen(global_comment);
2110
2111
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
2112
2113
if (err == ZIP_OK && size_global_comment > 0)
2114
{
2115
if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
2116
err = ZIP_ERRNO;
2117
}
2118
return err;
2119
}
2120
2121
extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
2122
zip64_internal* zi;
2123
int err = 0;
2124
uLong size_centraldir = 0;
2125
ZPOS64_T centraldir_pos_inzip;
2126
ZPOS64_T pos;
2127
2128
if (file == NULL)
2129
return ZIP_PARAMERROR;
2130
2131
zi = (zip64_internal*)file;
2132
2133
if (zi->in_opened_file_inzip == 1)
2134
{
2135
err = zipCloseFileInZip (file);
2136
}
2137
2138
#ifndef NO_ADDFILEINEXISTINGZIP
2139
if (global_comment==NULL)
2140
global_comment = zi->globalcomment;
2141
#endif
2142
2143
centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
2144
2145
if (err==ZIP_OK)
2146
{
2147
linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
2148
while (ldi!=NULL)
2149
{
2150
if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
2151
{
2152
if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
2153
err = ZIP_ERRNO;
2154
}
2155
2156
size_centraldir += ldi->filled_in_this_block;
2157
ldi = ldi->next_datablock;
2158
}
2159
}
2160
free_linkedlist(&(zi->central_dir));
2161
2162
set_end(&zi->set); /* set was zeroed, so this is safe */
2163
2164
pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2165
if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
2166
{
2167
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
2168
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2169
2170
Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
2171
}
2172
2173
if (err==ZIP_OK)
2174
err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2175
2176
if(err == ZIP_OK)
2177
err = Write_GlobalComment(zi, global_comment);
2178
2179
if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
2180
if (err == ZIP_OK)
2181
err = ZIP_ERRNO;
2182
2183
#ifndef NO_ADDFILEINEXISTINGZIP
2184
free(zi->globalcomment);
2185
#endif
2186
free(zi);
2187
2188
return err;
2189
}
2190
2191
extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) {
2192
char* p = pData;
2193
int size = 0;
2194
char* pNewHeader;
2195
char* pTmp;
2196
short header;
2197
short dataSize;
2198
2199
int retVal = ZIP_OK;
2200
2201
if(pData == NULL || dataLen == NULL || *dataLen < 4)
2202
return ZIP_PARAMERROR;
2203
2204
pNewHeader = (char*)ALLOC((unsigned)*dataLen);
2205
pTmp = pNewHeader;
2206
2207
while(p < (pData + *dataLen))
2208
{
2209
header = *(short*)p;
2210
dataSize = *(((short*)p)+1);
2211
2212
if( header == sHeader ) /* Header found. */
2213
{
2214
p += dataSize + 4; /* skip it. do not copy to temp buffer */
2215
}
2216
else
2217
{
2218
/* Extra Info block should not be removed, So copy it to the temp buffer. */
2219
memcpy(pTmp, p, dataSize + 4);
2220
p += dataSize + 4;
2221
size += dataSize + 4;
2222
}
2223
2224
}
2225
2226
if(size < *dataLen)
2227
{
2228
/* clean old extra info block. */
2229
memset(pData,0, *dataLen);
2230
2231
/* copy the new extra info block over the old */
2232
if(size > 0)
2233
memcpy(pData, pNewHeader, size);
2234
2235
/* set the new extra info size */
2236
*dataLen = size;
2237
2238
retVal = ZIP_OK;
2239
}
2240
else
2241
retVal = ZIP_ERRNO;
2242
2243
free(pNewHeader);
2244
2245
return retVal;
2246
}
2247

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button