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