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