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