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