OSDN Git Service

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