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