[System.Data] Cleanup after #4893 (PR) (#5841)
[mono-project.git] / support / minizip / zip.c
blobef81ecc032c93b179188a7639571b038142c627c
1 /* zip.c -- IO on .zip files using zlib
2 Version 1.01e, February 12th, 2005
4 27 Dec 2004 Rolf Kalbermatter
5 Modification to zipOpen2 to support globalComment retrieval.
7 Copyright (C) 1998-2005 Gilles Vollant
9 Read zip.h for more info
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 #include "zlib.h"
18 #include "zip.h"
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
32 #ifndef local
33 # define local static
34 #endif
35 /* compile with -Dlocal if your debugger can't find static symbols */
37 #ifndef VERSIONMADEBY
38 # define VERSIONMADEBY (0x0) /* platform depedent */
39 #endif
41 #ifndef Z_BUFSIZE
42 #define Z_BUFSIZE (16384)
43 #endif
45 #ifndef Z_MAXFILENAMEINZIP
46 #define Z_MAXFILENAMEINZIP (256)
47 #endif
49 #ifndef ALLOC
50 # define ALLOC(size) (malloc(size))
51 #endif
52 #ifndef TRYFREE
53 # define TRYFREE(p) {if (p) free(p);}
54 #endif
57 #define SIZECENTRALDIRITEM (0x2e)
58 #define SIZEZIPLOCALHEADER (0x1e)
61 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
63 #ifndef SEEK_CUR
64 #define SEEK_CUR 1
65 #endif
67 #ifndef SEEK_END
68 #define SEEK_END 2
69 #endif
71 #ifndef SEEK_SET
72 #define SEEK_SET 0
73 #endif
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";
86 #define SIZEDATA_INDATABLOCK (4096-(4*4))
88 #define LOCALHEADERMAGIC (0x04034b50)
89 #define CENTRALHEADERMAGIC (0x02014b50)
90 #define ENDHEADERMAGIC (0x06054b50)
92 #define FLAG_LOCALHEADER_OFFSET (0x06)
93 #define CRC_LOCALHEADER_OFFSET (0x0e)
95 #define SIZECENTRALHEADER (0x2e) /* 46 */
97 typedef struct linkedlist_datablock_internal_s
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;
106 typedef struct linkedlist_data_s
108 linkedlist_datablock_internal* first_block;
109 linkedlist_datablock_internal* last_block;
110 } linkedlist_data;
113 typedef struct
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 */
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 */
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;
138 typedef struct
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 */
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;
156 #ifndef NOCRYPT
157 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
158 #include "crypt.h"
159 #endif
161 local linkedlist_datablock_internal* allocate_new_datablock(void)
163 linkedlist_datablock_internal* ldi;
164 ldi = (linkedlist_datablock_internal*)
165 ALLOC(sizeof(linkedlist_datablock_internal));
166 if (ldi!=NULL)
168 ldi->next_datablock = NULL ;
169 ldi->filled_in_this_block = 0 ;
170 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
172 return ldi;
175 local void free_datablock(linkedlist_datablock_internal *ldi)
177 while (ldi!=NULL)
179 linkedlist_datablock_internal* ldinext = ldi->next_datablock;
180 TRYFREE(ldi);
181 ldi = ldinext;
185 local void init_linkedlist(linkedlist_data *ll)
187 ll->first_block = ll->last_block = NULL;
191 local void free_linkedlist(linkedlist_data *ll)
193 free_datablock(ll->first_block);
194 ll->first_block = ll->last_block = NULL;
198 local int add_data_in_datablock(linkedlist_data *ll, const void *buf, uLong len)
200 linkedlist_datablock_internal* ldi;
201 const unsigned char* from_copy;
203 if (ll==NULL)
204 return ZIP_INTERNALERROR;
206 if (ll->last_block == NULL)
208 ll->first_block = ll->last_block = allocate_new_datablock();
209 if (ll->first_block == NULL)
210 return ZIP_INTERNALERROR;
213 ldi = ll->last_block;
214 from_copy = (unsigned char*)buf;
216 while (len>0)
218 uInt copy_this;
219 uInt i;
220 unsigned char* to_copy;
222 if (ldi->avail_in_this_block==0)
224 ldi->next_datablock = allocate_new_datablock();
225 if (ldi->next_datablock == NULL)
226 return ZIP_INTERNALERROR;
227 ldi = ldi->next_datablock ;
228 ll->last_block = ldi;
231 if (ldi->avail_in_this_block < len)
232 copy_this = (uInt)ldi->avail_in_this_block;
233 else
234 copy_this = (uInt)len;
236 to_copy = &(ldi->data[ldi->filled_in_this_block]);
238 for (i=0;i<copy_this;i++)
239 *(to_copy+i)=*(from_copy+i);
241 ldi->filled_in_this_block += copy_this;
242 ldi->avail_in_this_block -= copy_this;
243 from_copy += copy_this ;
244 len -= copy_this;
246 return ZIP_OK;
251 /****************************************************************************/
253 #ifndef NO_ADDFILEINEXISTINGZIP
254 /* ===========================================================================
255 Inputs a long in LSB order to the given file
256 nbByte == 1, 2 or 4 (byte, short or long)
259 local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
260 voidpf filestream, uLong x, int nbByte));
261 local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
262 const zlib_filefunc_def* pzlib_filefunc_def;
263 voidpf filestream;
264 uLong x;
265 int nbByte;
267 unsigned char buf[4];
268 int n;
269 for (n = 0; n < nbByte; n++)
271 buf[n] = (unsigned char)(x & 0xff);
272 x >>= 8;
274 if (x != 0)
275 { /* data overflow - hack for ZIP64 (X Roche) */
276 for (n = 0; n < nbByte; n++)
278 buf[n] = 0xff;
282 if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
283 return ZIP_ERRNO;
284 else
285 return ZIP_OK;
288 local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
289 local void ziplocal_putValue_inmemory (dest, x, nbByte)
290 void* dest;
291 uLong x;
292 int nbByte;
294 unsigned char* buf=(unsigned char*)dest;
295 int n;
296 for (n = 0; n < nbByte; n++) {
297 buf[n] = (unsigned char)(x & 0xff);
298 x >>= 8;
301 if (x != 0)
302 { /* data overflow - hack for ZIP64 */
303 for (n = 0; n < nbByte; n++)
305 buf[n] = 0xff;
310 /****************************************************************************/
313 local uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm, uLong dosDate)
315 uLong year = (uLong)ptm->tm_year;
316 if (year>1980)
317 year-=1980;
318 else if (year>80)
319 year-=80;
320 return
321 (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
322 ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
326 /****************************************************************************/
328 local int ziplocal_getByte OF((
329 const zlib_filefunc_def* pzlib_filefunc_def,
330 voidpf filestream,
331 int *pi));
333 local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
334 const zlib_filefunc_def* pzlib_filefunc_def;
335 voidpf filestream;
336 int *pi;
338 unsigned char c;
339 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
340 if (err==1)
342 *pi = (int)c;
343 return ZIP_OK;
345 else
347 if (ZERROR(*pzlib_filefunc_def,filestream))
348 return ZIP_ERRNO;
349 else
350 return ZIP_EOF;
355 /* ===========================================================================
356 Reads a long in LSB order from the given gz_stream. Sets
358 local int ziplocal_getShort OF((
359 const zlib_filefunc_def* pzlib_filefunc_def,
360 voidpf filestream,
361 uLong *pX));
363 local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
364 const zlib_filefunc_def* pzlib_filefunc_def;
365 voidpf filestream;
366 uLong *pX;
368 uLong x ;
369 int i;
370 int err;
372 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
373 x = (uLong)i;
375 if (err==ZIP_OK)
376 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
377 x += ((uLong)i)<<8;
379 if (err==ZIP_OK)
380 *pX = x;
381 else
382 *pX = 0;
383 return err;
386 local int ziplocal_getLong OF((
387 const zlib_filefunc_def* pzlib_filefunc_def,
388 voidpf filestream,
389 uLong *pX));
391 local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
392 const zlib_filefunc_def* pzlib_filefunc_def;
393 voidpf filestream;
394 uLong *pX;
396 uLong x ;
397 int i;
398 int err;
400 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
401 x = (uLong)i;
403 if (err==ZIP_OK)
404 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
405 x += ((uLong)i)<<8;
407 if (err==ZIP_OK)
408 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
409 x += ((uLong)i)<<16;
411 if (err==ZIP_OK)
412 err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
413 x += ((uLong)i)<<24;
415 if (err==ZIP_OK)
416 *pX = x;
417 else
418 *pX = 0;
419 return err;
422 #ifndef BUFREADCOMMENT
423 #define BUFREADCOMMENT (0x400)
424 #endif
426 Locate the Central directory of a zipfile (at the end, just before
427 the global comment)
429 local uLong ziplocal_SearchCentralDir OF((
430 const zlib_filefunc_def* pzlib_filefunc_def,
431 voidpf filestream));
433 local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
434 const zlib_filefunc_def* pzlib_filefunc_def;
435 voidpf filestream;
437 unsigned char* buf;
438 uLong uSizeFile;
439 uLong uBackRead;
440 uLong uMaxBack=0xffff; /* maximum size of global comment */
441 uLong uPosFound=0;
443 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
444 return 0;
447 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
449 if (uMaxBack>uSizeFile)
450 uMaxBack = uSizeFile;
452 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
453 if (buf==NULL)
454 return 0;
456 uBackRead = 4;
457 while (uBackRead<uMaxBack)
459 uLong uReadSize,uReadPos ;
460 int i;
461 if (uBackRead+BUFREADCOMMENT>uMaxBack)
462 uBackRead = uMaxBack;
463 else
464 uBackRead+=BUFREADCOMMENT;
465 uReadPos = uSizeFile-uBackRead ;
467 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
468 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
469 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
470 break;
472 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
473 break;
475 for (i=(int)uReadSize-3; (i--)>0;)
476 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
477 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
479 uPosFound = uReadPos+i;
480 break;
483 if (uPosFound!=0)
484 break;
486 TRYFREE(buf);
487 return uPosFound;
489 #endif /* !NO_ADDFILEINEXISTINGZIP*/
491 /************************************************************/
492 extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
493 const char *pathname;
494 int append;
495 zipcharpc* globalcomment;
496 zlib_filefunc_def* pzlib_filefunc_def;
498 zip_internal ziinit;
499 zip_internal* zi;
500 int err=ZIP_OK;
503 if (pzlib_filefunc_def==NULL)
504 fill_fopen_filefunc(&ziinit.z_filefunc);
505 else
506 ziinit.z_filefunc = *pzlib_filefunc_def;
508 ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
509 (ziinit.z_filefunc.opaque,
510 pathname,
511 (append == APPEND_STATUS_CREATE) ?
512 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
513 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
515 if (ziinit.filestream == NULL)
516 return NULL;
517 ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
518 ziinit.in_opened_file_inzip = 0;
519 ziinit.ci.stream_initialised = 0;
520 ziinit.number_entry = 0;
521 ziinit.add_position_when_writting_offset = 0;
522 init_linkedlist(&(ziinit.central_dir));
525 zi = (zip_internal*)ALLOC(sizeof(zip_internal));
526 if (zi==NULL)
528 ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
529 return NULL;
532 /* now we add file in a zipfile */
533 # ifndef NO_ADDFILEINEXISTINGZIP
534 ziinit.globalcomment = NULL;
535 if (append == APPEND_STATUS_ADDINZIP)
537 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
539 uLong size_central_dir; /* size of the central directory */
540 uLong offset_central_dir; /* offset of start of central directory */
541 uLong central_pos,uL;
543 uLong number_disk; /* number of the current dist, used for
544 spaning ZIP, unsupported, always 0*/
545 uLong number_disk_with_CD; /* number the the disk with central dir, used
546 for spaning ZIP, unsupported, always 0*/
547 uLong number_entry;
548 uLong number_entry_CD; /* total number of entries in
549 the central dir
550 (same than number_entry on nospan) */
551 uLong size_comment;
553 central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
554 if (central_pos==0)
555 err=ZIP_ERRNO;
557 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
558 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
559 err=ZIP_ERRNO;
561 /* the signature, already checked */
562 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
563 err=ZIP_ERRNO;
565 /* number of this disk */
566 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
567 err=ZIP_ERRNO;
569 /* number of the disk with the start of the central directory */
570 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
571 err=ZIP_ERRNO;
573 /* total number of entries in the central dir on this disk */
574 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
575 err=ZIP_ERRNO;
577 /* total number of entries in the central dir */
578 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
579 err=ZIP_ERRNO;
581 if ((number_entry_CD!=number_entry) ||
582 (number_disk_with_CD!=0) ||
583 (number_disk!=0))
584 err=ZIP_BADZIPFILE;
586 /* size of the central directory */
587 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
588 err=ZIP_ERRNO;
590 /* offset of start of central directory with respect to the
591 starting disk number */
592 if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
593 err=ZIP_ERRNO;
595 /* zipfile global comment length */
596 if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
597 err=ZIP_ERRNO;
599 if ((central_pos<offset_central_dir+size_central_dir) &&
600 (err==ZIP_OK))
601 err=ZIP_BADZIPFILE;
603 if (err!=ZIP_OK)
605 ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
606 return NULL;
609 if (size_comment>0)
611 ziinit.globalcomment = ALLOC(size_comment+1);
612 if (ziinit.globalcomment)
614 size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
615 ziinit.globalcomment[size_comment]=0;
619 byte_before_the_zipfile = central_pos -
620 (offset_central_dir+size_central_dir);
621 ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
624 uLong size_central_dir_to_read = size_central_dir;
625 size_t buf_size = SIZEDATA_INDATABLOCK;
626 void* buf_read = (void*)ALLOC(buf_size);
627 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
628 offset_central_dir + byte_before_the_zipfile,
629 ZLIB_FILEFUNC_SEEK_SET) != 0)
630 err=ZIP_ERRNO;
632 while ((size_central_dir_to_read>0) && (err==ZIP_OK))
634 uLong read_this = SIZEDATA_INDATABLOCK;
635 if (read_this > size_central_dir_to_read)
636 read_this = size_central_dir_to_read;
637 if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
638 err=ZIP_ERRNO;
640 if (err==ZIP_OK)
641 err = add_data_in_datablock(&ziinit.central_dir,buf_read,
642 (uLong)read_this);
643 size_central_dir_to_read-=read_this;
645 TRYFREE(buf_read);
647 ziinit.begin_pos = byte_before_the_zipfile;
648 ziinit.number_entry = number_entry_CD;
650 if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
651 offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
652 err=ZIP_ERRNO;
655 if (globalcomment)
657 *globalcomment = ziinit.globalcomment;
659 # endif /* !NO_ADDFILEINEXISTINGZIP*/
661 if (err != ZIP_OK)
663 # ifndef NO_ADDFILEINEXISTINGZIP
664 TRYFREE(ziinit.globalcomment);
665 # endif /* !NO_ADDFILEINEXISTINGZIP*/
666 TRYFREE(zi);
667 return NULL;
669 else
671 *zi = ziinit;
672 return (zipFile)zi;
676 extern zipFile ZEXPORT zipOpen (pathname, append)
677 const char *pathname;
678 int append;
680 return zipOpen2(pathname,append,NULL,NULL);
683 extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
684 extrafield_local, size_extrafield_local,
685 extrafield_global, size_extrafield_global,
686 comment, method, level, raw,
687 windowBits, memLevel, strategy,
688 password, crcForCrypting)
689 zipFile file;
690 const char* filename;
691 const zip_fileinfo* zipfi;
692 const void* extrafield_local;
693 uInt size_extrafield_local;
694 const void* extrafield_global;
695 uInt size_extrafield_global;
696 const char* comment;
697 int method;
698 int level;
699 int raw;
700 int windowBits;
701 int memLevel;
702 int strategy;
703 const char* password;
704 uLong crcForCrypting;
706 zip_internal* zi;
707 uInt size_filename;
708 uInt size_comment;
709 uInt i;
710 int err = ZIP_OK;
712 # ifdef NOCRYPT
713 if (password != NULL)
714 return ZIP_PARAMERROR;
715 # endif
717 if (file == NULL)
718 return ZIP_PARAMERROR;
719 if ((method!=0) && (method!=Z_DEFLATED))
720 return ZIP_PARAMERROR;
722 zi = (zip_internal*)file;
724 if (zi->in_opened_file_inzip == 1)
726 err = zipCloseFileInZip (file);
727 if (err != ZIP_OK)
728 return err;
732 if (filename==NULL)
733 filename="-";
735 if (comment==NULL)
736 size_comment = 0;
737 else
738 size_comment = (uInt)strlen(comment);
740 size_filename = (uInt)strlen(filename);
742 if (zipfi == NULL)
743 zi->ci.dosDate = 0;
744 else
746 if (zipfi->dosDate != 0)
747 zi->ci.dosDate = zipfi->dosDate;
748 else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
751 zi->ci.flag = 0;
752 if ((level==8) || (level==9))
753 zi->ci.flag |= 2;
754 if ((level==2))
755 zi->ci.flag |= 4;
756 if ((level==1))
757 zi->ci.flag |= 6;
758 if (password != NULL)
759 zi->ci.flag |= 1;
761 zi->ci.crc32 = 0;
762 zi->ci.method = method;
763 zi->ci.encrypt = 0;
764 zi->ci.stream_initialised = 0;
765 zi->ci.pos_in_buffered_data = 0;
766 zi->ci.raw = raw;
767 zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
768 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
769 size_extrafield_global + size_comment;
770 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
772 ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
773 /* version info */
774 ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
775 ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
776 ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
777 ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
778 ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
779 ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
780 ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
781 ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
782 ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
783 ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
784 ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
785 ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
787 if (zipfi==NULL)
788 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
789 else
790 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
792 if (zipfi==NULL)
793 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
794 else
795 ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
797 ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
799 for (i=0;i<size_filename;i++)
800 *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
802 for (i=0;i<size_extrafield_global;i++)
803 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
804 *(((const char*)extrafield_global)+i);
806 for (i=0;i<size_comment;i++)
807 *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
808 size_extrafield_global+i) = *(comment+i);
809 if (zi->ci.central_header == NULL)
810 return ZIP_INTERNALERROR;
812 /* write the local header */
813 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
815 if (err==ZIP_OK)
816 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
817 if (err==ZIP_OK)
818 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
820 if (err==ZIP_OK)
821 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
823 if (err==ZIP_OK)
824 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
826 if (err==ZIP_OK)
827 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
828 if (err==ZIP_OK)
829 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
830 if (err==ZIP_OK)
831 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
833 if (err==ZIP_OK)
834 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
836 if (err==ZIP_OK)
837 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
839 if ((err==ZIP_OK) && (size_filename>0))
840 if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
841 err = ZIP_ERRNO;
843 if ((err==ZIP_OK) && (size_extrafield_local>0))
844 if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
845 !=size_extrafield_local)
846 err = ZIP_ERRNO;
848 zi->ci.stream.avail_in = (uInt)0;
849 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
850 zi->ci.stream.next_out = zi->ci.buffered_data;
851 zi->ci.stream.total_in = 0;
852 zi->ci.stream.total_out = 0;
854 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
856 zi->ci.stream.zalloc = (alloc_func)0;
857 zi->ci.stream.zfree = (free_func)0;
858 zi->ci.stream.opaque = (voidpf)0;
860 if (windowBits>0)
861 windowBits = -windowBits;
863 err = deflateInit2(&zi->ci.stream, level,
864 Z_DEFLATED, windowBits, memLevel, strategy);
866 if (err==Z_OK)
867 zi->ci.stream_initialised = 1;
869 # ifndef NOCRYPT
870 zi->ci.crypt_header_size = 0;
871 if ((err==Z_OK) && (password != NULL))
873 unsigned char bufHead[RAND_HEAD_LEN];
874 unsigned int sizeHead;
875 zi->ci.encrypt = 1;
876 zi->ci.pcrc_32_tab = get_crc_table();
877 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
879 sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
880 zi->ci.crypt_header_size = sizeHead;
882 if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
883 err = ZIP_ERRNO;
885 # endif
887 if (err==Z_OK)
888 zi->in_opened_file_inzip = 1;
889 return err;
892 extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
893 extrafield_local, size_extrafield_local,
894 extrafield_global, size_extrafield_global,
895 comment, method, level, raw)
896 zipFile file;
897 const char* filename;
898 const zip_fileinfo* zipfi;
899 const void* extrafield_local;
900 uInt size_extrafield_local;
901 const void* extrafield_global;
902 uInt size_extrafield_global;
903 const char* comment;
904 int method;
905 int level;
906 int raw;
908 return zipOpenNewFileInZip3 (file, filename, zipfi,
909 extrafield_local, size_extrafield_local,
910 extrafield_global, size_extrafield_global,
911 comment, method, level, raw,
912 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
913 NULL, 0);
916 extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
917 extrafield_local, size_extrafield_local,
918 extrafield_global, size_extrafield_global,
919 comment, method, level)
920 zipFile file;
921 const char* filename;
922 const zip_fileinfo* zipfi;
923 const void* extrafield_local;
924 uInt size_extrafield_local;
925 const void* extrafield_global;
926 uInt size_extrafield_global;
927 const char* comment;
928 int method;
929 int level;
931 return zipOpenNewFileInZip2 (file, filename, zipfi,
932 extrafield_local, size_extrafield_local,
933 extrafield_global, size_extrafield_global,
934 comment, method, level, 0);
937 local int zipFlushWriteBuffer(zip_internal *zi)
939 int err=ZIP_OK;
941 if (zi->ci.encrypt != 0)
943 #ifndef NOCRYPT
944 uInt i;
945 int t;
946 for (i=0;i<zi->ci.pos_in_buffered_data;i++)
947 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
948 zi->ci.buffered_data[i],t);
949 #endif
951 if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
952 !=zi->ci.pos_in_buffered_data)
953 err = ZIP_ERRNO;
954 zi->ci.pos_in_buffered_data = 0;
955 return err;
958 extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
959 zipFile file;
960 const void* buf;
961 unsigned len;
963 zip_internal* zi;
964 int err=ZIP_OK;
966 if (file == NULL)
967 return ZIP_PARAMERROR;
968 zi = (zip_internal*)file;
970 if (zi->in_opened_file_inzip == 0)
971 return ZIP_PARAMERROR;
973 zi->ci.stream.next_in = (void*)buf;
974 zi->ci.stream.avail_in = len;
975 zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
977 while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
979 if (zi->ci.stream.avail_out == 0)
981 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
982 err = ZIP_ERRNO;
983 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
984 zi->ci.stream.next_out = zi->ci.buffered_data;
988 if(err != ZIP_OK)
989 break;
991 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
993 uLong uTotalOutBefore = zi->ci.stream.total_out;
994 err=deflate(&zi->ci.stream, Z_NO_FLUSH);
995 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
998 else
1000 uInt copy_this,i;
1001 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1002 copy_this = zi->ci.stream.avail_in;
1003 else
1004 copy_this = zi->ci.stream.avail_out;
1005 for (i=0;i<copy_this;i++)
1006 *(((char*)zi->ci.stream.next_out)+i) =
1007 *(((const char*)zi->ci.stream.next_in)+i);
1009 zi->ci.stream.avail_in -= copy_this;
1010 zi->ci.stream.avail_out-= copy_this;
1011 zi->ci.stream.next_in+= copy_this;
1012 zi->ci.stream.next_out+= copy_this;
1013 zi->ci.stream.total_in+= copy_this;
1014 zi->ci.stream.total_out+= copy_this;
1015 zi->ci.pos_in_buffered_data += copy_this;
1020 return err;
1023 extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
1024 zipFile file;
1025 uLong uncompressed_size;
1026 uLong crc32;
1028 zip_internal* zi;
1029 uLong compressed_size;
1030 int err=ZIP_OK;
1032 if (file == NULL)
1033 return ZIP_PARAMERROR;
1034 zi = (zip_internal*)file;
1036 if (zi->in_opened_file_inzip == 0)
1037 return ZIP_PARAMERROR;
1038 zi->ci.stream.avail_in = 0;
1040 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1041 while (err==ZIP_OK)
1043 uLong uTotalOutBefore;
1044 if (zi->ci.stream.avail_out == 0)
1046 if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
1047 err = ZIP_ERRNO;
1048 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1049 zi->ci.stream.next_out = zi->ci.buffered_data;
1051 uTotalOutBefore = zi->ci.stream.total_out;
1052 err=deflate(&zi->ci.stream, Z_FINISH);
1053 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1056 if (err==Z_STREAM_END)
1057 err=ZIP_OK; /* this is normal */
1059 if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
1060 if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
1061 err = ZIP_ERRNO;
1063 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1065 err=deflateEnd(&zi->ci.stream);
1066 zi->ci.stream_initialised = 0;
1069 if (!zi->ci.raw)
1071 crc32 = (uLong)zi->ci.crc32;
1072 uncompressed_size = (uLong)zi->ci.stream.total_in;
1074 compressed_size = (uLong)zi->ci.stream.total_out;
1075 # ifndef NOCRYPT
1076 compressed_size += zi->ci.crypt_header_size;
1077 # endif
1079 ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
1080 ziplocal_putValue_inmemory(zi->ci.central_header+20,
1081 compressed_size,4); /*compr size*/
1082 if (zi->ci.stream.data_type == Z_ASCII)
1083 ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
1084 ziplocal_putValue_inmemory(zi->ci.central_header+24,
1085 uncompressed_size,4); /*uncompr size*/
1087 if (err==ZIP_OK)
1088 err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
1089 (uLong)zi->ci.size_centralheader);
1090 free(zi->ci.central_header);
1092 if (err==ZIP_OK)
1094 long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
1095 if (ZSEEK(zi->z_filefunc,zi->filestream,
1096 zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
1097 err = ZIP_ERRNO;
1099 if (err==ZIP_OK)
1100 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
1102 if (err==ZIP_OK) /* compressed size, unknown */
1103 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
1105 if (err==ZIP_OK) /* uncompressed size, unknown */
1106 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
1108 if (ZSEEK(zi->z_filefunc,zi->filestream,
1109 cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
1110 err = ZIP_ERRNO;
1113 zi->number_entry ++;
1114 zi->in_opened_file_inzip = 0;
1116 return err;
1119 extern int ZEXPORT zipCloseFileInZip (file)
1120 zipFile file;
1122 return zipCloseFileInZipRaw (file,0,0);
1125 extern int ZEXPORT zipClose (file, global_comment)
1126 zipFile file;
1127 const char* global_comment;
1129 zip_internal* zi;
1130 int err = 0;
1131 uLong size_centraldir = 0;
1132 uLong centraldir_pos_inzip;
1133 uInt size_global_comment;
1134 if (file == NULL)
1135 return ZIP_PARAMERROR;
1136 zi = (zip_internal*)file;
1138 if (zi->in_opened_file_inzip == 1)
1140 err = zipCloseFileInZip (file);
1143 #ifndef NO_ADDFILEINEXISTINGZIP
1144 if (global_comment==NULL)
1145 global_comment = zi->globalcomment;
1146 #endif
1147 if (global_comment==NULL)
1148 size_global_comment = 0;
1149 else
1150 size_global_comment = (uInt)strlen(global_comment);
1152 centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
1153 if (err==ZIP_OK)
1155 linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
1156 while (ldi!=NULL)
1158 if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
1159 if (ZWRITE(zi->z_filefunc,zi->filestream,
1160 ldi->data,ldi->filled_in_this_block)
1161 !=ldi->filled_in_this_block )
1162 err = ZIP_ERRNO;
1164 size_centraldir += ldi->filled_in_this_block;
1165 ldi = ldi->next_datablock;
1168 free_datablock(zi->central_dir.first_block);
1170 if (err==ZIP_OK) /* Magic End */
1171 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
1173 if (err==ZIP_OK) /* number of this disk */
1174 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1176 if (err==ZIP_OK) /* number of the disk with the start of the central directory */
1177 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1179 if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
1180 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
1182 if (err==ZIP_OK) /* total number of entries in the central dir */
1183 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
1185 if (err==ZIP_OK) /* size of the central directory */
1186 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
1188 if (err==ZIP_OK) /* offset of start of central directory with respect to the
1189 starting disk number */
1190 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
1191 (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
1193 if (err==ZIP_OK) /* zipfile comment length */
1194 err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
1196 if ((err==ZIP_OK) && (size_global_comment>0))
1197 if (ZWRITE(zi->z_filefunc,zi->filestream,
1198 global_comment,size_global_comment) != size_global_comment)
1199 err = ZIP_ERRNO;
1201 if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
1202 if (err == ZIP_OK)
1203 err = ZIP_ERRNO;
1205 #ifndef NO_ADDFILEINEXISTINGZIP
1206 TRYFREE(zi->globalcomment);
1207 #endif
1208 TRYFREE(zi);
1210 return err;