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