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