277 lines
5.2 KiB
C++
Executable File
277 lines
5.2 KiB
C++
Executable File
// TJP COPYRIGHT HEADER
|
|
|
|
|
|
#include "Decompress.h"
|
|
#include <assert.h>
|
|
#include <list>
|
|
#include "../endian/Endian.h"
|
|
#include "../file/File.h"
|
|
#include <fstream>
|
|
|
|
#include <tjp/core/log/Log.h>
|
|
#include "../file/Path.h"
|
|
|
|
#include <cstring>
|
|
#include <zlib/zlib.h>
|
|
|
|
#include "minizip/ioapi.h"
|
|
#ifdef WIN32
|
|
#include "minizip/iowin32.h"
|
|
#endif
|
|
|
|
using namespace tjp;
|
|
using namespace core;
|
|
using namespace core::zip;
|
|
|
|
|
|
#include "minizip/unzip.h"
|
|
|
|
void extractFile(
|
|
unzFile uf,
|
|
const char *password,
|
|
const std::string &basedirectory,
|
|
std::string &relativefilename
|
|
)
|
|
{
|
|
unz_file_info file_info;
|
|
char filename_inzip[256];
|
|
|
|
int err;
|
|
|
|
err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
throw zip::Exception ("unzGetCurrentFileInfo");
|
|
}
|
|
|
|
relativefilename = filename_inzip;
|
|
|
|
std::string filename = basedirectory + file::convertDelimiter (relativefilename);
|
|
file::ensurePath (filename);
|
|
|
|
const int size_buf = 16384;
|
|
char *buf = new char [size_buf];
|
|
|
|
try
|
|
{
|
|
std::ofstream outfile (filename.c_str(), std::ios::binary);
|
|
|
|
if (unzOpenCurrentFilePassword(uf,password)!=UNZ_OK)
|
|
{
|
|
throw zip::Exception ("unzOpenCurrentFilePassword");
|
|
}
|
|
|
|
int len;
|
|
do
|
|
{
|
|
len = unzReadCurrentFile(uf,buf,size_buf);
|
|
if (len<0)
|
|
{
|
|
throw zip::Exception("unzReadCurrentFile");
|
|
}
|
|
else
|
|
if (len>0)
|
|
{
|
|
if (!outfile.write (buf, len))
|
|
{
|
|
throw zip::Exception("error in writing extracted file\n");
|
|
}
|
|
}
|
|
}
|
|
while (len>0);
|
|
|
|
}
|
|
catch (zip::Exception &e)
|
|
{
|
|
file::deleteFile(filename);
|
|
unzCloseCurrentFile (uf);
|
|
delete[] buf;
|
|
throw e;
|
|
}
|
|
|
|
delete[] buf;
|
|
|
|
// change_file_date(filename,file_info.dosDate,
|
|
// file_info.tmu_date);
|
|
|
|
err = unzCloseCurrentFile (uf);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
throw zip::Exception("error %d with zipfile in unzCloseCurrentFile");
|
|
}
|
|
}
|
|
|
|
void extractZip(
|
|
unzFile uf,
|
|
const char* password,
|
|
const std::string &basedirectory,
|
|
std::list<std::string> &list
|
|
)
|
|
{
|
|
uLong i;
|
|
unz_global_info gi;
|
|
int err;
|
|
|
|
err = unzGetGlobalInfo (uf,&gi);
|
|
if (err!=UNZ_OK)
|
|
throw zip::Exception("unzGetGlobalInfo");
|
|
|
|
for (i=0;i<gi.number_entry;i++)
|
|
{
|
|
std::string filename;
|
|
extractFile(uf, password, basedirectory, filename);
|
|
list.push_back(filename);
|
|
|
|
if ((i+1)<gi.number_entry)
|
|
{
|
|
err = unzGoToNextFile(uf);
|
|
|
|
if (err!=UNZ_OK)
|
|
throw zip::Exception ("unzGoToNextFile");
|
|
}
|
|
}
|
|
}
|
|
|
|
void extractOneFile(
|
|
unzFile uf,
|
|
const std::string &filename,
|
|
const char* password,
|
|
const std::string &basedirectory
|
|
)
|
|
{
|
|
if (unzLocateFile(uf,filename.c_str(),false)!=UNZ_OK)
|
|
throw zip::Exception ("unzLocateFile");
|
|
|
|
std::string dummyfilename;
|
|
extractFile(uf,password,basedirectory,dummyfilename);
|
|
}
|
|
|
|
void zip::decompress (const std::string &file, const std::string &path, std::list<std::string> &files)
|
|
{
|
|
#ifdef WIN32
|
|
zlib_filefunc_def ffunc;
|
|
#endif
|
|
|
|
char filename_try[256+1];
|
|
strncpy(filename_try, file.c_str(),256-1);
|
|
/* strncpy doesnt append the trailing NULL, if the string is too long. */
|
|
filename_try[256] = '\0';
|
|
|
|
#ifdef WIN32
|
|
fill_win32_filefunc(&ffunc);
|
|
unzFile uf = unzOpen2(filename_try,&ffunc);
|
|
#else
|
|
unzFile uf = unzOpen(filename_try);
|
|
#endif
|
|
|
|
if (uf==NULL)
|
|
{
|
|
throw zip::Exception ("unzOpen");
|
|
}
|
|
|
|
try
|
|
{
|
|
extractZip (uf,NULL, path, files);
|
|
}
|
|
catch (zip::Exception &)
|
|
{
|
|
unzCloseCurrentFile(uf);
|
|
throw;
|
|
}
|
|
unzCloseCurrentFile(uf);
|
|
}
|
|
|
|
void zip::decompress (const std::string &from, const std::string &to)
|
|
{
|
|
gzFile gz = gzopen (from.c_str(), "rb");
|
|
|
|
if (gz == NULL)
|
|
throw zip::Exception ("gzopen");
|
|
|
|
int size_buf = 16384;
|
|
char *buf = new char[16384];
|
|
|
|
try
|
|
{
|
|
file::ensurePath (to);
|
|
std::ofstream outfile (to.c_str(), std::ios::binary);
|
|
|
|
int read = 0;
|
|
while ( (read = gzread (gz, buf, size_buf) > 0) && outfile)
|
|
{
|
|
outfile.write (buf, read);
|
|
}
|
|
|
|
if (read < 0 && !outfile)
|
|
{
|
|
throw zip::Exception ("gzread");
|
|
}
|
|
}
|
|
catch (zip::Exception &e)
|
|
{
|
|
delete[] buf;
|
|
file::deleteFile (to);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
typedef unsigned int Header;
|
|
|
|
bool zip::decompress (const char *in, int insize, char *&out, int &outsize)
|
|
{
|
|
const char *block = in;
|
|
const Header *header = (const Header *)block;
|
|
const char *data = block + sizeof (Header);
|
|
|
|
endian::swap (*header);
|
|
|
|
uLongf ulInSize = insize - sizeof (Header);
|
|
uLongf ulOutSize = *header;
|
|
|
|
char *uncompressed = new char[ulOutSize];
|
|
int error = ::uncompress((Bytef *)uncompressed, &ulOutSize, (const Bytef*)data, ulInSize);
|
|
|
|
if (error!=Z_OK)
|
|
{
|
|
delete[] uncompressed;
|
|
return false;
|
|
}
|
|
|
|
out = uncompressed;
|
|
outsize = (int)ulOutSize;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool zip::decompress (const char *in, int insize, std::vector<char> &out)
|
|
{
|
|
const char *block = in;
|
|
const Header *header = (const Header *)block;
|
|
const char *data = block + sizeof (Header);
|
|
|
|
endian::swap (*header);
|
|
|
|
uLongf ulInSize = insize - sizeof (Header);
|
|
uLongf ulOutSize = *header;
|
|
|
|
out.resize(ulOutSize);
|
|
char *uncompressed = out.data();
|
|
int error = ::uncompress((Bytef *)uncompressed, &ulOutSize, (const Bytef*)data, ulInSize);
|
|
|
|
if (error!=Z_OK)
|
|
{
|
|
delete[] uncompressed;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::vector<char> zip::decompress (const char *in, int insize)
|
|
{
|
|
std::vector<char> out;
|
|
zip::decompress(in, insize, out);
|
|
|
|
return out;
|
|
}
|