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