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