Merge pull request #1074 from esdrubal/bug18421
[mono.git] / support / minizip / zip.c
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
161 local linkedlist_datablock_internal* allocate_new_datablock(void)
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
175 local void free_datablock(linkedlist_datablock_internal *ldi)
176 {
177     while (ldi!=NULL)
178     {
179         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
180         TRYFREE(ldi);
181         ldi = ldinext;
182     }
183 }
184
185 local void init_linkedlist(linkedlist_data *ll)
186 {
187     ll->first_block = ll->last_block = NULL;
188 }
189
190 /*
191 local void free_linkedlist(linkedlist_data *ll)
192 {
193     free_datablock(ll->first_block);
194     ll->first_block = ll->last_block = NULL;
195 }
196 */
197
198 local int add_data_in_datablock(linkedlist_data *ll, const void *buf, uLong len)
199 {
200     linkedlist_datablock_internal* ldi;
201     const unsigned char* from_copy;
202
203     if (ll==NULL)
204         return ZIP_INTERNALERROR;
205
206     if (ll->last_block == NULL)
207     {
208         ll->first_block = ll->last_block = allocate_new_datablock();
209         if (ll->first_block == NULL)
210             return ZIP_INTERNALERROR;
211     }
212
213     ldi = ll->last_block;
214     from_copy = (unsigned char*)buf;
215
216     while (len>0)
217     {
218         uInt copy_this;
219         uInt i;
220         unsigned char* to_copy;
221
222         if (ldi->avail_in_this_block==0)
223         {
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;
229         }
230
231         if (ldi->avail_in_this_block < len)
232             copy_this = (uInt)ldi->avail_in_this_block;
233         else
234             copy_this = (uInt)len;
235
236         to_copy = &(ldi->data[ldi->filled_in_this_block]);
237
238         for (i=0;i<copy_this;i++)
239             *(to_copy+i)=*(from_copy+i);
240
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;
245     }
246     return ZIP_OK;
247 }
248
249
250
251 /****************************************************************************/
252
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)
257 */
258
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;
266 {
267     unsigned char buf[4];
268     int n;
269     for (n = 0; n < nbByte; n++)
270     {
271         buf[n] = (unsigned char)(x & 0xff);
272         x >>= 8;
273     }
274     if (x != 0)
275       {     /* data overflow - hack for ZIP64 (X Roche) */
276       for (n = 0; n < nbByte; n++)
277         {
278           buf[n] = 0xff;
279         }
280       }
281
282     if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
283         return ZIP_ERRNO;
284     else
285         return ZIP_OK;
286 }
287
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;
293 {
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;
299     }
300
301     if (x != 0)
302     {     /* data overflow - hack for ZIP64 */
303        for (n = 0; n < nbByte; n++)
304        {
305           buf[n] = 0xff;
306        }
307     }
308 }
309
310 /****************************************************************************/
311
312
313 local uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm, uLong dosDate)
314 {
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));
323 }
324
325
326 /****************************************************************************/
327
328 local int ziplocal_getByte OF((
329     const zlib_filefunc_def* pzlib_filefunc_def,
330     voidpf filestream,
331     int *pi));
332
333 local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
334     const zlib_filefunc_def* pzlib_filefunc_def;
335     voidpf filestream;
336     int *pi;
337 {
338     unsigned char c;
339     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
340     if (err==1)
341     {
342         *pi = (int)c;
343         return ZIP_OK;
344     }
345     else
346     {
347         if (ZERROR(*pzlib_filefunc_def,filestream))
348             return ZIP_ERRNO;
349         else
350             return ZIP_EOF;
351     }
352 }
353
354
355 /* ===========================================================================
356    Reads a long in LSB order from the given gz_stream. Sets
357 */
358 local int ziplocal_getShort OF((
359     const zlib_filefunc_def* pzlib_filefunc_def,
360     voidpf filestream,
361     uLong *pX));
362
363 local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
364     const zlib_filefunc_def* pzlib_filefunc_def;
365     voidpf filestream;
366     uLong *pX;
367 {
368     uLong x ;
369     int i;
370     int err;
371
372     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
373     x = (uLong)i;
374
375     if (err==ZIP_OK)
376         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
377     x += ((uLong)i)<<8;
378
379     if (err==ZIP_OK)
380         *pX = x;
381     else
382         *pX = 0;
383     return err;
384 }
385
386 local int ziplocal_getLong OF((
387     const zlib_filefunc_def* pzlib_filefunc_def,
388     voidpf filestream,
389     uLong *pX));
390
391 local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
392     const zlib_filefunc_def* pzlib_filefunc_def;
393     voidpf filestream;
394     uLong *pX;
395 {
396     uLong x ;
397     int i;
398     int err;
399
400     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
401     x = (uLong)i;
402
403     if (err==ZIP_OK)
404         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
405     x += ((uLong)i)<<8;
406
407     if (err==ZIP_OK)
408         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
409     x += ((uLong)i)<<16;
410
411     if (err==ZIP_OK)
412         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
413     x += ((uLong)i)<<24;
414
415     if (err==ZIP_OK)
416         *pX = x;
417     else
418         *pX = 0;
419     return err;
420 }
421
422 #ifndef BUFREADCOMMENT
423 #define BUFREADCOMMENT (0x400)
424 #endif
425 /*
426   Locate the Central directory of a zipfile (at the end, just before
427     the global comment)
428 */
429 local uLong ziplocal_SearchCentralDir OF((
430     const zlib_filefunc_def* pzlib_filefunc_def,
431     voidpf filestream));
432
433 local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
434     const zlib_filefunc_def* pzlib_filefunc_def;
435     voidpf filestream;
436 {
437     unsigned char* buf;
438     uLong uSizeFile;
439     uLong uBackRead;
440     uLong uMaxBack=0xffff; /* maximum size of global comment */
441     uLong uPosFound=0;
442
443     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
444         return 0;
445
446
447     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
448
449     if (uMaxBack>uSizeFile)
450         uMaxBack = uSizeFile;
451
452     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
453     if (buf==NULL)
454         return 0;
455
456     uBackRead = 4;
457     while (uBackRead<uMaxBack)
458     {
459         uLong uReadSize,uReadPos ;
460         int i;
461         if (uBackRead+BUFREADCOMMENT>uMaxBack)
462             uBackRead = uMaxBack;
463         else
464             uBackRead+=BUFREADCOMMENT;
465         uReadPos = uSizeFile-uBackRead ;
466
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;
471
472         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
473             break;
474
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))
478             {
479                 uPosFound = uReadPos+i;
480                 break;
481             }
482
483         if (uPosFound!=0)
484             break;
485     }
486     TRYFREE(buf);
487     return uPosFound;
488 }
489 #endif /* !NO_ADDFILEINEXISTINGZIP*/
490
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;
497 {
498     zip_internal ziinit;
499     zip_internal* zi;
500     int err=ZIP_OK;
501
502
503     if (pzlib_filefunc_def==NULL)
504         fill_fopen_filefunc(&ziinit.z_filefunc);
505     else
506         ziinit.z_filefunc = *pzlib_filefunc_def;
507
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));
514
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));
523
524
525     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
526     if (zi==NULL)
527     {
528         ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
529         return NULL;
530     }
531
532     /* now we add file in a zipfile */
533 #    ifndef NO_ADDFILEINEXISTINGZIP
534     ziinit.globalcomment = NULL;
535     if (append == APPEND_STATUS_ADDINZIP)
536     {
537         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
538
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;
542
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;
552
553         central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
554         if (central_pos==0)
555             err=ZIP_ERRNO;
556
557         if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
558                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
559             err=ZIP_ERRNO;
560
561         /* the signature, already checked */
562         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
563             err=ZIP_ERRNO;
564
565         /* number of this disk */
566         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
567             err=ZIP_ERRNO;
568
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;
572
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;
576
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;
580
581         if ((number_entry_CD!=number_entry) ||
582             (number_disk_with_CD!=0) ||
583             (number_disk!=0))
584             err=ZIP_BADZIPFILE;
585
586         /* size of the central directory */
587         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
588             err=ZIP_ERRNO;
589
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;
594
595         /* zipfile global comment length */
596         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
597             err=ZIP_ERRNO;
598
599         if ((central_pos<offset_central_dir+size_central_dir) &&
600             (err==ZIP_OK))
601             err=ZIP_BADZIPFILE;
602
603         if (err!=ZIP_OK)
604         {
605             ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
606             return NULL;
607         }
608
609         if (size_comment>0)
610         {
611             ziinit.globalcomment = ALLOC(size_comment+1);
612             if (ziinit.globalcomment)
613             {
614                size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
615                ziinit.globalcomment[size_comment]=0;
616             }
617         }
618
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;
622
623         {
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;
631
632             while ((size_central_dir_to_read>0) && (err==ZIP_OK))
633             {
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;
639
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;
644             }
645             TRYFREE(buf_read);
646         }
647         ziinit.begin_pos = byte_before_the_zipfile;
648         ziinit.number_entry = number_entry_CD;
649
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;
653     }
654
655     if (globalcomment)
656     {
657       *globalcomment = ziinit.globalcomment;
658     }
659 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
660
661     if (err != ZIP_OK)
662     {
663 #    ifndef NO_ADDFILEINEXISTINGZIP
664         TRYFREE(ziinit.globalcomment);
665 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
666         TRYFREE(zi);
667         return NULL;
668     }
669     else
670     {
671         *zi = ziinit;
672         return (zipFile)zi;
673     }
674 }
675
676 extern zipFile ZEXPORT zipOpen (pathname, append)
677     const char *pathname;
678     int append;
679 {
680     return zipOpen2(pathname,append,NULL,NULL);
681 }
682
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;
705 {
706     zip_internal* zi;
707     uInt size_filename;
708     uInt size_comment;
709     uInt i;
710     int err = ZIP_OK;
711
712 #    ifdef NOCRYPT
713     if (password != NULL)
714         return ZIP_PARAMERROR;
715 #    endif
716
717     if (file == NULL)
718         return ZIP_PARAMERROR;
719     if ((method!=0) && (method!=Z_DEFLATED))
720         return ZIP_PARAMERROR;
721
722     zi = (zip_internal*)file;
723
724     if (zi->in_opened_file_inzip == 1)
725     {
726         err = zipCloseFileInZip (file);
727         if (err != ZIP_OK)
728             return err;
729     }
730
731
732     if (filename==NULL)
733         filename="-";
734
735     if (comment==NULL)
736         size_comment = 0;
737     else
738         size_comment = (uInt)strlen(comment);
739
740     size_filename = (uInt)strlen(filename);
741
742     if (zipfi == NULL)
743         zi->ci.dosDate = 0;
744     else
745     {
746         if (zipfi->dosDate != 0)
747             zi->ci.dosDate = zipfi->dosDate;
748         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
749     }
750
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;
760
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);
771
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*/
786
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);
791
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);
796
797     ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
798
799     for (i=0;i<size_filename;i++)
800         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
801
802     for (i=0;i<size_extrafield_global;i++)
803         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
804               *(((const char*)extrafield_global)+i);
805
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;
811
812     /* write the local header */
813     err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
814
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);
819
820     if (err==ZIP_OK)
821         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
822
823     if (err==ZIP_OK)
824         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
825
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 */
832
833     if (err==ZIP_OK)
834         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
835
836     if (err==ZIP_OK)
837         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
838
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;
842
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;
847
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;
853
854     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
855     {
856         zi->ci.stream.zalloc = (alloc_func)0;
857         zi->ci.stream.zfree = (free_func)0;
858         zi->ci.stream.opaque = (voidpf)0;
859
860         if (windowBits>0)
861             windowBits = -windowBits;
862
863         err = deflateInit2(&zi->ci.stream, level,
864                Z_DEFLATED, windowBits, memLevel, strategy);
865
866         if (err==Z_OK)
867             zi->ci.stream_initialised = 1;
868     }
869 #    ifndef NOCRYPT
870     zi->ci.crypt_header_size = 0;
871     if ((err==Z_OK) && (password != NULL))
872     {
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);*/
878
879         sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
880         zi->ci.crypt_header_size = sizeHead;
881
882         if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
883                 err = ZIP_ERRNO;
884     }
885 #    endif
886
887     if (err==Z_OK)
888         zi->in_opened_file_inzip = 1;
889     return err;
890 }
891
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;
907 {
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);
914 }
915
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;
930 {
931     return zipOpenNewFileInZip2 (file, filename, zipfi,
932                                  extrafield_local, size_extrafield_local,
933                                  extrafield_global, size_extrafield_global,
934                                  comment, method, level, 0);
935 }
936
937 local int zipFlushWriteBuffer(zip_internal *zi)
938 {
939     int err=ZIP_OK;
940
941     if (zi->ci.encrypt != 0)
942     {
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
950     }
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;
956 }
957
958 extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
959     zipFile file;
960     const void* buf;
961     unsigned len;
962 {
963     zip_internal* zi;
964     int err=ZIP_OK;
965
966     if (file == NULL)
967         return ZIP_PARAMERROR;
968     zi = (zip_internal*)file;
969
970     if (zi->in_opened_file_inzip == 0)
971         return ZIP_PARAMERROR;
972
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);
976
977     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
978     {
979         if (zi->ci.stream.avail_out == 0)
980         {
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;
985         }
986
987
988         if(err != ZIP_OK)
989             break;
990
991         if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
992         {
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) ;
996
997         }
998         else
999         {
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);
1008             {
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;
1016             }
1017         }
1018     }
1019
1020     return err;
1021 }
1022
1023 extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
1024     zipFile file;
1025     uLong uncompressed_size;
1026     uLong crc32;
1027 {
1028     zip_internal* zi;
1029     uLong compressed_size;
1030     int err=ZIP_OK;
1031
1032     if (file == NULL)
1033         return ZIP_PARAMERROR;
1034     zi = (zip_internal*)file;
1035
1036     if (zi->in_opened_file_inzip == 0)
1037         return ZIP_PARAMERROR;
1038     zi->ci.stream.avail_in = 0;
1039
1040     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1041         while (err==ZIP_OK)
1042     {
1043         uLong uTotalOutBefore;
1044         if (zi->ci.stream.avail_out == 0)
1045         {
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;
1050         }
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) ;
1054     }
1055
1056     if (err==Z_STREAM_END)
1057         err=ZIP_OK; /* this is normal */
1058
1059     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
1060         if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
1061             err = ZIP_ERRNO;
1062
1063     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1064     {
1065         err=deflateEnd(&zi->ci.stream);
1066         zi->ci.stream_initialised = 0;
1067     }
1068
1069     if (!zi->ci.raw)
1070     {
1071         crc32 = (uLong)zi->ci.crc32;
1072         uncompressed_size = (uLong)zi->ci.stream.total_in;
1073     }
1074     compressed_size = (uLong)zi->ci.stream.total_out;
1075 #    ifndef NOCRYPT
1076     compressed_size += zi->ci.crypt_header_size;
1077 #    endif
1078
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*/
1086
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);
1091
1092     if (err==ZIP_OK)
1093     {
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;
1098
1099         if (err==ZIP_OK)
1100             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
1101
1102         if (err==ZIP_OK) /* compressed size, unknown */
1103             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
1104
1105         if (err==ZIP_OK) /* uncompressed size, unknown */
1106             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
1107
1108         if (ZSEEK(zi->z_filefunc,zi->filestream,
1109                   cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
1110             err = ZIP_ERRNO;
1111     }
1112
1113     zi->number_entry ++;
1114     zi->in_opened_file_inzip = 0;
1115
1116     return err;
1117 }
1118
1119 extern int ZEXPORT zipCloseFileInZip (file)
1120     zipFile file;
1121 {
1122     return zipCloseFileInZipRaw (file,0,0);
1123 }
1124
1125 extern int ZEXPORT zipClose (file, global_comment)
1126     zipFile file;
1127     const char* global_comment;
1128 {
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;
1137
1138     if (zi->in_opened_file_inzip == 1)
1139     {
1140         err = zipCloseFileInZip (file);
1141     }
1142
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);
1151
1152     centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
1153     if (err==ZIP_OK)
1154     {
1155         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
1156         while (ldi!=NULL)
1157         {
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;
1163
1164             size_centraldir += ldi->filled_in_this_block;
1165             ldi = ldi->next_datablock;
1166         }
1167     }
1168     free_datablock(zi->central_dir.first_block);
1169
1170     if (err==ZIP_OK) /* Magic End */
1171         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
1172
1173     if (err==ZIP_OK) /* number of this disk */
1174         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1175
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);
1178
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);
1181
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);
1184
1185     if (err==ZIP_OK) /* size of the central directory */
1186         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
1187
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);
1192
1193     if (err==ZIP_OK) /* zipfile comment length */
1194         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
1195
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;
1200
1201     if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
1202         if (err == ZIP_OK)
1203             err = ZIP_ERRNO;
1204
1205 #ifndef NO_ADDFILEINEXISTINGZIP
1206     TRYFREE(zi->globalcomment);
1207 #endif
1208     TRYFREE(zi);
1209
1210     return err;
1211 }