mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 18:08:10 +00:00
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
This commit is contained in:
parent
9a95d2a936
commit
22ce34e5d5
@ -431,6 +431,7 @@ src_support_minizip_files = Split('''
|
||||
ioapi.c
|
||||
iowin32.c
|
||||
zip.c
|
||||
zipunzip.cpp
|
||||
unzip.c
|
||||
''')
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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 ##################################
|
||||
|
||||
|
@ -50,44 +50,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRECT_H
|
||||
# include <direct.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_IO_H
|
||||
# include <io.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UTIME_H
|
||||
# include <sys/utime.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#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<pair<string, string> > 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<pair<string, string> >::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)<gi.number_entry) {
|
||||
err = unzGoToNextFile(uf);
|
||||
if (err != UNZ_OK) {
|
||||
lyxerr << "error " << err << " with zipfile in unzGoToNextFile" << endl;;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(uf);
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace support
|
||||
} // namespace lyx
|
||||
|
@ -314,13 +314,17 @@ typedef std::pair<int, std::string> 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<std::pair<std::string, std::string> > const & files);
|
||||
bool zipFiles(std::string const & zipfile, std::vector<std::pair<std::string, std::string> > const & files);
|
||||
|
||||
/// Unzip a zip file to a directory
|
||||
bool unzipToDir(std::string const & zipfile, std::string const & path);
|
||||
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
||||
#endif
|
||||
|
544
src/support/minizip/zipunzip.cpp
Normal file
544
src/support/minizip/zipunzip.cpp
Normal file
@ -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 <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRECT_H
|
||||
# include <direct.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_IO_H
|
||||
# include <io.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UTIME_H
|
||||
# include <sys/utime.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#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<pair<string, string> > 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<pair<string, string> >::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)<gi.number_entry) {
|
||||
err = unzGoToNextFile(uf);
|
||||
if (err != UNZ_OK) {
|
||||
printf("error %d with zipfile in unzGoToNextFile\n",err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(uf);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user