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