From 22ce34e5d5d39a0fd64b9a821ef2c3f0be09a4a8 Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Mon, 3 Sep 2007 21:09:11 +0000 Subject: [PATCH] Move two minizip functions from filetools.cpp to its own file minizip/zipunzip.cpp, covered by minizip's original license git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20025 a592a061-630c-0410-9148-cb99ea01b6c8 --- development/scons/scons_manifest.py | 1 + src/Buffer.cpp | 3 +- src/EmbeddedFiles.cpp | 3 +- src/support/Makefile.am | 3 +- src/support/filetools.cpp | 425 ---------------------- src/support/filetools.h | 10 +- src/support/minizip/zipunzip.cpp | 544 ++++++++++++++++++++++++++++ 7 files changed, 556 insertions(+), 433 deletions(-) create mode 100644 src/support/minizip/zipunzip.cpp diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index 82f05920e2..1dd4b41d2c 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -431,6 +431,7 @@ src_support_minizip_files = Split(''' ioapi.c iowin32.c zip.c + zipunzip.cpp unzip.c ''') diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 42a602b169..77faad5697 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -134,7 +134,6 @@ using support::subst; using support::tempName; using support::trim; using support::sum; -using support::unzipToDir; namespace Alert = frontend::Alert; namespace os = support::os; @@ -658,7 +657,7 @@ bool Buffer::readFile(FileName const & filename) if (format == "zip") { // decompress to a temp directory LYXERR(Debug::FILES) << filename << " is in zip format. Unzip to " << temppath() << endl; - unzipToDir(filename.toFilesystemEncoding(), temppath()); + ::unzipToDir(filename.toFilesystemEncoding(), temppath()); // FileName manifest(addName(temppath(), "manifest.txt")); FileName lyxfile(addName(temppath(), diff --git a/src/EmbeddedFiles.cpp b/src/EmbeddedFiles.cpp index 9218384542..180b88ed92 100644 --- a/src/EmbeddedFiles.cpp +++ b/src/EmbeddedFiles.cpp @@ -61,7 +61,6 @@ using support::onlyFilename; using support::makeRelPath; using support::changeExtension; using support::bformat; -using support::zipFiles; using support::prefixIs; using support::sum; using support::makedir; @@ -261,7 +260,7 @@ bool EmbeddedFiles::write(DocFileName const & filename) onlyFilename(changeExtension( filename.toFilesystemEncoding(), ".zip")))); - zipFiles(zipfile, filenames); + ::zipFiles(zipfile.toFilesystemEncoding(), filenames); // copy file back try { fs::copy_file(zipfile.toFilesystemEncoding(), filename.toFilesystemEncoding(), false); diff --git a/src/support/Makefile.am b/src/support/Makefile.am index 1692e9fa60..fdf1f7c8ea 100644 --- a/src/support/Makefile.am +++ b/src/support/Makefile.am @@ -101,7 +101,8 @@ liblyxsupport_la_SOURCES = \ minizip/unzip.c \ minizip/unzip.h \ minizip/zip.c \ - minizip/zip.h + minizip/zip.h \ + minizip/zipunzip.cpp ############################## Tests ################################## diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 727c0dffe6..44c8b1e4f8 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -50,44 +50,6 @@ #include #include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_DIRECT_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_IO_H -# include -#endif -#ifdef HAVE_SYS_UTIME_H -# include -#endif -#ifdef HAVE_UTIME_H -# include -#endif - -#include "zip.h" -#include "unzip.h" - -#ifdef WIN32 -#define USEWIN32IOAPI -#include "iowin32.h" -#endif - -#define WRITEBUFFERSIZE (16384) -#define MAXFILENAME (256) - - -#ifndef CXX_GLOBAL_CSTD -using std::fgetc; -#endif - using std::endl; using std::getline; using std::make_pair; @@ -1285,392 +1247,5 @@ int compare_timestamps(FileName const & filename1, FileName const & filename2) return cmp; } -// the following is adapted from zlib-1.2.3/contrib/minizip.c -// and miniunz.c, except that -// 1. mkdir, makedir is replaced by lyx' own version -// 2. printf is replaced by lyxerr - -#ifdef WIN32 -uLong filetime(const char * f, tm_zip * tmzip, uLong * dt) -{ - int ret = 0; - { - FILETIME ftLocal; - HANDLE hFind; - WIN32_FIND_DATA ff32; - - hFind = FindFirstFile(f,&ff32); - if (hFind != INVALID_HANDLE_VALUE) - { - FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); - FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); - FindClose(hFind); - ret = 1; - } - } - return ret; -} - -#else -#ifdef unix -uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/) -{ - int ret=0; - struct stat s; /* results of stat() */ - struct tm* filedate; - time_t tm_t=0; - - if (strcmp(f,"-")!=0) { - char name[MAXFILENAME+1]; - int len = strlen(f); - if (len > MAXFILENAME) - len = MAXFILENAME; - - strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ - name[ MAXFILENAME ] = '\0'; - - if (name[len - 1] == '/') - name[len - 1] = '\0'; - /* not all systems allow stat'ing a file with / appended */ - if (stat(name,&s)==0) { - tm_t = s.st_mtime; - ret = 1; - } - } - filedate = localtime(&tm_t); - - tmzip->tm_sec = filedate->tm_sec; - tmzip->tm_min = filedate->tm_min; - tmzip->tm_hour = filedate->tm_hour; - tmzip->tm_mday = filedate->tm_mday; - tmzip->tm_mon = filedate->tm_mon ; - tmzip->tm_year = filedate->tm_year; - - return ret; -} - -#else - -uLong filetime(const char * f, tm_zip * tmzip, uLong * dt) -{ - return 0; -} -#endif -#endif - -bool zipFiles(DocFileName const & zipfile, vector > const & files) -{ - int err = 0; - zipFile zf; - int errclose; - void * buf = NULL; - - int size_buf = WRITEBUFFERSIZE; - buf = (void*)malloc(size_buf); - if (buf==NULL) { - lyxerr << "Error allocating memory" << endl; - return false; - } - string const zfile = zipfile.toFilesystemEncoding(); - const char * fname = zfile.c_str(); - -#ifdef USEWIN32IOAPI - zlib_filefunc_def ffunc; - fill_win32_filefunc(&ffunc); - // false: not append - zf = zipOpen2(fname, false, NULL, &ffunc); -#else - zf = zipOpen(fname, false); -#endif - - if (zf == NULL) { - lyxerr << "error opening " << zipfile << endl; - return false; - } - - for (vector >::const_iterator it = files.begin(); it != files.end(); ++it) { - FILE * fin; - int size_read; - zip_fileinfo zi; - const char * diskfilename = it->first.c_str(); - const char * filenameinzip = it->second.c_str(); - unsigned long crcFile=0; - - zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = - zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; - zi.dosDate = 0; - zi.internal_fa = 0; - zi.external_fa = 0; - filetime(filenameinzip, &zi.tmz_date, &zi.dosDate); - - err = zipOpenNewFileInZip3(zf, filenameinzip, &zi, - NULL,0,NULL,0,NULL /* comment*/, - Z_DEFLATED, - Z_DEFAULT_COMPRESSION, // compression level - 0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, // password, - crcFile); - - if (err != ZIP_OK) { - lyxerr << "error in opening " << filenameinzip << " in zipfile" << endl; - return false; - } - fin = fopen(diskfilename, "rb"); - if (fin==NULL) { - lyxerr << "error in opening " << diskfilename << " for reading" << endl; - return false; - } - - do { - err = ZIP_OK; - size_read = (int)fread(buf, 1, size_buf, fin); - if (size_read < size_buf) - if (feof(fin)==0) { - lyxerr << "error in reading " << filenameinzip << endl; - return false; - } - - if (size_read>0) { - err = zipWriteInFileInZip (zf, buf, size_read); - if (err<0) { - lyxerr << "error in writing " << filenameinzip << " in the zipfile" << endl; - return false; - } - } - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - err = zipCloseFileInZip(zf); - if (err != ZIP_OK) { - lyxerr << "error in closing " << filenameinzip << "in the zipfile" << endl; - return false; - } - } - errclose = zipClose(zf, NULL); - if (errclose != ZIP_OK) { - lyxerr << "error in closing " << zipfile << endl; - return false; - } - free(buf); - return true; -} - -// adapted from miniunz.c - -/* change_file_date : change the date/time of a file - filename : the filename of the file where date/time must be modified - dosdate : the new date at the MSDos format (4 bytes) - tmu_date : the SAME new date at the tm_unz format */ -void change_file_date(const char * filename, uLong dosdate, tm_unz tmu_date) -{ -#ifdef WIN32 - HANDLE hFile; - FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; - - hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, - 0,NULL,OPEN_EXISTING,0,NULL); - GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); - DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); - LocalFileTimeToFileTime(&ftLocal,&ftm); - SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); - CloseHandle(hFile); -#else -#ifdef unix - utimbuf ut; - tm newdate; - - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min=tmu_date.tm_min; - newdate.tm_hour=tmu_date.tm_hour; - newdate.tm_mday=tmu_date.tm_mday; - newdate.tm_mon=tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year=tmu_date.tm_year - 1900; - else - newdate.tm_year=tmu_date.tm_year ; - newdate.tm_isdst=-1; - - ut.actime=ut.modtime=mktime(&newdate); - utime(filename,&ut); -#endif -#endif -} - - -int do_extract_currentfile(unzFile uf, - const int * popt_extract_without_path, - int * popt_overwrite, - const char * password, - const char * dirname) -{ - char filename_inzip[256]; - char* filename_withoutpath; - char* p; - int err=UNZ_OK; - FILE *fout=NULL; - void* buf; - uInt size_buf; - - unz_file_info file_info; - //uLong ratio=0; - err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); - - if (err!=UNZ_OK) { - lyxerr << "error " << err << " with zipfile in unzGetCurrentFileInfo" << endl; - return err; - } - - size_buf = WRITEBUFFERSIZE; - buf = (void*)malloc(size_buf); - if (buf==NULL) { - lyxerr << "Error allocating memory" << endl; - return UNZ_INTERNALERROR; - } - - p = filename_withoutpath = filename_inzip; - while ((*p) != '\0') { - if (((*p)=='/') || ((*p)=='\\')) - filename_withoutpath = p+1; - p++; - } - // this is a directory - if ((*filename_withoutpath)=='\0') { - if ((*popt_extract_without_path)==0) - makedir(filename_inzip); - } - // this is a filename - else { - char write_filename[1024]; - - strcpy(write_filename, dirname); - int len = strlen(write_filename); - if (write_filename[len-1] != '\\' && - write_filename[len-1] != '/') - strcat(write_filename, "/"); - - if ((*popt_extract_without_path)==0) - strcat(write_filename, filename_inzip); - else - strcat(write_filename, filename_withoutpath); - - err = unzOpenCurrentFilePassword(uf,password); - if (err!=UNZ_OK) { - lyxerr << "error " << err << " with zipfile in unzOpenCurrentFilePassword" << endl; - } else { - fout=fopen(write_filename, "wb"); - - /* some zipfile don't contain directory alone before file */ - if ((fout==NULL) && ((*popt_extract_without_path)==0) && - (filename_withoutpath!=(char*)filename_inzip)) { - char c=*(filename_withoutpath-1); - *(filename_withoutpath-1)='\0'; - makedir(write_filename); - *(filename_withoutpath-1)=c; - fout=fopen(write_filename,"wb"); - } - - if (fout==NULL) { - lyxerr << "error opening " << write_filename << endl; - } - } - - if (fout!=NULL) { - LYXERR(Debug::FILES) << " extracting: " << write_filename << endl; - - do { - err = unzReadCurrentFile(uf,buf,size_buf); - if (err<0) { - lyxerr << "error " << err << " with zipfile in unzReadCurrentFile" << endl; - break; - } - if (err>0) - if (fwrite(buf,err,1,fout)!=1) { - lyxerr << "error in writing extracted file" << endl; - err=UNZ_ERRNO; - break; - } - } while (err>0); - if (fout) - fclose(fout); - - if (err==0) - change_file_date(write_filename,file_info.dosDate, - file_info.tmu_date); - } - - if (err==UNZ_OK) { - err = unzCloseCurrentFile (uf); - if (err!=UNZ_OK) { - lyxerr << "error " << err << " with zipfile in unzCloseCurrentFile" << endl; - } - } - else - unzCloseCurrentFile(uf); /* don't lose the error */ - } - - free(buf); - return err; -} - - -bool unzipToDir(string const & zipfile, string const & dirname) -{ - unzFile uf=NULL; -#ifdef USEWIN32IOAPI - zlib_filefunc_def ffunc; -#endif - - const char * zipfilename = zipfile.c_str(); - -#ifdef USEWIN32IOAPI - fill_win32_filefunc(&ffunc); - uf = unzOpen2(zipfilename, &ffunc); -#else - uf = unzOpen(zipfilename); -#endif - - if (uf==NULL) { - lyxerr << "Cannot open " << zipfile << " or " << zipfile << ".zip" << endl; - return false; - } - - uLong i; - unz_global_info gi; - int err; - //FILE* fout=NULL; - int opt_extract_without_path = 0; - int opt_overwrite = 1; - char * password = NULL; - - err = unzGetGlobalInfo (uf, &gi); - if (err != UNZ_OK) { - lyxerr << "error " << err << " with zipfile in unzGetGlobalInfo " << endl; - return false; - } - - for (i=0; i < gi.number_entry; i++) { - if (do_extract_currentfile(uf, &opt_extract_without_path, - &opt_overwrite, - password, dirname.c_str()) != UNZ_OK) - break; - - if ((i+1) cmd_ret; cmd_ret const runCommand(std::string const & cmd); +} // namespace support +} // namespace lyx + +/// The following functions are implemented in minizip/zipunzip.cpp, and are not in +/// the lyx::support namespace + /// zip several files to a zipfile. In-zip filenames are also specified -bool zipFiles(DocFileName const & zipfile, std::vector > const & files); +bool zipFiles(std::string const & zipfile, std::vector > const & files); /// Unzip a zip file to a directory bool unzipToDir(std::string const & zipfile, std::string const & path); -} // namespace support -} // namespace lyx #endif diff --git a/src/support/minizip/zipunzip.cpp b/src/support/minizip/zipunzip.cpp new file mode 100644 index 0000000000..964dcd6b29 --- /dev/null +++ b/src/support/minizip/zipunzip.cpp @@ -0,0 +1,544 @@ +/* zipunzip.cpp -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + + +// The original minizip.c and miniunz.c distributed with minizip provide +// two command line tools minizip and miniunz. This file combines these two +// files and modifies the interface to provide two functions zipFiles and +// unzipToDir. This file is covered by the original minizip license. +// + +#include + +#include +#include +#include +using std::string; +using std::vector; +using std::pair; + + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_DIRECT_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_IO_H +# include +#endif +#ifdef HAVE_SYS_UTIME_H +# include +#endif +#ifdef HAVE_UTIME_H +# include +#endif +#include + +#include "zip.h" +#include "unzip.h" + +#ifdef WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + + +#ifndef CXX_GLOBAL_CSTD +using std::fgetc; +#endif + +#ifdef WIN32 +uLong filetime(const char * f, tm_zip * tmzip, uLong * dt) +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATA ff32; + + hFind = FindFirstFile(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} + +#else +#ifdef unix +uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/) +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) { + char name[MAXFILENAME+1]; + int len = strlen(f); + if (len > MAXFILENAME) + len = MAXFILENAME; + + strncpy(name, f,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + name[ MAXFILENAME ] = '\0'; + + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} + +#else + +uLong filetime(const char * f, tm_zip * tmzip, uLong * dt) +{ + return 0; +} +#endif +#endif + +bool zipFiles(string const & zipfile, vector > const & files) +{ + int err = 0; + zipFile zf; + int errclose; + void * buf = NULL; + + int size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) { + printf("Error allocating memory\n"); + return false; + } + const char * fname = zipfile.c_str(); + +#ifdef USEWIN32IOAPI + zlib_filefunc_def ffunc; + fill_win32_filefunc(&ffunc); + // false: not append + zf = zipOpen2(fname, false, NULL, &ffunc); +#else + zf = zipOpen(fname, false); +#endif + + if (zf == NULL) { + return false; + } + + for (vector >::const_iterator it = files.begin(); it != files.end(); ++it) { + FILE * fin; + int size_read; + zip_fileinfo zi; + const char * diskfilename = it->first.c_str(); + const char * filenameinzip = it->second.c_str(); + unsigned long crcFile=0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + filetime(filenameinzip, &zi.tmz_date, &zi.dosDate); + + err = zipOpenNewFileInZip3(zf, filenameinzip, &zi, + NULL,0,NULL,0,NULL /* comment*/, + Z_DEFLATED, + Z_DEFAULT_COMPRESSION, // compression level + 0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, // password, + crcFile); + + if (err != ZIP_OK) { + printf("error in opening %s in zipfile\n",filenameinzip); + return false; + } + fin = fopen(diskfilename, "rb"); + if (fin==NULL) { + return false; + } + + do { + err = ZIP_OK; + size_read = (int)fread(buf, 1, size_buf, fin); + if (size_read < size_buf) + if (feof(fin)==0) { + printf("error in reading %s\n",filenameinzip); + return false; + } + + if (size_read>0) { + err = zipWriteInFileInZip (zf, buf, size_read); + if (err<0) { + printf("error in writing %s in the zipfile\n", + filenameinzip); + return false; + } + } + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + err = zipCloseFileInZip(zf); + if (err != ZIP_OK) { + printf("error in closing %s in the zipfile\n", + filenameinzip); + return false; + } + } + errclose = zipClose(zf, NULL); + if (errclose != ZIP_OK) { + printf("error in closing zip file\n"); + return false; + } + free(buf); + return true; +} + +// adapted from miniunz.c + + +int mymkdir(char const * pathname, unsigned long int mode) +{ +#if HAVE_MKDIR +# if MKDIR_TAKES_ONE_ARG + // MinGW32 + return ::mkdir(pathname); +# else + // POSIX + return ::mkdir(pathname, mode_t(mode)); +# endif +#elif defined(_WIN32) + // plain Windows 32 + return CreateDirectory(pathname, 0) != 0 ? 0 : -1; +#elif HAVE__MKDIR + return ::_mkdir(pathname); +#else +# error "Don't know how to create a directory on this system." +#endif +} + + +int makedir(char * newdir) +{ + char *buffer; + char *p; + int len = (int)strlen(newdir); + int mode = 0775; + + if (len <= 0) + return 1; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') + buffer[len-1] = '\0'; + if (mymkdir(buffer, mode) == 0) { + free(buffer); + return 0; + } + + p = buffer + 1; + while (1) { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if (mymkdir(buffer, mode) != 0) { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 1; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 0; +} + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(const char * filename, uLong dosdate, tm_unz tmu_date) +{ +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix + utimbuf ut; + tm newdate; + + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +int do_extract_currentfile(unzFile uf, + const int * popt_extract_without_path, + int * popt_overwrite, + const char * password, + const char * dirname) +{ + char filename_inzip[256]; + char* filename_withoutpath; + char* p; + int err=UNZ_OK; + FILE *fout=NULL; + void* buf; + uInt size_buf; + + unz_file_info file_info; + //uLong ratio=0; + err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + + if (err!=UNZ_OK) { + printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); + return err; + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) { + printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + + p = filename_withoutpath = filename_inzip; + while ((*p) != '\0') { + if (((*p)=='/') || ((*p)=='\\')) + filename_withoutpath = p+1; + p++; + } + // this is a directory + if ((*filename_withoutpath)=='\0') { + if ((*popt_extract_without_path)==0) + makedir(filename_inzip); + } + // this is a filename + else { + char write_filename[1024]; + + strcpy(write_filename, dirname); + int len = strlen(write_filename); + if (write_filename[len-1] != '\\' && + write_filename[len-1] != '/') + strcat(write_filename, "/"); + + if ((*popt_extract_without_path)==0) + strcat(write_filename, filename_inzip); + else + strcat(write_filename, filename_withoutpath); + + err = unzOpenCurrentFilePassword(uf,password); + if (err!=UNZ_OK) { + printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); + } else { + fout=fopen(write_filename, "wb"); + + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=fopen(write_filename,"wb"); + } + + if (fout==NULL) { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) { + + do { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } while (err>0); + if (fout) + fclose(fout); + + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +bool unzipToDir(string const & zipfile, string const & dirname) +{ + unzFile uf=NULL; +#ifdef USEWIN32IOAPI + zlib_filefunc_def ffunc; +#endif + + const char * zipfilename = zipfile.c_str(); + +#ifdef USEWIN32IOAPI + fill_win32_filefunc(&ffunc); + uf = unzOpen2(zipfilename, &ffunc); +#else + uf = unzOpen(zipfilename); +#endif + + if (uf==NULL) { + return false; + } + + uLong i; + unz_global_info gi; + int err; + //FILE* fout=NULL; + int opt_extract_without_path = 0; + int opt_overwrite = 1; + char * password = NULL; + + err = unzGetGlobalInfo (uf, &gi); + if (err != UNZ_OK) { + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + return false; + } + + for (i=0; i < gi.number_entry; i++) { + if (do_extract_currentfile(uf, &opt_extract_without_path, + &opt_overwrite, + password, dirname.c_str()) != UNZ_OK) + break; + + if ((i+1)