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