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