1 /* unzip.c -- IO for uncompress .zip files using zlib
2    Version 1.01e, February 12th, 2005
3 
4    Copyright (C) 1998-2005 Gilles Vollant
5 
6    Read unzip.h for more info
7 */
8 
9 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
10 compatibility with older software. The following is from the original crypt.c. Code
11 woven in by Terry Thorsen 1/2003.
12 */
13 /*
14   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
15 
16   See the accompanying file LICENSE, version 2000-Apr-09 or later
17   (the contents of which are also included in zip.h) for terms of use.
18   If, for some reason, all these files are missing, the Info-ZIP license
19   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
20 */
21 /*
22   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
23 
24   The encryption/decryption parts of this source code (as opposed to the
25   non-echoing password parts) were originally written in Europe.  The
26   whole source package can be freely distributed, including from the USA.
27   (Prior to January 2000, re-export from the US was a violation of US law.)
28  */
29 
30 /*
31   This encryption code is a direct transcription of the algorithm from
32   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
33   file (appnote.txt) is distributed with the PKZIP program (even in the
34   version without encryption capabilities).
35  */
36 
37 
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <zlib.h> //RR
43 #include "unzip.h"
44 #include "iomem_simple.h"
45 #undef NOUNCRYPT
46 
47 #ifdef STDC
48 #  include <stddef.h>
49 #  include <string.h>
50 #  include <stdlib.h>
51 #endif
52 #ifdef NO_ERRNO_H
53     extern int errno;
54 #else
55 #   include <errno.h>
56 #endif
57 
58 
59 #ifndef local
60 #  define local static
61 #endif
62 /* compile with -Dlocal if your debugger can't find static symbols */
63 
64 
65 #ifndef CASESENSITIVITYDEFAULT_NO
66 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
67 #    define CASESENSITIVITYDEFAULT_NO
68 #  endif
69 #endif
70 
71 
72 #ifndef UNZ_BUFSIZE
73 #define UNZ_BUFSIZE (16384)
74 #endif
75 
76 #ifndef UNZ_MAXFILENAMEINZIP
77 #define UNZ_MAXFILENAMEINZIP (256)
78 #endif
79 
80 #ifndef ALLOC
81 # define ALLOC(size) (malloc(size))
82 #endif
83 #ifndef TRYFREE
84 # define TRYFREE(p) {if (p) free(p);}
85 #endif
86 
87 #define SIZECENTRALDIRITEM (0x2e)
88 #define SIZEZIPLOCALHEADER (0x1e)
89 
90 
91 
92 
93 const char libkml_unz_copyright[] =
94    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
95 
96 /* unz_file_info_interntal contain internal info about a file in zipfile*/
97 typedef struct unz_file_info_internal_s
98 {
99     uLong offset_curfile;/* relative offset of local header 4 bytes */
100 } unz_file_info_internal;
101 
102 
103 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
104     when reading and decompress it */
105 typedef struct
106 {
107     char  *read_buffer;         /* internal buffer for compressed data */
108     z_stream stream;            /* zLib stream structure for inflate */
109 
110     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
111     uLong stream_initialised;   /* flag set if stream structure is initialised*/
112 
113     uLong offset_local_extrafield;/* offset of the local extra field */
114     uInt  size_local_extrafield;/* size of the local extra field */
115     uLong pos_local_extrafield;   /* position in the local extra field in read*/
116 
117     uLong crc32;                /* crc32 of all data uncompressed */
118     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
119     uLong rest_read_compressed; /* number of byte to be decompressed */
120     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
121     zlib_filefunc_def z_filefunc;
122     voidpf filestream;        /* io structore of the zipfile */
123     uLong compression_method;   /* compression method (0==store) */
124     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
125     int   raw;
126 } file_in_zip_read_info_s;
127 
128 
129 /* unz_s contain internal information about the zipfile
130 */
131 typedef struct
132 {
133     zlib_filefunc_def z_filefunc;
134     voidpf filestream;        /* io structore of the zipfile */
135     unz_global_info gi;       /* public global information */
136     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
137     uLong num_file;             /* number of the current file in the zipfile*/
138     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
139     uLong current_file_ok;      /* flag about the usability of the current file*/
140     uLong central_pos;          /* position of the beginning of the central dir*/
141 
142     uLong size_central_dir;     /* size of the central directory  */
143     uLong offset_central_dir;   /* offset of start of central directory with
144                                    respect to the starting disk number */
145 
146     unz_file_info cur_file_info; /* public info about the current file in zip*/
147     unz_file_info_internal cur_file_info_internal; /* private info about it*/
148     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
149                                         file if we are decompressing it */
150     int encrypted;
151 #    ifndef NOUNCRYPT
152     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
153     const z_crc_t* pcrc_32_tab;
154 #    endif
155 } unz_s;
156 
init_unz_s(unz_s * un)157 void init_unz_s(unz_s* un)
158 {
159 
160   un->filestream = NULL;
161 
162   un->byte_before_the_zipfile = 0UL;
163   un->num_file = 0UL;
164   un->pos_in_central_dir = 0UL;
165   un->current_file_ok = 0UL;
166 
167   un->central_pos = 0UL;
168   un->size_central_dir  = 0UL;
169   un->offset_central_dir  = 0UL;
170 
171   un->pfile_in_zip_read = NULL;
172 
173   un->encrypted = 0;
174 #ifndef NOUNCRYPT
175   un->keys [0] = 0UL;
176   un->keys [1] = 0UL;
177   un->keys [2] = 0UL;
178   un->pcrc_32_tab = NULL;
179 #endif
180 }
181 
182 #ifndef NOUNCRYPT
183 #include <minizip/crypt.h>
184 #endif
185 
186 /* ===========================================================================
187      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
188    for end of file.
189    IN assertion: the stream s has been sucessfully opened for reading.
190 */
191 
192 
193 local int unzlocal_getByte OF((
194     const zlib_filefunc_def* pzlib_filefunc_def,
195     voidpf filestream,
196     int *pi));
197 
unzlocal_getByte(pzlib_filefunc_def,filestream,pi)198 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
199     const zlib_filefunc_def* pzlib_filefunc_def;
200     voidpf filestream;
201     int *pi;
202 {
203     unsigned char c;
204     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
205     if (err==1)
206     {
207         *pi = (int)c;
208         return UNZ_OK;
209     }
210     else
211     {
212         if (ZERROR(*pzlib_filefunc_def,filestream))
213             return UNZ_ERRNO;
214         else
215             return UNZ_EOF;
216     }
217 }
218 
219 
220 /* ===========================================================================
221    Reads a long in LSB order from the given gz_stream. Sets
222 */
223 local int unzlocal_getShort OF((
224     const zlib_filefunc_def* pzlib_filefunc_def,
225     voidpf filestream,
226     uLong *pX));
227 
unzlocal_getShort(pzlib_filefunc_def,filestream,pX)228 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
229     const zlib_filefunc_def* pzlib_filefunc_def;
230     voidpf filestream;
231     uLong *pX;
232 {
233     uLong x ;
234     int i = 0;
235     int err;
236 
237     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
238     x = (uLong)i;
239 
240     if (err==UNZ_OK)
241         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
242     x += ((uLong)i)<<8;
243 
244     if (err==UNZ_OK)
245         *pX = x;
246     else
247         *pX = 0;
248     return err;
249 }
250 
251 local int unzlocal_getLong OF((
252     const zlib_filefunc_def* pzlib_filefunc_def,
253     voidpf filestream,
254     uLong *pX));
255 
unzlocal_getLong(pzlib_filefunc_def,filestream,pX)256 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
257     const zlib_filefunc_def* pzlib_filefunc_def;
258     voidpf filestream;
259     uLong *pX;
260 {
261     uLong x ;
262     int i = 0;
263     int err;
264 
265     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
266     x = (uLong)i;
267 
268     if (err==UNZ_OK)
269         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
270     x += ((uLong)i)<<8;
271 
272     if (err==UNZ_OK)
273         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
274     x += ((uLong)i)<<16;
275 
276     if (err==UNZ_OK)
277         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
278     x += ((uLong)i)<<24;
279 
280     if (err==UNZ_OK)
281         *pX = x;
282     else
283         *pX = 0;
284     return err;
285 }
286 
287 
288 /* My own strcmpi / strcasecmp */
strcmpcasenosensitive_internal(fileName1,fileName2)289 local int strcmpcasenosensitive_internal (fileName1,fileName2)
290     const char* fileName1;
291     const char* fileName2;
292 {
293     for (;;)
294     {
295         char c1=*(fileName1++);
296         char c2=*(fileName2++);
297         if ((c1>='a') && (c1<='z'))
298             c1 -= 0x20;
299         if ((c2>='a') && (c2<='z'))
300             c2 -= 0x20;
301         if (c1=='\0')
302             return ((c2=='\0') ? 0 : -1);
303         if (c2=='\0')
304             return 1;
305         if (c1<c2)
306             return -1;
307         if (c1>c2)
308             return 1;
309     }
310 }
311 
312 
313 #ifdef  CASESENSITIVITYDEFAULT_NO
314 #define CASESENSITIVITYDEFAULTVALUE 2
315 #else
316 #define CASESENSITIVITYDEFAULTVALUE 1
317 #endif
318 
319 #ifndef STRCMPCASENOSENTIVEFUNCTION
320 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
321 #endif
322 
323 /*
324    Compare two filename (fileName1,fileName2).
325    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
326    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
327                                                                 or strcasecmp)
328    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
329         (like 1 on Unix, 2 on Windows)
330 
331 */
332 extern int ZEXPORT libkml_unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
333     const char* fileName1;
334     const char* fileName2;
335     int iCaseSensitivity;
336 {
337     if (iCaseSensitivity==0)
338         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
339 
340     if (iCaseSensitivity==1)
341         return strcmp(fileName1,fileName2);
342 
343     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
344 }
345 
346 #ifndef BUFREADCOMMENT
347 #define BUFREADCOMMENT (0x400)
348 #endif
349 
350 /*
351   Locate the Central directory of a zipfile (at the end, just before
352     the global comment)
353 */
354 local uLong unzlocal_SearchCentralDir OF((
355     const zlib_filefunc_def* pzlib_filefunc_def,
356     voidpf filestream));
357 
unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)358 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
359     const zlib_filefunc_def* pzlib_filefunc_def;
360     voidpf filestream;
361 {
362     unsigned char* buf;
363     uLong uSizeFile;
364     uLong uBackRead;
365     uLong uMaxBack=0xffff; /* maximum size of global comment */
366     uLong uPosFound=0;
367 
368     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
369         return 0;
370 
371 
372     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
373 
374     if (uMaxBack>uSizeFile)
375         uMaxBack = uSizeFile;
376 
377     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
378     if (buf==NULL)
379         return 0;
380 
381     uBackRead = 4;
382     while (uBackRead<uMaxBack)
383     {
384         uLong uReadSize,uReadPos ;
385         int i;
386         if (uBackRead+BUFREADCOMMENT>uMaxBack)
387             uBackRead = uMaxBack;
388         else
389             uBackRead+=BUFREADCOMMENT;
390         uReadPos = uSizeFile-uBackRead ;
391 
392         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
393                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
394         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
395             break;
396 
397         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
398             break;
399 
400         for (i=(int)uReadSize-3; (i--)>0;)
401             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
402                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
403             {
404                 uPosFound = uReadPos+i;
405                 break;
406             }
407 
408         if (uPosFound!=0)
409             break;
410     }
411     TRYFREE(buf);
412     return uPosFound;
413 }
414 
415 /*
416   Open a Zip file. path contain the full pathname (by example,
417      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
418      "zlib/zlib114.zip".
419      If the zipfile cannot be opened (file doesn't exist or in not valid), the
420        return value is NULL.
421      Else, the return value is a unzFile Handle, usable with other function
422        of this unzip package.
423 */
424 extern unzFile ZEXPORT libkml_unzOpen2 (path, pzlib_filefunc_def)
425     const char *path;
426     zlib_filefunc_def* pzlib_filefunc_def;
427 {
428     unz_s us;
429 
430     unz_s *s;
431 
432     uLong central_pos,uL;
433 
434     uLong number_disk;          /* number of the current dist, used for
435                                    spaning ZIP, unsupported, always 0*/
436     uLong number_disk_with_CD;  /* number the the disk with central dir, used
437                                    for spaning ZIP, unsupported, always 0*/
438     uLong number_entry_CD;      /* total number of entries in
439                                    the central dir
440                                    (same than number_entry on nospan) */
441 
442     int err=UNZ_OK;
443 
444     init_unz_s(&us);
445 
446     if (libkml_unz_copyright[0]!=' ')
447         return NULL;
448 
449     if (pzlib_filefunc_def==NULL)
450         fill_fopen_filefunc(&us.z_filefunc);
451     else
452         us.z_filefunc = *pzlib_filefunc_def;
453 
454     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
455                                                  path,
456                                                  ZLIB_FILEFUNC_MODE_READ |
457                                                  ZLIB_FILEFUNC_MODE_EXISTING);
458     if (us.filestream==NULL)
459         return NULL;
460 
461     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
462     if (central_pos==0)
463         err=UNZ_ERRNO;
464 
465     if (ZSEEK(us.z_filefunc, us.filestream,
466                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
467         err=UNZ_ERRNO;
468 
469     /* the signature, already checked */
470     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
471         err=UNZ_ERRNO;
472 
473     /* number of this disk */
474     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
475         err=UNZ_ERRNO;
476 
477     /* number of the disk with the start of the central directory */
478     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
479         err=UNZ_ERRNO;
480 
481     /* total number of entries in the central dir on this disk */
482     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
483         err=UNZ_ERRNO;
484 
485     /* total number of entries in the central dir */
486     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
487         err=UNZ_ERRNO;
488 
489     if ((number_entry_CD!=us.gi.number_entry) ||
490         (number_disk_with_CD!=0) ||
491         (number_disk!=0))
492         err=UNZ_BADZIPFILE;
493 
494     /* size of the central directory */
495     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
496         err=UNZ_ERRNO;
497 
498     /* offset of start of central directory with respect to the
499           starting disk number */
500     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
501         err=UNZ_ERRNO;
502 
503     /* zipfile comment length */
504     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
505         err=UNZ_ERRNO;
506 
507     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
508         (err==UNZ_OK))
509         err=UNZ_BADZIPFILE;
510 
511     if (err!=UNZ_OK)
512     {
513         ZCLOSE(us.z_filefunc, us.filestream);
514         return NULL;
515     }
516 
517     us.byte_before_the_zipfile = central_pos -
518                             (us.offset_central_dir+us.size_central_dir);
519     us.central_pos = central_pos;
520     us.pfile_in_zip_read = NULL;
521     us.encrypted = 0;
522 
523     s=(unz_s*)ALLOC(sizeof(unz_s));
524     *s=us;
525     libkml_unzGoToFirstFile((unzFile)s);
526     return (unzFile)s;
527 }
528 
529 
530 extern unzFile ZEXPORT libkml_unzOpen (path)
531     const char *path;
532 {
533     return libkml_unzOpen2(path, NULL);
534 }
535 
536 /*
537   Close a ZipFile opened with unzipOpen.
538   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
539     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
540   return UNZ_OK if there is no problem. */
541 extern int ZEXPORT libkml_unzClose (file)
542     unzFile file;
543 {
544     unz_s* s;
545     if (file==NULL)
546         return UNZ_PARAMERROR;
547     s=(unz_s*)file;
548 
549     if (s->pfile_in_zip_read!=NULL)
550         libkml_unzCloseCurrentFile(file);
551 
552     ZCLOSE(s->z_filefunc, s->filestream);
553     TRYFREE(s);
554     return UNZ_OK;
555 }
556 
557 
558 /*
559   Write info about the ZipFile in the *pglobal_info structure.
560   No preparation of the structure is needed
561   return UNZ_OK if there is no problem. */
562 extern int ZEXPORT libkml_unzGetGlobalInfo (file,pglobal_info)
563     unzFile file;
564     unz_global_info *pglobal_info;
565 {
566     unz_s* s;
567     if (file==NULL)
568         return UNZ_PARAMERROR;
569     s=(unz_s*)file;
570     *pglobal_info=s->gi;
571     return UNZ_OK;
572 }
573 
574 
575 /*
576    Translate date/time from Dos format to tm_unz (readable more easilty)
577 */
unzlocal_DosDateToTmuDate(ulDosDate,ptm)578 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
579     uLong ulDosDate;
580     tm_unz* ptm;
581 {
582     uLong uDate;
583     uDate = (uLong)(ulDosDate>>16);
584     ptm->tm_mday = (uInt)(uDate&0x1f) ;
585     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
586     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
587 
588     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
589     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
590     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
591 }
592 
593 /*
594   Get Info about the current file in the zipfile, with internal only info
595 */
596 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
597                                                   unz_file_info *pfile_info,
598                                                   unz_file_info_internal
599                                                   *pfile_info_internal,
600                                                   char *szFileName,
601                                                   uLong fileNameBufferSize,
602                                                   void *extraField,
603                                                   uLong extraFieldBufferSize,
604                                                   char *szComment,
605                                                   uLong commentBufferSize));
606 
unzlocal_GetCurrentFileInfoInternal(file,pfile_info,pfile_info_internal,szFileName,fileNameBufferSize,extraField,extraFieldBufferSize,szComment,commentBufferSize)607 local int unzlocal_GetCurrentFileInfoInternal (file,
608                                               pfile_info,
609                                               pfile_info_internal,
610                                               szFileName, fileNameBufferSize,
611                                               extraField, extraFieldBufferSize,
612                                               szComment,  commentBufferSize)
613     unzFile file;
614     unz_file_info *pfile_info;
615     unz_file_info_internal *pfile_info_internal;
616     char *szFileName;
617     uLong fileNameBufferSize;
618     void *extraField;
619     uLong extraFieldBufferSize;
620     char *szComment;
621     uLong commentBufferSize;
622 {
623     unz_s* s;
624     unz_file_info file_info;
625     unz_file_info_internal file_info_internal;
626     int err=UNZ_OK;
627     uLong uMagic;
628     long lSeek=0;
629 
630     if (file==NULL)
631         return UNZ_PARAMERROR;
632     s=(unz_s*)file;
633     if (ZSEEK(s->z_filefunc, s->filestream,
634               s->pos_in_central_dir+s->byte_before_the_zipfile,
635               ZLIB_FILEFUNC_SEEK_SET)!=0)
636         err=UNZ_ERRNO;
637 
638 
639     /* we check the magic */
640     if (err==UNZ_OK)
641         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
642             err=UNZ_ERRNO;
643         else if (uMagic!=0x02014b50)
644             err=UNZ_BADZIPFILE;
645 
646     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
647         err=UNZ_ERRNO;
648 
649     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
650         err=UNZ_ERRNO;
651 
652     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
653         err=UNZ_ERRNO;
654 
655     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
656         err=UNZ_ERRNO;
657 
658     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
659         err=UNZ_ERRNO;
660 
661     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
662 
663     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
664         err=UNZ_ERRNO;
665 
666     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
667         err=UNZ_ERRNO;
668 
669     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
670         err=UNZ_ERRNO;
671 
672     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
673         err=UNZ_ERRNO;
674 
675     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
676         err=UNZ_ERRNO;
677 
678     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
679         err=UNZ_ERRNO;
680 
681     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
682         err=UNZ_ERRNO;
683 
684     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
685         err=UNZ_ERRNO;
686 
687     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
688         err=UNZ_ERRNO;
689 
690     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
691         err=UNZ_ERRNO;
692 
693     lSeek+=file_info.size_filename;
694     if ((err==UNZ_OK) && (szFileName!=NULL))
695     {
696         uLong uSizeRead ;
697         if (file_info.size_filename<fileNameBufferSize)
698         {
699             *(szFileName+file_info.size_filename)='\0';
700             uSizeRead = file_info.size_filename;
701         }
702         else
703             uSizeRead = fileNameBufferSize;
704 
705         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
706             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
707                 err=UNZ_ERRNO;
708         lSeek -= uSizeRead;
709     }
710 
711 
712     if ((err==UNZ_OK) && (extraField!=NULL))
713     {
714         uLong uSizeRead ;
715         if (file_info.size_file_extra<extraFieldBufferSize)
716             uSizeRead = file_info.size_file_extra;
717         else
718             uSizeRead = extraFieldBufferSize;
719 
720         if (lSeek!=0)
721             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
722                 lSeek=0;
723             else
724                 err=UNZ_ERRNO;
725         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
726             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
727                 err=UNZ_ERRNO;
728         lSeek += file_info.size_file_extra - uSizeRead;
729     }
730     else
731         lSeek+=file_info.size_file_extra;
732 
733 
734     if ((err==UNZ_OK) && (szComment!=NULL))
735     {
736         uLong uSizeRead ;
737         if (file_info.size_file_comment<commentBufferSize)
738         {
739             *(szComment+file_info.size_file_comment)='\0';
740             uSizeRead = file_info.size_file_comment;
741         }
742         else
743             uSizeRead = commentBufferSize;
744 
745         if (lSeek!=0)
746             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
747                 lSeek=0;
748             else
749                 err=UNZ_ERRNO;
750         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
751             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
752                 err=UNZ_ERRNO;
753         lSeek+=file_info.size_file_comment - uSizeRead;
754     }
755     else
756         lSeek+=file_info.size_file_comment;
757 
758     if ((err==UNZ_OK) && (pfile_info!=NULL))
759         *pfile_info=file_info;
760 
761     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
762         *pfile_info_internal=file_info_internal;
763 
764     return err;
765 }
766 
767 
768 
769 /*
770   Write info about the ZipFile in the *pglobal_info structure.
771   No preparation of the structure is needed
772   return UNZ_OK if there is no problem.
773 */
774 extern int ZEXPORT libkml_unzGetCurrentFileInfo (file,
775                                           pfile_info,
776                                           szFileName, fileNameBufferSize,
777                                           extraField, extraFieldBufferSize,
778                                           szComment,  commentBufferSize)
779     unzFile file;
780     unz_file_info *pfile_info;
781     char *szFileName;
782     uLong fileNameBufferSize;
783     void *extraField;
784     uLong extraFieldBufferSize;
785     char *szComment;
786     uLong commentBufferSize;
787 {
788     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
789                                                 szFileName,fileNameBufferSize,
790                                                 extraField,extraFieldBufferSize,
791                                                 szComment,commentBufferSize);
792 }
793 
794 /*
795   Set the current file of the zipfile to the first file.
796   return UNZ_OK if there is no problem
797 */
798 extern int ZEXPORT libkml_unzGoToFirstFile (file)
799     unzFile file;
800 {
801     int err=UNZ_OK;
802     unz_s* s;
803     if (file==NULL)
804         return UNZ_PARAMERROR;
805     s=(unz_s*)file;
806     s->pos_in_central_dir=s->offset_central_dir;
807     s->num_file=0;
808     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
809                                              &s->cur_file_info_internal,
810                                              NULL,0,NULL,0,NULL,0);
811     s->current_file_ok = (err == UNZ_OK);
812     return err;
813 }
814 
815 /*
816   Set the current file of the zipfile to the next file.
817   return UNZ_OK if there is no problem
818   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
819 */
820 extern int ZEXPORT libkml_unzGoToNextFile (file)
821     unzFile file;
822 {
823     unz_s* s;
824     int err;
825 
826     if (file==NULL)
827         return UNZ_PARAMERROR;
828     s=(unz_s*)file;
829     if (!s->current_file_ok)
830         return UNZ_END_OF_LIST_OF_FILE;
831     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
832       if (s->num_file+1==s->gi.number_entry)
833         return UNZ_END_OF_LIST_OF_FILE;
834 
835     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
836             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
837     s->num_file++;
838     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
839                                                &s->cur_file_info_internal,
840                                                NULL,0,NULL,0,NULL,0);
841     s->current_file_ok = (err == UNZ_OK);
842     return err;
843 }
844 
845 
846 /*
847   Try locate the file szFileName in the zipfile.
848   For the iCaseSensitivity signification, see unzipStringFileNameCompare
849 
850   return value :
851   UNZ_OK if the file is found. It becomes the current file.
852   UNZ_END_OF_LIST_OF_FILE if the file is not found
853 */
854 extern int ZEXPORT libkml_unzLocateFile (file, szFileName, iCaseSensitivity)
855     unzFile file;
856     const char *szFileName;
857     int iCaseSensitivity;
858 {
859     unz_s* s;
860     int err;
861 
862     /* We remember the 'current' position in the file so that we can jump
863      * back there if we fail.
864      */
865     unz_file_info cur_file_infoSaved;
866     unz_file_info_internal cur_file_info_internalSaved;
867     uLong num_fileSaved;
868     uLong pos_in_central_dirSaved;
869 
870 
871     if (file==NULL)
872         return UNZ_PARAMERROR;
873 
874     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
875         return UNZ_PARAMERROR;
876 
877     s=(unz_s*)file;
878     if (!s->current_file_ok)
879         return UNZ_END_OF_LIST_OF_FILE;
880 
881     /* Save the current state */
882     num_fileSaved = s->num_file;
883     pos_in_central_dirSaved = s->pos_in_central_dir;
884     cur_file_infoSaved = s->cur_file_info;
885     cur_file_info_internalSaved = s->cur_file_info_internal;
886 
887     err = libkml_unzGoToFirstFile(file);
888 
889     while (err == UNZ_OK)
890     {
891         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
892         err = libkml_unzGetCurrentFileInfo(file,NULL,
893                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
894                                     NULL,0,NULL,0);
895         if (err == UNZ_OK)
896         {
897             if (libkml_unzStringFileNameCompare(szCurrentFileName,
898                                             szFileName,iCaseSensitivity)==0)
899                 return UNZ_OK;
900             err = libkml_unzGoToNextFile(file);
901         }
902     }
903 
904     /* We failed, so restore the state of the 'current file' to where we
905      * were.
906      */
907     s->num_file = num_fileSaved ;
908     s->pos_in_central_dir = pos_in_central_dirSaved ;
909     s->cur_file_info = cur_file_infoSaved;
910     s->cur_file_info_internal = cur_file_info_internalSaved;
911     return err;
912 }
913 
914 
915 /*
916 ///////////////////////////////////////////
917 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
918 // I need random access
919 //
920 // Further optimization could be realized by adding an ability
921 // to cache the directory in memory. The goal being a single
922 // comprehensive file read to put the file I need in a memory.
923 */
924 
925 /*
926 typedef struct unz_file_pos_s
927 {
928     uLong pos_in_zip_directory;   // offset in file
929     uLong num_of_file;            // # of file
930 } unz_file_pos;
931 */
932 
933 extern int ZEXPORT libkml_unzGetFilePos(file, file_pos)
934     unzFile file;
935     unz_file_pos* file_pos;
936 {
937     unz_s* s;
938 
939     if (file==NULL || file_pos==NULL)
940         return UNZ_PARAMERROR;
941     s=(unz_s*)file;
942     if (!s->current_file_ok)
943         return UNZ_END_OF_LIST_OF_FILE;
944 
945     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
946     file_pos->num_of_file           = s->num_file;
947 
948     return UNZ_OK;
949 }
950 
951 extern int ZEXPORT libkml_unzGoToFilePos(file, file_pos)
952     unzFile file;
953     unz_file_pos* file_pos;
954 {
955     unz_s* s;
956     int err;
957 
958     if (file==NULL || file_pos==NULL)
959         return UNZ_PARAMERROR;
960     s=(unz_s*)file;
961 
962     /* jump to the right spot */
963     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
964     s->num_file           = file_pos->num_of_file;
965 
966     /* set the current file */
967     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
968                                                &s->cur_file_info_internal,
969                                                NULL,0,NULL,0,NULL,0);
970     /* return results */
971     s->current_file_ok = (err == UNZ_OK);
972     return err;
973 }
974 
975 /*
976 // Unzip Helper Functions - should be here?
977 ///////////////////////////////////////////
978 */
979 
980 /*
981   Read the local header of the current zipfile
982   Check the coherency of the local header and info in the end of central
983         directory about this file
984   store in *piSizeVar the size of extra info in local header
985         (filename and size of extra field data)
986 */
unzlocal_CheckCurrentFileCoherencyHeader(s,piSizeVar,poffset_local_extrafield,psize_local_extrafield)987 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
988                                                     poffset_local_extrafield,
989                                                     psize_local_extrafield)
990     unz_s* s;
991     uInt* piSizeVar;
992     uLong *poffset_local_extrafield;
993     uInt  *psize_local_extrafield;
994 {
995     uLong uMagic,uData,uFlags;
996     uLong size_filename;
997     uLong size_extra_field;
998     int err=UNZ_OK;
999 
1000     *piSizeVar = 0;
1001     *poffset_local_extrafield = 0;
1002     *psize_local_extrafield = 0;
1003 
1004     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1005                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1006         return UNZ_ERRNO;
1007 
1008 
1009     if (err==UNZ_OK)
1010         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1011             err=UNZ_ERRNO;
1012         else if (uMagic!=0x04034b50)
1013             err=UNZ_BADZIPFILE;
1014 
1015     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1016         err=UNZ_ERRNO;
1017 /*
1018     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1019         err=UNZ_BADZIPFILE;
1020 */
1021     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1022         err=UNZ_ERRNO;
1023 
1024     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1025         err=UNZ_ERRNO;
1026     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1027         err=UNZ_BADZIPFILE;
1028 
1029     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1030                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1031         err=UNZ_BADZIPFILE;
1032 
1033     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1034         err=UNZ_ERRNO;
1035 
1036     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1037         err=UNZ_ERRNO;
1038     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1039                               ((uFlags & 8)==0))
1040         err=UNZ_BADZIPFILE;
1041 
1042     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1043         err=UNZ_ERRNO;
1044     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1045                               ((uFlags & 8)==0))
1046         err=UNZ_BADZIPFILE;
1047 
1048     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1049         err=UNZ_ERRNO;
1050     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1051                               ((uFlags & 8)==0))
1052         err=UNZ_BADZIPFILE;
1053 
1054 
1055     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1056         err=UNZ_ERRNO;
1057     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1058         err=UNZ_BADZIPFILE;
1059 
1060     *piSizeVar += (uInt)size_filename;
1061 
1062     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1063         err=UNZ_ERRNO;
1064     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1065                                     SIZEZIPLOCALHEADER + size_filename;
1066     *psize_local_extrafield = (uInt)size_extra_field;
1067 
1068     *piSizeVar += (uInt)size_extra_field;
1069 
1070     return err;
1071 }
1072 
1073 /*
1074   Open for reading data the current file in the zipfile.
1075   If there is no error and the file is opened, the return value is UNZ_OK.
1076 */
1077 extern int ZEXPORT libkml_unzOpenCurrentFile3 (file, method, level, raw, password)
1078     unzFile file;
1079     int* method;
1080     int* level;
1081     int raw;
1082     const char* password;
1083 {
1084     int err=UNZ_OK;
1085     uInt iSizeVar;
1086     unz_s* s;
1087     file_in_zip_read_info_s* pfile_in_zip_read_info;
1088     uLong offset_local_extrafield;  /* offset of the local extra field */
1089     uInt  size_local_extrafield;    /* size of the local extra field */
1090 #    ifndef NOUNCRYPT
1091     char source[12];
1092 #    else
1093     if (password != NULL)
1094         return UNZ_PARAMERROR;
1095 #    endif
1096 
1097     if (file==NULL)
1098         return UNZ_PARAMERROR;
1099     s=(unz_s*)file;
1100     if (!s->current_file_ok)
1101         return UNZ_PARAMERROR;
1102 
1103     if (s->pfile_in_zip_read != NULL)
1104         libkml_unzCloseCurrentFile(file);
1105 
1106     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1107                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1108         return UNZ_BADZIPFILE;
1109 
1110     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1111                                         ALLOC(sizeof(file_in_zip_read_info_s));
1112     if (pfile_in_zip_read_info==NULL)
1113         return UNZ_INTERNALERROR;
1114 
1115     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1116     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1117     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1118     pfile_in_zip_read_info->pos_local_extrafield=0;
1119     pfile_in_zip_read_info->raw=raw;
1120 
1121     if (pfile_in_zip_read_info->read_buffer==NULL)
1122     {
1123         TRYFREE(pfile_in_zip_read_info);
1124         return UNZ_INTERNALERROR;
1125     }
1126 
1127     pfile_in_zip_read_info->stream_initialised=0;
1128 
1129     if (method!=NULL)
1130         *method = (int)s->cur_file_info.compression_method;
1131 
1132     if (level!=NULL)
1133     {
1134         *level = 6;
1135         switch (s->cur_file_info.flag & 0x06)
1136         {
1137           case 6 : *level = 1; break;
1138           case 4 : *level = 2; break;
1139           case 2 : *level = 9; break;
1140         }
1141     }
1142 
1143     if ((s->cur_file_info.compression_method!=0) &&
1144         (s->cur_file_info.compression_method!=Z_DEFLATED))
1145         err=UNZ_BADZIPFILE;
1146 
1147     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1148     pfile_in_zip_read_info->crc32=0;
1149     pfile_in_zip_read_info->compression_method =
1150             s->cur_file_info.compression_method;
1151     pfile_in_zip_read_info->filestream=s->filestream;
1152     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1153     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1154 
1155     pfile_in_zip_read_info->stream.total_out = 0;
1156 
1157     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1158         (!raw))
1159     {
1160       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1161       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1162       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1163       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1164       pfile_in_zip_read_info->stream.avail_in = 0;
1165 
1166       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1167       if (err == Z_OK)
1168         pfile_in_zip_read_info->stream_initialised=1;
1169       else
1170       {
1171         TRYFREE(pfile_in_zip_read_info);
1172         return err;
1173       }
1174         /* windowBits is passed < 0 to tell that there is no zlib header.
1175          * Note that in this case inflate *requires* an extra "dummy" byte
1176          * after the compressed stream in order to complete decompression and
1177          * return Z_STREAM_END.
1178          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1179          * size of both compressed and uncompressed data
1180          */
1181     }
1182     pfile_in_zip_read_info->rest_read_compressed =
1183             s->cur_file_info.compressed_size ;
1184     pfile_in_zip_read_info->rest_read_uncompressed =
1185             s->cur_file_info.uncompressed_size ;
1186 
1187 
1188     pfile_in_zip_read_info->pos_in_zipfile =
1189             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1190               iSizeVar;
1191 
1192     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1193 
1194     s->pfile_in_zip_read = pfile_in_zip_read_info;
1195 
1196 #    ifndef NOUNCRYPT
1197     if (password != NULL)
1198     {
1199         int i;
1200         s->pcrc_32_tab = get_crc_table();
1201         init_keys(password,s->keys,s->pcrc_32_tab);
1202         if (ZSEEK(s->z_filefunc, s->filestream,
1203                   s->pfile_in_zip_read->pos_in_zipfile +
1204                      s->pfile_in_zip_read->byte_before_the_zipfile,
1205                   SEEK_SET)!=0)
1206             return UNZ_INTERNALERROR;
1207         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1208             return UNZ_INTERNALERROR;
1209 
1210         for (i = 0; i<12; i++)
1211             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1212 
1213         s->pfile_in_zip_read->pos_in_zipfile+=12;
1214         s->encrypted=1;
1215     }
1216 #    endif
1217 
1218 
1219     return UNZ_OK;
1220 }
1221 
1222 extern int ZEXPORT libkml_unzOpenCurrentFile (file)
1223     unzFile file;
1224 {
1225     return libkml_unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1226 }
1227 
1228 extern int ZEXPORT libkml_unzOpenCurrentFilePassword (file, password)
1229     unzFile file;
1230     const char* password;
1231 {
1232     return libkml_unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1233 }
1234 
1235 extern int ZEXPORT libkml_unzOpenCurrentFile2 (file,method,level,raw)
1236     unzFile file;
1237     int* method;
1238     int* level;
1239     int raw;
1240 {
1241     return libkml_unzOpenCurrentFile3(file, method, level, raw, NULL);
1242 }
1243 
1244 /*
1245   Read bytes from the current file.
1246   buf contain buffer where data must be copied
1247   len the size of buf.
1248 
1249   return the number of byte copied if somes bytes are copied
1250   return 0 if the end of file was reached
1251   return <0 with error code if there is an error
1252     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1253 */
1254 extern int ZEXPORT libkml_unzReadCurrentFile  (file, buf, len)
1255     unzFile file;
1256     voidp buf;
1257     unsigned len;
1258 {
1259     int err=UNZ_OK;
1260     uInt iRead = 0;
1261     unz_s* s;
1262     file_in_zip_read_info_s* pfile_in_zip_read_info;
1263     if (file==NULL)
1264         return UNZ_PARAMERROR;
1265     s=(unz_s*)file;
1266     pfile_in_zip_read_info=s->pfile_in_zip_read;
1267 
1268     if (pfile_in_zip_read_info==NULL)
1269         return UNZ_PARAMERROR;
1270 
1271 
1272     if ((pfile_in_zip_read_info->read_buffer == NULL))
1273         return UNZ_END_OF_LIST_OF_FILE;
1274     if (len==0)
1275         return 0;
1276 
1277     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1278 
1279     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1280 
1281     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1282         (!(pfile_in_zip_read_info->raw)))
1283         pfile_in_zip_read_info->stream.avail_out =
1284             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1285 
1286     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1287            pfile_in_zip_read_info->stream.avail_in) &&
1288          (pfile_in_zip_read_info->raw))
1289         pfile_in_zip_read_info->stream.avail_out =
1290             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1291             pfile_in_zip_read_info->stream.avail_in;
1292 
1293     while (pfile_in_zip_read_info->stream.avail_out>0)
1294     {
1295         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1296             (pfile_in_zip_read_info->rest_read_compressed>0))
1297         {
1298             uInt uReadThis = UNZ_BUFSIZE;
1299             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1300                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1301             if (uReadThis == 0)
1302                 return UNZ_EOF;
1303             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1304                       pfile_in_zip_read_info->filestream,
1305                       pfile_in_zip_read_info->pos_in_zipfile +
1306                          pfile_in_zip_read_info->byte_before_the_zipfile,
1307                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1308                 return UNZ_ERRNO;
1309             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1310                       pfile_in_zip_read_info->filestream,
1311                       pfile_in_zip_read_info->read_buffer,
1312                       uReadThis)!=uReadThis)
1313                 return UNZ_ERRNO;
1314 
1315 
1316 #            ifndef NOUNCRYPT
1317             if(s->encrypted)
1318             {
1319                 uInt i;
1320                 for(i=0;i<uReadThis;i++)
1321                   pfile_in_zip_read_info->read_buffer[i] =
1322                       zdecode(s->keys,s->pcrc_32_tab,
1323                               pfile_in_zip_read_info->read_buffer[i]);
1324             }
1325 #            endif
1326 
1327 
1328             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1329 
1330             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1331 
1332             pfile_in_zip_read_info->stream.next_in =
1333                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1334             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1335         }
1336 
1337         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1338         {
1339             uInt uDoCopy,i ;
1340 
1341             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1342                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1343                 return (iRead==0) ? UNZ_EOF : iRead;
1344 
1345             if (pfile_in_zip_read_info->stream.avail_out <
1346                             pfile_in_zip_read_info->stream.avail_in)
1347                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1348             else
1349                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1350 
1351             for (i=0;i<uDoCopy;i++)
1352                 *(pfile_in_zip_read_info->stream.next_out+i) =
1353                         *(pfile_in_zip_read_info->stream.next_in+i);
1354 
1355             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1356                                 pfile_in_zip_read_info->stream.next_out,
1357                                 uDoCopy);
1358             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1359             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1360             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1361             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1362             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1363             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1364             iRead += uDoCopy;
1365         }
1366         else
1367         {
1368             uLong uTotalOutBefore,uTotalOutAfter;
1369             const Bytef *bufBefore;
1370             uLong uOutThis;
1371             int flush=Z_SYNC_FLUSH;
1372 
1373             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1374             bufBefore = pfile_in_zip_read_info->stream.next_out;
1375 
1376             /*
1377             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1378                      pfile_in_zip_read_info->stream.avail_out) &&
1379                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1380                 flush = Z_FINISH;
1381             */
1382             err=inflate(&pfile_in_zip_read_info->stream,flush);
1383 
1384             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1385               err = Z_DATA_ERROR;
1386 
1387             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1388             uOutThis = uTotalOutAfter-uTotalOutBefore;
1389 
1390             pfile_in_zip_read_info->crc32 =
1391                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1392                         (uInt)(uOutThis));
1393 
1394             pfile_in_zip_read_info->rest_read_uncompressed -=
1395                 uOutThis;
1396 
1397             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1398 
1399             if (err==Z_STREAM_END)
1400                 return (iRead==0) ? UNZ_EOF : iRead;
1401             if (err!=Z_OK)
1402                 break;
1403         }
1404     }
1405 
1406     if (err==Z_OK)
1407         return iRead;
1408     return err;
1409 }
1410 
1411 
1412 /*
1413   Give the current position in uncompressed data
1414 */
1415 extern z_off_t ZEXPORT libkml_unztell (file)
1416     unzFile file;
1417 {
1418     unz_s* s;
1419     file_in_zip_read_info_s* pfile_in_zip_read_info;
1420     if (file==NULL)
1421         return UNZ_PARAMERROR;
1422     s=(unz_s*)file;
1423     pfile_in_zip_read_info=s->pfile_in_zip_read;
1424 
1425     if (pfile_in_zip_read_info==NULL)
1426         return UNZ_PARAMERROR;
1427 
1428     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1429 }
1430 
1431 
1432 /*
1433   return 1 if the end of file was reached, 0 elsewhere
1434 */
1435 extern int ZEXPORT libkml_unzeof (file)
1436     unzFile file;
1437 {
1438     unz_s* s;
1439     file_in_zip_read_info_s* pfile_in_zip_read_info;
1440     if (file==NULL)
1441         return UNZ_PARAMERROR;
1442     s=(unz_s*)file;
1443     pfile_in_zip_read_info=s->pfile_in_zip_read;
1444 
1445     if (pfile_in_zip_read_info==NULL)
1446         return UNZ_PARAMERROR;
1447 
1448     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1449         return 1;
1450     else
1451         return 0;
1452 }
1453 
1454 
1455 
1456 /*
1457   Read extra field from the current file (opened by libkml_unzOpenCurrentFile)
1458   This is the local-header version of the extra field (sometimes, there is
1459     more info in the local-header version than in the central-header)
1460 
1461   if buf==NULL, it return the size of the local extra field that can be read
1462 
1463   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1464     buf.
1465   the return value is the number of bytes copied in buf, or (if <0)
1466     the error code
1467 */
1468 extern int ZEXPORT libkml_unzGetLocalExtrafield (file,buf,len)
1469     unzFile file;
1470     voidp buf;
1471     unsigned len;
1472 {
1473     unz_s* s;
1474     file_in_zip_read_info_s* pfile_in_zip_read_info;
1475     uInt read_now;
1476     uLong size_to_read;
1477 
1478     if (file==NULL)
1479         return UNZ_PARAMERROR;
1480     s=(unz_s*)file;
1481     pfile_in_zip_read_info=s->pfile_in_zip_read;
1482 
1483     if (pfile_in_zip_read_info==NULL)
1484         return UNZ_PARAMERROR;
1485 
1486     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1487                 pfile_in_zip_read_info->pos_local_extrafield);
1488 
1489     if (buf==NULL)
1490         return (int)size_to_read;
1491 
1492     if (len>size_to_read)
1493         read_now = (uInt)size_to_read;
1494     else
1495         read_now = (uInt)len ;
1496 
1497     if (read_now==0)
1498         return 0;
1499 
1500     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1501               pfile_in_zip_read_info->filestream,
1502               pfile_in_zip_read_info->offset_local_extrafield +
1503               pfile_in_zip_read_info->pos_local_extrafield,
1504               ZLIB_FILEFUNC_SEEK_SET)!=0)
1505         return UNZ_ERRNO;
1506 
1507     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1508               pfile_in_zip_read_info->filestream,
1509               buf,read_now)!=read_now)
1510         return UNZ_ERRNO;
1511 
1512     return (int)read_now;
1513 }
1514 
1515 /*
1516   Close the file in zip opened with unzipOpenCurrentFile
1517   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1518 */
1519 extern int ZEXPORT libkml_unzCloseCurrentFile (file)
1520     unzFile file;
1521 {
1522     int err=UNZ_OK;
1523 
1524     unz_s* s;
1525     file_in_zip_read_info_s* pfile_in_zip_read_info;
1526     if (file==NULL)
1527         return UNZ_PARAMERROR;
1528     s=(unz_s*)file;
1529     pfile_in_zip_read_info=s->pfile_in_zip_read;
1530 
1531     if (pfile_in_zip_read_info==NULL)
1532         return UNZ_PARAMERROR;
1533 
1534 
1535     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1536         (!pfile_in_zip_read_info->raw))
1537     {
1538         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1539             err=UNZ_CRCERROR;
1540     }
1541 
1542 
1543     TRYFREE(pfile_in_zip_read_info->read_buffer);
1544     pfile_in_zip_read_info->read_buffer = NULL;
1545     if (pfile_in_zip_read_info->stream_initialised)
1546         inflateEnd(&pfile_in_zip_read_info->stream);
1547 
1548     pfile_in_zip_read_info->stream_initialised = 0;
1549     TRYFREE(pfile_in_zip_read_info);
1550 
1551     s->pfile_in_zip_read=NULL;
1552 
1553     return err;
1554 }
1555 
1556 
1557 /*
1558   Get the global comment string of the ZipFile, in the szComment buffer.
1559   uSizeBuf is the size of the szComment buffer.
1560   return the number of byte copied or an error code <0
1561 */
1562 extern int ZEXPORT libkml_unzGetGlobalComment (file, szComment, uSizeBuf)
1563     unzFile file;
1564     char *szComment;
1565     uLong uSizeBuf;
1566 {
1567     int err=UNZ_OK;
1568     unz_s* s;
1569     uLong uReadThis ;
1570     if (file==NULL)
1571         return UNZ_PARAMERROR;
1572     s=(unz_s*)file;
1573 
1574     uReadThis = uSizeBuf;
1575     if (uReadThis>s->gi.size_comment)
1576         uReadThis = s->gi.size_comment;
1577 
1578     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1579         return UNZ_ERRNO;
1580 
1581     if (uReadThis>0)
1582     {
1583       *szComment='\0';
1584       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1585         return UNZ_ERRNO;
1586     }
1587 
1588     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1589         *(szComment+s->gi.size_comment)='\0';
1590     return (int)uReadThis;
1591 }
1592 
1593 /* Additions by RX '2004 */
1594 extern uLong ZEXPORT libkml_unzGetOffset (file)
1595     unzFile file;
1596 {
1597     unz_s* s;
1598 
1599     if (file==NULL)
1600           return UNZ_PARAMERROR;
1601     s=(unz_s*)file;
1602     if (!s->current_file_ok)
1603       return 0;
1604     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1605       if (s->num_file==s->gi.number_entry)
1606          return 0;
1607     return s->pos_in_central_dir;
1608 }
1609 
1610 extern int ZEXPORT libkml_unzSetOffset (file, pos)
1611         unzFile file;
1612         uLong pos;
1613 {
1614     unz_s* s;
1615     int err;
1616 
1617     if (file==NULL)
1618         return UNZ_PARAMERROR;
1619     s=(unz_s*)file;
1620 
1621     s->pos_in_central_dir = pos;
1622     s->num_file = s->gi.number_entry;      /* hack */
1623     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1624                                               &s->cur_file_info_internal,
1625                                               NULL,0,NULL,0,NULL,0);
1626     s->current_file_ok = (err == UNZ_OK);
1627     return err;
1628 }
1629 
1630 /* The following methods (unzAttach, unzDetach) come from the proposed
1631  * iomem_simple package at http://code.trak.dk/
1632  * See iomem_simple.c in this directory.
1633  */
libkml_unzDetach(file)1634 ZEXTERN voidpf ZEXPORT libkml_unzDetach(file)
1635     unzFile* file;
1636 {
1637     voidpf stream;
1638     unz_s* s;
1639     if (*file==NULL)
1640         return NULL;
1641     s=(unz_s*)*file;
1642 
1643     if (s->pfile_in_zip_read!=NULL)
1644         libkml_unzCloseCurrentFile(*file);
1645     stream = s->filestream;
1646     TRYFREE(s);
1647     *file = NULL;
1648     return stream;
1649 }
1650 
1651 extern unzFile ZEXPORT libkml_unzAttach (stream, pzlib_filefunc_def)
1652     voidpf stream;
1653     zlib_filefunc_def* pzlib_filefunc_def;
1654 {
1655     unz_s us;
1656 
1657     unz_s *s;
1658 
1659     uLong central_pos;
1660 
1661     uLong uL;
1662 
1663     uLong number_disk;          /* number of the current dist, used for
1664                                    spaning ZIP, unsupported, always 0*/
1665     uLong number_disk_with_CD;  /* number the the disk with central dir, used
1666                                    for spaning ZIP, unsupported, always 0*/
1667     uLong number_entry_CD;      /* total number of entries in
1668                                    the central dir
1669                                    (same than number_entry on nospan) */
1670 
1671     int err=UNZ_OK;
1672 
1673     init_unz_s(&us);
1674 
1675     if (libkml_unz_copyright[0]!=' ')
1676         return NULL;
1677 
1678     us.num_file = 0UL;
1679 
1680     us.z_filefunc = *pzlib_filefunc_def;
1681 
1682     us.filestream= stream;
1683 
1684     if (us.filestream==NULL)
1685         return NULL;
1686 
1687     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
1688     if (central_pos==0)
1689         err=UNZ_ERRNO;
1690 
1691     if (ZSEEK(us.z_filefunc, us.filestream,
1692                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
1693         err=UNZ_ERRNO;
1694 
1695     /* the signature, already checked */
1696     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
1697         err=UNZ_ERRNO;
1698 
1699     /* number of this disk */
1700     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
1701         err=UNZ_ERRNO;
1702 
1703     /* number of the disk with the start of the central directory */
1704     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
1705         err=UNZ_ERRNO;
1706 
1707     /* total number of entries in the central dir on this disk */
1708     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
1709         err=UNZ_ERRNO;
1710 
1711     /* total number of entries in the central dir */
1712     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
1713         err=UNZ_ERRNO;
1714 
1715     if ((number_entry_CD!=us.gi.number_entry) ||
1716         (number_disk_with_CD!=0) ||
1717         (number_disk!=0))
1718         err=UNZ_BADZIPFILE;
1719 
1720     /* size of the central directory */
1721     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
1722         err=UNZ_ERRNO;
1723 
1724     /* offset of start of central directory with respect to the
1725           starting disk number */
1726     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
1727         err=UNZ_ERRNO;
1728 
1729     /* zipfile comment length */
1730     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
1731         err=UNZ_ERRNO;
1732 
1733     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
1734         (err==UNZ_OK))
1735         err=UNZ_BADZIPFILE;
1736 
1737     if (err!=UNZ_OK)
1738     {
1739         return NULL;
1740     }
1741 
1742     us.byte_before_the_zipfile = central_pos -
1743                             (us.offset_central_dir+us.size_central_dir);
1744     us.central_pos = central_pos;
1745     us.pfile_in_zip_read = NULL;
1746     us.encrypted = 0;
1747 
1748     s=(unz_s*)ALLOC(sizeof(unz_s));
1749 
1750     *s=us;
1751     libkml_unzGoToFirstFile((unzFile)s);
1752     return (unzFile)s;
1753 }
1754