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
;
190 local
void free_linkedlist(linkedlist_data
*ll
)
192 free_datablock(ll
->first_block
);
193 ll
->first_block
= ll
->last_block
= NULL
;
197 local
int add_data_in_datablock(linkedlist_data
*ll
, const void *buf
, uLong len
)
199 linkedlist_datablock_internal
* ldi
;
200 const unsigned char* from_copy
;
203 return ZIP_INTERNALERROR
;
205 if (ll
->last_block
== NULL
)
207 ll
->first_block
= ll
->last_block
= allocate_new_datablock();
208 if (ll
->first_block
== NULL
)
209 return ZIP_INTERNALERROR
;
212 ldi
= ll
->last_block
;
213 from_copy
= (unsigned char*)buf
;
219 unsigned char* to_copy
;
221 if (ldi
->avail_in_this_block
==0)
223 ldi
->next_datablock
= allocate_new_datablock();
224 if (ldi
->next_datablock
== NULL
)
225 return ZIP_INTERNALERROR
;
226 ldi
= ldi
->next_datablock
;
227 ll
->last_block
= ldi
;
230 if (ldi
->avail_in_this_block
< len
)
231 copy_this
= (uInt
)ldi
->avail_in_this_block
;
233 copy_this
= (uInt
)len
;
235 to_copy
= &(ldi
->data
[ldi
->filled_in_this_block
]);
237 for (i
=0;i
<copy_this
;i
++)
238 *(to_copy
+i
)=*(from_copy
+i
);
240 ldi
->filled_in_this_block
+= copy_this
;
241 ldi
->avail_in_this_block
-= copy_this
;
242 from_copy
+= copy_this
;
250 /****************************************************************************/
252 #ifndef NO_ADDFILEINEXISTINGZIP
253 /* ===========================================================================
254 Inputs a long in LSB order to the given file
255 nbByte == 1, 2 or 4 (byte, short or long)
258 local
int ziplocal_putValue
OF((const zlib_filefunc_def
* pzlib_filefunc_def
,
259 voidpf filestream
, uLong x
, int nbByte
));
260 local
int ziplocal_putValue (pzlib_filefunc_def
, filestream
, x
, nbByte
)
261 const zlib_filefunc_def
* pzlib_filefunc_def
;
266 unsigned char buf
[4];
268 for (n
= 0; n
< nbByte
; n
++)
270 buf
[n
] = (unsigned char)(x
& 0xff);
274 { /* data overflow - hack for ZIP64 (X Roche) */
275 for (n
= 0; n
< nbByte
; n
++)
281 if (ZWRITE(*pzlib_filefunc_def
,filestream
,buf
,nbByte
)!=(uLong
)nbByte
)
287 local
void ziplocal_putValue_inmemory
OF((void* dest
, uLong x
, int nbByte
));
288 local
void ziplocal_putValue_inmemory (dest
, x
, nbByte
)
293 unsigned char* buf
=(unsigned char*)dest
;
295 for (n
= 0; n
< nbByte
; n
++) {
296 buf
[n
] = (unsigned char)(x
& 0xff);
301 { /* data overflow - hack for ZIP64 */
302 for (n
= 0; n
< nbByte
; n
++)
309 /****************************************************************************/
312 local uLong
ziplocal_TmzDateToDosDate(const tm_zip
*ptm
, uLong dosDate
)
314 uLong year
= (uLong
)ptm
->tm_year
;
320 (uLong
) (((ptm
->tm_mday
) + (32 * (ptm
->tm_mon
+1)) + (512 * year
)) << 16) |
321 ((ptm
->tm_sec
/2) + (32* ptm
->tm_min
) + (2048 * (uLong
)ptm
->tm_hour
));
325 /****************************************************************************/
327 local
int ziplocal_getByte
OF((
328 const zlib_filefunc_def
* pzlib_filefunc_def
,
332 local
int ziplocal_getByte(pzlib_filefunc_def
,filestream
,pi
)
333 const zlib_filefunc_def
* pzlib_filefunc_def
;
338 int err
= (int)ZREAD(*pzlib_filefunc_def
,filestream
,&c
,1);
346 if (ZERROR(*pzlib_filefunc_def
,filestream
))
354 /* ===========================================================================
355 Reads a long in LSB order from the given gz_stream. Sets
357 local
int ziplocal_getShort
OF((
358 const zlib_filefunc_def
* pzlib_filefunc_def
,
362 local
int ziplocal_getShort (pzlib_filefunc_def
,filestream
,pX
)
363 const zlib_filefunc_def
* pzlib_filefunc_def
;
371 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
375 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
385 local
int ziplocal_getLong
OF((
386 const zlib_filefunc_def
* pzlib_filefunc_def
,
390 local
int ziplocal_getLong (pzlib_filefunc_def
,filestream
,pX
)
391 const zlib_filefunc_def
* pzlib_filefunc_def
;
399 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
403 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
407 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
411 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
421 #ifndef BUFREADCOMMENT
422 #define BUFREADCOMMENT (0x400)
425 Locate the Central directory of a zipfile (at the end, just before
428 local uLong ziplocal_SearchCentralDir
OF((
429 const zlib_filefunc_def
* pzlib_filefunc_def
,
432 local uLong
ziplocal_SearchCentralDir(pzlib_filefunc_def
,filestream
)
433 const zlib_filefunc_def
* pzlib_filefunc_def
;
439 uLong uMaxBack
=0xffff; /* maximum size of global comment */
442 if (ZSEEK(*pzlib_filefunc_def
,filestream
,0,ZLIB_FILEFUNC_SEEK_END
) != 0)
446 uSizeFile
= ZTELL(*pzlib_filefunc_def
,filestream
);
448 if (uMaxBack
>uSizeFile
)
449 uMaxBack
= uSizeFile
;
451 buf
= (unsigned char*)ALLOC(BUFREADCOMMENT
+4);
456 while (uBackRead
<uMaxBack
)
458 uLong uReadSize
,uReadPos
;
460 if (uBackRead
+BUFREADCOMMENT
>uMaxBack
)
461 uBackRead
= uMaxBack
;
463 uBackRead
+=BUFREADCOMMENT
;
464 uReadPos
= uSizeFile
-uBackRead
;
466 uReadSize
= ((BUFREADCOMMENT
+4) < (uSizeFile
-uReadPos
)) ?
467 (BUFREADCOMMENT
+4) : (uSizeFile
-uReadPos
);
468 if (ZSEEK(*pzlib_filefunc_def
,filestream
,uReadPos
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
471 if (ZREAD(*pzlib_filefunc_def
,filestream
,buf
,uReadSize
)!=uReadSize
)
474 for (i
=(int)uReadSize
-3; (i
--)>0;)
475 if (((*(buf
+i
))==0x50) && ((*(buf
+i
+1))==0x4b) &&
476 ((*(buf
+i
+2))==0x05) && ((*(buf
+i
+3))==0x06))
478 uPosFound
= uReadPos
+i
;
488 #endif /* !NO_ADDFILEINEXISTINGZIP*/
490 /************************************************************/
491 extern zipFile ZEXPORT
zipOpen2 (pathname
, append
, globalcomment
, pzlib_filefunc_def
)
492 const char *pathname
;
494 zipcharpc
* globalcomment
;
495 zlib_filefunc_def
* pzlib_filefunc_def
;
502 if (pzlib_filefunc_def
==NULL
)
503 fill_fopen_filefunc(&ziinit
.z_filefunc
);
505 ziinit
.z_filefunc
= *pzlib_filefunc_def
;
507 ziinit
.filestream
= (*(ziinit
.z_filefunc
.zopen_file
))
508 (ziinit
.z_filefunc
.opaque
,
510 (append
== APPEND_STATUS_CREATE
) ?
511 (ZLIB_FILEFUNC_MODE_READ
| ZLIB_FILEFUNC_MODE_WRITE
| ZLIB_FILEFUNC_MODE_CREATE
) :
512 (ZLIB_FILEFUNC_MODE_READ
| ZLIB_FILEFUNC_MODE_WRITE
| ZLIB_FILEFUNC_MODE_EXISTING
));
514 if (ziinit
.filestream
== NULL
)
516 ziinit
.begin_pos
= ZTELL(ziinit
.z_filefunc
,ziinit
.filestream
);
517 ziinit
.in_opened_file_inzip
= 0;
518 ziinit
.ci
.stream_initialised
= 0;
519 ziinit
.number_entry
= 0;
520 ziinit
.add_position_when_writting_offset
= 0;
521 init_linkedlist(&(ziinit
.central_dir
));
524 zi
= (zip_internal
*)ALLOC(sizeof(zip_internal
));
527 ZCLOSE(ziinit
.z_filefunc
,ziinit
.filestream
);
531 /* now we add file in a zipfile */
532 # ifndef NO_ADDFILEINEXISTINGZIP
533 ziinit
.globalcomment
= NULL
;
534 if (append
== APPEND_STATUS_ADDINZIP
)
536 uLong byte_before_the_zipfile
;/* byte before the zipfile, (>0 for sfx)*/
538 uLong size_central_dir
; /* size of the central directory */
539 uLong offset_central_dir
; /* offset of start of central directory */
540 uLong central_pos
,uL
;
542 uLong number_disk
; /* number of the current dist, used for
543 spaning ZIP, unsupported, always 0*/
544 uLong number_disk_with_CD
; /* number the the disk with central dir, used
545 for spaning ZIP, unsupported, always 0*/
547 uLong number_entry_CD
; /* total number of entries in
549 (same than number_entry on nospan) */
552 central_pos
= ziplocal_SearchCentralDir(&ziinit
.z_filefunc
,ziinit
.filestream
);
556 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
557 central_pos
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
560 /* the signature, already checked */
561 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&uL
)!=ZIP_OK
)
564 /* number of this disk */
565 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_disk
)!=ZIP_OK
)
568 /* number of the disk with the start of the central directory */
569 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_disk_with_CD
)!=ZIP_OK
)
572 /* total number of entries in the central dir on this disk */
573 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_entry
)!=ZIP_OK
)
576 /* total number of entries in the central dir */
577 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_entry_CD
)!=ZIP_OK
)
580 if ((number_entry_CD
!=number_entry
) ||
581 (number_disk_with_CD
!=0) ||
585 /* size of the central directory */
586 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_central_dir
)!=ZIP_OK
)
589 /* offset of start of central directory with respect to the
590 starting disk number */
591 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&offset_central_dir
)!=ZIP_OK
)
594 /* zipfile global comment length */
595 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_comment
)!=ZIP_OK
)
598 if ((central_pos
<offset_central_dir
+size_central_dir
) &&
604 ZCLOSE(ziinit
.z_filefunc
, ziinit
.filestream
);
610 ziinit
.globalcomment
= ALLOC(size_comment
+1);
611 if (ziinit
.globalcomment
)
613 size_comment
= ZREAD(ziinit
.z_filefunc
, ziinit
.filestream
,ziinit
.globalcomment
,size_comment
);
614 ziinit
.globalcomment
[size_comment
]=0;
618 byte_before_the_zipfile
= central_pos
-
619 (offset_central_dir
+size_central_dir
);
620 ziinit
.add_position_when_writting_offset
= byte_before_the_zipfile
;
623 uLong size_central_dir_to_read
= size_central_dir
;
624 size_t buf_size
= SIZEDATA_INDATABLOCK
;
625 void* buf_read
= (void*)ALLOC(buf_size
);
626 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
627 offset_central_dir
+ byte_before_the_zipfile
,
628 ZLIB_FILEFUNC_SEEK_SET
) != 0)
631 while ((size_central_dir_to_read
>0) && (err
==ZIP_OK
))
633 uLong read_this
= SIZEDATA_INDATABLOCK
;
634 if (read_this
> size_central_dir_to_read
)
635 read_this
= size_central_dir_to_read
;
636 if (ZREAD(ziinit
.z_filefunc
, ziinit
.filestream
,buf_read
,read_this
) != read_this
)
640 err
= add_data_in_datablock(&ziinit
.central_dir
,buf_read
,
642 size_central_dir_to_read
-=read_this
;
646 ziinit
.begin_pos
= byte_before_the_zipfile
;
647 ziinit
.number_entry
= number_entry_CD
;
649 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
650 offset_central_dir
+byte_before_the_zipfile
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
656 *globalcomment
= ziinit
.globalcomment
;
658 # endif /* !NO_ADDFILEINEXISTINGZIP*/
662 # ifndef NO_ADDFILEINEXISTINGZIP
663 TRYFREE(ziinit
.globalcomment
);
664 # endif /* !NO_ADDFILEINEXISTINGZIP*/
675 extern zipFile ZEXPORT
zipOpen (pathname
, append
)
676 const char *pathname
;
679 return zipOpen2(pathname
,append
,NULL
,NULL
);
682 extern int ZEXPORT
zipOpenNewFileInZip3 (file
, filename
, zipfi
,
683 extrafield_local
, size_extrafield_local
,
684 extrafield_global
, size_extrafield_global
,
685 comment
, method
, level
, raw
,
686 windowBits
, memLevel
, strategy
,
687 password
, crcForCrypting
)
689 const char* filename
;
690 const zip_fileinfo
* zipfi
;
691 const void* extrafield_local
;
692 uInt size_extrafield_local
;
693 const void* extrafield_global
;
694 uInt size_extrafield_global
;
702 const char* password
;
703 uLong crcForCrypting
;
712 if (password
!= NULL
)
713 return ZIP_PARAMERROR
;
717 return ZIP_PARAMERROR
;
718 if ((method
!=0) && (method
!=Z_DEFLATED
))
719 return ZIP_PARAMERROR
;
721 zi
= (zip_internal
*)file
;
723 if (zi
->in_opened_file_inzip
== 1)
725 err
= zipCloseFileInZip (file
);
737 size_comment
= (uInt
)strlen(comment
);
739 size_filename
= (uInt
)strlen(filename
);
745 if (zipfi
->dosDate
!= 0)
746 zi
->ci
.dosDate
= zipfi
->dosDate
;
747 else zi
->ci
.dosDate
= ziplocal_TmzDateToDosDate(&zipfi
->tmz_date
,zipfi
->dosDate
);
751 if ((level
==8) || (level
==9))
757 if (password
!= NULL
)
761 zi
->ci
.method
= method
;
763 zi
->ci
.stream_initialised
= 0;
764 zi
->ci
.pos_in_buffered_data
= 0;
766 zi
->ci
.pos_local_header
= ZTELL(zi
->z_filefunc
,zi
->filestream
) ;
767 zi
->ci
.size_centralheader
= SIZECENTRALHEADER
+ size_filename
+
768 size_extrafield_global
+ size_comment
;
769 zi
->ci
.central_header
= (char*)ALLOC((uInt
)zi
->ci
.size_centralheader
);
771 ziplocal_putValue_inmemory(zi
->ci
.central_header
,(uLong
)CENTRALHEADERMAGIC
,4);
773 ziplocal_putValue_inmemory(zi
->ci
.central_header
+4,(uLong
)VERSIONMADEBY
,2);
774 ziplocal_putValue_inmemory(zi
->ci
.central_header
+6,(uLong
)20,2);
775 ziplocal_putValue_inmemory(zi
->ci
.central_header
+8,(uLong
)zi
->ci
.flag
,2);
776 ziplocal_putValue_inmemory(zi
->ci
.central_header
+10,(uLong
)zi
->ci
.method
,2);
777 ziplocal_putValue_inmemory(zi
->ci
.central_header
+12,(uLong
)zi
->ci
.dosDate
,4);
778 ziplocal_putValue_inmemory(zi
->ci
.central_header
+16,(uLong
)0,4); /*crc*/
779 ziplocal_putValue_inmemory(zi
->ci
.central_header
+20,(uLong
)0,4); /*compr size*/
780 ziplocal_putValue_inmemory(zi
->ci
.central_header
+24,(uLong
)0,4); /*uncompr size*/
781 ziplocal_putValue_inmemory(zi
->ci
.central_header
+28,(uLong
)size_filename
,2);
782 ziplocal_putValue_inmemory(zi
->ci
.central_header
+30,(uLong
)size_extrafield_global
,2);
783 ziplocal_putValue_inmemory(zi
->ci
.central_header
+32,(uLong
)size_comment
,2);
784 ziplocal_putValue_inmemory(zi
->ci
.central_header
+34,(uLong
)0,2); /*disk nm start*/
787 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)0,2);
789 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)zipfi
->internal_fa
,2);
792 ziplocal_putValue_inmemory(zi
->ci
.central_header
+38,(uLong
)0,4);
794 ziplocal_putValue_inmemory(zi
->ci
.central_header
+38,(uLong
)zipfi
->external_fa
,4);
796 ziplocal_putValue_inmemory(zi
->ci
.central_header
+42,(uLong
)zi
->ci
.pos_local_header
- zi
->add_position_when_writting_offset
,4);
798 for (i
=0;i
<size_filename
;i
++)
799 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+i
) = *(filename
+i
);
801 for (i
=0;i
<size_extrafield_global
;i
++)
802 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+size_filename
+i
) =
803 *(((const char*)extrafield_global
)+i
);
805 for (i
=0;i
<size_comment
;i
++)
806 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+size_filename
+
807 size_extrafield_global
+i
) = *(comment
+i
);
808 if (zi
->ci
.central_header
== NULL
)
809 return ZIP_INTERNALERROR
;
811 /* write the local header */
812 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)LOCALHEADERMAGIC
,4);
815 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)20,2);/* version needed to extract */
817 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.flag
,2);
820 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.method
,2);
823 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.dosDate
,4);
826 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* crc 32, unknown */
828 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* compressed size, unknown */
830 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* uncompressed size, unknown */
833 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_filename
,2);
836 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_extrafield_local
,2);
838 if ((err
==ZIP_OK
) && (size_filename
>0))
839 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,filename
,size_filename
)!=size_filename
)
842 if ((err
==ZIP_OK
) && (size_extrafield_local
>0))
843 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,extrafield_local
,size_extrafield_local
)
844 !=size_extrafield_local
)
847 zi
->ci
.stream
.avail_in
= (uInt
)0;
848 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
849 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
850 zi
->ci
.stream
.total_in
= 0;
851 zi
->ci
.stream
.total_out
= 0;
853 if ((err
==ZIP_OK
) && (zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
855 zi
->ci
.stream
.zalloc
= (alloc_func
)0;
856 zi
->ci
.stream
.zfree
= (free_func
)0;
857 zi
->ci
.stream
.opaque
= (voidpf
)0;
860 windowBits
= -windowBits
;
862 err
= deflateInit2(&zi
->ci
.stream
, level
,
863 Z_DEFLATED
, windowBits
, memLevel
, strategy
);
866 zi
->ci
.stream_initialised
= 1;
869 zi
->ci
.crypt_header_size
= 0;
870 if ((err
==Z_OK
) && (password
!= NULL
))
872 unsigned char bufHead
[RAND_HEAD_LEN
];
873 unsigned int sizeHead
;
875 zi
->ci
.pcrc_32_tab
= get_crc_table();
876 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
878 sizeHead
=crypthead(password
,bufHead
,RAND_HEAD_LEN
,zi
->ci
.keys
,zi
->ci
.pcrc_32_tab
,crcForCrypting
);
879 zi
->ci
.crypt_header_size
= sizeHead
;
881 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,bufHead
,sizeHead
) != sizeHead
)
887 zi
->in_opened_file_inzip
= 1;
891 extern int ZEXPORT
zipOpenNewFileInZip2(file
, filename
, zipfi
,
892 extrafield_local
, size_extrafield_local
,
893 extrafield_global
, size_extrafield_global
,
894 comment
, method
, level
, raw
)
896 const char* filename
;
897 const zip_fileinfo
* zipfi
;
898 const void* extrafield_local
;
899 uInt size_extrafield_local
;
900 const void* extrafield_global
;
901 uInt size_extrafield_global
;
907 return zipOpenNewFileInZip3 (file
, filename
, zipfi
,
908 extrafield_local
, size_extrafield_local
,
909 extrafield_global
, size_extrafield_global
,
910 comment
, method
, level
, raw
,
911 -MAX_WBITS
, DEF_MEM_LEVEL
, Z_DEFAULT_STRATEGY
,
915 extern int ZEXPORT
zipOpenNewFileInZip (file
, filename
, zipfi
,
916 extrafield_local
, size_extrafield_local
,
917 extrafield_global
, size_extrafield_global
,
918 comment
, method
, level
)
920 const char* filename
;
921 const zip_fileinfo
* zipfi
;
922 const void* extrafield_local
;
923 uInt size_extrafield_local
;
924 const void* extrafield_global
;
925 uInt size_extrafield_global
;
930 return zipOpenNewFileInZip2 (file
, filename
, zipfi
,
931 extrafield_local
, size_extrafield_local
,
932 extrafield_global
, size_extrafield_global
,
933 comment
, method
, level
, 0);
936 local
int zipFlushWriteBuffer(zip_internal
*zi
)
940 if (zi
->ci
.encrypt
!= 0)
945 for (i
=0;i
<zi
->ci
.pos_in_buffered_data
;i
++)
946 zi
->ci
.buffered_data
[i
] = zencode(zi
->ci
.keys
, zi
->ci
.pcrc_32_tab
,
947 zi
->ci
.buffered_data
[i
],t
);
950 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,zi
->ci
.buffered_data
,zi
->ci
.pos_in_buffered_data
)
951 !=zi
->ci
.pos_in_buffered_data
)
953 zi
->ci
.pos_in_buffered_data
= 0;
957 extern int ZEXPORT
zipWriteInFileInZip (file
, buf
, len
)
966 return ZIP_PARAMERROR
;
967 zi
= (zip_internal
*)file
;
969 if (zi
->in_opened_file_inzip
== 0)
970 return ZIP_PARAMERROR
;
972 zi
->ci
.stream
.next_in
= (void*)buf
;
973 zi
->ci
.stream
.avail_in
= len
;
974 zi
->ci
.crc32
= crc32(zi
->ci
.crc32
,buf
,len
);
976 while ((err
==ZIP_OK
) && (zi
->ci
.stream
.avail_in
>0))
978 if (zi
->ci
.stream
.avail_out
== 0)
980 if (zipFlushWriteBuffer(zi
) == ZIP_ERRNO
)
982 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
983 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
990 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
992 uLong uTotalOutBefore
= zi
->ci
.stream
.total_out
;
993 err
=deflate(&zi
->ci
.stream
, Z_NO_FLUSH
);
994 zi
->ci
.pos_in_buffered_data
+= (uInt
)(zi
->ci
.stream
.total_out
- uTotalOutBefore
) ;
1000 if (zi
->ci
.stream
.avail_in
< zi
->ci
.stream
.avail_out
)
1001 copy_this
= zi
->ci
.stream
.avail_in
;
1003 copy_this
= zi
->ci
.stream
.avail_out
;
1004 for (i
=0;i
<copy_this
;i
++)
1005 *(((char*)zi
->ci
.stream
.next_out
)+i
) =
1006 *(((const char*)zi
->ci
.stream
.next_in
)+i
);
1008 zi
->ci
.stream
.avail_in
-= copy_this
;
1009 zi
->ci
.stream
.avail_out
-= copy_this
;
1010 zi
->ci
.stream
.next_in
+= copy_this
;
1011 zi
->ci
.stream
.next_out
+= copy_this
;
1012 zi
->ci
.stream
.total_in
+= copy_this
;
1013 zi
->ci
.stream
.total_out
+= copy_this
;
1014 zi
->ci
.pos_in_buffered_data
+= copy_this
;
1022 extern int ZEXPORT
zipCloseFileInZipRaw (file
, uncompressed_size
, crc32
)
1024 uLong uncompressed_size
;
1028 uLong compressed_size
;
1032 return ZIP_PARAMERROR
;
1033 zi
= (zip_internal
*)file
;
1035 if (zi
->in_opened_file_inzip
== 0)
1036 return ZIP_PARAMERROR
;
1037 zi
->ci
.stream
.avail_in
= 0;
1039 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1042 uLong uTotalOutBefore
;
1043 if (zi
->ci
.stream
.avail_out
== 0)
1045 if (zipFlushWriteBuffer(zi
) == ZIP_ERRNO
)
1047 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
1048 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
1050 uTotalOutBefore
= zi
->ci
.stream
.total_out
;
1051 err
=deflate(&zi
->ci
.stream
, Z_FINISH
);
1052 zi
->ci
.pos_in_buffered_data
+= (uInt
)(zi
->ci
.stream
.total_out
- uTotalOutBefore
) ;
1055 if (err
==Z_STREAM_END
)
1056 err
=ZIP_OK
; /* this is normal */
1058 if ((zi
->ci
.pos_in_buffered_data
>0) && (err
==ZIP_OK
))
1059 if (zipFlushWriteBuffer(zi
)==ZIP_ERRNO
)
1062 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1064 err
=deflateEnd(&zi
->ci
.stream
);
1065 zi
->ci
.stream_initialised
= 0;
1070 crc32
= (uLong
)zi
->ci
.crc32
;
1071 uncompressed_size
= (uLong
)zi
->ci
.stream
.total_in
;
1073 compressed_size
= (uLong
)zi
->ci
.stream
.total_out
;
1075 compressed_size
+= zi
->ci
.crypt_header_size
;
1078 ziplocal_putValue_inmemory(zi
->ci
.central_header
+16,crc32
,4); /*crc*/
1079 ziplocal_putValue_inmemory(zi
->ci
.central_header
+20,
1080 compressed_size
,4); /*compr size*/
1081 if (zi
->ci
.stream
.data_type
== Z_ASCII
)
1082 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)Z_ASCII
,2);
1083 ziplocal_putValue_inmemory(zi
->ci
.central_header
+24,
1084 uncompressed_size
,4); /*uncompr size*/
1087 err
= add_data_in_datablock(&zi
->central_dir
,zi
->ci
.central_header
,
1088 (uLong
)zi
->ci
.size_centralheader
);
1089 free(zi
->ci
.central_header
);
1093 long cur_pos_inzip
= ZTELL(zi
->z_filefunc
,zi
->filestream
);
1094 if (ZSEEK(zi
->z_filefunc
,zi
->filestream
,
1095 zi
->ci
.pos_local_header
+ 14,ZLIB_FILEFUNC_SEEK_SET
)!=0)
1099 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,crc32
,4); /* crc 32, unknown */
1101 if (err
==ZIP_OK
) /* compressed size, unknown */
1102 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,compressed_size
,4);
1104 if (err
==ZIP_OK
) /* uncompressed size, unknown */
1105 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,uncompressed_size
,4);
1107 if (ZSEEK(zi
->z_filefunc
,zi
->filestream
,
1108 cur_pos_inzip
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
1112 zi
->number_entry
++;
1113 zi
->in_opened_file_inzip
= 0;
1118 extern int ZEXPORT
zipCloseFileInZip (file
)
1121 return zipCloseFileInZipRaw (file
,0,0);
1124 extern int ZEXPORT
zipClose (file
, global_comment
)
1126 const char* global_comment
;
1130 uLong size_centraldir
= 0;
1131 uLong centraldir_pos_inzip
;
1132 uInt size_global_comment
;
1134 return ZIP_PARAMERROR
;
1135 zi
= (zip_internal
*)file
;
1137 if (zi
->in_opened_file_inzip
== 1)
1139 err
= zipCloseFileInZip (file
);
1142 #ifndef NO_ADDFILEINEXISTINGZIP
1143 if (global_comment
==NULL
)
1144 global_comment
= zi
->globalcomment
;
1146 if (global_comment
==NULL
)
1147 size_global_comment
= 0;
1149 size_global_comment
= (uInt
)strlen(global_comment
);
1151 centraldir_pos_inzip
= ZTELL(zi
->z_filefunc
,zi
->filestream
);
1154 linkedlist_datablock_internal
* ldi
= zi
->central_dir
.first_block
;
1157 if ((err
==ZIP_OK
) && (ldi
->filled_in_this_block
>0))
1158 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,
1159 ldi
->data
,ldi
->filled_in_this_block
)
1160 !=ldi
->filled_in_this_block
)
1163 size_centraldir
+= ldi
->filled_in_this_block
;
1164 ldi
= ldi
->next_datablock
;
1167 free_datablock(zi
->central_dir
.first_block
);
1169 if (err
==ZIP_OK
) /* Magic End */
1170 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)ENDHEADERMAGIC
,4);
1172 if (err
==ZIP_OK
) /* number of this disk */
1173 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,2);
1175 if (err
==ZIP_OK
) /* number of the disk with the start of the central directory */
1176 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,2);
1178 if (err
==ZIP_OK
) /* total number of entries in the central dir on this disk */
1179 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->number_entry
,2);
1181 if (err
==ZIP_OK
) /* total number of entries in the central dir */
1182 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->number_entry
,2);
1184 if (err
==ZIP_OK
) /* size of the central directory */
1185 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_centraldir
,4);
1187 if (err
==ZIP_OK
) /* offset of start of central directory with respect to the
1188 starting disk number */
1189 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,
1190 (uLong
)(centraldir_pos_inzip
- zi
->add_position_when_writting_offset
),4);
1192 if (err
==ZIP_OK
) /* zipfile comment length */
1193 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_global_comment
,2);
1195 if ((err
==ZIP_OK
) && (size_global_comment
>0))
1196 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,
1197 global_comment
,size_global_comment
) != size_global_comment
)
1200 if (ZCLOSE(zi
->z_filefunc
,zi
->filestream
) != 0)
1204 #ifndef NO_ADDFILEINEXISTINGZIP
1205 TRYFREE(zi
->globalcomment
);