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
35 /* compile with -Dlocal if your debugger can't find static symbols */
38 # define VERSIONMADEBY (0x0) /* platform depedent */
42 #define Z_BUFSIZE (16384)
45 #ifndef Z_MAXFILENAMEINZIP
46 #define Z_MAXFILENAMEINZIP (256)
50 # define ALLOC(size) (malloc(size))
53 # define TRYFREE(p) {if (p) free(p);}
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.... */
76 #if MAX_MEM_LEVEL >= 8
77 # define DEF_MEM_LEVEL 8
79 # define DEF_MEM_LEVEL MAX_MEM_LEVEL
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
;
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
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*/
132 unsigned long keys
[3]; /* keys defining the pseudo-random sequence */
133 const unsigned long* pcrc_32_tab
;
134 int crypt_header_size
;
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
;
149 #ifndef NO_ADDFILEINEXISTINGZIP
157 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
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
));
168 ldi
->next_datablock
= NULL
;
169 ldi
->filled_in_this_block
= 0 ;
170 ldi
->avail_in_this_block
= SIZEDATA_INDATABLOCK
;
175 local
void free_datablock(linkedlist_datablock_internal
*ldi
)
179 linkedlist_datablock_internal
* ldinext
= ldi
->next_datablock
;
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
;
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
;
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
;
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
;
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
;
267 unsigned char buf
[4];
269 for (n
= 0; n
< nbByte
; n
++)
271 buf
[n
] = (unsigned char)(x
& 0xff);
275 { /* data overflow - hack for ZIP64 (X Roche) */
276 for (n
= 0; n
< nbByte
; n
++)
282 if (ZWRITE(*pzlib_filefunc_def
,filestream
,buf
,nbByte
)!=(uLong
)nbByte
)
288 local
void ziplocal_putValue_inmemory
OF((void* dest
, uLong x
, int nbByte
));
289 local
void ziplocal_putValue_inmemory (dest
, x
, nbByte
)
294 unsigned char* buf
=(unsigned char*)dest
;
296 for (n
= 0; n
< nbByte
; n
++) {
297 buf
[n
] = (unsigned char)(x
& 0xff);
302 { /* data overflow - hack for ZIP64 */
303 for (n
= 0; n
< nbByte
; n
++)
310 /****************************************************************************/
313 local uLong
ziplocal_TmzDateToDosDate(const tm_zip
*ptm
, uLong dosDate
)
315 uLong year
= (uLong
)ptm
->tm_year
;
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
,
333 local
int ziplocal_getByte(pzlib_filefunc_def
,filestream
,pi
)
334 const zlib_filefunc_def
* pzlib_filefunc_def
;
339 int err
= (int)ZREAD(*pzlib_filefunc_def
,filestream
,&c
,1);
347 if (ZERROR(*pzlib_filefunc_def
,filestream
))
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
,
363 local
int ziplocal_getShort (pzlib_filefunc_def
,filestream
,pX
)
364 const zlib_filefunc_def
* pzlib_filefunc_def
;
372 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
376 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
386 local
int ziplocal_getLong
OF((
387 const zlib_filefunc_def
* pzlib_filefunc_def
,
391 local
int ziplocal_getLong (pzlib_filefunc_def
,filestream
,pX
)
392 const zlib_filefunc_def
* pzlib_filefunc_def
;
400 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
404 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
408 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
412 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
422 #ifndef BUFREADCOMMENT
423 #define BUFREADCOMMENT (0x400)
426 Locate the Central directory of a zipfile (at the end, just before
429 local uLong ziplocal_SearchCentralDir
OF((
430 const zlib_filefunc_def
* pzlib_filefunc_def
,
433 local uLong
ziplocal_SearchCentralDir(pzlib_filefunc_def
,filestream
)
434 const zlib_filefunc_def
* pzlib_filefunc_def
;
440 uLong uMaxBack
=0xffff; /* maximum size of global comment */
443 if (ZSEEK(*pzlib_filefunc_def
,filestream
,0,ZLIB_FILEFUNC_SEEK_END
) != 0)
447 uSizeFile
= ZTELL(*pzlib_filefunc_def
,filestream
);
449 if (uMaxBack
>uSizeFile
)
450 uMaxBack
= uSizeFile
;
452 buf
= (unsigned char*)ALLOC(BUFREADCOMMENT
+4);
457 while (uBackRead
<uMaxBack
)
459 uLong uReadSize
,uReadPos
;
461 if (uBackRead
+BUFREADCOMMENT
>uMaxBack
)
462 uBackRead
= uMaxBack
;
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)
472 if (ZREAD(*pzlib_filefunc_def
,filestream
,buf
,uReadSize
)!=uReadSize
)
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
;
489 #endif /* !NO_ADDFILEINEXISTINGZIP*/
491 /************************************************************/
492 extern zipFile ZEXPORT
zipOpen2 (pathname
, append
, globalcomment
, pzlib_filefunc_def
)
493 const char *pathname
;
495 zipcharpc
* globalcomment
;
496 zlib_filefunc_def
* pzlib_filefunc_def
;
503 if (pzlib_filefunc_def
==NULL
)
504 fill_fopen_filefunc(&ziinit
.z_filefunc
);
506 ziinit
.z_filefunc
= *pzlib_filefunc_def
;
508 ziinit
.filestream
= (*(ziinit
.z_filefunc
.zopen_file
))
509 (ziinit
.z_filefunc
.opaque
,
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
)
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
));
528 ZCLOSE(ziinit
.z_filefunc
,ziinit
.filestream
);
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*/
548 uLong number_entry_CD
; /* total number of entries in
550 (same than number_entry on nospan) */
553 central_pos
= ziplocal_SearchCentralDir(&ziinit
.z_filefunc
,ziinit
.filestream
);
557 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
558 central_pos
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
561 /* the signature, already checked */
562 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&uL
)!=ZIP_OK
)
565 /* number of this disk */
566 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_disk
)!=ZIP_OK
)
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
)
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
)
577 /* total number of entries in the central dir */
578 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_entry_CD
)!=ZIP_OK
)
581 if ((number_entry_CD
!=number_entry
) ||
582 (number_disk_with_CD
!=0) ||
586 /* size of the central directory */
587 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_central_dir
)!=ZIP_OK
)
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
)
595 /* zipfile global comment length */
596 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_comment
)!=ZIP_OK
)
599 if ((central_pos
<offset_central_dir
+size_central_dir
) &&
605 ZCLOSE(ziinit
.z_filefunc
, ziinit
.filestream
);
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)
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
)
641 err
= add_data_in_datablock(&ziinit
.central_dir
,buf_read
,
643 size_central_dir_to_read
-=read_this
;
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)
657 *globalcomment
= ziinit
.globalcomment
;
659 # endif /* !NO_ADDFILEINEXISTINGZIP*/
663 # ifndef NO_ADDFILEINEXISTINGZIP
664 TRYFREE(ziinit
.globalcomment
);
665 # endif /* !NO_ADDFILEINEXISTINGZIP*/
676 extern zipFile ZEXPORT
zipOpen (pathname
, append
)
677 const char *pathname
;
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
)
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
;
703 const char* password
;
704 uLong crcForCrypting
;
713 if (password
!= NULL
)
714 return ZIP_PARAMERROR
;
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
);
738 size_comment
= (uInt
)strlen(comment
);
740 size_filename
= (uInt
)strlen(filename
);
746 if (zipfi
->dosDate
!= 0)
747 zi
->ci
.dosDate
= zipfi
->dosDate
;
748 else zi
->ci
.dosDate
= ziplocal_TmzDateToDosDate(&zipfi
->tmz_date
,zipfi
->dosDate
);
752 if ((level
==8) || (level
==9))
758 if (password
!= NULL
)
762 zi
->ci
.method
= method
;
764 zi
->ci
.stream_initialised
= 0;
765 zi
->ci
.pos_in_buffered_data
= 0;
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);
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*/
788 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)0,2);
790 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)zipfi
->internal_fa
,2);
793 ziplocal_putValue_inmemory(zi
->ci
.central_header
+38,(uLong
)0,4);
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);
816 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)20,2);/* version needed to extract */
818 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.flag
,2);
821 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.method
,2);
824 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.dosDate
,4);
827 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* crc 32, unknown */
829 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* compressed size, unknown */
831 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* uncompressed size, unknown */
834 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_filename
,2);
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
)
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
)
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;
861 windowBits
= -windowBits
;
863 err
= deflateInit2(&zi
->ci
.stream
, level
,
864 Z_DEFLATED
, windowBits
, memLevel
, strategy
);
867 zi
->ci
.stream_initialised
= 1;
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
;
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
)
888 zi
->in_opened_file_inzip
= 1;
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
)
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
;
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
,
916 extern int ZEXPORT
zipOpenNewFileInZip (file
, filename
, zipfi
,
917 extrafield_local
, size_extrafield_local
,
918 extrafield_global
, size_extrafield_global
,
919 comment
, method
, level
)
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
;
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
)
941 if (zi
->ci
.encrypt
!= 0)
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
);
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
)
954 zi
->ci
.pos_in_buffered_data
= 0;
958 extern int ZEXPORT
zipWriteInFileInZip (file
, buf
, len
)
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
)
983 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
984 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
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
) ;
1001 if (zi
->ci
.stream
.avail_in
< zi
->ci
.stream
.avail_out
)
1002 copy_this
= zi
->ci
.stream
.avail_in
;
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
;
1023 extern int ZEXPORT
zipCloseFileInZipRaw (file
, uncompressed_size
, crc32
)
1025 uLong uncompressed_size
;
1029 uLong compressed_size
;
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
))
1043 uLong uTotalOutBefore
;
1044 if (zi
->ci
.stream
.avail_out
== 0)
1046 if (zipFlushWriteBuffer(zi
) == 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
)
1063 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1065 err
=deflateEnd(&zi
->ci
.stream
);
1066 zi
->ci
.stream_initialised
= 0;
1071 crc32
= (uLong
)zi
->ci
.crc32
;
1072 uncompressed_size
= (uLong
)zi
->ci
.stream
.total_in
;
1074 compressed_size
= (uLong
)zi
->ci
.stream
.total_out
;
1076 compressed_size
+= zi
->ci
.crypt_header_size
;
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*/
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
);
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)
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)
1113 zi
->number_entry
++;
1114 zi
->in_opened_file_inzip
= 0;
1119 extern int ZEXPORT
zipCloseFileInZip (file
)
1122 return zipCloseFileInZipRaw (file
,0,0);
1125 extern int ZEXPORT
zipClose (file
, global_comment
)
1127 const char* global_comment
;
1131 uLong size_centraldir
= 0;
1132 uLong centraldir_pos_inzip
;
1133 uInt size_global_comment
;
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
;
1147 if (global_comment
==NULL
)
1148 size_global_comment
= 0;
1150 size_global_comment
= (uInt
)strlen(global_comment
);
1152 centraldir_pos_inzip
= ZTELL(zi
->z_filefunc
,zi
->filestream
);
1155 linkedlist_datablock_internal
* ldi
= zi
->central_dir
.first_block
;
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
)
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
)
1201 if (ZCLOSE(zi
->z_filefunc
,zi
->filestream
) != 0)
1205 #ifndef NO_ADDFILEINEXISTINGZIP
1206 TRYFREE(zi
->globalcomment
);