/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "HeadSpin.h" #include "plUnzip.h" #include "hsTypes.h" #include "hsWindows.h" #include "hsStream.h" plUnzip::plUnzip() : fFile(nil) { } bool plUnzip::Open(const char* filename) { fFile = unzOpen(filename); return (fFile != nil); } bool plUnzip::Close() { bool ret = false; if (fFile != nil) { ret = (UNZ_OK == unzClose(fFile)); fFile = nil; } return ret; } void plUnzip::IGetFullPath(const char* destDir, const char* filename, char* outFilename) { // Make sure the dest ends with a slash strcpy(outFilename, destDir); char lastChar = outFilename[strlen(outFilename)-1]; if (lastChar != '\\' && lastChar != '/') strcat(outFilename, "\\"); // Check if the output filename has any directories in it const char* forward = strrchr(filename, '/'); const char* backward = strrchr(filename, '\\'); if (!forward && !backward) { CreateDirectory(outFilename, NULL); strcat(outFilename, filename); } else { const char* fileOnly = (forward > backward) ? forward+1 : backward+1; strncat(outFilename, filename, fileOnly-filename); CreateDirectory(outFilename, NULL); strcat(outFilename, fileOnly); } } void plUnzip::IExtractCurrent(const char* destDir, char* fileName) { char filename[MAX_PATH]; if (unzGetCurrentFileInfo(fFile, nil, filename, sizeof(filename), nil, 0, nil, 0) == UNZ_OK) { strcpy(fileName, filename); if (unzOpenCurrentFile(fFile) == UNZ_OK) { char outFilename[MAX_PATH]; IGetFullPath(destDir, filename, outFilename); // Make sure to take off the read-only flag if the file exists, and is RO DWORD attrs = GetFileAttributes(outFilename); if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_READONLY)) SetFileAttributes(outFilename, attrs & ~FILE_ATTRIBUTE_READONLY); hsUNIXStream outFile; if (outFile.Open(outFilename, "wb")) { char buf[2048]; int numRead; while ((numRead = unzReadCurrentFile(fFile, buf, sizeof(buf))) > 0) { outFile.Write(numRead, buf); } outFile.Close(); unz_file_info_s info; unzGetCurrentFileInfo(fFile, &info, NULL, 0, NULL, 0, NULL, 0); SYSTEMTIME sysTime = {0}; sysTime.wDay = info.tmu_date.tm_mday; sysTime.wMonth = info.tmu_date.tm_mon+1; sysTime.wYear = info.tmu_date.tm_year; sysTime.wHour = info.tmu_date.tm_hour; sysTime.wMinute = info.tmu_date.tm_min; sysTime.wSecond = info.tmu_date.tm_sec; FILETIME localFileTime, utcFileTime; SystemTimeToFileTime(&sysTime, &localFileTime); LocalFileTimeToFileTime(&localFileTime, &utcFileTime); HANDLE hFile = CreateFile(outFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetFileTime(hFile, NULL, NULL, &utcFileTime); CloseHandle(hFile); } unzCloseCurrentFile(fFile); } } } void plUnzip::ExtractAll(const char* destDir) { if (unzGoToFirstFile(fFile) != UNZ_OK) return; do { IExtractCurrent(destDir); } while (unzGoToNextFile(fFile) == UNZ_OK); } bool plUnzip::ExtractNext(const char* destDir, char* fileName) { IExtractCurrent(destDir, fileName); return (unzGoToNextFile(fFile) == UNZ_OK); }