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