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
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <zlib.h>
12 #include "unzip.h"
13
14 #ifdef STDC
15 # include <stddef.h>
16 # include <string.h>
17 # include <stdlib.h>
18 #endif
19 #ifdef NO_ERRNO_H
20 extern int errno;
21 #else
22 #include <errno.h>
23 #endif
24
25
26 #ifndef local
27 #define local static
28 #endif
29 /* compile with -Dlocal if your debugger can't find static symbols */
30
31
32
33 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
34 !defined(CASESENSITIVITYDEFAULT_NO)
35 #define CASESENSITIVITYDEFAULT_NO
36 #endif
37
38
39 #ifndef UNZ_BUFSIZE
40 #define UNZ_BUFSIZE (16384)
41 #endif
42
43 #ifndef UNZ_MAXFILENAMEINZIP
44 #define UNZ_MAXFILENAMEINZIP (256)
45 #endif
46
47 #ifndef ALLOC
48 # define ALLOC(size) (malloc(size))
49 #endif
50 #ifndef TRYFREE
51 # define TRYFREE(p) {if (p) free(p);}
52 #endif
53
54 #define SIZECENTRALDIRITEM (0x2e)
55 #define SIZEZIPLOCALHEADER (0x1e)
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 = 0;
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 = 0;
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 s=(unz_s*)ALLOC(sizeof(unz_s));
428 *s=us;
429 unzGoToFirstFile((unzFile)s);
430 return (unzFile)s;
431 }
432
433
434 /*
435 Close a ZipFile opened with unzipOpen.
436 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
437 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
438 return UNZ_OK if there is no problem. */
439 extern int ZEXPORT unzClose (file)
440 unzFile file;
441 {
442 unz_s* s;
443 if (file==NULL)
444 return UNZ_PARAMERROR;
445 s=(unz_s*)file;
446
447 if (s->pfile_in_zip_read!=NULL)
448 unzCloseCurrentFile(file);
449
450 fclose(s->file);
451 TRYFREE(s);
452 return UNZ_OK;
453 }
454
455
456 /*
457 Write info about the ZipFile in the *pglobal_info structure.
458 No preparation of the structure is needed
459 return UNZ_OK if there is no problem. */
460 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
461 unzFile file;
462 unz_global_info *pglobal_info;
463 {
464 unz_s* s;
465 if (file==NULL)
466 return UNZ_PARAMERROR;
467 s=(unz_s*)file;
468 *pglobal_info=s->gi;
469 return UNZ_OK;
470 }
471
472
473 /*
474 Translate date/time from Dos format to tm_unz (readable more easilty)
475 */
unzlocal_DosDateToTmuDate(ulDosDate,ptm)476 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
477 uLong ulDosDate;
478 tm_unz* ptm;
479 {
480 uLong uDate;
481 uDate = (uLong)(ulDosDate>>16);
482 ptm->tm_mday = (uInt)(uDate&0x1f) ;
483 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
484 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
485
486 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
487 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
488 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
489 }
490
491 /*
492 Get Info about the current file in the zipfile, with internal only info
493 */
494 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
495 unz_file_info *pfile_info,
496 unz_file_info_internal
497 *pfile_info_internal,
498 char *szFileName,
499 uLong fileNameBufferSize,
500 void *extraField,
501 uLong extraFieldBufferSize,
502 char *szComment,
503 uLong commentBufferSize));
504
unzlocal_GetCurrentFileInfoInternal(file,pfile_info,pfile_info_internal,szFileName,fileNameBufferSize,extraField,extraFieldBufferSize,szComment,commentBufferSize)505 local int unzlocal_GetCurrentFileInfoInternal (file,
506 pfile_info,
507 pfile_info_internal,
508 szFileName, fileNameBufferSize,
509 extraField, extraFieldBufferSize,
510 szComment, commentBufferSize)
511 unzFile file;
512 unz_file_info *pfile_info;
513 unz_file_info_internal *pfile_info_internal;
514 char *szFileName;
515 uLong fileNameBufferSize;
516 void *extraField;
517 uLong extraFieldBufferSize;
518 char *szComment;
519 uLong commentBufferSize;
520 {
521 unz_s* s;
522 unz_file_info file_info;
523 unz_file_info_internal file_info_internal;
524 int err=UNZ_OK;
525 uLong uMagic;
526 long lSeek=0;
527
528 if (file==NULL)
529 return UNZ_PARAMERROR;
530 s=(unz_s*)file;
531 if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
532 err=UNZ_ERRNO;
533
534
535 /* we check the magic */
536 if (err==UNZ_OK)
537 {
538 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
539 err=UNZ_ERRNO;
540 else if (uMagic!=0x02014b50)
541 err=UNZ_BADZIPFILE;
542 }
543
544 if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
545 err=UNZ_ERRNO;
546
547 if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
548 err=UNZ_ERRNO;
549
550 if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
551 err=UNZ_ERRNO;
552
553 if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
554 err=UNZ_ERRNO;
555
556 if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
557 err=UNZ_ERRNO;
558
559 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
560
561 if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
562 err=UNZ_ERRNO;
563
564 if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
565 err=UNZ_ERRNO;
566
567 if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
568 err=UNZ_ERRNO;
569
570 if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
571 err=UNZ_ERRNO;
572
573 if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
574 err=UNZ_ERRNO;
575
576 if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
577 err=UNZ_ERRNO;
578
579 if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
580 err=UNZ_ERRNO;
581
582 if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
583 err=UNZ_ERRNO;
584
585 if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
586 err=UNZ_ERRNO;
587
588 if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
589 err=UNZ_ERRNO;
590
591 lSeek+=file_info.size_filename;
592 if ((err==UNZ_OK) && (szFileName!=NULL))
593 {
594 uLong uSizeRead ;
595 if (file_info.size_filename<fileNameBufferSize)
596 {
597 *(szFileName+file_info.size_filename)='\0';
598 uSizeRead = file_info.size_filename;
599 }
600 else
601 uSizeRead = fileNameBufferSize;
602
603 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
604 if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
605 err=UNZ_ERRNO;
606 lSeek -= uSizeRead;
607 }
608
609 if ((err==UNZ_OK) && (extraField!=NULL))
610 {
611 uLong uSizeRead ;
612 if (file_info.size_file_extra<extraFieldBufferSize)
613 uSizeRead = file_info.size_file_extra;
614 else
615 uSizeRead = extraFieldBufferSize;
616
617 if (lSeek!=0)
618 {
619 if (fseek(s->file,lSeek,SEEK_CUR)==0)
620 lSeek=0;
621 else
622 err=UNZ_ERRNO;
623 }
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
652 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
653 if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
654 err=UNZ_ERRNO;
655 lSeek+=file_info.size_file_comment - uSizeRead;
656 }
657 else
658 lSeek+=file_info.size_file_comment;
659
660 if ((err==UNZ_OK) && (pfile_info!=NULL))
661 *pfile_info=file_info;
662
663 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
664 *pfile_info_internal=file_info_internal;
665
666 return err;
667 }
668
669
670
671 /*
672 Write info about the ZipFile in the *pglobal_info structure.
673 No preparation of the structure is needed
674 return UNZ_OK if there is no problem.
675 */
676 extern int ZEXPORT unzGetCurrentFileInfo (file,
677 pfile_info,
678 szFileName, fileNameBufferSize,
679 extraField, extraFieldBufferSize,
680 szComment, commentBufferSize)
681 unzFile file;
682 unz_file_info *pfile_info;
683 char *szFileName;
684 uLong fileNameBufferSize;
685 void *extraField;
686 uLong extraFieldBufferSize;
687 char *szComment;
688 uLong commentBufferSize;
689 {
690 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
691 szFileName,fileNameBufferSize,
692 extraField,extraFieldBufferSize,
693 szComment,commentBufferSize);
694 }
695
696 /*
697 Set the current file of the zipfile to the first file.
698 return UNZ_OK if there is no problem
699 */
700 extern int ZEXPORT unzGoToFirstFile (file)
701 unzFile file;
702 {
703 int err=UNZ_OK;
704 unz_s* s;
705 if (file==NULL)
706 return UNZ_PARAMERROR;
707 s=(unz_s*)file;
708 s->pos_in_central_dir=s->offset_central_dir;
709 s->num_file=0;
710 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
711 &s->cur_file_info_internal,
712 NULL,0,NULL,0,NULL,0);
713 s->current_file_ok = (err == UNZ_OK);
714 return err;
715 }
716
717
718 /*
719 Set the current file of the zipfile to the next file.
720 return UNZ_OK if there is no problem
721 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
722 */
723 extern int ZEXPORT unzGoToNextFile (file)
724 unzFile file;
725 {
726 unz_s* s;
727 int err;
728
729 if (file==NULL)
730 return UNZ_PARAMERROR;
731 s=(unz_s*)file;
732 if (!s->current_file_ok)
733 return UNZ_END_OF_LIST_OF_FILE;
734 if (s->num_file+1==s->gi.number_entry)
735 return UNZ_END_OF_LIST_OF_FILE;
736
737 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
738 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
739 s->num_file++;
740 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
741 &s->cur_file_info_internal,
742 NULL,0,NULL,0,NULL,0);
743 s->current_file_ok = (err == UNZ_OK);
744 return err;
745 }
746
747
748 /*
749 Try locate the file szFileName in the zipfile.
750 For the iCaseSensitivity signification, see unzipStringFileNameCompare
751
752 return value :
753 UNZ_OK if the file is found. It becomes the current file.
754 UNZ_END_OF_LIST_OF_FILE if the file is not found
755 */
756 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
757 unzFile file;
758 const char *szFileName;
759 int iCaseSensitivity;
760 {
761 unz_s* s;
762 int err;
763
764 uLong num_fileSaved;
765 uLong pos_in_central_dirSaved;
766
767 if (file==NULL)
768 return UNZ_PARAMERROR;
769
770 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
771 return UNZ_PARAMERROR;
772
773 s=(unz_s*)file;
774 if (!s->current_file_ok)
775 return UNZ_END_OF_LIST_OF_FILE;
776
777 num_fileSaved = s->num_file;
778 pos_in_central_dirSaved = s->pos_in_central_dir;
779
780 err = unzGoToFirstFile(file);
781
782 while (err == UNZ_OK)
783 {
784 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
785 unzGetCurrentFileInfo(file,NULL,
786 szCurrentFileName,sizeof(szCurrentFileName)-1,
787 NULL,0,NULL,0);
788 if (unzStringFileNameCompare(szCurrentFileName,
789 szFileName,iCaseSensitivity)==0)
790 return UNZ_OK;
791 err = unzGoToNextFile(file);
792 }
793
794 s->num_file = num_fileSaved ;
795 s->pos_in_central_dir = pos_in_central_dirSaved ;
796 return err;
797 }
798
799
800 /*
801 Read the local header of the current zipfile
802 Check the coherency of the local header and info in the end of central
803 directory about this file
804 store in *piSizeVar the size of extra info in local header
805 (filename and size of extra field data)
806 */
unzlocal_CheckCurrentFileCoherencyHeader(s,piSizeVar,poffset_local_extrafield,psize_local_extrafield)807 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
808 poffset_local_extrafield,
809 psize_local_extrafield)
810 unz_s* s;
811 uInt* piSizeVar;
812 uLong *poffset_local_extrafield;
813 uInt *psize_local_extrafield;
814 {
815 uLong uMagic,uData,uFlags;
816 uLong size_filename;
817 uLong size_extra_field;
818 int err=UNZ_OK;
819
820 *piSizeVar = 0;
821 *poffset_local_extrafield = 0;
822 *psize_local_extrafield = 0;
823
824 if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
825 s->byte_before_the_zipfile,SEEK_SET)!=0)
826 return UNZ_ERRNO;
827
828
829 if (err==UNZ_OK)
830 {
831 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
832 err=UNZ_ERRNO;
833 else if (uMagic!=0x04034b50)
834 err=UNZ_BADZIPFILE;
835 }
836
837 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
838 err=UNZ_ERRNO;
839 /*
840 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
841 err=UNZ_BADZIPFILE;
842 */
843 if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
844 err=UNZ_ERRNO;
845
846 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
847 err=UNZ_ERRNO;
848 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
849 err=UNZ_BADZIPFILE;
850
851 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
852 (s->cur_file_info.compression_method!=Z_DEFLATED))
853 err=UNZ_BADZIPFILE;
854
855 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
856 err=UNZ_ERRNO;
857
858 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
859 err=UNZ_ERRNO;
860 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
861 ((uFlags & 8)==0))
862 err=UNZ_BADZIPFILE;
863
864 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
865 err=UNZ_ERRNO;
866 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
867 ((uFlags & 8)==0))
868 err=UNZ_BADZIPFILE;
869
870 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
871 err=UNZ_ERRNO;
872 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
873 ((uFlags & 8)==0))
874 err=UNZ_BADZIPFILE;
875
876
877 if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
878 err=UNZ_ERRNO;
879 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
880 err=UNZ_BADZIPFILE;
881
882 *piSizeVar += (uInt)size_filename;
883
884 if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
885 err=UNZ_ERRNO;
886 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
887 SIZEZIPLOCALHEADER + size_filename;
888 *psize_local_extrafield = (uInt)size_extra_field;
889
890 *piSizeVar += (uInt)size_extra_field;
891
892 return err;
893 }
894
895 /*
896 Open for reading data the current file in the zipfile.
897 If there is no error and the file is opened, the return value is UNZ_OK.
898 */
899 extern int ZEXPORT unzOpenCurrentFile (file)
900 unzFile file;
901 {
902 int err=UNZ_OK;
903 int Store;
904 uInt iSizeVar;
905 unz_s* s;
906 file_in_zip_read_info_s* pfile_in_zip_read_info;
907 uLong offset_local_extrafield; /* offset of the local extra field */
908 uInt size_local_extrafield; /* size of the local extra field */
909
910 if (file==NULL)
911 return UNZ_PARAMERROR;
912 s=(unz_s*)file;
913 if (!s->current_file_ok)
914 return UNZ_PARAMERROR;
915
916 if (s->pfile_in_zip_read != NULL)
917 unzCloseCurrentFile(file);
918
919 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
920 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
921 return UNZ_BADZIPFILE;
922
923 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
924 ALLOC(sizeof(file_in_zip_read_info_s));
925 if (pfile_in_zip_read_info==NULL)
926 return UNZ_INTERNALERROR;
927
928 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
929 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
930 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
931 pfile_in_zip_read_info->pos_local_extrafield=0;
932
933 if (pfile_in_zip_read_info->read_buffer==NULL)
934 {
935 TRYFREE(pfile_in_zip_read_info);
936 return UNZ_INTERNALERROR;
937 }
938
939 pfile_in_zip_read_info->stream_initialised=0;
940
941 if ((s->cur_file_info.compression_method!=0) &&
942 (s->cur_file_info.compression_method!=Z_DEFLATED))
943 err=UNZ_BADZIPFILE;
944 Store = s->cur_file_info.compression_method==0;
945
946 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
947 pfile_in_zip_read_info->crc32=0;
948 pfile_in_zip_read_info->compression_method =
949 s->cur_file_info.compression_method;
950 pfile_in_zip_read_info->file=s->file;
951 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
952
953 pfile_in_zip_read_info->stream.total_out = 0;
954
955 if (!Store)
956 {
957 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
958 pfile_in_zip_read_info->stream.zfree = (free_func)0;
959 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
960
961 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
962 if (err == Z_OK)
963 pfile_in_zip_read_info->stream_initialised=1;
964 /* windowBits is passed < 0 to tell that there is no zlib header.
965 * Note that in this case inflate *requires* an extra "dummy" byte
966 * after the compressed stream in order to complete decompression and
967 * return Z_STREAM_END.
968 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
969 * size of both compressed and uncompressed data
970 */
971 }
972 pfile_in_zip_read_info->rest_read_compressed =
973 s->cur_file_info.compressed_size ;
974 pfile_in_zip_read_info->rest_read_uncompressed =
975 s->cur_file_info.uncompressed_size ;
976
977 pfile_in_zip_read_info->pos_in_zipfile =
978 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
979 iSizeVar;
980
981 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
982
983
984 s->pfile_in_zip_read = pfile_in_zip_read_info;
985 return UNZ_OK;
986 }
987
988
989 /*
990 Read bytes from the current file.
991 buf contain buffer where data must be copied
992 len the size of buf.
993
994 return the number of byte copied if somes bytes are copied
995 return 0 if the end of file was reached
996 return <0 with error code if there is an error
997 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
998 */
999 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1000 unzFile file;
1001 voidp buf;
1002 unsigned len;
1003 {
1004 int err=UNZ_OK;
1005 uInt iRead = 0;
1006 unz_s* s;
1007 file_in_zip_read_info_s* pfile_in_zip_read_info;
1008 if (file==NULL)
1009 return UNZ_PARAMERROR;
1010 s=(unz_s*)file;
1011 pfile_in_zip_read_info=s->pfile_in_zip_read;
1012
1013 if (pfile_in_zip_read_info==NULL)
1014 return UNZ_PARAMERROR;
1015
1016 if ((pfile_in_zip_read_info->read_buffer == NULL))
1017 return UNZ_END_OF_LIST_OF_FILE;
1018 if (len==0)
1019 return 0;
1020
1021 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1022
1023 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1024
1025 if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1026 pfile_in_zip_read_info->stream.avail_out =
1027 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1028
1029 while (pfile_in_zip_read_info->stream.avail_out>0)
1030 {
1031 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1032 (pfile_in_zip_read_info->rest_read_compressed>0))
1033 {
1034 uInt uReadThis = UNZ_BUFSIZE;
1035 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1036 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1037 if (uReadThis == 0)
1038 return UNZ_EOF;
1039 if (fseek(pfile_in_zip_read_info->file,
1040 pfile_in_zip_read_info->pos_in_zipfile +
1041 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1042 return UNZ_ERRNO;
1043 if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1044 pfile_in_zip_read_info->file)!=1)
1045 return UNZ_ERRNO;
1046 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1047
1048 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1049
1050 pfile_in_zip_read_info->stream.next_in =
1051 (Bytef*)pfile_in_zip_read_info->read_buffer;
1052 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1053 }
1054
1055 if (pfile_in_zip_read_info->compression_method==0)
1056 {
1057 uInt uDoCopy,i ;
1058 if (pfile_in_zip_read_info->stream.avail_out <
1059 pfile_in_zip_read_info->stream.avail_in)
1060 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1061 else
1062 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1063
1064 for (i=0;i<uDoCopy;i++)
1065 *(pfile_in_zip_read_info->stream.next_out+i) =
1066 *(pfile_in_zip_read_info->stream.next_in+i);
1067
1068 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1069 pfile_in_zip_read_info->stream.next_out,
1070 uDoCopy);
1071 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1072 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1073 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1074 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1075 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1076 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1077 iRead += uDoCopy;
1078 }
1079 else
1080 {
1081 uLong uTotalOutBefore,uTotalOutAfter;
1082 const Bytef *bufBefore;
1083 uLong uOutThis;
1084 int flush=Z_SYNC_FLUSH;
1085
1086 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1087 bufBefore = pfile_in_zip_read_info->stream.next_out;
1088
1089 /*
1090 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1091 pfile_in_zip_read_info->stream.avail_out) &&
1092 (pfile_in_zip_read_info->rest_read_compressed == 0))
1093 flush = Z_FINISH;
1094 */
1095 err=inflate(&pfile_in_zip_read_info->stream,flush);
1096
1097 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1098 uOutThis = uTotalOutAfter-uTotalOutBefore;
1099
1100 pfile_in_zip_read_info->crc32 =
1101 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1102 (uInt)(uOutThis));
1103
1104 pfile_in_zip_read_info->rest_read_uncompressed -=
1105 uOutThis;
1106
1107 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1108
1109 if (err==Z_STREAM_END)
1110 return (iRead==0) ? UNZ_EOF : iRead;
1111 if (err!=Z_OK)
1112 break;
1113 }
1114 }
1115
1116 if (err==Z_OK)
1117 return iRead;
1118 return err;
1119 }
1120
1121
1122 /*
1123 Give the current position in uncompressed data
1124 */
1125 extern z_off_t ZEXPORT unztell (file)
1126 unzFile file;
1127 {
1128 unz_s* s;
1129 file_in_zip_read_info_s* pfile_in_zip_read_info;
1130 if (file==NULL)
1131 return UNZ_PARAMERROR;
1132 s=(unz_s*)file;
1133 pfile_in_zip_read_info=s->pfile_in_zip_read;
1134
1135 if (pfile_in_zip_read_info==NULL)
1136 return UNZ_PARAMERROR;
1137
1138 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1139 }
1140
1141
1142 /*
1143 return 1 if the end of file was reached, 0 elsewhere
1144 */
1145 extern int ZEXPORT unzeof (file)
1146 unzFile file;
1147 {
1148 unz_s* s;
1149 file_in_zip_read_info_s* pfile_in_zip_read_info;
1150 if (file==NULL)
1151 return UNZ_PARAMERROR;
1152 s=(unz_s*)file;
1153 pfile_in_zip_read_info=s->pfile_in_zip_read;
1154
1155 if (pfile_in_zip_read_info==NULL)
1156 return UNZ_PARAMERROR;
1157
1158 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1159 return 1;
1160 else
1161 return 0;
1162 }
1163
1164 /*
1165 Read extra field from the current file (opened by unzOpenCurrentFile)
1166 This is the local-header version of the extra field (sometimes, there is
1167 more info in the local-header version than in the central-header)
1168
1169 if buf==NULL, it return the size of the local extra field that can be read
1170
1171 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1172 buf.
1173 the return value is the number of bytes copied in buf, or (if <0)
1174 the error code
1175 */
1176 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1177 unzFile file;
1178 voidp buf;
1179 unsigned len;
1180 {
1181 unz_s* s;
1182 file_in_zip_read_info_s* pfile_in_zip_read_info;
1183 uInt read_now;
1184 uLong size_to_read;
1185
1186 if (file==NULL)
1187 return UNZ_PARAMERROR;
1188 s=(unz_s*)file;
1189 pfile_in_zip_read_info=s->pfile_in_zip_read;
1190
1191 if (pfile_in_zip_read_info==NULL)
1192 return UNZ_PARAMERROR;
1193
1194 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1195 pfile_in_zip_read_info->pos_local_extrafield);
1196
1197 if (buf==NULL)
1198 return (int)size_to_read;
1199
1200 if (len>size_to_read)
1201 read_now = (uInt)size_to_read;
1202 else
1203 read_now = (uInt)len ;
1204
1205 if (read_now==0)
1206 return 0;
1207
1208 if (fseek(pfile_in_zip_read_info->file,
1209 pfile_in_zip_read_info->offset_local_extrafield +
1210 pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1211 return UNZ_ERRNO;
1212
1213 if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1214 return UNZ_ERRNO;
1215
1216 return (int)read_now;
1217 }
1218
1219 /*
1220 Close the file in zip opened with unzipOpenCurrentFile
1221 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1222 */
1223 extern int ZEXPORT unzCloseCurrentFile (file)
1224 unzFile file;
1225 {
1226 int err=UNZ_OK;
1227
1228 unz_s* s;
1229 file_in_zip_read_info_s* pfile_in_zip_read_info;
1230 if (file==NULL)
1231 return UNZ_PARAMERROR;
1232 s=(unz_s*)file;
1233 pfile_in_zip_read_info=s->pfile_in_zip_read;
1234
1235 if (pfile_in_zip_read_info==NULL)
1236 return UNZ_PARAMERROR;
1237
1238
1239 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1240 {
1241 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1242 err=UNZ_CRCERROR;
1243 }
1244
1245
1246 TRYFREE(pfile_in_zip_read_info->read_buffer);
1247 pfile_in_zip_read_info->read_buffer = NULL;
1248 if (pfile_in_zip_read_info->stream_initialised)
1249 inflateEnd(&pfile_in_zip_read_info->stream);
1250
1251 pfile_in_zip_read_info->stream_initialised = 0;
1252 TRYFREE(pfile_in_zip_read_info);
1253
1254 s->pfile_in_zip_read=NULL;
1255
1256 return err;
1257 }
1258
1259
1260 /*
1261 Get the global comment string of the ZipFile, in the szComment buffer.
1262 uSizeBuf is the size of the szComment buffer.
1263 return the number of byte copied or an error code <0
1264 */
1265 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1266 unzFile file;
1267 char *szComment;
1268 uLong uSizeBuf;
1269 {
1270 /* int err=UNZ_OK; */
1271 unz_s* s;
1272 uLong uReadThis ;
1273 if (file==NULL)
1274 return UNZ_PARAMERROR;
1275 s=(unz_s*)file;
1276
1277 uReadThis = uSizeBuf;
1278 if (uReadThis>s->gi.size_comment)
1279 uReadThis = s->gi.size_comment;
1280
1281 if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1282 return UNZ_ERRNO;
1283
1284 if (uReadThis>0)
1285 {
1286 *szComment='\0';
1287 if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1288 return UNZ_ERRNO;
1289 }
1290
1291 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1292 *(szComment+s->gi.size_comment)='\0';
1293 return (int)uReadThis;
1294 }
1295