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