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