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