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