1 /*****************************************************************************
2 ** $Source: /cvsroot/bluemsx/blueMSX/Src/Utils/ziphelper.c,v $
3 **
4 ** $Revision: 1.6 $
5 **
6 ** $Date: 2008/03/30 21:38:43 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "ziphelper.h"
29 
30 #include "zip.h"
31 #include "unzip.h"
32 #include "ctype.h"
33 #include "ZipFromMem.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/stat.h>
38 #include <errno.h>
39 #ifdef WIN32
40 #include <direct.h>
41 #endif
42 
43 #if defined(MINGW)
44  #define MKDIR(x) mkdir(x)
45 #elif defined(WIN32)
46  #define MKDIR(x) _mkdir(x)
47 #else
48  #define MKDIR(x) mkdir(x,0777)
49 #endif
50 
toLower(char * str)51 static void toLower(char* str) {
52     while (*str) {
53         *str = tolower(*str);
54         str++;
55     }
56 }
57 
58 #if 1
59 
60 #define MAX_FILES_IN_ZIP 64
61 
62 typedef struct
63 {
64     char  filename[32];
65     int   size;
66     char* buffer;
67 } MemFile;
68 
69 typedef struct
70 {
71     char    zipName[32];
72     MemFile* memFiles[MAX_FILES_IN_ZIP];
73     int     count;
74 } MemZipFile;
75 
76 static MemZipFile** memZipFiles = NULL;
77 static int memZipFileCount = 0;
78 
memZipFileDestroy(MemZipFile * memZipFile)79 void memZipFileDestroy(MemZipFile* memZipFile)
80 {
81     int i;
82 
83     if (memZipFile == NULL)
84     {
85         return;
86     }
87 
88     // Remove node
89     for (i = 0; i < memZipFileCount; i++)
90     {
91         if (memZipFiles[i] == memZipFile)
92         {
93             memZipFiles[i] = NULL;
94         }
95     }
96 
97     // Delete file contents
98     for (i = 0; i < memZipFile->count; i++)
99     {
100         if (memZipFile->memFiles[i]->buffer != NULL)
101         {
102             free(memZipFile->memFiles[i]->buffer);
103         }
104         free(memZipFile->memFiles[i]);
105     }
106     free(memZipFile);
107 }
108 
memZipFileSystemCreate(int maxFiles)109 void memZipFileSystemCreate(int maxFiles)
110 {
111     memZipFileCount = maxFiles;
112     memZipFiles = (MemZipFile**) calloc(memZipFileCount, sizeof(MemZipFile*));
113 }
114 
memZipFileSystemDestroy()115 void memZipFileSystemDestroy()
116 {
117     int i;
118 
119     if (memZipFileCount == 0)
120     {
121         return;
122     }
123 
124     for (i = 0; i < memZipFileCount; i++)
125     {
126         memZipFileDestroy(memZipFiles[i]);
127     }
128     free(memZipFiles);
129 
130     memZipFileCount = 0;
131 }
132 
memZipFileFind(const char * zipName)133 MemZipFile* memZipFileFind(const char* zipName)
134 {
135     int i;
136     for (i = 0; i < memZipFileCount; i++)
137     {
138         if (memZipFiles[i] != NULL &&
139             strcmp(memZipFiles[i]->zipName, zipName) == 0)
140         {
141             return memZipFiles[i];
142         }
143     }
144     return NULL;
145 }
146 
memZipFileCreate(const char * zipName)147 MemZipFile* memZipFileCreate(const char* zipName)
148 {
149     int i;
150 
151     for (i = 0; i < memZipFileCount; i++)
152     {
153         if (memZipFiles[i] == NULL)
154         {
155             memZipFiles[i] = malloc(sizeof(MemZipFile));
156             strcpy(memZipFiles[i]->zipName, zipName);
157             memZipFiles[i]->count = 0;
158             return memZipFiles[i];
159         }
160     }
161     return NULL;
162 }
163 
memFileFindInZip(MemZipFile * memZipFile,const char * filename)164 MemFile* memFileFindInZip(MemZipFile* memZipFile, const char* filename)
165 {
166     if (memZipFile != NULL)
167     {
168         int i;
169         for (i = 0; i < memZipFile->count; i++)
170         {
171             if (strcmp(memZipFile->memFiles[i]->filename, filename) == 0)
172             {
173                 return memZipFile->memFiles[i];
174             }
175         }
176     }
177     return NULL;
178 }
179 
memFileLoad(const char * zipName,const char * filename,int * size)180 void* memFileLoad(const char* zipName, const char* filename, int* size)
181 {
182     MemFile* memFile = memFileFindInZip(memZipFileFind(zipName), filename);
183     if (memFile != NULL && memFile->size > 0)
184     {
185         void* buffer = malloc(memFile->size);
186         memcpy(buffer, memFile->buffer, memFile->size);
187         *size = memFile->size;
188         return buffer;
189     }
190     *size = 0;
191     return NULL;
192 }
193 
memFileSave(const char * zipName,const char * filename,int append,void * buffer,int size)194 int memFileSave(const char* zipName, const char* filename, int append, void* buffer, int size)
195 {
196     MemZipFile* memZipFile = memZipFileFind(zipName);
197     MemFile* memFile;
198 
199     if (!append)
200     {
201         memZipFileDestroy(memZipFile);
202         memZipFile = NULL;
203     }
204 
205     if (memZipFile == NULL)
206     {
207         memZipFile = memZipFileCreate(zipName);
208     }
209 
210     if (memZipFile == NULL || memZipFile->count == MAX_FILES_IN_ZIP)
211     {
212         return 0;
213     }
214 
215     memFile = malloc(sizeof(MemFile));
216     memFile->buffer = malloc(size);
217     memcpy(memFile->buffer, buffer, size);
218     memFile->size = size;
219     strcpy(memFile->filename, filename);
220 
221     memZipFile->memFiles[memZipFile->count++] = memFile;
222 
223     return 1;
224 }
225 
226 #else
227 //////////////////////////////////////////
228 // Memory zip files
229 
230 typedef struct {
231     char  filename[32];
232     void* data;
233     int   size;
234     unsigned long compSize;
235 } MemFile;
236 
237 typedef struct {
238     char    zipName[32];
239     MemFile memFile[32];
240     int     count;
241 } MemZipFile;
242 
memZipFileCreate(const char * zipName)243 MemZipFile* memZipFileCreate(const char* zipName)
244 {
245     MemZipFile* zipFile = (MemZipFile*)malloc(sizeof(MemZipFile));
246     if (zipFile == NULL) {
247         return NULL;
248     }
249     strcpy(zipFile->zipName, zipName);
250     zipFile->count = 0;
251 
252     return zipFile;
253 }
254 
memZipFileErase(MemZipFile * zipFile)255 void memZipFileErase(MemZipFile* zipFile)
256 {
257     int i;
258     for (i = 0; i < zipFile->count; i++) {
259         free(zipFile->memFile[i].data);
260     }
261     zipFile->count = 0;
262 }
263 
memZipFileDestroy(MemZipFile * zipFile)264 void memZipFileDestroy(MemZipFile* zipFile)
265 {
266     memZipFileErase(zipFile);
267     free(zipFile);
268 }
269 
memZipFileRead(MemZipFile * zipFile,const char * filename,int * size)270 void* memZipFileRead(MemZipFile* zipFile, const char* filename, int* size)
271 {
272     int i;
273     *size = 0;
274     for (i = 0; i < zipFile->count; i++) {
275         if (strcmp(filename, zipFile->memFile[i].filename) == 0) {
276             if (zipFile->memFile[i].size) {
277                 unsigned long sz = zipFile->memFile[i].size;
278                 void* buf = zipUncompress(zipFile->memFile[i].data, zipFile->memFile[i].compSize, &sz);
279                 if (buf) {
280                     *size = (int)sz;
281                     return buf;
282                 }
283             }
284         }
285     }
286     return NULL;
287 }
288 
memZipFileWrite(MemZipFile * zipFile,const char * filename,void * buffer,int size)289 int memZipFileWrite(MemZipFile* zipFile, const char* filename, void* buffer, int size)
290 {
291     static const int MemFileCount = sizeof(zipFile->memFile) / sizeof(zipFile->memFile[0]);
292     unsigned long compSize;
293     void* compBuf;
294     MemFile* memFile = NULL;
295     int i;
296     for (i = 0; i < zipFile->count; i++) {
297         if (strcmp(filename, zipFile->memFile[i].filename) == 0) {
298             memFile = &zipFile->memFile[i];
299             free(memFile->data);
300         }
301     }
302     if (memFile == NULL && zipFile->count < MemFileCount) {
303         memFile = &zipFile->memFile[zipFile->count++];
304     }
305     if (memFile == NULL) {
306         return 0;
307     }
308 
309     compBuf = zipCompress(buffer, size, &compSize);
310     memFile->data = malloc(compSize);
311     memcpy(memFile->data, compBuf, compSize);
312     memFile->size = memFile->data ? size : 0;
313     memFile->compSize = compSize;
314     strcpy(memFile->filename, filename);
315     free(compBuf);
316 
317     return 1;
318 }
319 
320 //////////////////////////////////////////
321 // Memory zip file system
322 
323 
324 typedef struct {
325     MemZipFile** zipFiles;
326     int count;
327     int maxFiles;
328 } MemZipFileSystem;
329 
330 MemZipFileSystem memZipFileSystem;
331 
memZipFileSystemCreate(int maxFiles)332 void memZipFileSystemCreate(int maxFiles)
333 {
334     memZipFileSystem.zipFiles = (MemZipFile**)malloc(maxFiles * sizeof(MemZipFile*));
335     memZipFileSystem.count    = 0;
336     memZipFileSystem.maxFiles = maxFiles;
337 }
338 
memZipFileSystemDestroy()339 void memZipFileSystemDestroy()
340 {
341     int i;
342 
343     if (memZipFileSystem.zipFiles == NULL) {
344         return;
345     }
346 
347     for (i = 0; i < memZipFileSystem.count; i++) {
348         memZipFileDestroy(memZipFileSystem.zipFiles[i]);
349     }
350 
351     free(memZipFileSystem.zipFiles);
352     memZipFileSystem.zipFiles = NULL;
353     memZipFileSystem.count = 0;
354 }
355 
memZipFileSystemOpen(const char * filename,int create)356 MemZipFile* memZipFileSystemOpen(const char* filename, int create)
357 {
358     int i;
359     for (i = 0; i < memZipFileSystem.count; i++) {
360         MemZipFile* zipFile = memZipFileSystem.zipFiles[i];
361         if (strcmp(filename, zipFile->zipName) == 0) {
362             return zipFile;
363         }
364     }
365     if (create) {
366         if (memZipFileSystem.count < memZipFileSystem.maxFiles) {
367             MemZipFile* zipFile = memZipFileCreate(filename);
368             if (zipFile != NULL) {
369                 memZipFileSystem.zipFiles[memZipFileSystem.count++] = zipFile;
370             }
371             return zipFile;
372         }
373     }
374     return NULL;
375 }
376 
377 ////////////////////////////////////////
378 
memFileLoad(const char * zipName,const char * filename,int * size)379 void* memFileLoad(const char* zipName, const char* filename, int* size)
380 {
381     MemZipFile* zipFile;
382 
383     *size = 0;
384 
385     zipFile = memZipFileSystemOpen(zipName, 0);
386     if (zipFile == NULL) {
387         return NULL;
388     }
389 
390     return memZipFileRead(zipFile, filename, size);
391 }
392 
memFileSave(const char * zipName,const char * filename,int append,void * buffer,int size)393 int memFileSave(const char* zipName, const char* filename, int append, void* buffer, int size)
394 {
395     MemZipFile* zipFile = memZipFileSystemOpen(zipName, 1);
396     if (zipFile == NULL) {
397         return 0;
398     }
399 
400     if (!append) {
401         memZipFileErase(zipFile);
402     }
403 
404     return memZipFileWrite(zipFile, filename, buffer, size);
405 }
406 
407 #endif
408 
409 /******************************************************************************
410 *** Description
411 ***     Load a file in a zip file into memory.
412 ***
413 *** Arguments
414 ***     zipName     - Name of zip file
415 ***     fileName    - Name of file insize zipfile to load
416 ***     size        - Output of size of file
417 ***
418 *** Return
419 ***     Pointer to allocate memory buffer with file content or NULL on
420 ***     failure.
421 ***
422 *******************************************************************************
423 */
_zipLoadFile(const char * zipName,const char * fileName,int * size,zlib_filefunc_def * filefunc)424 void* _zipLoadFile(const char* zipName, const char* fileName, int* size, zlib_filefunc_def* filefunc)
425 {
426     void* buf;
427     char name[256];
428     unzFile zip;
429     unz_file_info info;
430 
431     *size = 0;
432 
433     if (fileName[0] == '*') {
434         strcpy(name, zipName);
435         name[strlen(zipName) - 3] = fileName[strlen(fileName) - 3];
436         name[strlen(zipName) - 2] = fileName[strlen(fileName) - 2];
437         name[strlen(zipName) - 1] = fileName[strlen(fileName) - 1];
438     }
439     else {
440         strcpy(name, fileName);
441     }
442 
443     zip = unzOpen2(zipName, filefunc);
444     if (!zip) {
445         return NULL;
446     }
447 
448 #ifdef __APPLE__
449     // Most OS X installs are on a case-insensitive FS
450     if (unzLocateFile(zip, name, 2) == UNZ_END_OF_LIST_OF_FILE) {
451 #else
452     if (unzLocateFile(zip, name, 1) == UNZ_END_OF_LIST_OF_FILE) {
453 #endif
454         unzClose(zip);
455         return NULL;
456     }
457 
458     if (unzOpenCurrentFile(zip) != UNZ_OK) {
459         return NULL;
460     }
461 
462     unzGetCurrentFileInfo(zip,&info,NULL,0,NULL,0,NULL,0);
463 
464     buf = malloc(info.uncompressed_size);
465     *size = info.uncompressed_size;
466 
467     if (!buf) {
468         unzCloseCurrentFile(zip);
469         unzClose(zip);
470         return NULL;
471     }
472 
473     unzReadCurrentFile(zip, buf, info.uncompressed_size);
474     unzCloseCurrentFile(zip);
475     unzClose(zip);
476 
477     return buf;
478 }
479 
480 
481 /******************************************************************************
482 *** Description
483 ***     Read cache to speed-up reading multiple files from one zip.
484 ***
485 ******************************************************************************/
486 
487 static char *cacheData = NULL, cacheFile[512];
488 static zlib_filefunc_def cacheFilefunc;
489 
490 void* zipLoadFile(const char* zipName, const char* fileName, int* size)
491 {
492     if (strncmp(zipName, "mem", 3) == 0) {
493         return memFileLoad(zipName, fileName, size);
494     }
495     if( cacheData != NULL && *cacheFile != '\0' && 0==strcmp(cacheFile, zipName) ) {
496         return _zipLoadFile(cacheData, fileName, size, &cacheFilefunc);
497     }else{
498         return _zipLoadFile(zipName, fileName, size, NULL);
499     }
500 }
501 
502 void zipCacheReadOnlyZip(const char* zipName)
503 {
504     if (zipName != NULL && strncmp(zipName, "mem", 3) == 0) {
505         return;
506     }
507 
508     *cacheFile = '\0';
509     if( cacheData != NULL ) {
510         free(cacheData);
511         cacheData = NULL;
512         free_fopen_memfunc(&cacheFilefunc);
513     }
514     if( zipName != NULL ) {
515         FILE *file;
516         file = fopen(zipName, "rb");
517         if( file != NULL ) {
518             unsigned int filesize;
519             fseek(file, 0, SEEK_END);
520             filesize = ftell(file);
521             fill_fopen_memfunc(&cacheFilefunc, filesize);
522             fseek(file, 0, SEEK_SET);
523             cacheData = malloc(filesize);
524             if( cacheData != NULL ) {
525                 size_t size = fread(cacheData, 1, filesize, file);
526                 if( size == filesize ) {
527                     strcpy(cacheFile, zipName);
528                 }
529             }
530             fclose(file);
531         }
532     }
533 }
534 
535 
536 /******************************************************************************
537 *** Description
538 ***     Load a file in a zip file into memory.
539 ***
540 *** Arguments
541 ***     zipName     - Name of zip file
542 ***     fileName    - Name of file insize zipfile to save
543 ***     buffer      - Buffer to save
544 ***     size        - Size of buffer to save
545 ***
546 *******************************************************************************
547 */
548 int zipSaveFile(const char* zipName, const char* fileName, int append, void* buffer, int size)
549 {
550     zipFile zip;
551     zip_fileinfo zi;
552     int err;
553 
554     if (strncmp(zipName, "mem", 3) == 0) {
555         return memFileSave(zipName, fileName, append, buffer, size);
556     }
557 
558     zip = zipOpen(zipName, append ? 2 : 0);
559     if (zip == NULL) {
560         return 0;
561     }
562 
563     memset(&zi, 0, sizeof(zi));
564 
565     err = zipOpenNewFileInZip(zip, fileName, &zi,
566                               NULL, 0, NULL, 0, NULL,
567                               Z_DEFLATED, Z_DEFAULT_COMPRESSION);
568     if (err == ZIP_OK) {
569         err = zipWriteInFileInZip(zip, buffer, size);
570     }
571 
572     zipClose(zip, NULL);
573 
574     return err >= 0;
575 }
576 
577 int zipHasFileType(char* zipName, char* ext) {
578     char tempName[256];
579     char extension[8];
580     unzFile zip;
581     unz_file_info info;
582     int found = 0;
583     int status;
584 
585     zip = unzOpen(zipName);
586     if (!zip) {
587         return 0;
588     }
589 
590     strcpy(extension, ext);
591     toLower(extension);
592 
593     status = unzGoToFirstFile(zip);
594     unzGetCurrentFileInfo(zip,&info,tempName,256,NULL,0,NULL,0);
595 
596     while (status == UNZ_OK) {
597         unzGetCurrentFileInfo(zip, &info, tempName, 256, NULL, 0, NULL, 0);
598 
599         toLower(tempName);
600         if (strstr(tempName, extension) != NULL) {
601             found = 1;
602             break;
603         }
604 
605         status = unzGoToNextFile(zip);
606     }
607 
608     unzClose(zip);
609 
610     return found;
611 }
612 
613 /******************************************************************************
614 *** Description
615 ***     Checks if a file exists in a zip file.
616 ***
617 *** Arguments
618 ***     zipName     - Name of zip file
619 ***     fileName    - Name of file insize zipfile to load
620 ***
621 *** Return
622 ***     1 = file exists, 0 = non existing zip or file in zip does not exists
623 ***     failure.
624 ***
625 *******************************************************************************
626 */
627 int zipFileExists(const char* zipName, const char* fileName)
628 {
629     char name[256];
630     unzFile zip;
631 
632     if (fileName[0] == '*') {
633         strcpy(name, zipName);
634         name[strlen(zipName) - 3] = fileName[strlen(fileName) - 3];
635         name[strlen(zipName) - 2] = fileName[strlen(fileName) - 2];
636         name[strlen(zipName) - 1] = fileName[strlen(fileName) - 1];
637     }
638     else {
639         strcpy(name, fileName);
640     }
641 
642     zip = unzOpen(zipName);
643     if (!zip) {
644         return 0;
645     }
646 
647 #ifdef __APPLE__
648     // Most OS X installs are on a case-insensitive FS
649     if (unzLocateFile(zip, name, 2) == UNZ_END_OF_LIST_OF_FILE) {
650 #else
651     if (unzLocateFile(zip, name, 1) == UNZ_END_OF_LIST_OF_FILE) {
652 #endif
653         unzClose(zip);
654         return 0;
655     }else{
656         unzClose(zip);
657         return 1;
658     }
659 }
660 
661 /******************************************************************************
662 *** Description
663 ***     Creates a list of file names inside a zip that matches a given
664 ***     extension.
665 ***
666 *** Arguments
667 ***     zipName     - Name of zip file
668 ***     ext         - Extension to check
669 ***     count       - Output for number of matching files in zip file.
670 ***
671 *** Return
672 ***     1 if files with the given extension exists in the zip file,
673 ***     0 otherwise.
674 ***
675 *******************************************************************************
676 */
677 char* zipGetFileList(const char* zipName, const char* ext, int* count) {
678     char tempName[256];
679     char extension[8];
680     unzFile zip;
681     unz_file_info info;
682     char* fileArray = NULL;
683     int totalLen = 0;
684     int status;
685 
686     *count = 0;
687 
688     zip = unzOpen(zipName);
689     if (!zip) {
690         return 0;
691     }
692 
693     strcpy(extension, ext);
694     toLower(extension);
695 
696     status = unzGoToFirstFile(zip);
697     unzGetCurrentFileInfo(zip,&info,tempName,256,NULL,0,NULL,0);
698 
699     while (status == UNZ_OK) {
700         char tmp[256];
701 
702         unzGetCurrentFileInfo(zip, &info, tempName, 256, NULL, 0, NULL, 0);
703 
704         strcpy(tmp, tempName);
705 
706         toLower(tmp);
707         if (strstr(tmp, extension) != NULL) {
708             int entryLen = strlen(tempName) + 1;
709             fileArray = realloc(fileArray, totalLen +  entryLen + 1);
710             strcpy(fileArray + totalLen, tempName);
711             totalLen += entryLen;
712             fileArray[totalLen] = '\0'; // double null termination at end
713 
714             *count = *count + 1;
715         }
716 
717         status = unzGoToNextFile(zip);
718     }
719 
720     unzClose(zip);
721 
722     return fileArray;
723 }
724 
725 /******************************************************************************
726 *** Description
727 ***     zipExtractCurrentfile - Extracts the current file from the zip
728 ***     zipExtract - Extracts the whole zip file
729 ***
730 *** Arguments
731 ***     uf        - The zip file
732 ***     overwrite - 1 = overwrite files, 0 = do not overwrite files
733 ***     password  - Optional password for the zip
734 ***
735 *** Return
736 ***     1 okay,
737 ***     0 failed.
738 ***
739 *******************************************************************************
740 */
741 #define WRITEBUFFERSIZE 8192
742 
743 static int makedir(const char *newdir)
744 {
745     char *buffer;
746     char *p;
747     int len = (int)strlen(newdir);
748 
749     if (len <= 0) return 0;
750 
751     buffer = (char*)malloc(len+1);
752     strcpy(buffer,newdir);
753 
754     if (buffer[len-1] == '/') {
755         buffer[len-1] = '\0';
756     }
757     if (MKDIR(buffer) == 0) {
758         free(buffer);
759         return 1;
760     }
761 
762     p = buffer+1;
763     while (1) {
764         char hold;
765 
766         while(*p && *p != '\\' && *p != '/') p++;
767         hold = *p;
768         *p = 0;
769         if ((MKDIR(buffer) == -1) && (errno == ENOENT))
770         {
771             printf("couldn't create directory %s\n",buffer);
772             free(buffer);
773             return 0;
774         }
775         if (hold == 0) break;
776         *p++ = hold;
777     }
778     free(buffer);
779     return 1;
780 }
781 
782 int zipExtractCurrentfile(unzFile uf, int overwrite, const char* password)
783 {
784     char filename_inzip[256];
785     char* filename_withoutpath;
786     char* p;
787     int err=UNZ_OK;
788     FILE *fout=NULL;
789     void* buf;
790     uInt size_buf;
791 
792     unz_file_info file_info;
793     err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
794 
795     if( err != UNZ_OK ) {
796         printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
797         return 0;
798     }
799 
800     size_buf = WRITEBUFFERSIZE;
801     buf = (void*)malloc(size_buf);
802 
803     p = filename_withoutpath = filename_inzip;
804     while ((*p) != '\0') {
805         if (((*p)=='/') || ((*p)=='\\'))
806             filename_withoutpath = p+1;
807         p++;
808     }
809 
810     if ((*filename_withoutpath)=='\0') {
811         MKDIR(filename_inzip);
812     }else{
813         const char* write_filename;
814         int skip=0;
815 
816         write_filename = filename_inzip;
817 
818         err = unzOpenCurrentFilePassword(uf,password);
819         if (err!=UNZ_OK) {
820             printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
821         }
822 
823         if ((overwrite==0) && (err==UNZ_OK)) {
824             FILE* ftestexist = fopen(write_filename,"rb");
825             if (ftestexist!=NULL) {
826                 fclose(ftestexist);
827                 skip = 1;
828             }
829         }
830 
831         if ((skip==0) && (err==UNZ_OK)) {
832             fout=fopen(write_filename,"wb");
833 
834             /* some zipfile don't contain directory alone before file */
835             if( (fout==NULL) && (filename_withoutpath!=(char*)filename_inzip) ) {
836                 char c=*(filename_withoutpath-1);
837                 *(filename_withoutpath-1)='\0';
838                 makedir(write_filename);
839                 *(filename_withoutpath-1)=c;
840                 fout=fopen(write_filename,"wb");
841             }
842 
843             if( fout == NULL ) {
844                 printf("error opening %s\n",write_filename);
845             }
846         }
847 
848         if (fout!=NULL)
849         {
850             printf(" extracting: %s\n",write_filename);
851             do {
852                 err = unzReadCurrentFile(uf,buf,size_buf);
853                 if( err < 0 ) {
854                     printf("error %d with zipfile in unzReadCurrentFile\n",err);
855                     break;
856                 }
857                 if( err > 0 ) {
858                     if (fwrite(buf,err,1,fout)!=1) {
859                         printf("error in writing extracted file\n");
860                         err=UNZ_ERRNO;
861                         break;
862                     }
863                 }
864             }while( err > 0 );
865             if( fout ) fclose(fout);
866         }
867 
868         if(err == UNZ_OK) {
869             err = unzCloseCurrentFile (uf);
870             if( err != UNZ_OK ) {
871                 printf("error %d with zipfile in unzCloseCurrentFile\n",err);
872             }
873         }else{
874             unzCloseCurrentFile(uf); /* don't lose the error */
875         }
876     }
877 
878     free(buf);
879     return 1;
880 }
881 
882 int zipExtract(unzFile uf, int overwrite, const char* password,
883                ZIP_EXTRACT_CB progress_callback)
884 {
885     uLong i;
886     unz_global_info gi;
887     int err;
888 
889     err = unzGetGlobalInfo(uf,&gi);
890     if (err!=UNZ_OK) {
891         printf("error %d with zipfile in unzGetGlobalInfo \n",err);
892         return 0;
893     }
894 
895     for (i = 0; i < gi.number_entry; i++)
896     {
897         if( progress_callback ) {
898             progress_callback(gi.number_entry, i);
899         }
900         if( !zipExtractCurrentfile(uf, overwrite, password) ) {
901             return 0;
902         }
903         if ((i+1) < gi.number_entry)
904         {
905             err = unzGoToNextFile(uf);
906             if (err!=UNZ_OK)
907             {
908                 printf("error %d with zipfile in unzGoToNextFile\n",err);
909                 return 0;
910             }
911         }
912     }
913 
914     return 1;
915 }
916 
917 void* zipCompress(void* buffer, int size, unsigned long* retSize)
918 {
919     void* retBuf;
920 
921     *retSize = (size * 1001) / 1000 + 12;
922     retBuf = malloc(*retSize);
923 
924     if (compress(retBuf, retSize, buffer, size) != Z_OK) {
925         free(retBuf);
926         retBuf = NULL;
927     }
928 
929     return retBuf;
930 }
931 
932 void* zipUncompress(void* buffer, int size, unsigned long* retSize)
933 {
934     void* retBuf = malloc(*retSize);
935 
936     if (uncompress(retBuf, retSize, buffer, size) != Z_OK) {
937         free(retBuf);
938         retBuf = NULL;
939     }
940 
941     return retBuf;
942 }
943