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