3f78121948
Files correlati : xvaga.dll Ricompilazione Demo : [ ] Commento : Aggiunto supporto per help zippati git-svn-id: svn://10.65.10.50/trunk@11462 c028cbd2-c16b-5b4b-a496-9718f37d4682
321 lines
8.2 KiB
C++
Executable File
321 lines
8.2 KiB
C++
Executable File
#include "wxinc.h"
|
|
#include <fstream.h>
|
|
|
|
#ifdef LINUX
|
|
#include "xvt_type.h"
|
|
#endif
|
|
|
|
#include "agasys.h"
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Unzip support
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#include <wx/wfstream.h>
|
|
#include <wx/zipstrm.h>
|
|
|
|
#pragma pack(2)
|
|
|
|
struct ZipLocalFileHeader
|
|
{
|
|
unsigned short nVersionNeeded;
|
|
unsigned short nFlags;
|
|
unsigned short nMethod;
|
|
unsigned short nLastModTime;
|
|
unsigned short nLastModDate;
|
|
unsigned long dwCRC;
|
|
unsigned long dwCompressedSize;
|
|
unsigned long dwUncompressedSize;
|
|
unsigned short nNameLength;
|
|
unsigned short nExtraLength;
|
|
};
|
|
|
|
struct ZipDirectoryFileHeader
|
|
{
|
|
unsigned short nVersionUsed;
|
|
ZipLocalFileHeader zlfh;
|
|
unsigned short nCommentLength;
|
|
unsigned short nStartDisk;
|
|
unsigned short nInternalAttr;
|
|
unsigned long nExternalAttr;
|
|
unsigned long nLocalHeaderOffset;
|
|
};
|
|
|
|
struct ZipDirectoryEnd
|
|
{
|
|
unsigned short nThisDisk;
|
|
unsigned short nStartDisk;
|
|
unsigned short nDiskEntries;
|
|
unsigned short nTotalEntries;
|
|
unsigned long nSize;
|
|
unsigned long nStartOffset;
|
|
unsigned short nCommentLength;
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
unsigned int aga_ziplist(const char* zipfile, wxArrayString& aFiles)
|
|
{
|
|
const unsigned long dwDirectorySignature = 0x02014B50;
|
|
const unsigned long dwEndDirectorySignature = 0x06054B50;
|
|
|
|
wxFileInputStream fin(zipfile);
|
|
|
|
const off_t off = sizeof(ZipDirectoryEnd)+sizeof(dwEndDirectorySignature);
|
|
fin.SeekI(-off, wxFromEnd);
|
|
|
|
unsigned long dwSignature = 0;
|
|
fin.Read(&dwSignature, sizeof(dwSignature));
|
|
if (dwSignature != dwEndDirectorySignature)
|
|
return 0;
|
|
|
|
ZipDirectoryEnd zde;
|
|
fin.Read(&zde, sizeof(zde));
|
|
if (zde.nThisDisk < zde.nStartDisk || zde.nDiskEntries == 0 || zde.nSize == 0)
|
|
return 0;
|
|
|
|
fin.SeekI(zde.nStartOffset, wxFromStart);
|
|
|
|
for (unsigned int f = 0; f < zde.nDiskEntries; f++)
|
|
{
|
|
fin.Read(&dwSignature, sizeof(dwSignature));
|
|
if (dwSignature != dwDirectorySignature)
|
|
break;
|
|
|
|
ZipDirectoryFileHeader zdfh; memset(&zdfh, 0, sizeof(zdfh));
|
|
fin.Read(&zdfh, sizeof(zdfh));
|
|
char name[_MAX_PATH]; memset(name, 0, sizeof(name));
|
|
fin.Read(name, zdfh.zlfh.nNameLength);
|
|
aFiles.Add(name);
|
|
}
|
|
|
|
return aFiles.GetCount();
|
|
}
|
|
|
|
bool aga_unzip(const char* zipfile, const char* destdir)
|
|
{
|
|
wxArrayString aFiles;
|
|
const unsigned int files = aga_ziplist(zipfile, aFiles);
|
|
for (unsigned int f = 0; f < files; f++)
|
|
{
|
|
const wxString& strFileName = aFiles[f];
|
|
wxZipInputStream fin(zipfile, strFileName);
|
|
|
|
wxString strOutFile = destdir;
|
|
if (!wxEndsWithPathSeparator(strOutFile))
|
|
strOutFile += wxFILE_SEP_PATH;
|
|
strOutFile += strFileName;
|
|
|
|
wxString strPath;
|
|
::wxSplitPath(strOutFile, &strPath, NULL, NULL);
|
|
if (!::wxDirExists(strPath))
|
|
::wxMkdir(strPath);
|
|
|
|
wxFileOutputStream fout(strOutFile);
|
|
fout.Write(fin);
|
|
}
|
|
return files > 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Zip support
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#include <wx/zstream.h>
|
|
#include <../src/zlib/zlib.h>
|
|
|
|
class AgaZlibOutputStream : public wxZlibOutputStream
|
|
{
|
|
enum { AGA_COMPRESSION_LEVEL = 9 };
|
|
|
|
public:
|
|
AgaZlibOutputStream(wxOutputStream& stream);
|
|
};
|
|
|
|
#if wxCHECK_VERSION(2,3,4)
|
|
|
|
// Da questa vesrione si deve taroccare il sorgente della deflateInit in zlib
|
|
AgaZlibOutputStream::AgaZlibOutputStream(wxOutputStream& stream)
|
|
: wxZlibOutputStream(stream, AGA_COMPRESSION_LEVEL)
|
|
{ }
|
|
|
|
#else
|
|
|
|
AgaZlibOutputStream::AgaZlibOutputStream(wxOutputStream& stream)
|
|
: wxZlibOutputStream(stream, AGA_COMPRESSION_LEVEL)
|
|
{
|
|
const int DEF_MEM_LEVEL = 8;
|
|
deflateInit2_(m_deflate, AGA_COMPRESSION_LEVEL, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL,
|
|
Z_DEFAULT_STRATEGY, "1.1.2", sizeof(*m_deflate));
|
|
}
|
|
|
|
#endif
|
|
|
|
static int AddFilesToList(const wxString& strBase, const wxString& strMask, wxStringList& aFiles)
|
|
{
|
|
int n = 0;
|
|
wxString f = strBase + "/" + strMask;
|
|
f = ::wxFindFirstFile(f, 0);
|
|
while (!f.IsEmpty())
|
|
{
|
|
if (wxDirExists(f))
|
|
{
|
|
n += AddFilesToList(f, strMask, aFiles);
|
|
}
|
|
else
|
|
{
|
|
aFiles.Add(f);
|
|
n++;
|
|
}
|
|
f = ::wxFindNextFile();
|
|
}
|
|
return n;
|
|
}
|
|
|
|
static void AddFileToZip(const wxString& strPrefix, const wxString& strFile,
|
|
wxFileOutputStream& fout, wxFileOutputStream& fdir)
|
|
{
|
|
if (!wxFileExists(strFile))
|
|
return;
|
|
|
|
wxString strPath, strName, strExt;
|
|
wxSplitPath(strFile, &strPath, &strName, &strExt);
|
|
|
|
wxString strRelName;
|
|
strRelName = strPath.Mid(strPrefix.Length());
|
|
if (!strRelName.IsEmpty())
|
|
strRelName += '/';
|
|
strRelName += strName;
|
|
strRelName += '.';
|
|
strRelName += strExt;
|
|
|
|
const off_t nStartPos = fout.TellO(); // Memorizzo posizione
|
|
|
|
const unsigned long dwLocalSignature = 0x04034B50;
|
|
fout.Write(&dwLocalSignature, sizeof(dwLocalSignature)); // Scrivo PK34
|
|
ZipLocalFileHeader zlfh; memset(&zlfh, 0, sizeof(zlfh));
|
|
zlfh.nVersionNeeded = 20; // You need at least pkunzip 2.0
|
|
zlfh.nFlags = 0x0002; // Deep Hacking ???
|
|
zlfh.nMethod = 8; // Implode
|
|
zlfh.nNameLength = strRelName.Length();
|
|
fout.Write(&zlfh, sizeof(zlfh)); // Scrivo header azzerato
|
|
fout.Write((const char*)strRelName, zlfh.nNameLength); // Scrivo nome file
|
|
|
|
const off_t nDataStart = fout.TellO(); // Memorizzo posizione dati compressi
|
|
const int nMagicOffset = -4; // Deep hacking :-)
|
|
|
|
{
|
|
wxFileInputStream fin(strFile);
|
|
AgaZlibOutputStream zout(fout);
|
|
zout.Write(fin); // Scrivo file compresso
|
|
zlfh.dwUncompressedSize = fin.TellI();
|
|
}
|
|
|
|
fout.SeekO(nMagicOffset, wxFromEnd);
|
|
|
|
zlfh.dwCompressedSize = fout.TellO();
|
|
zlfh.dwCompressedSize -= nDataStart;
|
|
zlfh.dwCRC = ComputeFileCRC32(strFile);
|
|
|
|
const time_t tMod = ::wxFileModificationTime(strFile);
|
|
const struct tm* t = localtime(&tMod);
|
|
if (t != NULL)
|
|
{
|
|
zlfh.nLastModDate = t->tm_mday + ((t->tm_mon+1) << 5) + ((t->tm_year-80) << 9);
|
|
zlfh.nLastModTime = t->tm_sec/2 + (t->tm_min << 5) + (t->tm_hour << 11);
|
|
}
|
|
|
|
fout.SeekO(nStartPos+sizeof(dwLocalSignature), wxFromStart);
|
|
fout.Write(&zlfh, sizeof(zlfh));
|
|
// fout.Write((const char*)strRelName, strRelName.Length());
|
|
|
|
// Deep Hacking Here!
|
|
// const wxByte pkHeader = 0x85;
|
|
// fout.Write(&pkHeader, 1);
|
|
|
|
fout.SeekO(nMagicOffset, wxFromEnd);
|
|
|
|
ZipDirectoryFileHeader zdfh; memset(&zdfh, 0, sizeof(zdfh));
|
|
zdfh.nVersionUsed = zlfh.nVersionNeeded;
|
|
memcpy(&zdfh.zlfh, &zlfh, sizeof(zlfh));
|
|
zdfh.nLocalHeaderOffset = nStartPos;
|
|
|
|
const unsigned long dwDirectorySignature = 0x02014B50; // Scrivo PK12
|
|
fdir.Write(&dwDirectorySignature, sizeof(dwDirectorySignature));
|
|
fdir.Write(&zdfh, sizeof(zdfh)); // Scrivo entry directory
|
|
fdir.Write((const char*)strRelName, strRelName.Length());
|
|
}
|
|
|
|
static bool AddFilesToZip(const wxString& strBase, wxStringList& aFiles, const char* zipfile)
|
|
{
|
|
const char* zipdir = "zipdir.tmp";
|
|
|
|
wxFileOutputStream fout(zipfile);
|
|
|
|
off_t nDirSize = 0, nDirStart = 0;
|
|
|
|
if (aFiles.GetCount() > 0) // Dummy test
|
|
{
|
|
wxFileOutputStream fdir(zipdir);
|
|
wxStringListNode* node = aFiles.GetFirst();
|
|
while (node)
|
|
{
|
|
const wxString strFile = node->GetData();
|
|
AddFileToZip(strBase, strFile, fout, fdir);
|
|
node = node->GetNext();
|
|
}
|
|
nDirSize = fdir.TellO();
|
|
nDirStart = fout.TellO();
|
|
}
|
|
|
|
if (nDirSize > 0)
|
|
{
|
|
wxFileInputStream fdir(zipdir);
|
|
fout.Write(fdir); // Append central directory
|
|
|
|
ZipDirectoryEnd zde; memset(&zde, 0, sizeof(zde));
|
|
zde.nDiskEntries = zde.nTotalEntries = aFiles.GetCount();
|
|
zde.nSize = nDirSize;
|
|
zde.nStartOffset = nDirStart;
|
|
|
|
const unsigned long dwEndDirectorySignature = 0x06054B50;
|
|
fout.Write(&dwEndDirectorySignature, sizeof(dwEndDirectorySignature));
|
|
fout.Write(&zde, sizeof(zde));
|
|
}
|
|
|
|
if (nDirSize > 0)
|
|
wxRemoveFile(zipdir);
|
|
|
|
return nDirSize > 0;
|
|
}
|
|
|
|
bool aga_zip(const char* srcfiles, const char* zipfile)
|
|
{
|
|
wxString strBase, strMask, strExt;
|
|
wxSplitPath(srcfiles, &strBase, &strMask, &strExt);
|
|
strMask += '.';
|
|
strMask += strExt;
|
|
|
|
wxStringList aFiles;
|
|
AddFilesToList(strBase, strMask, aFiles);
|
|
|
|
return AddFilesToZip(strBase, aFiles, zipfile);
|
|
}
|
|
|
|
bool aga_zip_filelist(const char* filelist, const char* zipfile)
|
|
{
|
|
wxStringList aFiles;
|
|
ifstream fin(filelist);
|
|
while (!fin.eof())
|
|
{
|
|
char name[_MAX_PATH];
|
|
fin.getline(name, sizeof(name));
|
|
if (*name)
|
|
aFiles.Add(name);
|
|
else
|
|
break;
|
|
}
|
|
return AddFilesToZip("", aFiles, zipfile);
|
|
}
|
|
|