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