Next save.
[cacao.git] / unzip.c
1 #include "config.h"
2 #ifdef USE_ZLIB
3
4 /* unzip.c -- IO on .zip files using zlib 
5    Version 0.15 beta, Mar 19th, 1998,
6
7    Read unzip.h for more info
8 */
9
10 /* Modified my  Joseph Wenninger*/
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "zlib.h"
16 #include "unzip.h"
17 #include "toolbox/logging.h"
18
19 #ifdef STDC
20 #  include <stddef.h>
21 #  include <string.h>
22 #  include <stdlib.h>
23 #endif
24 #ifdef NO_ERRNO_H
25     extern int errno;
26 #else
27 #   include <errno.h>
28 #endif
29
30
31 #include "global.h"
32 #include "tables.h"
33
34
35
36
37 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
38                       !defined(CASESENSITIVITYDEFAULT_NO)
39 #define CASESENSITIVITYDEFAULT_NO
40 #endif
41
42
43 #ifndef UNZ_BUFSIZE
44 #define UNZ_BUFSIZE (16384)
45 #endif
46
47 #ifndef UNZ_MAXFILENAMEINZIP
48 #define UNZ_MAXFILENAMEINZIP (256)
49 #endif
50
51 #ifndef ALLOC
52 # define ALLOC(size) (malloc(size))
53 #endif
54 #ifndef TRYFREE
55 # define TRYFREE(p) {if (p) free(p);}
56 #endif
57
58 #define SIZECENTRALDIRITEM (0x2e)
59 #define SIZEZIPLOCALHEADER (0x1e)
60
61
62 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
63
64 #ifndef SEEK_CUR
65 #define SEEK_CUR    1
66 #endif
67
68 #ifndef SEEK_END
69 #define SEEK_END    2
70 #endif
71
72 #ifndef SEEK_SET
73 #define SEEK_SET    0
74 #endif
75
76 const char unz_copyright[] =
77    " unzip 0.15 Copyright 1998 Gilles Vollant ";
78
79
80 /* ===========================================================================
81      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
82    for end of file.
83    IN assertion: the stream s has been sucessfully opened for reading.
84 */
85
86
87  int unzlocal_getByte(fin,pi)
88         FILE *fin;
89         int *pi;
90 {
91     unsigned char c;
92         int err = fread(&c, 1, 1, fin);
93     if (err==1)
94     {
95         *pi = (int)c;
96         return UNZ_OK;
97     }
98     else
99     {
100         if (ferror(fin)) 
101             return UNZ_ERRNO;
102         else
103             return UNZ_EOF;
104     }
105 }
106
107
108 /* ===========================================================================
109    Reads a long in LSB order from the given gz_stream. Sets 
110 */
111  int unzlocal_getShort (fin,pX)
112         FILE* fin;
113     uLong *pX;
114 {
115     uLong x ;
116     int i;
117     int err;
118
119     err = unzlocal_getByte(fin,&i);
120     x = (uLong)i;
121     
122     if (err==UNZ_OK)
123         err = unzlocal_getByte(fin,&i);
124     x += ((uLong)i)<<8;
125    
126     if (err==UNZ_OK)
127         *pX = x;
128     else
129         *pX = 0;
130     return err;
131 }
132
133  int unzlocal_getLong (fin,pX)
134         FILE* fin;
135     uLong *pX;
136 {
137     uLong x ;
138     int i;
139     int err;
140
141     err = unzlocal_getByte(fin,&i);
142     x = (uLong)i;
143     
144     if (err==UNZ_OK)
145         err = unzlocal_getByte(fin,&i);
146     x += ((uLong)i)<<8;
147
148     if (err==UNZ_OK)
149         err = unzlocal_getByte(fin,&i);
150     x += ((uLong)i)<<16;
151
152     if (err==UNZ_OK)
153         err = unzlocal_getByte(fin,&i);
154     x += ((uLong)i)<<24;
155    
156     if (err==UNZ_OK)
157         *pX = x;
158     else
159         *pX = 0;
160     return err;
161 }
162
163
164 /* My own strcmpi / strcasecmp */
165  int strcmpcasenosensitive_internal (fileName1,fileName2)
166         const char* fileName1;
167         const char* fileName2;
168 {
169         for (;;)
170         {
171                 char c1=*(fileName1++);
172                 char c2=*(fileName2++);
173                 if ((c1>='a') && (c1<='z'))
174                         c1 -= 0x20;
175                 if ((c2>='a') && (c2<='z'))
176                         c2 -= 0x20;
177                 if (c1=='\0')
178                         return ((c2=='\0') ? 0 : -1);
179                 if (c2=='\0')
180                         return 1;
181                 if (c1<c2)
182                         return -1;
183                 if (c1>c2)
184                         return 1;
185         }
186 }
187
188
189 #ifdef  CASESENSITIVITYDEFAULT_NO
190 #define CASESENSITIVITYDEFAULTVALUE 2
191 #else
192 #define CASESENSITIVITYDEFAULTVALUE 1
193 #endif
194
195 #ifndef STRCMPCASENOSENTIVEFUNCTION
196 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
197 #endif
198
199 /* 
200    Compare two filename (fileName1,fileName2).
201    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
202    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
203                                                                 or strcasecmp)
204    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
205         (like 1 on Unix, 2 on Windows)
206
207 */
208  int  unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
209         const char* fileName1;
210         const char* fileName2;
211         int iCaseSensitivity;
212 {
213         if (iCaseSensitivity==0)
214                 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
215
216         if (iCaseSensitivity==1)
217                 return strcmp(fileName1,fileName2);
218
219         return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
220
221
222 #define BUFREADCOMMENT (0x400)
223
224 /*
225   Locate the Central directory of a zipfile (at the end, just before
226     the global comment)
227 */
228  uLong unzlocal_SearchCentralDir(fin)
229         FILE *fin;
230 {
231         unsigned char* buf;
232         uLong uSizeFile;
233         uLong uBackRead;
234         uLong uMaxBack=0xffff; /* maximum size of global comment */
235         uLong uPosFound=0;
236         
237         if (fseek(fin,0,SEEK_END) != 0)
238                 return 0;
239
240
241         uSizeFile = ftell( fin );
242         
243         if (uMaxBack>uSizeFile)
244                 uMaxBack = uSizeFile;
245
246         buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
247         if (buf==NULL)
248                 return 0;
249
250         uBackRead = 4;
251         while (uBackRead<uMaxBack)
252         {
253                 uLong uReadSize,uReadPos ;
254                 int i;
255                 if (uBackRead+BUFREADCOMMENT>uMaxBack) 
256                         uBackRead = uMaxBack;
257                 else
258                         uBackRead+=BUFREADCOMMENT;
259                 uReadPos = uSizeFile-uBackRead ;
260                 
261                 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
262                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
263                 if (fseek(fin,uReadPos,SEEK_SET)!=0)
264                         break;
265
266                 if (fread(buf,(uInt)uReadSize,1,fin)!=1)
267                         break;
268
269                 for (i=(int)uReadSize-3; (i--)>0;)
270                         if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
271                                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
272                         {
273                                 uPosFound = uReadPos+i;
274                                 break;
275                         }
276
277                 if (uPosFound!=0)
278                         break;
279         }
280         TRYFREE(buf);
281         return uPosFound;
282 }
283
284 /*
285   Open a Zip file. path contain the full pathname (by example,
286      on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
287          "zlib/zlib109.zip".
288          If the zipfile cannot be opened (file don't exist or in not valid), the
289            return value is NULL.
290      Else, the return value is a unzFile Handle, usable with other function
291            of this unzip package.
292 */
293  unzFile  unzOpen (path)
294         const char *path;
295 {
296         unz_s us;
297         unz_s *s;
298         uLong central_pos,uL;
299         FILE * fin ;
300
301         uLong number_disk;          /* number of the current dist, used for 
302                                                                    spaning ZIP, unsupported, always 0*/
303         uLong number_disk_with_CD;  /* number the the disk with central dir, used
304                                                                    for spaning ZIP, unsupported, always 0*/
305         uLong number_entry_CD;      /* total number of entries in
306                                        the central dir 
307                                        (same than number_entry on nospan) */
308
309         int err=UNZ_OK;
310
311     if (unz_copyright[0]!=' ')
312         return NULL;
313
314     fin=fopen(path,"rb");
315         if (fin==NULL)
316                 return NULL;
317
318         central_pos = unzlocal_SearchCentralDir(fin);
319         if (central_pos==0)
320                 err=UNZ_ERRNO;
321
322         if (fseek(fin,central_pos,SEEK_SET)!=0)
323                 err=UNZ_ERRNO;
324
325         /* the signature, already checked */
326         if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
327                 err=UNZ_ERRNO;
328
329         /* number of this disk */
330         if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
331                 err=UNZ_ERRNO;
332
333         /* number of the disk with the start of the central directory */
334         if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
335                 err=UNZ_ERRNO;
336
337         /* total number of entries in the central dir on this disk */
338         if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
339                 err=UNZ_ERRNO;
340
341         /* total number of entries in the central dir */
342         if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
343                 err=UNZ_ERRNO;
344
345         if ((number_entry_CD!=us.gi.number_entry) ||
346                 (number_disk_with_CD!=0) ||
347                 (number_disk!=0))
348                 err=UNZ_BADZIPFILE;
349
350         /* size of the central directory */
351         if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
352                 err=UNZ_ERRNO;
353         /* offset of start of central directory with respect to the 
354               starting disk number */
355         if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
356                 err=UNZ_ERRNO;
357
358         /* zipfile comment length */
359         if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
360                 err=UNZ_ERRNO;
361
362         if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
363                 (err==UNZ_OK))
364                 err=UNZ_BADZIPFILE;
365
366         if (err!=UNZ_OK)
367         {
368                 fclose(fin);
369                 return NULL;
370         }
371
372         us.file=fin;
373         us.byte_before_the_zipfile = central_pos -
374                                     (us.offset_central_dir+us.size_central_dir);
375         us.central_pos = central_pos;
376     us.pfile_in_zip_read = NULL;
377         
378
379         s=(unz_s*)ALLOC(sizeof(unz_s));
380         *s=us;
381
382         cacao_create_directoryList(s);
383
384         unzGoToFirstFile((unzFile)s);   
385         return (unzFile)s;      
386 }
387
388
389 /*
390   Close a ZipFile opened with unzipOpen.
391   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
392     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
393   return UNZ_OK if there is no problem. */
394  int  unzClose (file)
395         unzFile file;
396 {
397         unz_s* s;
398         if (file==NULL)
399                 return UNZ_PARAMERROR;
400         s=(unz_s*)file;
401
402     if (s->pfile_in_zip_read!=NULL)
403         unzCloseCurrentFile(file);
404
405         fclose(s->file);
406         TRYFREE(s);
407         return UNZ_OK;
408 }
409
410
411 /*
412   Write info about the ZipFile in the *pglobal_info structure.
413   No preparation of the structure is needed
414   return UNZ_OK if there is no problem. */
415  int  unzGetGlobalInfo (file,pglobal_info)
416         unzFile file;
417         unz_global_info *pglobal_info;
418 {
419         unz_s* s;
420         if (file==NULL)
421                 return UNZ_PARAMERROR;
422         s=(unz_s*)file;
423         *pglobal_info=s->gi;
424         return UNZ_OK;
425 }
426
427
428 /*
429    Translate date/time from Dos format to tm_unz (readable more easilty)
430 */
431  void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
432     uLong ulDosDate;
433     tm_unz* ptm;
434 {
435     uLong uDate;
436     uDate = (uLong)(ulDosDate>>16);
437     ptm->tm_mday = (uInt)(uDate&0x1f) ;
438     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
439     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
440
441     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
442     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
443     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
444 }
445
446 /*
447   Get Info about the current file in the zipfile, with internal only info
448 */
449  int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
450                                                   unz_file_info *pfile_info,
451                                                   unz_file_info_internal 
452                                                   *pfile_info_internal,
453                                                   char *szFileName,
454                                                                                                   uLong fileNameBufferSize,
455                                                   void *extraField,
456                                                                                                   uLong extraFieldBufferSize,
457                                                   char *szComment,
458                                                                                                   uLong commentBufferSize));
459
460  int unzlocal_GetCurrentFileInfoInternal (file,
461                                               pfile_info,
462                                               pfile_info_internal,
463                                               szFileName, fileNameBufferSize,
464                                               extraField, extraFieldBufferSize,
465                                               szComment,  commentBufferSize)
466         unzFile file;
467         unz_file_info *pfile_info;
468         unz_file_info_internal *pfile_info_internal;
469         char *szFileName;
470         uLong fileNameBufferSize;
471         void *extraField;
472         uLong extraFieldBufferSize;
473         char *szComment;
474         uLong commentBufferSize;
475 {
476         unz_s* s;
477         unz_file_info file_info;
478         unz_file_info_internal file_info_internal;
479         int err=UNZ_OK;
480         uLong uMagic;
481         long lSeek=0;
482
483         if (file==NULL)
484                 return UNZ_PARAMERROR;
485         s=(unz_s*)file;
486         if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
487                 err=UNZ_ERRNO;
488
489
490         /* we check the magic */
491         if (err==UNZ_OK) {
492                 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
493                         err=UNZ_ERRNO;
494                 else if (uMagic!=0x02014b50)
495                         err=UNZ_BADZIPFILE;
496         }
497
498         if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
499                 err=UNZ_ERRNO;
500
501         if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
502                 err=UNZ_ERRNO;
503
504         if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
505                 err=UNZ_ERRNO;
506
507         if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
508                 err=UNZ_ERRNO;
509
510         if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
511                 err=UNZ_ERRNO;
512
513     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
514
515         if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
516                 err=UNZ_ERRNO;
517
518         if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
519                 err=UNZ_ERRNO;
520
521         if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
522                 err=UNZ_ERRNO;
523
524         if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
525                 err=UNZ_ERRNO;
526
527         if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
528                 err=UNZ_ERRNO;
529
530         if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
531                 err=UNZ_ERRNO;
532
533         if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
534                 err=UNZ_ERRNO;
535
536         if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
537                 err=UNZ_ERRNO;
538
539         if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
540                 err=UNZ_ERRNO;
541
542         if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
543                 err=UNZ_ERRNO;
544
545         lSeek+=file_info.size_filename;
546         if ((err==UNZ_OK) && (szFileName!=NULL))
547         {
548                 uLong uSizeRead ;
549                 if (file_info.size_filename<fileNameBufferSize)
550                 {
551                         *(szFileName+file_info.size_filename)='\0';
552                         uSizeRead = file_info.size_filename;
553                 }
554                 else
555                         uSizeRead = fileNameBufferSize;
556
557                 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
558                         if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
559                                 err=UNZ_ERRNO;
560                 lSeek -= uSizeRead;
561         }
562
563         
564         if ((err==UNZ_OK) && (extraField!=NULL))
565         {
566                 uLong uSizeRead ;
567                 if (file_info.size_file_extra<extraFieldBufferSize)
568                         uSizeRead = file_info.size_file_extra;
569                 else
570                         uSizeRead = extraFieldBufferSize;
571
572                 if (lSeek!=0) {
573                         if (fseek(s->file,lSeek,SEEK_CUR)==0)
574                                 lSeek=0;
575                         else
576                                 err=UNZ_ERRNO;
577                 }
578
579                 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
580                         if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
581                                 err=UNZ_ERRNO;
582                 lSeek += file_info.size_file_extra - uSizeRead;
583         }
584         else
585                 lSeek+=file_info.size_file_extra; 
586
587         
588         if ((err==UNZ_OK) && (szComment!=NULL))
589         {
590                 uLong uSizeRead ;
591                 if (file_info.size_file_comment<commentBufferSize)
592                 {
593                         *(szComment+file_info.size_file_comment)='\0';
594                         uSizeRead = file_info.size_file_comment;
595                 }
596                 else
597                         uSizeRead = commentBufferSize;
598
599                 if (lSeek!=0) {
600                         if (fseek(s->file,lSeek,SEEK_CUR)==0)
601                                 lSeek=0;
602                         else
603                                 err=UNZ_ERRNO;
604                 }
605
606                 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
607                         if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
608                                 err=UNZ_ERRNO;
609                 lSeek+=file_info.size_file_comment - uSizeRead;
610         }
611         else
612                 lSeek+=file_info.size_file_comment;
613
614         if ((err==UNZ_OK) && (pfile_info!=NULL))
615                 *pfile_info=file_info;
616
617         if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
618                 *pfile_info_internal=file_info_internal;
619
620         return err;
621 }
622
623
624
625 /*
626   Write info about the ZipFile in the *pglobal_info structure.
627   No preparation of the structure is needed
628   return UNZ_OK if there is no problem.
629 */
630  int  unzGetCurrentFileInfo (file,
631                                                   pfile_info,
632                                                   szFileName, fileNameBufferSize,
633                                                   extraField, extraFieldBufferSize,
634                                                   szComment,  commentBufferSize)
635         unzFile file;
636         unz_file_info *pfile_info;
637         char *szFileName;
638         uLong fileNameBufferSize;
639         void *extraField;
640         uLong extraFieldBufferSize;
641         char *szComment;
642         uLong commentBufferSize;
643 {
644         return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
645                                                                                                 szFileName,fileNameBufferSize,
646                                                                                                 extraField,extraFieldBufferSize,
647                                                                                                 szComment,commentBufferSize);
648 }
649
650 /*
651   Set the current file of the zipfile to the first file.
652   return UNZ_OK if there is no problem
653 */
654  int  unzGoToFirstFile (file)
655         unzFile file;
656 {
657         int err=UNZ_OK;
658         unz_s* s;
659         if (file==NULL)
660                 return UNZ_PARAMERROR;
661         s=(unz_s*)file;
662         s->pos_in_central_dir=s->offset_central_dir;
663         s->num_file=0;
664         err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
665                                                                                          &s->cur_file_info_internal,
666                                                                                          NULL,0,NULL,0,NULL,0);
667         s->current_file_ok = (err == UNZ_OK);
668         return err;
669 }
670
671
672
673 /*
674   Set the current file of the zipfile to the next file.
675   return UNZ_OK if there is no problem
676   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
677 */
678  int  unzGoToNextFile (file)
679         unzFile file;
680 {
681         unz_s* s;       
682         int err;
683
684         if (file==NULL)
685                 return UNZ_PARAMERROR;
686         s=(unz_s*)file;
687         if (!s->current_file_ok)
688                 return UNZ_END_OF_LIST_OF_FILE;
689         if (s->num_file+1==s->gi.number_entry)
690                 return UNZ_END_OF_LIST_OF_FILE;
691
692         s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
693                         s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
694         s->num_file++;
695         err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
696                                                                                            &s->cur_file_info_internal,
697                                                                                            NULL,0,NULL,0,NULL,0);
698         s->current_file_ok = (err == UNZ_OK);
699         return err;
700 }
701
702
703 void cacao_create_directoryList(unzFile file)
704 {
705   cacao_entry_s* ent;
706         unz_s* s=(unz_s*)file;
707         char *c;
708         int i;
709         unz_file_info tmp;
710         char filename[200];
711         if (unzGoToFirstFile(file)!=UNZ_OK) {
712                 s->cacao_dir_list=0;
713                 return;
714         }
715         i=0;
716         ent = s->cacao_dir_list = (cacao_entry_s *) ALLOC(sizeof(cacao_entry_s));
717         ent->next=0;
718         ent->pos=s->pos_in_central_dir;
719
720         if (unzGetCurrentFileInfo (file,
721                                                   &tmp,
722                                                   filename, 200,
723                                                   0, 0,
724                                                   0,  0) !=UNZ_OK) {
725         
726                 panic("Error in ZIP archive");
727         }
728
729
730
731         ent->name=utf_new_char(filename);
732         while (unzGoToNextFile(file)==UNZ_OK) {
733                 i++;
734                 ent->next=(cacao_entry_s*)ALLOC(sizeof(cacao_entry_s));
735                 ent=ent->next;
736                 ent->next=0;
737                 ent->pos=s->pos_in_central_dir;
738
739                 if (unzGetCurrentFileInfo (file,
740                                                   &tmp,
741                                                   filename, 200,
742                                                   0, 0,
743                                                   0,  0) !=UNZ_OK) {
744         
745                         panic("Error in ZIP archive");
746                 }
747                 c=strstr(filename,".class");
748                 if (c) *c='\0';
749                 ent->name=utf_new_char(filename);
750         };
751         /*printf("Archive contains %d files\n",i);*/
752 }
753
754
755 /*
756   Try locate the file szFileName in the zipfile.
757   For the iCaseSensitivity signification, see unzipStringFileNameCompare
758
759   return value :
760   UNZ_OK if the file is found. It becomes the current file.
761   UNZ_END_OF_LIST_OF_FILE if the file is not found
762 */
763  int  unzLocateFile (file, szFileName, iCaseSensitivity)
764         unzFile file;
765         const char *szFileName;
766         int iCaseSensitivity;
767 {
768         unz_s* s;       
769         int err;
770
771         
772         uLong num_fileSaved;
773         uLong pos_in_central_dirSaved;
774
775         printf("Starting lookup\n");
776         fflush(stdout);
777
778         if (file==NULL)
779                 return UNZ_PARAMERROR;
780
781     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
782         return UNZ_PARAMERROR;
783
784         s=(unz_s*)file;
785         if (!s->current_file_ok)
786                 return UNZ_END_OF_LIST_OF_FILE;
787
788         num_fileSaved = s->num_file;
789         pos_in_central_dirSaved = s->pos_in_central_dir;
790
791         err = unzGoToFirstFile(file);
792
793         while (err == UNZ_OK)
794         {
795                 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
796                 unzGetCurrentFileInfo(file,NULL,
797                                                                 szCurrentFileName,sizeof(szCurrentFileName)-1,
798                                                                 NULL,0,NULL,0);
799                 if (unzStringFileNameCompare(szCurrentFileName,
800                                                                                 szFileName,iCaseSensitivity)==0) {
801                 printf("class found in zip directory\n");
802                 fflush(stdout);
803
804                         return UNZ_OK;
805                 }
806                 err = unzGoToNextFile(file);
807         }
808
809         s->num_file = num_fileSaved ;
810         s->pos_in_central_dir = pos_in_central_dirSaved ;
811         return err;
812 }
813
814 int cacao_locate(unzFile file,utf* filename) {
815         unz_s* s=(unz_s*)file;
816         cacao_entry_s *ent;
817         for (ent=s->cacao_dir_list;ent;ent=ent->next) {
818 /*              printf("searching: ");utf_display(filename);
819                 printf(" current: ");utf_display(ent->name);
820                 printf("\n");*/
821                 if (ent->name==filename) {
822                         s->pos_in_central_dir=ent->pos;
823                         return  unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
824                                                                                            &s->cur_file_info_internal,
825                                                                                            NULL,0,NULL,0,NULL,0);
826                 }
827         }
828         return UNZ_END_OF_LIST_OF_FILE;
829         /*return 0;*/
830 }
831
832 /*
833   Read the local header of the current zipfile
834   Check the coherency of the local header and info in the end of central
835         directory about this file
836   store in *piSizeVar the size of extra info in local header
837         (filename and size of extra field data)
838 */
839  int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
840                                                                                                         poffset_local_extrafield,
841                                                                                                         psize_local_extrafield)
842         unz_s* s;
843         uInt* piSizeVar;
844         uLong *poffset_local_extrafield;
845         uInt  *psize_local_extrafield;
846 {
847         uLong uMagic,uData,uFlags;
848         uLong size_filename;
849         uLong size_extra_field;
850         int err=UNZ_OK;
851
852         *piSizeVar = 0;
853         *poffset_local_extrafield = 0;
854         *psize_local_extrafield = 0;
855
856         if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
857                                                                 s->byte_before_the_zipfile,SEEK_SET)!=0)
858                 return UNZ_ERRNO;
859
860
861         if (err==UNZ_OK) {
862                 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
863                         err=UNZ_ERRNO;
864                 else if (uMagic!=0x04034b50)
865                         err=UNZ_BADZIPFILE;
866         }
867
868         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
869                 err=UNZ_ERRNO;
870 /*
871         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
872                 err=UNZ_BADZIPFILE;
873 */
874         if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
875                 err=UNZ_ERRNO;
876
877         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
878                 err=UNZ_ERRNO;
879         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
880                 err=UNZ_BADZIPFILE;
881
882     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
883                          (s->cur_file_info.compression_method!=Z_DEFLATED))
884         err=UNZ_BADZIPFILE;
885
886         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
887                 err=UNZ_ERRNO;
888
889         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
890                 err=UNZ_ERRNO;
891         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
892                                       ((uFlags & 8)==0))
893                 err=UNZ_BADZIPFILE;
894
895         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
896                 err=UNZ_ERRNO;
897         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
898                                                           ((uFlags & 8)==0))
899                 err=UNZ_BADZIPFILE;
900
901         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
902                 err=UNZ_ERRNO;
903         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
904                                                           ((uFlags & 8)==0))
905                 err=UNZ_BADZIPFILE;
906
907
908         if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
909                 err=UNZ_ERRNO;
910         else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
911                 err=UNZ_BADZIPFILE;
912
913         *piSizeVar += (uInt)size_filename;
914
915         if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
916                 err=UNZ_ERRNO;
917         *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
918                                                                         SIZEZIPLOCALHEADER + size_filename;
919         *psize_local_extrafield = (uInt)size_extra_field;
920
921         *piSizeVar += (uInt)size_extra_field;
922
923         return err;
924 }
925                                                                                                 
926 /*
927   Open for reading data the current file in the zipfile.
928   If there is no error and the file is opened, the return value is UNZ_OK.
929 */
930  int  unzOpenCurrentFile (file)
931         unzFile file;
932 {
933         int err=UNZ_OK;
934         int Store;
935         uInt iSizeVar;
936         unz_s* s;
937         file_in_zip_read_info_s* pfile_in_zip_read_info;
938         uLong offset_local_extrafield;  /* offset of the local extra field */
939         uInt  size_local_extrafield;    /* size of the local extra field */
940
941         if (file==NULL)
942                 return UNZ_PARAMERROR;
943         s=(unz_s*)file;
944         if (!s->current_file_ok)
945                 return UNZ_PARAMERROR;
946
947     if (s->pfile_in_zip_read != NULL)
948         unzCloseCurrentFile(file);
949
950         if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
951                                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
952                 return UNZ_BADZIPFILE;
953
954         pfile_in_zip_read_info = (file_in_zip_read_info_s*)
955                                                                             ALLOC(sizeof(file_in_zip_read_info_s));
956         if (pfile_in_zip_read_info==NULL)
957                 return UNZ_INTERNALERROR;
958
959         pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
960         pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
961         pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
962         pfile_in_zip_read_info->pos_local_extrafield=0;
963
964         if (pfile_in_zip_read_info->read_buffer==NULL)
965         {
966                 TRYFREE(pfile_in_zip_read_info);
967                 return UNZ_INTERNALERROR;
968         }
969
970         pfile_in_zip_read_info->stream_initialised=0;
971         
972         if ((s->cur_file_info.compression_method!=0) &&
973         (s->cur_file_info.compression_method!=Z_DEFLATED))
974                 err=UNZ_BADZIPFILE;
975         Store = s->cur_file_info.compression_method==0;
976
977         pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
978         pfile_in_zip_read_info->crc32=0;
979         pfile_in_zip_read_info->compression_method =
980             s->cur_file_info.compression_method;
981         pfile_in_zip_read_info->file=s->file;
982         pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
983
984     pfile_in_zip_read_info->stream.total_out = 0;
985
986         if (!Store)
987         {
988           pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
989           pfile_in_zip_read_info->stream.zfree = (free_func)0;
990           pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
991       
992           err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
993           if (err == Z_OK)
994             pfile_in_zip_read_info->stream_initialised=1;
995         /* windowBits is passed < 0 to tell that there is no zlib header.
996          * Note that in this case inflate *requires* an extra "dummy" byte
997          * after the compressed stream in order to complete decompression and
998          * return Z_STREAM_END. 
999          * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
1000          * size of both compressed and uncompressed data
1001          */
1002         }
1003         pfile_in_zip_read_info->rest_read_compressed = 
1004             s->cur_file_info.compressed_size ;
1005         pfile_in_zip_read_info->rest_read_uncompressed = 
1006             s->cur_file_info.uncompressed_size ;
1007
1008         
1009         pfile_in_zip_read_info->pos_in_zipfile = 
1010             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
1011                           iSizeVar;
1012         
1013         pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1014
1015
1016         s->pfile_in_zip_read = pfile_in_zip_read_info;
1017
1018     return UNZ_OK;
1019 }
1020
1021
1022 /*
1023   Read bytes from the current file.
1024   buf contain buffer where data must be copied
1025   len the size of buf.
1026
1027   return the number of byte copied if somes bytes are copied
1028   return 0 if the end of file was reached
1029   return <0 with error code if there is an error
1030     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1031 */
1032  int  unzReadCurrentFile  (file, buf, len)
1033         unzFile file;
1034         voidp buf;
1035         unsigned len;
1036 {
1037         int err=UNZ_OK;
1038         uInt iRead = 0;
1039         unz_s* s;
1040         file_in_zip_read_info_s* pfile_in_zip_read_info;
1041         if (file==NULL)
1042                 return UNZ_PARAMERROR;
1043         s=(unz_s*)file;
1044     pfile_in_zip_read_info=s->pfile_in_zip_read;
1045
1046         if (pfile_in_zip_read_info==NULL)
1047                 return UNZ_PARAMERROR;
1048
1049
1050         if ((pfile_in_zip_read_info->read_buffer == NULL))
1051                 return UNZ_END_OF_LIST_OF_FILE;
1052         if (len==0)
1053                 return 0;
1054
1055         pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1056
1057         pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1058         
1059         if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1060                 pfile_in_zip_read_info->stream.avail_out = 
1061                   (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1062
1063         while (pfile_in_zip_read_info->stream.avail_out>0)
1064         {
1065                 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1066             (pfile_in_zip_read_info->rest_read_compressed>0))
1067                 {
1068                         uInt uReadThis = UNZ_BUFSIZE;
1069                         if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1070                                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1071                         if (uReadThis == 0)
1072                                 return UNZ_EOF;
1073                         if (fseek(pfile_in_zip_read_info->file,
1074                       pfile_in_zip_read_info->pos_in_zipfile + 
1075                          pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1076                                 return UNZ_ERRNO;
1077                         if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1078                          pfile_in_zip_read_info->file)!=1)
1079                                 return UNZ_ERRNO;
1080                         pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1081
1082                         pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1083                         
1084                         pfile_in_zip_read_info->stream.next_in = 
1085                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1086                         pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1087                 }
1088
1089                 if (pfile_in_zip_read_info->compression_method==0)
1090                 {
1091                         uInt uDoCopy,i ;
1092                         if (pfile_in_zip_read_info->stream.avail_out < 
1093                             pfile_in_zip_read_info->stream.avail_in)
1094                                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1095                         else
1096                                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1097                                 
1098                         for (i=0;i<uDoCopy;i++)
1099                                 *(pfile_in_zip_read_info->stream.next_out+i) =
1100                         *(pfile_in_zip_read_info->stream.next_in+i);
1101                                         
1102                         pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1103                                                                 pfile_in_zip_read_info->stream.next_out,
1104                                                                 uDoCopy);
1105                         pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1106                         pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1107                         pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1108                         pfile_in_zip_read_info->stream.next_out += uDoCopy;
1109                         pfile_in_zip_read_info->stream.next_in += uDoCopy;
1110             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1111                         iRead += uDoCopy;
1112                 }
1113                 else
1114                 {
1115                         uLong uTotalOutBefore,uTotalOutAfter;
1116                         const Bytef *bufBefore;
1117                         uLong uOutThis;
1118                         int flush=Z_SYNC_FLUSH;
1119
1120                         uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1121                         bufBefore = pfile_in_zip_read_info->stream.next_out;
1122
1123                         /*
1124                         if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1125                                  pfile_in_zip_read_info->stream.avail_out) &&
1126                                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1127                                 flush = Z_FINISH;
1128                         */
1129                         err=inflate(&pfile_in_zip_read_info->stream,flush);
1130
1131                         uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1132                         uOutThis = uTotalOutAfter-uTotalOutBefore;
1133                         
1134                         pfile_in_zip_read_info->crc32 = 
1135                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1136                         (uInt)(uOutThis));
1137
1138                         pfile_in_zip_read_info->rest_read_uncompressed -=
1139                 uOutThis;
1140
1141                         iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1142             
1143                         if (err==Z_STREAM_END)
1144                                 return (iRead==0) ? UNZ_EOF : iRead;
1145                         if (err!=Z_OK) 
1146                                 break;
1147                 }
1148         }
1149
1150         if (err==Z_OK)
1151                 return iRead;
1152         return err;
1153 }
1154
1155
1156 /*
1157   Give the current position in uncompressed data
1158 */
1159  z_off_t  unztell (file)
1160         unzFile file;
1161 {
1162         unz_s* s;
1163         file_in_zip_read_info_s* pfile_in_zip_read_info;
1164         if (file==NULL)
1165                 return UNZ_PARAMERROR;
1166         s=(unz_s*)file;
1167     pfile_in_zip_read_info=s->pfile_in_zip_read;
1168
1169         if (pfile_in_zip_read_info==NULL)
1170                 return UNZ_PARAMERROR;
1171
1172         return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1173 }
1174
1175
1176 /*
1177   return 1 if the end of file was reached, 0 elsewhere 
1178 */
1179  int  unzeof (file)
1180         unzFile file;
1181 {
1182         unz_s* s;
1183         file_in_zip_read_info_s* pfile_in_zip_read_info;
1184         if (file==NULL)
1185                 return UNZ_PARAMERROR;
1186         s=(unz_s*)file;
1187     pfile_in_zip_read_info=s->pfile_in_zip_read;
1188
1189         if (pfile_in_zip_read_info==NULL)
1190                 return UNZ_PARAMERROR;
1191         
1192         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1193                 return 1;
1194         else
1195                 return 0;
1196 }
1197
1198
1199
1200 /*
1201   Read extra field from the current file (opened by unzOpenCurrentFile)
1202   This is the local-header version of the extra field (sometimes, there is
1203     more info in the local-header version than in the central-header)
1204
1205   if buf==NULL, it return the size of the local extra field that can be read
1206
1207   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1208         buf.
1209   the return value is the number of bytes copied in buf, or (if <0) 
1210         the error code
1211 */
1212  int  unzGetLocalExtrafield (file,buf,len)
1213         unzFile file;
1214         voidp buf;
1215         unsigned len;
1216 {
1217         unz_s* s;
1218         file_in_zip_read_info_s* pfile_in_zip_read_info;
1219         uInt read_now;
1220         uLong size_to_read;
1221
1222         if (file==NULL)
1223                 return UNZ_PARAMERROR;
1224         s=(unz_s*)file;
1225     pfile_in_zip_read_info=s->pfile_in_zip_read;
1226
1227         if (pfile_in_zip_read_info==NULL)
1228                 return UNZ_PARAMERROR;
1229
1230         size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
1231                                 pfile_in_zip_read_info->pos_local_extrafield);
1232
1233         if (buf==NULL)
1234                 return (int)size_to_read;
1235         
1236         if (len>size_to_read)
1237                 read_now = (uInt)size_to_read;
1238         else
1239                 read_now = (uInt)len ;
1240
1241         if (read_now==0)
1242                 return 0;
1243         
1244         if (fseek(pfile_in_zip_read_info->file,
1245               pfile_in_zip_read_info->offset_local_extrafield + 
1246                           pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1247                 return UNZ_ERRNO;
1248
1249         if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1250                 return UNZ_ERRNO;
1251
1252         return (int)read_now;
1253 }
1254
1255 /*
1256   Close the file in zip opened with unzipOpenCurrentFile
1257   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1258 */
1259  int  unzCloseCurrentFile (file)
1260         unzFile file;
1261 {
1262         int err=UNZ_OK;
1263
1264         unz_s* s;
1265         file_in_zip_read_info_s* pfile_in_zip_read_info;
1266         if (file==NULL)
1267                 return UNZ_PARAMERROR;
1268         s=(unz_s*)file;
1269     pfile_in_zip_read_info=s->pfile_in_zip_read;
1270
1271         if (pfile_in_zip_read_info==NULL)
1272                 return UNZ_PARAMERROR;
1273
1274
1275         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1276         {
1277                 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1278                         err=UNZ_CRCERROR;
1279         }
1280
1281
1282         TRYFREE(pfile_in_zip_read_info->read_buffer);
1283         pfile_in_zip_read_info->read_buffer = NULL;
1284         if (pfile_in_zip_read_info->stream_initialised)
1285                 inflateEnd(&pfile_in_zip_read_info->stream);
1286
1287         pfile_in_zip_read_info->stream_initialised = 0;
1288         TRYFREE(pfile_in_zip_read_info);
1289
1290     s->pfile_in_zip_read=NULL;
1291
1292         return err;
1293 }
1294
1295
1296 /*
1297   Get the global comment string of the ZipFile, in the szComment buffer.
1298   uSizeBuf is the size of the szComment buffer.
1299   return the number of byte copied or an error code <0
1300 */
1301  int  unzGetGlobalComment (file, szComment, uSizeBuf)
1302         unzFile file;
1303         char *szComment;
1304         uLong uSizeBuf;
1305 {
1306         int err=UNZ_OK;
1307         unz_s* s;
1308         uLong uReadThis ;
1309         if (file==NULL)
1310                 return UNZ_PARAMERROR;
1311         s=(unz_s*)file;
1312
1313         uReadThis = uSizeBuf;
1314         if (uReadThis>s->gi.size_comment)
1315                 uReadThis = s->gi.size_comment;
1316
1317         if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1318                 return UNZ_ERRNO;
1319
1320         if (uReadThis>0)
1321     {
1322       *szComment='\0';
1323           if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1324                 return UNZ_ERRNO;
1325     }
1326
1327         if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1328                 *(szComment+s->gi.size_comment)='\0';
1329         return (int)uReadThis;
1330 }
1331
1332 #endif