1 /* unzip.c -- IO on .zip files using zlib
2 Version 0.15 beta, Mar 19th, 1998,
3
4 Read unzip.h for more info
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "zlib.h"
11 #include "unzip.h"
12
13 #ifdef STDC
14 # include <stddef.h>
15 # include <string.h>
16 # include <stdlib.h>
17 #endif
18 #ifdef NO_ERRNO_H
19 extern int errno;
20 #else
21 # include <errno.h>
22 #endif
23
24
25 #ifndef local
26 # define local static
27 #endif
28 /* compile with -Dlocal if your debugger can't find static symbols */
29
30
31
32 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
33 !defined(CASESENSITIVITYDEFAULT_NO)
34 #define CASESENSITIVITYDEFAULT_NO
35 #endif
36
37
38 #ifndef UNZ_BUFSIZE
39 #define UNZ_BUFSIZE (16384)
40 #endif
41
42 #ifndef UNZ_MAXFILENAMEINZIP
43 #define UNZ_MAXFILENAMEINZIP (256)
44 #endif
45
46 #ifndef ALLOC
47 # define ALLOC(size) (malloc(size))
48 #endif
49 #ifndef TRYFREE
50 # define TRYFREE(p) {if (p) free(p);}
51 #endif
52
53 #define SIZECENTRALDIRITEM (0x2e)
54 #define SIZEZIPLOCALHEADER (0x1e)
55
56
57 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
58
59 #ifndef SEEK_CUR
60 #define SEEK_CUR 1
61 #endif
62
63 #ifndef SEEK_END
64 #define SEEK_END 2
65 #endif
66
67 #ifndef SEEK_SET
68 #define SEEK_SET 0
69 #endif
70
71 const char unz_copyright[] =
72 " unzip 0.15 Copyright 1998 Gilles Vollant ";
73
74 /* unz_file_info_interntal contain internal info about a file in zipfile*/
75 typedef struct unz_file_info_internal_s
76 {
77 uLong offset_curfile;/* relative offset of local header 4 bytes */
78 } unz_file_info_internal;
79
80
81 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
82 when reading and decompress it */
83 typedef struct
84 {
85 char *read_buffer; /* internal buffer for compressed data */
86 z_stream stream; /* zLib stream structure for inflate */
87
88 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
89 uLong stream_initialised; /* flag set if stream structure is initialised*/
90
91 uLong offset_local_extrafield;/* offset of the local extra field */
92 uInt size_local_extrafield;/* size of the local extra field */
93 uLong pos_local_extrafield; /* position in the local extra field in read*/
94
95 uLong crc32; /* crc32 of all data uncompressed */
96 uLong crc32_wait; /* crc32 we must obtain after decompress all */
97 uLong rest_read_compressed; /* number of byte to be decompressed */
98 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
99 FILE* file; /* io structore of the zipfile */
100 uLong compression_method; /* compression method (0==store) */
101 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
102 } file_in_zip_read_info_s;
103
104
105 /* unz_s contain internal information about the zipfile
106 */
107 typedef struct
108 {
109 FILE* file; /* io structore of the zipfile */
110 unz_global_info gi; /* public global information */
111 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
112 uLong num_file; /* number of the current file in the zipfile*/
113 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
114 uLong current_file_ok; /* flag about the usability of the current file*/
115 uLong central_pos; /* position of the beginning of the central dir*/
116
117 uLong size_central_dir; /* size of the central directory */
118 uLong offset_central_dir; /* offset of start of central directory with
119 respect to the starting disk number */
120
121 unz_file_info cur_file_info; /* public info about the current file in zip*/
122 unz_file_info_internal cur_file_info_internal; /* private info about it*/
123 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
124 file if we are decompressing it */
125 } unz_s;
126
127
128 /* ===========================================================================
129 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
130 for end of file.
131 IN assertion: the stream s has been sucessfully opened for reading.
132 */
133
134
unzlocal_getByte(fin,pi)135 local int unzlocal_getByte(fin,pi)
136 FILE *fin;
137 int *pi;
138 {
139 unsigned char c;
140 int err = fread(&c, 1, 1, fin);
141 if (err==1)
142 {
143 *pi = (int)c;
144 return UNZ_OK;
145 }
146 else
147 {
148 if (ferror(fin))
149 return UNZ_ERRNO;
150 else
151 return UNZ_EOF;
152 }
153 }
154
155
156 /* ===========================================================================
157 Reads a long in LSB order from the given gz_stream. Sets
158 */
unzlocal_getShort(fin,pX)159 local int unzlocal_getShort (fin,pX)
160 FILE* fin;
161 uLong *pX;
162 {
163 uLong x ;
164 int i;
165 int err;
166
167 err = unzlocal_getByte(fin,&i);
168 x = (uLong)i;
169
170 if (err==UNZ_OK)
171 err = unzlocal_getByte(fin,&i);
172 x += ((uLong)i)<<8;
173
174 if (err==UNZ_OK)
175 *pX = x;
176 else
177 *pX = 0;
178 return err;
179 }
180
unzlocal_getLong(fin,pX)181 local int unzlocal_getLong (fin,pX)
182 FILE* fin;
183 uLong *pX;
184 {
185 uLong x ;
186 int i;
187 int err;
188
189 err = unzlocal_getByte(fin,&i);
190 x = (uLong)i;
191
192 if (err==UNZ_OK)
193 err = unzlocal_getByte(fin,&i);
194 x += ((uLong)i)<<8;
195
196 if (err==UNZ_OK)
197 err = unzlocal_getByte(fin,&i);
198 x += ((uLong)i)<<16;
199
200 if (err==UNZ_OK)
201 err = unzlocal_getByte(fin,&i);
202 x += ((uLong)i)<<24;
203
204 if (err==UNZ_OK)
205 *pX = x;
206 else
207 *pX = 0;
208 return err;
209 }
210
211
212 /* My own strcmpi / strcasecmp */
strcmpcasenosensitive_internal(fileName1,fileName2)213 local int strcmpcasenosensitive_internal (fileName1,fileName2)
214 const char* fileName1;
215 const char* fileName2;
216 {
217 for (;;)
218 {
219 char c1=*(fileName1++);
220 char c2=*(fileName2++);
221 if ((c1>='a') && (c1<='z'))
222 c1 -= 0x20;
223 if ((c2>='a') && (c2<='z'))
224 c2 -= 0x20;
225 if (c1=='\0')
226 return ((c2=='\0') ? 0 : -1);
227 if (c2=='\0')
228 return 1;
229 if (c1<c2)
230 return -1;
231 if (c1>c2)
232 return 1;
233 }
234 }
235
236
237 #ifdef CASESENSITIVITYDEFAULT_NO
238 #define CASESENSITIVITYDEFAULTVALUE 2
239 #else
240 #define CASESENSITIVITYDEFAULTVALUE 1
241 #endif
242
243 #ifndef STRCMPCASENOSENTIVEFUNCTION
244 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
245 #endif
246
247 /*
248 Compare two filename (fileName1,fileName2).
249 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
250 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
251 or strcasecmp)
252 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
253 (like 1 on Unix, 2 on Windows)
254
255 */
256 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
257 const char* fileName1;
258 const char* fileName2;
259 int iCaseSensitivity;
260 {
261 if (iCaseSensitivity==0)
262 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
263
264 if (iCaseSensitivity==1)
265 return strcmp(fileName1,fileName2);
266
267 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
268 }
269
270 #define BUFREADCOMMENT (0x400)
271
272 /*
273 Locate the Central directory of a zipfile (at the end, just before
274 the global comment)
275 */
unzlocal_SearchCentralDir(fin)276 local uLong unzlocal_SearchCentralDir(fin)
277 FILE *fin;
278 {
279 unsigned char* buf;
280 uLong uSizeFile;
281 uLong uBackRead;
282 uLong uMaxBack=0xffff; /* maximum size of global comment */
283 uLong uPosFound=0;
284
285 if (fseek(fin,0,SEEK_END) != 0)
286 return 0;
287
288
289 uSizeFile = ftell( fin );
290
291 if (uMaxBack>uSizeFile)
292 uMaxBack = uSizeFile;
293
294 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
295 if (buf==NULL)
296 return 0;
297
298 uBackRead = 4;
299 while (uBackRead<uMaxBack)
300 {
301 uLong uReadSize,uReadPos ;
302 int i;
303 if (uBackRead+BUFREADCOMMENT>uMaxBack)
304 uBackRead = uMaxBack;
305 else
306 uBackRead+=BUFREADCOMMENT;
307 uReadPos = uSizeFile-uBackRead ;
308
309 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
310 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
311 if (fseek(fin,uReadPos,SEEK_SET)!=0)
312 break;
313
314 if (fread(buf,(uInt)uReadSize,1,fin)!=1)
315 break;
316
317 for (i=(int)uReadSize-3; (i--)>0;)
318 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
319 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
320 {
321 uPosFound = uReadPos+i;
322 break;
323 }
324
325 if (uPosFound!=0)
326 break;
327 }
328 TRYFREE(buf);
329 return uPosFound;
330 }
331
332 /*
333 Open a Zip file. path contain the full pathname (by example,
334 on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
335 "zlib/zlib109.zip".
336 If the zipfile cannot be opened (file don't exist or in not valid), the
337 return value is NULL.
338 Else, the return value is a unzFile Handle, usable with other function
339 of this unzip package.
340 */
341 extern unzFile ZEXPORT unzOpen (path)
342 const char *path;
343 {
344 unz_s us;
345 unz_s *s;
346 uLong central_pos,uL;
347 FILE * fin ;
348
349 uLong number_disk; /* number of the current dist, used for
350 spaning ZIP, unsupported, always 0*/
351 uLong number_disk_with_CD; /* number the the disk with central dir, used
352 for spaning ZIP, unsupported, always 0*/
353 uLong number_entry_CD; /* total number of entries in
354 the central dir
355 (same than number_entry on nospan) */
356
357 int err=UNZ_OK;
358
359 if (unz_copyright[0]!=' ')
360 return NULL;
361
362 fin=fopen(path,"rb");
363 if (fin==NULL)
364 return NULL;
365
366 central_pos = unzlocal_SearchCentralDir(fin);
367 if (central_pos==0)
368 err=UNZ_ERRNO;
369
370 if (fseek(fin,central_pos,SEEK_SET)!=0)
371 err=UNZ_ERRNO;
372
373 /* the signature, already checked */
374 if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
375 err=UNZ_ERRNO;
376
377 /* number of this disk */
378 if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
379 err=UNZ_ERRNO;
380
381 /* number of the disk with the start of the central directory */
382 if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
383 err=UNZ_ERRNO;
384
385 /* total number of entries in the central dir on this disk */
386 if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
387 err=UNZ_ERRNO;
388
389 /* total number of entries in the central dir */
390 if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
391 err=UNZ_ERRNO;
392
393 if ((number_entry_CD!=us.gi.number_entry) ||
394 (number_disk_with_CD!=0) ||
395 (number_disk!=0))
396 err=UNZ_BADZIPFILE;
397
398 /* size of the central directory */
399 if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
400 err=UNZ_ERRNO;
401
402 /* offset of start of central directory with respect to the
403 starting disk number */
404 if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
405 err=UNZ_ERRNO;
406
407 /* zipfile comment length */
408 if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
409 err=UNZ_ERRNO;
410
411 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
412 (err==UNZ_OK))
413 err=UNZ_BADZIPFILE;
414
415 if (err!=UNZ_OK)
416 {
417 fclose(fin);
418 return NULL;
419 }
420
421 us.file=fin;
422 us.byte_before_the_zipfile = central_pos -
423 (us.offset_central_dir+us.size_central_dir);
424 us.central_pos = central_pos;
425 us.pfile_in_zip_read = NULL;
426
427
428 s=(unz_s*)ALLOC(sizeof(unz_s));
429 *s=us;
430 unzGoToFirstFile((unzFile)s);
431 return (unzFile)s;
432 }
433
434
435 /*
436 Close a ZipFile opened with unzipOpen.
437 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
438 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
439 return UNZ_OK if there is no problem. */
440 extern int ZEXPORT unzClose (file)
441 unzFile file;
442 {
443 unz_s* s;
444 if (file==NULL)
445 return UNZ_PARAMERROR;
446 s=(unz_s*)file;
447
448 if (s->pfile_in_zip_read!=NULL)
449 unzCloseCurrentFile(file);
450
451 fclose(s->file);
452 TRYFREE(s);
453 return UNZ_OK;
454 }
455
456
457 /*
458 Write info about the ZipFile in the *pglobal_info structure.
459 No preparation of the structure is needed
460 return UNZ_OK if there is no problem. */
461 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
462 unzFile file;
463 unz_global_info *pglobal_info;
464 {
465 unz_s* s;
466 if (file==NULL)
467 return UNZ_PARAMERROR;
468 s=(unz_s*)file;
469 *pglobal_info=s->gi;
470 return UNZ_OK;
471 }
472
473
474 /*
475 Translate date/time from Dos format to tm_unz (readable more easilty)
476 */
unzlocal_DosDateToTmuDate(ulDosDate,ptm)477 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
478 uLong ulDosDate;
479 tm_unz* ptm;
480 {
481 uLong uDate;
482 uDate = (uLong)(ulDosDate>>16);
483 ptm->tm_mday = (uInt)(uDate&0x1f) ;
484 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
485 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
486
487 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
488 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
489 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
490 }
491
492 /*
493 Get Info about the current file in the zipfile, with internal only info
494 */
495 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
496 unz_file_info *pfile_info,
497 unz_file_info_internal
498 *pfile_info_internal,
499 char *szFileName,
500 uLong fileNameBufferSize,
501 void *extraField,
502 uLong extraFieldBufferSize,
503 char *szComment,
504 uLong commentBufferSize));
505
unzlocal_GetCurrentFileInfoInternal(file,pfile_info,pfile_info_internal,szFileName,fileNameBufferSize,extraField,extraFieldBufferSize,szComment,commentBufferSize)506 local int unzlocal_GetCurrentFileInfoInternal (file,
507 pfile_info,
508 pfile_info_internal,
509 szFileName, fileNameBufferSize,
510 extraField, extraFieldBufferSize,
511 szComment, commentBufferSize)
512 unzFile file;
513 unz_file_info *pfile_info;
514 unz_file_info_internal *pfile_info_internal;
515 char *szFileName;
516 uLong fileNameBufferSize;
517 void *extraField;
518 uLong extraFieldBufferSize;
519 char *szComment;
520 uLong commentBufferSize;
521 {
522 unz_s* s;
523 unz_file_info file_info;
524 unz_file_info_internal file_info_internal;
525 int err=UNZ_OK;
526 uLong uMagic;
527 long lSeek=0;
528
529 if (file==NULL)
530 return UNZ_PARAMERROR;
531 s=(unz_s*)file;
532 if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
533 err=UNZ_ERRNO;
534
535
536 /* we check the magic */
537 if (err==UNZ_OK)
538 {
539 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
540 err=UNZ_ERRNO;
541 else if (uMagic!=0x02014b50)
542 err=UNZ_BADZIPFILE;
543 }
544
545 if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
546 err=UNZ_ERRNO;
547
548 if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
549 err=UNZ_ERRNO;
550
551 if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
552 err=UNZ_ERRNO;
553
554 if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
555 err=UNZ_ERRNO;
556
557 if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
558 err=UNZ_ERRNO;
559
560 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
561
562 if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
563 err=UNZ_ERRNO;
564
565 if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
566 err=UNZ_ERRNO;
567
568 if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
569 err=UNZ_ERRNO;
570
571 if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
572 err=UNZ_ERRNO;
573
574 if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
575 err=UNZ_ERRNO;
576
577 if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
578 err=UNZ_ERRNO;
579
580 if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
581 err=UNZ_ERRNO;
582
583 if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
584 err=UNZ_ERRNO;
585
586 if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
587 err=UNZ_ERRNO;
588
589 if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
590 err=UNZ_ERRNO;
591
592 lSeek+=file_info.size_filename;
593 if ((err==UNZ_OK) && (szFileName!=NULL))
594 {
595 uLong uSizeRead ;
596 if (file_info.size_filename<fileNameBufferSize)
597 {
598 *(szFileName+file_info.size_filename)='\0';
599 uSizeRead = file_info.size_filename;
600 }
601 else
602 uSizeRead = fileNameBufferSize;
603
604 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
605 if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
606 err=UNZ_ERRNO;
607 lSeek -= uSizeRead;
608 }
609
610 if ((err==UNZ_OK) && (extraField!=NULL))
611 {
612 uLong uSizeRead ;
613 if (file_info.size_file_extra<extraFieldBufferSize)
614 uSizeRead = file_info.size_file_extra;
615 else
616 uSizeRead = extraFieldBufferSize;
617
618 if (lSeek!=0)
619 {
620 if (fseek(s->file,lSeek,SEEK_CUR)==0)
621 lSeek=0;
622 else
623 err=UNZ_ERRNO;
624 }
625 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
626 if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
627 err=UNZ_ERRNO;
628 lSeek += file_info.size_file_extra - uSizeRead;
629 }
630 else
631 lSeek+=file_info.size_file_extra;
632
633 if ((err==UNZ_OK) && (szComment!=NULL))
634 {
635 uLong uSizeRead ;
636 if (file_info.size_file_comment<commentBufferSize)
637 {
638 *(szComment+file_info.size_file_comment)='\0';
639 uSizeRead = file_info.size_file_comment;
640 }
641 else
642 uSizeRead = commentBufferSize;
643
644 if (lSeek!=0)
645 {
646 if (fseek(s->file,lSeek,SEEK_CUR)==0)
647 lSeek=0;
648 else
649 err=UNZ_ERRNO;
650 }
651 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
652 if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
653 err=UNZ_ERRNO;
654 lSeek+=file_info.size_file_comment - uSizeRead;
655 }
656 else
657 lSeek+=file_info.size_file_comment;
658
659 if ((err==UNZ_OK) && (pfile_info!=NULL))
660 *pfile_info=file_info;
661
662 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
663 *pfile_info_internal=file_info_internal;
664
665 return err;
666 }
667
668
669
670 /*
671 Write info about the ZipFile in the *pglobal_info structure.
672 No preparation of the structure is needed
673 return UNZ_OK if there is no problem.
674 */
675 extern int ZEXPORT unzGetCurrentFileInfo (file,
676 pfile_info,
677 szFileName, fileNameBufferSize,
678 extraField, extraFieldBufferSize,
679 szComment, commentBufferSize)
680 unzFile file;
681 unz_file_info *pfile_info;
682 char *szFileName;
683 uLong fileNameBufferSize;
684 void *extraField;
685 uLong extraFieldBufferSize;
686 char *szComment;
687 uLong commentBufferSize;
688 {
689 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
690 szFileName,fileNameBufferSize,
691 extraField,extraFieldBufferSize,
692 szComment,commentBufferSize);
693 }
694
695 /*
696 Set the current file of the zipfile to the first file.
697 return UNZ_OK if there is no problem
698 */
699 extern int ZEXPORT unzGoToFirstFile (file)
700 unzFile file;
701 {
702 int err=UNZ_OK;
703 unz_s* s;
704 if (file==NULL)
705 return UNZ_PARAMERROR;
706 s=(unz_s*)file;
707 s->pos_in_central_dir=s->offset_central_dir;
708 s->num_file=0;
709 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
710 &s->cur_file_info_internal,
711 NULL,0,NULL,0,NULL,0);
712 s->current_file_ok = (err == UNZ_OK);
713 return err;
714 }
715
716
717 /*
718 Set the current file of the zipfile to the next file.
719 return UNZ_OK if there is no problem
720 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
721 */
722 extern int ZEXPORT unzGoToNextFile (file)
723 unzFile file;
724 {
725 unz_s* s;
726 int err;
727
728 if (file==NULL)
729 return UNZ_PARAMERROR;
730 s=(unz_s*)file;
731 if (!s->current_file_ok)
732 return UNZ_END_OF_LIST_OF_FILE;
733 if (s->num_file+1==s->gi.number_entry)
734 return UNZ_END_OF_LIST_OF_FILE;
735
736 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
737 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
738 s->num_file++;
739 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
740 &s->cur_file_info_internal,
741 NULL,0,NULL,0,NULL,0);
742 s->current_file_ok = (err == UNZ_OK);
743 return err;
744 }
745
746
747 /*
748 Try locate the file szFileName in the zipfile.
749 For the iCaseSensitivity signification, see unzipStringFileNameCompare
750
751 return value :
752 UNZ_OK if the file is found. It becomes the current file.
753 UNZ_END_OF_LIST_OF_FILE if the file is not found
754 */
755 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
756 unzFile file;
757 const char *szFileName;
758 int iCaseSensitivity;
759 {
760 unz_s* s;
761 int err;
762
763
764 uLong num_fileSaved;
765 uLong pos_in_central_dirSaved;
766
767
768 if (file==NULL)
769 return UNZ_PARAMERROR;
770
771 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
772 return UNZ_PARAMERROR;
773
774 s=(unz_s*)file;
775 if (!s->current_file_ok)
776 return UNZ_END_OF_LIST_OF_FILE;
777
778 num_fileSaved = s->num_file;
779 pos_in_central_dirSaved = s->pos_in_central_dir;
780
781 err = unzGoToFirstFile(file);
782
783 while (err == UNZ_OK)
784 {
785 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
786 unzGetCurrentFileInfo(file,NULL,
787 szCurrentFileName,sizeof(szCurrentFileName)-1,
788 NULL,0,NULL,0);
789 if (unzStringFileNameCompare(szCurrentFileName,
790 szFileName,iCaseSensitivity)==0)
791 return UNZ_OK;
792 err = unzGoToNextFile(file);
793 }
794
795 s->num_file = num_fileSaved ;
796 s->pos_in_central_dir = pos_in_central_dirSaved ;
797 return err;
798 }
799
800
801 /*
802 Read the local header of the current zipfile
803 Check the coherency of the local header and info in the end of central
804 directory about this file
805 store in *piSizeVar the size of extra info in local header
806 (filename and size of extra field data)
807 */
unzlocal_CheckCurrentFileCoherencyHeader(s,piSizeVar,poffset_local_extrafield,psize_local_extrafield)808 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
809 poffset_local_extrafield,
810 psize_local_extrafield)
811 unz_s* s;
812 uInt* piSizeVar;
813 uLong *poffset_local_extrafield;
814 uInt *psize_local_extrafield;
815 {
816 uLong uMagic,uData,uFlags;
817 uLong size_filename;
818 uLong size_extra_field;
819 int err=UNZ_OK;
820
821 *piSizeVar = 0;
822 *poffset_local_extrafield = 0;
823 *psize_local_extrafield = 0;
824
825 if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
826 s->byte_before_the_zipfile,SEEK_SET)!=0)
827 return UNZ_ERRNO;
828
829
830 if (err==UNZ_OK)
831 {
832 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
833 err=UNZ_ERRNO;
834 else if (uMagic!=0x04034b50)
835 err=UNZ_BADZIPFILE;
836 }
837
838 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
839 err=UNZ_ERRNO;
840 /*
841 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
842 err=UNZ_BADZIPFILE;
843 */
844 if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
845 err=UNZ_ERRNO;
846
847 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
848 err=UNZ_ERRNO;
849 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
850 err=UNZ_BADZIPFILE;
851
852 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
853 (s->cur_file_info.compression_method!=Z_DEFLATED))
854 err=UNZ_BADZIPFILE;
855
856 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
857 err=UNZ_ERRNO;
858
859 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
860 err=UNZ_ERRNO;
861 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
862 ((uFlags & 8)==0))
863 err=UNZ_BADZIPFILE;
864
865 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
866 err=UNZ_ERRNO;
867 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
868 ((uFlags & 8)==0))
869 err=UNZ_BADZIPFILE;
870
871 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
872 err=UNZ_ERRNO;
873 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
874 ((uFlags & 8)==0))
875 err=UNZ_BADZIPFILE;
876
877
878 if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
879 err=UNZ_ERRNO;
880 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
881 err=UNZ_BADZIPFILE;
882
883 *piSizeVar += (uInt)size_filename;
884
885 if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
886 err=UNZ_ERRNO;
887 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
888 SIZEZIPLOCALHEADER + size_filename;
889 *psize_local_extrafield = (uInt)size_extra_field;
890
891 *piSizeVar += (uInt)size_extra_field;
892
893 return err;
894 }
895
896 /*
897 Open for reading data the current file in the zipfile.
898 If there is no error and the file is opened, the return value is UNZ_OK.
899 */
900 extern int ZEXPORT unzOpenCurrentFile (file)
901 unzFile file;
902 {
903 int err=UNZ_OK;
904 int Store;
905 uInt iSizeVar;
906 unz_s* s;
907 file_in_zip_read_info_s* pfile_in_zip_read_info;
908 uLong offset_local_extrafield; /* offset of the local extra field */
909 uInt size_local_extrafield; /* size of the local extra field */
910
911 if (file==NULL)
912 return UNZ_PARAMERROR;
913 s=(unz_s*)file;
914 if (!s->current_file_ok)
915 return UNZ_PARAMERROR;
916
917 if (s->pfile_in_zip_read != NULL)
918 unzCloseCurrentFile(file);
919
920 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
921 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
922 return UNZ_BADZIPFILE;
923
924 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
925 ALLOC(sizeof(file_in_zip_read_info_s));
926 if (pfile_in_zip_read_info==NULL)
927 return UNZ_INTERNALERROR;
928
929 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
930 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
931 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
932 pfile_in_zip_read_info->pos_local_extrafield=0;
933
934 if (pfile_in_zip_read_info->read_buffer==NULL)
935 {
936 TRYFREE(pfile_in_zip_read_info);
937 return UNZ_INTERNALERROR;
938 }
939
940 pfile_in_zip_read_info->stream_initialised=0;
941
942 if ((s->cur_file_info.compression_method!=0) &&
943 (s->cur_file_info.compression_method!=Z_DEFLATED))
944 err=UNZ_BADZIPFILE;
945 Store = s->cur_file_info.compression_method==0;
946
947 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
948 pfile_in_zip_read_info->crc32=0;
949 pfile_in_zip_read_info->compression_method =
950 s->cur_file_info.compression_method;
951 pfile_in_zip_read_info->file=s->file;
952 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
953
954 pfile_in_zip_read_info->stream.total_out = 0;
955
956 if (!Store)
957 {
958 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
959 pfile_in_zip_read_info->stream.zfree = (free_func)0;
960 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
961
962 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
963 if (err == Z_OK)
964 pfile_in_zip_read_info->stream_initialised=1;
965 /* windowBits is passed < 0 to tell that there is no zlib header.
966 * Note that in this case inflate *requires* an extra "dummy" byte
967 * after the compressed stream in order to complete decompression and
968 * return Z_STREAM_END.
969 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
970 * size of both compressed and uncompressed data
971 */
972 }
973 pfile_in_zip_read_info->rest_read_compressed =
974 s->cur_file_info.compressed_size ;
975 pfile_in_zip_read_info->rest_read_uncompressed =
976 s->cur_file_info.uncompressed_size ;
977
978
979 pfile_in_zip_read_info->pos_in_zipfile =
980 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
981 iSizeVar;
982
983 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
984
985
986 s->pfile_in_zip_read = pfile_in_zip_read_info;
987 return UNZ_OK;
988 }
989
990
991 /*
992 Read bytes from the current file.
993 buf contain buffer where data must be copied
994 len the size of buf.
995
996 return the number of byte copied if somes bytes are copied
997 return 0 if the end of file was reached
998 return <0 with error code if there is an error
999 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1000 */
1001 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1002 unzFile file;
1003 voidp buf;
1004 unsigned len;
1005 {
1006 int err=UNZ_OK;
1007 uInt iRead = 0;
1008 unz_s* s;
1009 file_in_zip_read_info_s* pfile_in_zip_read_info;
1010 if (file==NULL)
1011 return UNZ_PARAMERROR;
1012 s=(unz_s*)file;
1013 pfile_in_zip_read_info=s->pfile_in_zip_read;
1014
1015 if (pfile_in_zip_read_info==NULL)
1016 return UNZ_PARAMERROR;
1017
1018
1019 if ((pfile_in_zip_read_info->read_buffer == NULL))
1020 return UNZ_END_OF_LIST_OF_FILE;
1021 if (len==0)
1022 return 0;
1023
1024 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1025
1026 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1027
1028 if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1029 pfile_in_zip_read_info->stream.avail_out =
1030 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1031
1032 while (pfile_in_zip_read_info->stream.avail_out>0)
1033 {
1034 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1035 (pfile_in_zip_read_info->rest_read_compressed>0))
1036 {
1037 uInt uReadThis = UNZ_BUFSIZE;
1038 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1039 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1040 if (uReadThis == 0)
1041 return UNZ_EOF;
1042 if (fseek(pfile_in_zip_read_info->file,
1043 pfile_in_zip_read_info->pos_in_zipfile +
1044 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1045 return UNZ_ERRNO;
1046 if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1047 pfile_in_zip_read_info->file)!=1)
1048 return UNZ_ERRNO;
1049 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1050
1051 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1052
1053 pfile_in_zip_read_info->stream.next_in =
1054 (Bytef*)pfile_in_zip_read_info->read_buffer;
1055 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1056 }
1057
1058 if (pfile_in_zip_read_info->compression_method==0)
1059 {
1060 uInt uDoCopy,i ;
1061 if (pfile_in_zip_read_info->stream.avail_out <
1062 pfile_in_zip_read_info->stream.avail_in)
1063 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1064 else
1065 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1066
1067 for (i=0;i<uDoCopy;i++)
1068 *(pfile_in_zip_read_info->stream.next_out+i) =
1069 *(pfile_in_zip_read_info->stream.next_in+i);
1070
1071 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1072 pfile_in_zip_read_info->stream.next_out,
1073 uDoCopy);
1074 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1075 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1076 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1077 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1078 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1079 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1080 iRead += uDoCopy;
1081 }
1082 else
1083 {
1084 uLong uTotalOutBefore,uTotalOutAfter;
1085 const Bytef *bufBefore;
1086 uLong uOutThis;
1087 int flush=Z_SYNC_FLUSH;
1088
1089 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1090 bufBefore = pfile_in_zip_read_info->stream.next_out;
1091
1092 /*
1093 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1094 pfile_in_zip_read_info->stream.avail_out) &&
1095 (pfile_in_zip_read_info->rest_read_compressed == 0))
1096 flush = Z_FINISH;
1097 */
1098 err=inflate(&pfile_in_zip_read_info->stream,flush);
1099
1100 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1101 uOutThis = uTotalOutAfter-uTotalOutBefore;
1102
1103 pfile_in_zip_read_info->crc32 =
1104 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1105 (uInt)(uOutThis));
1106
1107 pfile_in_zip_read_info->rest_read_uncompressed -=
1108 uOutThis;
1109
1110 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1111
1112 if (err==Z_STREAM_END)
1113 return (iRead==0) ? UNZ_EOF : iRead;
1114 if (err!=Z_OK)
1115 break;
1116 }
1117 }
1118
1119 if (err==Z_OK)
1120 return iRead;
1121 return err;
1122 }
1123
1124
1125 /*
1126 Give the current position in uncompressed data
1127 */
1128 extern z_off_t ZEXPORT unztell (file)
1129 unzFile file;
1130 {
1131 unz_s* s;
1132 file_in_zip_read_info_s* pfile_in_zip_read_info;
1133 if (file==NULL)
1134 return UNZ_PARAMERROR;
1135 s=(unz_s*)file;
1136 pfile_in_zip_read_info=s->pfile_in_zip_read;
1137
1138 if (pfile_in_zip_read_info==NULL)
1139 return UNZ_PARAMERROR;
1140
1141 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1142 }
1143
1144
1145 /*
1146 return 1 if the end of file was reached, 0 elsewhere
1147 */
1148 extern int ZEXPORT unzeof (file)
1149 unzFile file;
1150 {
1151 unz_s* s;
1152 file_in_zip_read_info_s* pfile_in_zip_read_info;
1153 if (file==NULL)
1154 return UNZ_PARAMERROR;
1155 s=(unz_s*)file;
1156 pfile_in_zip_read_info=s->pfile_in_zip_read;
1157
1158 if (pfile_in_zip_read_info==NULL)
1159 return UNZ_PARAMERROR;
1160
1161 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1162 return 1;
1163 else
1164 return 0;
1165 }
1166
1167
1168
1169 /*
1170 Read extra field from the current file (opened by unzOpenCurrentFile)
1171 This is the local-header version of the extra field (sometimes, there is
1172 more info in the local-header version than in the central-header)
1173
1174 if buf==NULL, it return the size of the local extra field that can be read
1175
1176 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1177 buf.
1178 the return value is the number of bytes copied in buf, or (if <0)
1179 the error code
1180 */
1181 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1182 unzFile file;
1183 voidp buf;
1184 unsigned len;
1185 {
1186 unz_s* s;
1187 file_in_zip_read_info_s* pfile_in_zip_read_info;
1188 uInt read_now;
1189 uLong size_to_read;
1190
1191 if (file==NULL)
1192 return UNZ_PARAMERROR;
1193 s=(unz_s*)file;
1194 pfile_in_zip_read_info=s->pfile_in_zip_read;
1195
1196 if (pfile_in_zip_read_info==NULL)
1197 return UNZ_PARAMERROR;
1198
1199 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1200 pfile_in_zip_read_info->pos_local_extrafield);
1201
1202 if (buf==NULL)
1203 return (int)size_to_read;
1204
1205 if (len>size_to_read)
1206 read_now = (uInt)size_to_read;
1207 else
1208 read_now = (uInt)len ;
1209
1210 if (read_now==0)
1211 return 0;
1212
1213 if (fseek(pfile_in_zip_read_info->file,
1214 pfile_in_zip_read_info->offset_local_extrafield +
1215 pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1216 return UNZ_ERRNO;
1217
1218 if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1219 return UNZ_ERRNO;
1220
1221 return (int)read_now;
1222 }
1223
1224 /*
1225 Close the file in zip opened with unzipOpenCurrentFile
1226 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1227 */
1228 extern int ZEXPORT unzCloseCurrentFile (file)
1229 unzFile file;
1230 {
1231 int err=UNZ_OK;
1232
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->rest_read_uncompressed == 0)
1245 {
1246 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1247 err=UNZ_CRCERROR;
1248 }
1249
1250
1251 TRYFREE(pfile_in_zip_read_info->read_buffer);
1252 pfile_in_zip_read_info->read_buffer = NULL;
1253 if (pfile_in_zip_read_info->stream_initialised)
1254 inflateEnd(&pfile_in_zip_read_info->stream);
1255
1256 pfile_in_zip_read_info->stream_initialised = 0;
1257 TRYFREE(pfile_in_zip_read_info);
1258
1259 s->pfile_in_zip_read=NULL;
1260
1261 return err;
1262 }
1263
1264
1265 /*
1266 Get the global comment string of the ZipFile, in the szComment buffer.
1267 uSizeBuf is the size of the szComment buffer.
1268 return the number of byte copied or an error code <0
1269 */
1270 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1271 unzFile file;
1272 char *szComment;
1273 uLong uSizeBuf;
1274 {
1275 unz_s* s;
1276 uLong uReadThis;
1277
1278 if (file==NULL)
1279 return UNZ_PARAMERROR;
1280 s=(unz_s*)file;
1281
1282 uReadThis = uSizeBuf;
1283 if (uReadThis>s->gi.size_comment)
1284 uReadThis = s->gi.size_comment;
1285
1286 if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1287 return UNZ_ERRNO;
1288
1289 if (uReadThis>0)
1290 {
1291 *szComment='\0';
1292 if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1293 return UNZ_ERRNO;
1294 }
1295
1296 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1297 *(szComment+s->gi.size_comment)='\0';
1298 return (int)uReadThis;
1299 }
1300