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