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
58 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
59
60 #ifndef SEEK_CUR
61 #define SEEK_CUR 1
62 #endif
63
64 #ifndef SEEK_END
65 #define SEEK_END 2
66 #endif
67
68 #ifndef SEEK_SET
69 #define SEEK_SET 0
70 #endif
71
72 const char unz_copyright[] =
73 " unzip 0.15 Copyright 1998 Gilles Vollant ";
74
75 /* unz_file_info_interntal contain internal info about a file in zipfile*/
76 typedef struct unz_file_info_internal_s
77 {
78 uLong offset_curfile;/* relative offset of local header 4 bytes */
79 } unz_file_info_internal;
80
81
82 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
83 when reading and decompress it */
84 typedef struct
85 {
86 char *read_buffer; /* internal buffer for compressed data */
87 z_stream stream; /* zLib stream structure for inflate */
88
89 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
90 uLong stream_initialised; /* flag set if stream structure is initialised*/
91
92 uLong offset_local_extrafield;/* offset of the local extra field */
93 uInt size_local_extrafield;/* size of the local extra field */
94 uLong pos_local_extrafield; /* position in the local extra field in read*/
95
96 uLong crc32; /* crc32 of all data uncompressed */
97 uLong crc32_wait; /* crc32 we must obtain after decompress all */
98 uLong rest_read_compressed; /* number of byte to be decompressed */
99 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
100 FILE* file; /* io structore of the zipfile */
101 uLong compression_method; /* compression method (0==store) */
102 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
103 } file_in_zip_read_info_s;
104
105
106 /* unz_s contain internal information about the zipfile
107 */
108 typedef struct
109 {
110 FILE* file; /* io structore of the zipfile */
111 unz_global_info gi; /* public global information */
112 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
113 uLong num_file; /* number of the current file in the zipfile*/
114 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
115 uLong current_file_ok; /* flag about the usability of the current file*/
116 uLong central_pos; /* position of the beginning of the central dir*/
117
118 uLong size_central_dir; /* size of the central directory */
119 uLong offset_central_dir; /* offset of start of central directory with
120 respect to the starting disk number */
121
122 unz_file_info cur_file_info; /* public info about the current file in zip*/
123 unz_file_info_internal cur_file_info_internal; /* private info about it*/
124 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
125 file if we are decompressing it */
126 } unz_s;
127
128
129 /* ===========================================================================
130 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
131 for end of file.
132 IN assertion: the stream s has been sucessfully opened for reading.
133 */
134
135
unzlocal_getByte(fin,pi)136 local int unzlocal_getByte(fin,pi)
137 FILE *fin;
138 int *pi;
139 {
140 unsigned char c;
141 int err = fread(&c, 1, 1, fin);
142 if (err==1)
143 {
144 *pi = (int)c;
145 return UNZ_OK;
146 }
147 else
148 {
149 if (ferror(fin))
150 return UNZ_ERRNO;
151 else
152 return UNZ_EOF;
153 }
154 }
155
156
157 /* ===========================================================================
158 Reads a long in LSB order from the given gz_stream. Sets
159 */
unzlocal_getShort(fin,pX)160 local int unzlocal_getShort (fin,pX)
161 FILE* fin;
162 uLong *pX;
163 {
164 uLong x ;
165 int i;
166 int err;
167
168 err = unzlocal_getByte(fin,&i);
169 x = (uLong)i;
170
171 if (err==UNZ_OK)
172 err = unzlocal_getByte(fin,&i);
173 x += ((uLong)i)<<8;
174
175 if (err==UNZ_OK)
176 *pX = x;
177 else
178 *pX = 0;
179 return err;
180 }
181
unzlocal_getLong(fin,pX)182 local int unzlocal_getLong (fin,pX)
183 FILE* fin;
184 uLong *pX;
185 {
186 uLong x ;
187 int i;
188 int err;
189
190 err = unzlocal_getByte(fin,&i);
191 x = (uLong)i;
192
193 if (err==UNZ_OK)
194 err = unzlocal_getByte(fin,&i);
195 x += ((uLong)i)<<8;
196
197 if (err==UNZ_OK)
198 err = unzlocal_getByte(fin,&i);
199 x += ((uLong)i)<<16;
200
201 if (err==UNZ_OK)
202 err = unzlocal_getByte(fin,&i);
203 x += ((uLong)i)<<24;
204
205 if (err==UNZ_OK)
206 *pX = x;
207 else
208 *pX = 0;
209 return err;
210 }
211
212
213 /* My own strcmpi / strcasecmp */
strcmpcasenosensitive_internal(fileName1,fileName2)214 local int strcmpcasenosensitive_internal (fileName1,fileName2)
215 const char* fileName1;
216 const char* fileName2;
217 {
218 for (;;)
219 {
220 char c1=*(fileName1++);
221 char c2=*(fileName2++);
222 if ((c1>='a') && (c1<='z'))
223 c1 -= 0x20;
224 if ((c2>='a') && (c2<='z'))
225 c2 -= 0x20;
226 if (c1=='\0')
227 return ((c2=='\0') ? 0 : -1);
228 if (c2=='\0')
229 return 1;
230 if (c1<c2)
231 return -1;
232 if (c1>c2)
233 return 1;
234 }
235 }
236
237
238 #ifdef CASESENSITIVITYDEFAULT_NO
239 #define CASESENSITIVITYDEFAULTVALUE 2
240 #else
241 #define CASESENSITIVITYDEFAULTVALUE 1
242 #endif
243
244 #ifndef STRCMPCASENOSENTIVEFUNCTION
245 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
246 #endif
247
248 /*
249 Compare two filename (fileName1,fileName2).
250 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
251 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
252 or strcasecmp)
253 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
254 (like 1 on Unix, 2 on Windows)
255
256 */
257 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
258 const char* fileName1;
259 const char* fileName2;
260 int iCaseSensitivity;
261 {
262 if (iCaseSensitivity==0)
263 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
264
265 if (iCaseSensitivity==1)
266 return strcmp(fileName1,fileName2);
267
268 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
269 }
270
271 #define BUFREADCOMMENT (0x400)
272
273 /*
274 Locate the Central directory of a zipfile (at the end, just before
275 the global comment)
276 */
unzlocal_SearchCentralDir(fin)277 local uLong unzlocal_SearchCentralDir(fin)
278 FILE *fin;
279 {
280 unsigned char* buf;
281 uLong uSizeFile;
282 uLong uBackRead;
283 uLong uMaxBack=0xffff; /* maximum size of global comment */
284 uLong uPosFound=0;
285
286 if (fseek(fin,0,SEEK_END) != 0)
287 return 0;
288
289
290 uSizeFile = ftell( fin );
291
292 if (uMaxBack>uSizeFile)
293 uMaxBack = uSizeFile;
294
295 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
296 if (buf==NULL)
297 return 0;
298
299 uBackRead = 4;
300 while (uBackRead<uMaxBack)
301 {
302 uLong uReadSize,uReadPos ;
303 int i;
304 if (uBackRead+BUFREADCOMMENT>uMaxBack)
305 uBackRead = uMaxBack;
306 else
307 uBackRead+=BUFREADCOMMENT;
308 uReadPos = uSizeFile-uBackRead ;
309
310 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
311 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
312 if (fseek(fin,uReadPos,SEEK_SET)!=0)
313 break;
314
315 if (fread(buf,(uInt)uReadSize,1,fin)!=1)
316 break;
317
318 for (i=(int)uReadSize-3; (i--)>0;)
319 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
320 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
321 {
322 uPosFound = uReadPos+i;
323 break;
324 }
325
326 if (uPosFound!=0)
327 break;
328 }
329 TRYFREE(buf);
330 return uPosFound;
331 }
332
333 /*
334 Open a Zip file. path contain the full pathname (by example,
335 on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
336 "zlib/zlib109.zip".
337 If the zipfile cannot be opened (file don't exist or in not valid), the
338 return value is NULL.
339 Else, the return value is a unzFile Handle, usable with other function
340 of this unzip package.
341 */
342 extern unzFile ZEXPORT unzOpen (path)
343 const char *path;
344 {
345 unz_s us;
346 unz_s *s;
347 uLong central_pos,uL;
348 FILE * fin ;
349
350 uLong number_disk; /* number of the current dist, used for
351 spaning ZIP, unsupported, always 0*/
352 uLong number_disk_with_CD; /* number the the disk with central dir, used
353 for spaning ZIP, unsupported, always 0*/
354 uLong number_entry_CD; /* total number of entries in
355 the central dir
356 (same than number_entry on nospan) */
357
358 int err=UNZ_OK;
359
360 if (unz_copyright[0]!=' ')
361 return NULL;
362
363 fin=fopen(path,"rb");
364 if (fin==NULL)
365 return NULL;
366
367 central_pos = unzlocal_SearchCentralDir(fin);
368 if (central_pos==0)
369 err=UNZ_ERRNO;
370
371 if (fseek(fin,central_pos,SEEK_SET)!=0)
372 err=UNZ_ERRNO;
373
374 /* the signature, already checked */
375 if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
376 err=UNZ_ERRNO;
377
378 /* number of this disk */
379 if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
380 err=UNZ_ERRNO;
381
382 /* number of the disk with the start of the central directory */
383 if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
384 err=UNZ_ERRNO;
385
386 /* total number of entries in the central dir on this disk */
387 if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
388 err=UNZ_ERRNO;
389
390 /* total number of entries in the central dir */
391 if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
392 err=UNZ_ERRNO;
393
394 if ((number_entry_CD!=us.gi.number_entry) ||
395 (number_disk_with_CD!=0) ||
396 (number_disk!=0))
397 err=UNZ_BADZIPFILE;
398
399 /* size of the central directory */
400 if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
401 err=UNZ_ERRNO;
402
403 /* offset of start of central directory with respect to the
404 starting disk number */
405 if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
406 err=UNZ_ERRNO;
407
408 /* zipfile comment length */
409 if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
410 err=UNZ_ERRNO;
411
412 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
413 (err==UNZ_OK))
414 err=UNZ_BADZIPFILE;
415
416 if (err!=UNZ_OK)
417 {
418 fclose(fin);
419 return NULL;
420 }
421
422 us.file=fin;
423 us.byte_before_the_zipfile = central_pos -
424 (us.offset_central_dir+us.size_central_dir);
425 us.central_pos = central_pos;
426 us.pfile_in_zip_read = NULL;
427
428
429 s=(unz_s*)ALLOC(sizeof(unz_s));
430 *s=us;
431 unzGoToFirstFile((unzFile)s);
432 return (unzFile)s;
433 }
434
435
436 /*
437 Close a ZipFile opened with unzipOpen.
438 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
439 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
440 return UNZ_OK if there is no problem. */
441 extern int ZEXPORT unzClose (file)
442 unzFile file;
443 {
444 unz_s* s;
445 if (file==NULL)
446 return UNZ_PARAMERROR;
447 s=(unz_s*)file;
448
449 if (s->pfile_in_zip_read!=NULL)
450 unzCloseCurrentFile(file);
451
452 fclose(s->file);
453 TRYFREE(s);
454 return UNZ_OK;
455 }
456
457
458 /*
459 Write info about the ZipFile in the *pglobal_info structure.
460 No preparation of the structure is needed
461 return UNZ_OK if there is no problem. */
462 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
463 unzFile file;
464 unz_global_info *pglobal_info;
465 {
466 unz_s* s;
467 if (file==NULL)
468 return UNZ_PARAMERROR;
469 s=(unz_s*)file;
470 *pglobal_info=s->gi;
471 return UNZ_OK;
472 }
473
474
475 /*
476 Translate date/time from Dos format to tm_unz (readable more easilty)
477 */
unzlocal_DosDateToTmuDate(ulDosDate,ptm)478 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
479 uLong ulDosDate;
480 tm_unz* ptm;
481 {
482 uLong uDate;
483 uDate = (uLong)(ulDosDate>>16);
484 ptm->tm_mday = (uInt)(uDate&0x1f) ;
485 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
486 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
487
488 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
489 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
490 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
491 }
492
493 /*
494 Get Info about the current file in the zipfile, with internal only info
495 */
496 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
497 unz_file_info *pfile_info,
498 unz_file_info_internal
499 *pfile_info_internal,
500 char *szFileName,
501 uLong fileNameBufferSize,
502 void *extraField,
503 uLong extraFieldBufferSize,
504 char *szComment,
505 uLong commentBufferSize));
506
unzlocal_GetCurrentFileInfoInternal(file,pfile_info,pfile_info_internal,szFileName,fileNameBufferSize,extraField,extraFieldBufferSize,szComment,commentBufferSize)507 local int unzlocal_GetCurrentFileInfoInternal (file,
508 pfile_info,
509 pfile_info_internal,
510 szFileName, fileNameBufferSize,
511 extraField, extraFieldBufferSize,
512 szComment, commentBufferSize)
513 unzFile file;
514 unz_file_info *pfile_info;
515 unz_file_info_internal *pfile_info_internal;
516 char *szFileName;
517 uLong fileNameBufferSize;
518 void *extraField;
519 uLong extraFieldBufferSize;
520 char *szComment;
521 uLong commentBufferSize;
522 {
523 unz_s* s;
524 unz_file_info file_info;
525 unz_file_info_internal file_info_internal;
526 int err=UNZ_OK;
527 uLong uMagic;
528 long lSeek=0;
529
530 if (file==NULL)
531 return UNZ_PARAMERROR;
532 s=(unz_s*)file;
533 if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
534 err=UNZ_ERRNO;
535
536
537 /* we check the magic */
538 if (err==UNZ_OK) {
539 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
540 err=UNZ_ERRNO;
541 else if (uMagic!=0x02014b50)
542 err=UNZ_BADZIPFILE;
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
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 if (fseek(s->file,lSeek,SEEK_CUR)==0)
620 lSeek=0;
621 else
622 err=UNZ_ERRNO;
623 }
624 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
625 if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
626 err=UNZ_ERRNO;
627 lSeek += file_info.size_file_extra - uSizeRead;
628 }
629 else
630 lSeek+=file_info.size_file_extra;
631
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 if (fseek(s->file,lSeek,SEEK_CUR)==0)
646 lSeek=0;
647 else
648 err=UNZ_ERRNO;
649 }
650 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
651 if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
652 err=UNZ_ERRNO;
653 lSeek+=file_info.size_file_comment - uSizeRead;
654 }
655 else
656 lSeek+=file_info.size_file_comment;
657
658 if ((err==UNZ_OK) && (pfile_info!=NULL))
659 *pfile_info=file_info;
660
661 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
662 *pfile_info_internal=file_info_internal;
663
664 return err;
665 }
666
667
668
669 /*
670 Write info about the ZipFile in the *pglobal_info structure.
671 No preparation of the structure is needed
672 return UNZ_OK if there is no problem.
673 */
674 extern int ZEXPORT unzGetCurrentFileInfo (file,
675 pfile_info,
676 szFileName, fileNameBufferSize,
677 extraField, extraFieldBufferSize,
678 szComment, commentBufferSize)
679 unzFile file;
680 unz_file_info *pfile_info;
681 char *szFileName;
682 uLong fileNameBufferSize;
683 void *extraField;
684 uLong extraFieldBufferSize;
685 char *szComment;
686 uLong commentBufferSize;
687 {
688 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
689 szFileName,fileNameBufferSize,
690 extraField,extraFieldBufferSize,
691 szComment,commentBufferSize);
692 }
693
694 /*
695 Set the current file of the zipfile to the first file.
696 return UNZ_OK if there is no problem
697 */
698 extern int ZEXPORT unzGoToFirstFile (file)
699 unzFile file;
700 {
701 int err=UNZ_OK;
702 unz_s* s;
703 if (file==NULL)
704 return UNZ_PARAMERROR;
705 s=(unz_s*)file;
706 s->pos_in_central_dir=s->offset_central_dir;
707 s->num_file=0;
708 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
709 &s->cur_file_info_internal,
710 NULL,0,NULL,0,NULL,0);
711 s->current_file_ok = (err == UNZ_OK);
712 return err;
713 }
714
715
716 /*
717 Set the current file of the zipfile to the next file.
718 return UNZ_OK if there is no problem
719 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
720 */
721 extern int ZEXPORT unzGoToNextFile (file)
722 unzFile file;
723 {
724 unz_s* s;
725 int err;
726
727 if (file==NULL)
728 return UNZ_PARAMERROR;
729 s=(unz_s*)file;
730 if (!s->current_file_ok)
731 return UNZ_END_OF_LIST_OF_FILE;
732 if (s->num_file+1==s->gi.number_entry)
733 return UNZ_END_OF_LIST_OF_FILE;
734
735 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
736 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
737 s->num_file++;
738 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
739 &s->cur_file_info_internal,
740 NULL,0,NULL,0,NULL,0);
741 s->current_file_ok = (err == UNZ_OK);
742 return err;
743 }
744
745
746 /*
747 Try locate the file szFileName in the zipfile.
748 For the iCaseSensitivity signification, see unzipStringFileNameCompare
749
750 return value :
751 UNZ_OK if the file is found. It becomes the current file.
752 UNZ_END_OF_LIST_OF_FILE if the file is not found
753 */
754 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
755 unzFile file;
756 const char *szFileName;
757 int iCaseSensitivity;
758 {
759 unz_s* s;
760 int err;
761
762
763 uLong num_fileSaved;
764 uLong pos_in_central_dirSaved;
765
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 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
831 err=UNZ_ERRNO;
832 else if (uMagic!=0x04034b50)
833 err=UNZ_BADZIPFILE;
834 }
835 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
836 err=UNZ_ERRNO;
837 /*
838 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
839 err=UNZ_BADZIPFILE;
840 */
841 if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
842 err=UNZ_ERRNO;
843
844 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
845 err=UNZ_ERRNO;
846 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
847 err=UNZ_BADZIPFILE;
848
849 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
850 (s->cur_file_info.compression_method!=Z_DEFLATED))
851 err=UNZ_BADZIPFILE;
852
853 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
854 err=UNZ_ERRNO;
855
856 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
857 err=UNZ_ERRNO;
858 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
859 ((uFlags & 8)==0))
860 err=UNZ_BADZIPFILE;
861
862 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
863 err=UNZ_ERRNO;
864 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
865 ((uFlags & 8)==0))
866 err=UNZ_BADZIPFILE;
867
868 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
869 err=UNZ_ERRNO;
870 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
871 ((uFlags & 8)==0))
872 err=UNZ_BADZIPFILE;
873
874
875 if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
876 err=UNZ_ERRNO;
877 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
878 err=UNZ_BADZIPFILE;
879
880 *piSizeVar += (uInt)size_filename;
881
882 if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
883 err=UNZ_ERRNO;
884 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
885 SIZEZIPLOCALHEADER + size_filename;
886 *psize_local_extrafield = (uInt)size_extra_field;
887
888 *piSizeVar += (uInt)size_extra_field;
889
890 return err;
891 }
892
893 /*
894 Open for reading data the current file in the zipfile.
895 If there is no error and the file is opened, the return value is UNZ_OK.
896 */
897 extern int ZEXPORT unzOpenCurrentFile (file)
898 unzFile file;
899 {
900 int err=UNZ_OK;
901 int Store;
902 uInt iSizeVar;
903 unz_s* s;
904 file_in_zip_read_info_s* pfile_in_zip_read_info;
905 uLong offset_local_extrafield; /* offset of the local extra field */
906 uInt size_local_extrafield; /* size of the local extra field */
907
908 if (file==NULL)
909 return UNZ_PARAMERROR;
910 s=(unz_s*)file;
911 if (!s->current_file_ok)
912 return UNZ_PARAMERROR;
913
914 if (s->pfile_in_zip_read != NULL)
915 unzCloseCurrentFile(file);
916
917 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
918 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
919 return UNZ_BADZIPFILE;
920
921 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
922 ALLOC(sizeof(file_in_zip_read_info_s));
923 if (pfile_in_zip_read_info==NULL)
924 return UNZ_INTERNALERROR;
925
926 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
927 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
928 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
929 pfile_in_zip_read_info->pos_local_extrafield=0;
930
931 if (pfile_in_zip_read_info->read_buffer==NULL)
932 {
933 TRYFREE(pfile_in_zip_read_info);
934 return UNZ_INTERNALERROR;
935 }
936
937 pfile_in_zip_read_info->stream_initialised=0;
938
939 if ((s->cur_file_info.compression_method!=0) &&
940 (s->cur_file_info.compression_method!=Z_DEFLATED))
941 err=UNZ_BADZIPFILE;
942 Store = s->cur_file_info.compression_method==0;
943
944 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
945 pfile_in_zip_read_info->crc32=0;
946 pfile_in_zip_read_info->compression_method =
947 s->cur_file_info.compression_method;
948 pfile_in_zip_read_info->file=s->file;
949 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
950
951 pfile_in_zip_read_info->stream.total_out = 0;
952
953 if (!Store)
954 {
955 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
956 pfile_in_zip_read_info->stream.zfree = (free_func)0;
957 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
958
959 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
960 if (err == Z_OK)
961 pfile_in_zip_read_info->stream_initialised=1;
962 /* windowBits is passed < 0 to tell that there is no zlib header.
963 * Note that in this case inflate *requires* an extra "dummy" byte
964 * after the compressed stream in order to complete decompression and
965 * return Z_STREAM_END.
966 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
967 * size of both compressed and uncompressed data
968 */
969 }
970 pfile_in_zip_read_info->rest_read_compressed =
971 s->cur_file_info.compressed_size ;
972 pfile_in_zip_read_info->rest_read_uncompressed =
973 s->cur_file_info.uncompressed_size ;
974
975
976 pfile_in_zip_read_info->pos_in_zipfile =
977 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
978 iSizeVar;
979
980 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
981
982
983 s->pfile_in_zip_read = pfile_in_zip_read_info;
984 return UNZ_OK;
985 }
986
987
988 /*
989 Read bytes from the current file.
990 buf contain buffer where data must be copied
991 len the size of buf.
992
993 return the number of byte copied if somes bytes are copied
994 return 0 if the end of file was reached
995 return <0 with error code if there is an error
996 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
997 */
998 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
999 unzFile file;
1000 voidp buf;
1001 unsigned len;
1002 {
1003 int err=UNZ_OK;
1004 uInt iRead = 0;
1005 unz_s* s;
1006 file_in_zip_read_info_s* pfile_in_zip_read_info;
1007 if (file==NULL)
1008 return UNZ_PARAMERROR;
1009 s=(unz_s*)file;
1010 pfile_in_zip_read_info=s->pfile_in_zip_read;
1011
1012 if (pfile_in_zip_read_info==NULL)
1013 return UNZ_PARAMERROR;
1014
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
1166 /*
1167 Read extra field from the current file (opened by unzOpenCurrentFile)
1168 This is the local-header version of the extra field (sometimes, there is
1169 more info in the local-header version than in the central-header)
1170
1171 if buf==NULL, it return the size of the local extra field that can be read
1172
1173 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1174 buf.
1175 the return value is the number of bytes copied in buf, or (if <0)
1176 the error code
1177 */
1178 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1179 unzFile file;
1180 voidp buf;
1181 unsigned len;
1182 {
1183 unz_s* s;
1184 file_in_zip_read_info_s* pfile_in_zip_read_info;
1185 uInt read_now;
1186 uLong size_to_read;
1187
1188 if (file==NULL)
1189 return UNZ_PARAMERROR;
1190 s=(unz_s*)file;
1191 pfile_in_zip_read_info=s->pfile_in_zip_read;
1192
1193 if (pfile_in_zip_read_info==NULL)
1194 return UNZ_PARAMERROR;
1195
1196 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1197 pfile_in_zip_read_info->pos_local_extrafield);
1198
1199 if (buf==NULL)
1200 return (int)size_to_read;
1201
1202 if (len>size_to_read)
1203 read_now = (uInt)size_to_read;
1204 else
1205 read_now = (uInt)len ;
1206
1207 if (read_now==0)
1208 return 0;
1209
1210 if (fseek(pfile_in_zip_read_info->file,
1211 pfile_in_zip_read_info->offset_local_extrafield +
1212 pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1213 return UNZ_ERRNO;
1214
1215 if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1216 return UNZ_ERRNO;
1217
1218 return (int)read_now;
1219 }
1220
1221 /*
1222 Close the file in zip opened with unzipOpenCurrentFile
1223 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1224 */
1225 extern int ZEXPORT unzCloseCurrentFile (file)
1226 unzFile file;
1227 {
1228 int err=UNZ_OK;
1229
1230 unz_s* s;
1231 file_in_zip_read_info_s* pfile_in_zip_read_info;
1232 if (file==NULL)
1233 return UNZ_PARAMERROR;
1234 s=(unz_s*)file;
1235 pfile_in_zip_read_info=s->pfile_in_zip_read;
1236
1237 if (pfile_in_zip_read_info==NULL)
1238 return UNZ_PARAMERROR;
1239
1240
1241 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1242 {
1243 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1244 err=UNZ_CRCERROR;
1245 }
1246
1247
1248 TRYFREE(pfile_in_zip_read_info->read_buffer);
1249 pfile_in_zip_read_info->read_buffer = NULL;
1250 if (pfile_in_zip_read_info->stream_initialised)
1251 inflateEnd(&pfile_in_zip_read_info->stream);
1252
1253 pfile_in_zip_read_info->stream_initialised = 0;
1254 TRYFREE(pfile_in_zip_read_info);
1255
1256 s->pfile_in_zip_read=NULL;
1257
1258 return err;
1259 }
1260
1261
1262 /*
1263 Get the global comment string of the ZipFile, in the szComment buffer.
1264 uSizeBuf is the size of the szComment buffer.
1265 return the number of byte copied or an error code <0
1266 */
1267 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1268 unzFile file;
1269 char *szComment;
1270 uLong uSizeBuf;
1271 {
1272 int err=UNZ_OK;
1273 unz_s* s;
1274 uLong uReadThis ;
1275 if (file==NULL)
1276 return UNZ_PARAMERROR;
1277 s=(unz_s*)file;
1278
1279 uReadThis = uSizeBuf;
1280 if (uReadThis>s->gi.size_comment)
1281 uReadThis = s->gi.size_comment;
1282
1283 if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1284 return UNZ_ERRNO;
1285
1286 if (uReadThis>0)
1287 {
1288 *szComment='\0';
1289 if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1290 return UNZ_ERRNO;
1291 }
1292
1293 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1294 *(szComment+s->gi.size_comment)='\0';
1295 return (int)uReadThis;
1296 }
1297