#include "wxinc.h" #include #include "agasys.h" bool aga_get_host_name(char* name, int maxlen) { wxString str = wxGetHostName(); const int len = str.Length(); strncpy(name, str, maxlen); name[maxlen-1] = '\0'; return len > 0; } bool aga_get_user_name(char* name, int maxlen) { wxString str = wxGetUserId(); str.MakeUpper(); const int len = str.Length(); strncpy(name, str, maxlen); name[maxlen-1] = '\0'; return len > 0; } void aga_log(const char* fmt, ...) { static bool bStarted = false; FILE* log = fopen("aga.log", bStarted ? "a" : "w"); va_list argptr; va_start(argptr,fmt); vfprintf(log, fmt, argptr); va_end(argptr); fprintf(log, "\n"); fclose(log); bStarted = true; } /////////////////////////////////////////////////////////// // Unzip support /////////////////////////////////////////////////////////// #include #include #include #include <../src/zlib/zlib.h> #include <../src/common/unzip.h> class WXDLLEXPORT wxAgaZipFSHandler : public wxFileSystemHandler { public: wxAgaZipFSHandler(); virtual bool CanOpen(const wxString& location); virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); virtual wxString FindFirst(const wxString& spec, int flags = 0); virtual wxString FindNext(); ~wxAgaZipFSHandler(); private: // these vars are used by FindFirst/Next: unzFile m_Archive; wxString m_Pattern, m_BaseDir, m_ZipFile; bool m_AllowDirs, m_AllowFiles; wxString DoFind(); }; wxAgaZipFSHandler::wxAgaZipFSHandler() : wxFileSystemHandler() { m_Archive = NULL; m_ZipFile = m_Pattern = m_BaseDir = wxEmptyString; m_AllowDirs = m_AllowFiles = TRUE; } wxAgaZipFSHandler::~wxAgaZipFSHandler() { if (m_Archive) unzClose(m_Archive); } bool wxAgaZipFSHandler::CanOpen(const wxString& location) { wxString p = GetProtocol(location); return (p == wxT("zip")); } wxFSFile* wxAgaZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) { return NULL; } wxString wxAgaZipFSHandler::FindFirst(const wxString& spec, int flags) { wxString right = GetRightLocation(spec); wxString left = GetLeftLocation(spec); if (right.Last() == wxT('/')) right.RemoveLast(); if (m_Archive) { unzClose(m_Archive); m_Archive = NULL; } if (GetProtocol(left) != wxT("file")) return wxEmptyString; switch (flags) { case wxFILE: m_AllowDirs = FALSE, m_AllowFiles = TRUE; break; case wxDIR: m_AllowDirs = TRUE, m_AllowFiles = FALSE; break; default: m_AllowDirs = m_AllowFiles = TRUE; break; } m_ZipFile = left; m_Archive = (void*) unzOpen(m_ZipFile.mb_str()); m_Pattern = right.AfterLast(wxT('/')); m_BaseDir = right.BeforeLast(wxT('/')); if (m_Archive) { if (unzGoToFirstFile((unzFile)m_Archive) != UNZ_OK) { unzClose((unzFile)m_Archive); m_Archive = NULL; } else return DoFind(); } return wxEmptyString; } wxString wxAgaZipFSHandler::FindNext() { if (!m_Archive) return wxEmptyString; return DoFind(); } wxString wxAgaZipFSHandler::DoFind() { const size_t nBufSize = 1024; char* namebuf = new char[nBufSize]; // char, not wxChar! char *c; wxString fn, dir, name; wxString match = wxEmptyString; bool wasdir; while (match == wxEmptyString) { unzGetCurrentFileInfo(m_Archive, NULL, namebuf, nBufSize, NULL, 0, NULL, 0); for (c = namebuf; *c; c++) if (*c == wxT('\\')) *c = wxT('/'); fn = namebuf; if (fn.Length() > 0 && fn.Last() == wxT('/')) { fn.RemoveLast(); wasdir = TRUE; } else wasdir = FALSE; name = fn.AfterLast(wxT('/')); dir = fn.BeforeLast(wxT('/')); if (m_AllowDirs || dir == m_BaseDir) { if (m_AllowFiles && !wasdir && wxMatchWild(m_Pattern, name, FALSE)) match = m_ZipFile + wxT("#zip:") + fn; if (m_AllowDirs && wasdir && wxMatchWild(m_Pattern, name, FALSE)) match = m_ZipFile + wxT("#zip:") + fn; } if (unzGoToNextFile(m_Archive) != UNZ_OK) { unzClose(m_Archive); m_Archive = NULL; break; } } delete [] namebuf; return match; } bool aga_unzip(const char* zipfile, const char* destdir) { wxString str = zipfile; str += "#zip:*"; wxAgaZipFSHandler fs; wxString strInFile = fs.FindFirst(str, 0); while (!strInFile.IsEmpty()) { const int nDiesis = strInFile.Find('#'); const wxString strFileName = strInFile.Mid(nDiesis+5); wxZipInputStream fin(zipfile, strFileName); wxString strOutFile = destdir; strOutFile += '/'; strOutFile += strFileName; wxString strPath; ::wxSplitPath(strOutFile, &strPath, NULL, NULL); if (!::wxDirExists(strPath)) ::wxMkdir(strPath); wxFFileOutputStream fout(strOutFile); fout.Write(fin); strInFile = fs.FindNext(); } return TRUE; } /////////////////////////////////////////////////////////// // Zip support /////////////////////////////////////////////////////////// #include #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() class AgaZlibOutputStream : public wxZlibOutputStream { public: AgaZlibOutputStream(wxOutputStream& stream, int level); }; AgaZlibOutputStream::AgaZlibOutputStream(wxOutputStream& stream, int level) : wxZlibOutputStream(stream, level) { const int DEF_MEM_LEVEL = 8; deflateInit2_(m_deflate, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, "1.1.2", sizeof(*m_deflate)); } 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 unsigned long ComputeCRC(const char* strFile) { const int nSize = 1024*64; wxByte* buffer = new wxByte[nSize]; unsigned long dwCrc = 0; wxFFileInputStream fin(strFile); unsigned long nLastRead = nSize; while (nLastRead == nSize) { fin.Read(buffer, nSize); nLastRead= fin.LastRead(); dwCrc = crc32(dwCrc, buffer, nLastRead); } return dwCrc; } static void AddFileToZip(const wxString& strPrefix, const wxString& strFile, wxFFileOutputStream& fout, wxFFileOutputStream& 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 :-) { wxFFileInputStream fin(strFile); AgaZlibOutputStream zout(fout, 9); zout.Write(fin); // Scrivo file compresso zlfh.dwUncompressedSize = fin.TellI(); } fout.SeekO(nMagicOffset, wxFromEnd); zlfh.dwCompressedSize = fout.TellO(); zlfh.dwCompressedSize -= nDataStart; zlfh.dwCRC = ComputeCRC(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"; wxFFileOutputStream fout(zipfile); off_t nDirSize = 0, nDirStart = 0; if (aFiles.GetCount() > 0) // Dummy test { wxFFileOutputStream 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) { wxFFileInputStream 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); }