You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.5 KiB

/*==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 <http://www.gnu.org/licenses/>.
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);
}