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