1604 lines
35 KiB
C++
1604 lines
35 KiB
C++
#include "StdAfx.h"
|
||
|
||
#include <windows.h>
|
||
#include <mmsystem.h>
|
||
#include <io.h>
|
||
#include <assert.h>
|
||
|
||
#include "EterPack.h"
|
||
#include "Inline.h"
|
||
#include "EterPackPolicy_CSHybridCrypt.h"
|
||
|
||
#pragma warning(push, 3)
|
||
#include <cryptopp/cryptlib.h>
|
||
#include <cryptopp/filters.h>
|
||
#include <cryptopp/modes.h>
|
||
#include <cryptopp/tiger.h>
|
||
#include <cryptopp/sha.h>
|
||
#include <cryptopp/ripemd.h>
|
||
#include <cryptopp/whrlpool.h>
|
||
#include <cryptopp/panama.h>
|
||
|
||
#pragma warning(pop)
|
||
|
||
#include "../EterBase/utils.h"
|
||
#include "../EterBase/Debug.h"
|
||
#include "../EterBase/CRC32.h"
|
||
|
||
#ifdef __THEMIDA__
|
||
#include <ThemidaSDK.h>
|
||
#endif
|
||
|
||
#include <iostream>
|
||
#include <fstream>
|
||
|
||
void CMakePackLog::SetFileName(const char* c_szFileName)
|
||
{
|
||
m_stFileName=c_szFileName;
|
||
m_stFileName +=".log";
|
||
m_stErrorFileName = c_szFileName;
|
||
m_stErrorFileName += ".err";
|
||
}
|
||
|
||
CMakePackLog& CMakePackLog::GetSingleton()
|
||
{
|
||
static CMakePackLog s_kMakePackLog;
|
||
return s_kMakePackLog;
|
||
}
|
||
|
||
CMakePackLog::CMakePackLog()
|
||
{
|
||
m_fp=NULL;
|
||
m_fp_err = NULL;
|
||
}
|
||
|
||
CMakePackLog::~CMakePackLog()
|
||
{
|
||
if (NULL!=m_fp)
|
||
{
|
||
fclose(m_fp);
|
||
m_fp=NULL;
|
||
}
|
||
if (NULL != m_fp_err)
|
||
{
|
||
fclose(m_fp_err);
|
||
m_fp_err = NULL;
|
||
}
|
||
}
|
||
|
||
bool CMakePackLog::__IsLogMode()
|
||
{
|
||
if (m_stFileName.empty())
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
void CMakePackLog::Writef(const char* c_szFormat, ...)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
va_list args;
|
||
va_start(args, c_szFormat);
|
||
|
||
char szBuf[1024];
|
||
int nBufLen = _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
|
||
szBuf[nBufLen++] = '\0';
|
||
__Write(szBuf, nBufLen);
|
||
}
|
||
|
||
void CMakePackLog::Writenf(const char* c_szFormat, ...)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
va_list args;
|
||
va_start(args, c_szFormat);
|
||
|
||
char szBuf[1024+1];
|
||
int nBufLen = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
|
||
if (nBufLen > 0)
|
||
{
|
||
szBuf[nBufLen++] = '\n';
|
||
szBuf[nBufLen++] = '\0';
|
||
}
|
||
__Write(szBuf, nBufLen);
|
||
}
|
||
|
||
void CMakePackLog::Write(const char* c_szBuf)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
__Write(c_szBuf, strlen(c_szBuf)+1);
|
||
}
|
||
|
||
void CMakePackLog::__Write(const char* c_szBuf, int nBufLen)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
if (NULL==m_fp)
|
||
m_fp=fopen(m_stFileName.c_str(), "w");
|
||
|
||
fwrite(c_szBuf, nBufLen, 1, m_fp);
|
||
|
||
printf("%s", c_szBuf);
|
||
}
|
||
|
||
|
||
|
||
void CMakePackLog::WriteErrorf(const char* c_szFormat, ...)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
va_list args;
|
||
va_start(args, c_szFormat);
|
||
|
||
char szBuf[1024];
|
||
int nBufLen = _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
|
||
szBuf[nBufLen++] = '\0';
|
||
__WriteError(szBuf, nBufLen);
|
||
}
|
||
|
||
void CMakePackLog::WriteErrornf(const char* c_szFormat, ...)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
va_list args;
|
||
va_start(args, c_szFormat);
|
||
|
||
char szBuf[1024+1];
|
||
int nBufLen = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
|
||
if (nBufLen > 0)
|
||
{
|
||
szBuf[nBufLen++] = '\n';
|
||
szBuf[nBufLen++] = '\0';
|
||
}
|
||
__WriteError(szBuf, nBufLen);
|
||
}
|
||
|
||
void CMakePackLog::WriteError(const char* c_szBuf)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
__WriteError(c_szBuf, strlen(c_szBuf)+1);
|
||
}
|
||
|
||
void CMakePackLog::__WriteError(const char* c_szBuf, int nBufLen)
|
||
{
|
||
if (!__IsLogMode())
|
||
return;
|
||
|
||
if (NULL==m_fp_err)
|
||
m_fp_err=fopen(m_stErrorFileName.c_str(), "w");
|
||
|
||
fwrite(c_szBuf, nBufLen, 1, m_fp_err);
|
||
|
||
printf("Error: %s", c_szBuf);
|
||
}
|
||
|
||
void CMakePackLog::FlushError()
|
||
{
|
||
std::wifstream iFile(m_stErrorFileName.c_str());
|
||
std::istream_iterator <std::wstring, wchar_t> iit(iFile);
|
||
std::istream_iterator <std::wstring, wchar_t> eos;
|
||
|
||
std::vector <std::wstring> vText;
|
||
|
||
std::copy (iit, eos, std::back_inserter(vText));
|
||
|
||
std::ostream_iterator <std::wstring, wchar_t, std::char_traits <wchar_t> > oit(std::wcout);
|
||
|
||
std::sort (vText.begin(), vText.end());
|
||
std::copy (vText.begin(), vText.end(), oit);
|
||
}
|
||
#ifdef __MAKE_PACK__
|
||
FILE * CEterPack::ms_PackLogFile = NULL;
|
||
#endif
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
CEterPack::CEterPack() : m_indexCount(0), m_indexData(NULL), m_FragmentSize(0), m_bEncrypted(false), m_bReadOnly(false), m_bDecrypedIV(false)
|
||
{
|
||
m_pCSHybridCryptPolicy = new EterPackPolicy_CSHybridCrypt;
|
||
|
||
}
|
||
|
||
CEterPack::~CEterPack()
|
||
{
|
||
Destroy();
|
||
|
||
delete m_pCSHybridCryptPolicy;
|
||
m_pCSHybridCryptPolicy = NULL;
|
||
}
|
||
|
||
void CEterPack::Destroy()
|
||
{
|
||
m_bReadOnly = false;
|
||
m_bEncrypted = false;
|
||
m_indexCount = 0;
|
||
m_DataPositionMap.clear();
|
||
|
||
for (int i = 0; i < FREE_INDEX_MAX_SIZE + 1; ++i)
|
||
m_FreeIndexList[i].clear();
|
||
|
||
SAFE_DELETE_ARRAY(m_indexData);
|
||
|
||
m_FragmentSize = 0;
|
||
|
||
memset(m_dbName, 0, sizeof(m_dbName));
|
||
memset(m_indexFileName, 0, sizeof(m_indexFileName));
|
||
}
|
||
|
||
const std::string& CEterPack::GetPathName()
|
||
{
|
||
return m_stPathName;
|
||
}
|
||
|
||
bool CEterPack::Create(CEterFileDict& rkFileDict, const char * dbname, const char* pathName, bool bReadOnly, const BYTE* iv)
|
||
{
|
||
if (iv)
|
||
{
|
||
m_stIV_Panama.assign((const char*) iv, 32);
|
||
m_bDecrypedIV = false;
|
||
}
|
||
|
||
m_stPathName = pathName;
|
||
|
||
strncpy(m_dbName, dbname, DBNAME_MAX_LEN);
|
||
|
||
strncpy(m_indexFileName, dbname, MAX_PATH);
|
||
strcat(m_indexFileName, ".eix");
|
||
|
||
m_stDataFileName = dbname;
|
||
m_stDataFileName += ".epk";
|
||
|
||
m_bReadOnly = bReadOnly;
|
||
|
||
// bReadOnly <20><><EFBFBD>尡 <20>ƴϰ<C6B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̽<EFBFBD><CCBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if (!CreateIndexFile())
|
||
return false;
|
||
|
||
if (!CreateDataFile())
|
||
return false;
|
||
|
||
bool bOverwrite = (iv != NULL);
|
||
__BuildIndex(rkFileDict, bOverwrite);
|
||
|
||
if (m_bReadOnly)
|
||
{
|
||
//m_bIsDataLoaded = true;
|
||
//if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0))
|
||
// return false;
|
||
}
|
||
else
|
||
{
|
||
DecryptIndexFile();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::DecryptIV(DWORD dwPanamaKey)
|
||
{
|
||
if (m_stIV_Panama.length() != 32)
|
||
return false;
|
||
|
||
if (m_bDecrypedIV) // <20>̹<EFBFBD> <20><>ȣȭ<C8A3><C8AD> Ǯ<><C7AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٽ<EFBFBD> ó<><C3B3> <20><><EFBFBD><EFBFBD>
|
||
return true;
|
||
|
||
DWORD* ivs = (DWORD*)&m_stIV_Panama[0];
|
||
for (int i = 0; i != m_stIV_Panama.length() / sizeof(DWORD); ++i)
|
||
{
|
||
ivs[i] ^= dwPanamaKey + i * 16777619;
|
||
}
|
||
|
||
m_bDecrypedIV = true;
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::DecryptIndexFile()
|
||
{
|
||
if (!m_bEncrypted)
|
||
return true;
|
||
|
||
CFileBase file;
|
||
|
||
if (!file.Create(m_indexFileName, CFileBase::FILEMODE_WRITE))
|
||
return false;
|
||
|
||
file.Write(&eterpack::c_IndexCC, sizeof(DWORD));
|
||
file.Write(&eterpack::c_Version, sizeof(DWORD));
|
||
file.Write(&m_indexCount, sizeof(long));
|
||
file.Write(m_indexData, sizeof(TEterPackIndex) * m_indexCount);
|
||
|
||
file.Close();
|
||
|
||
m_bEncrypted = false;
|
||
return true;
|
||
}
|
||
|
||
static DWORD s_adwEterPackKey[] =
|
||
{
|
||
45129401,
|
||
92367215,
|
||
681285731,
|
||
1710201,
|
||
};
|
||
|
||
static DWORD s_adwEterPackSecurityKey[] =
|
||
{
|
||
78952482,
|
||
527348324,
|
||
1632942,
|
||
486274726,
|
||
};
|
||
|
||
bool CEterPack::EncryptIndexFile()
|
||
{
|
||
CMappedFile file;
|
||
LPCVOID pvData;
|
||
|
||
if (NULL == file.Create(m_indexFileName, &pvData, 0, 0))
|
||
{
|
||
TraceError("EncryptIndex: Cannot open pack index file! %s", m_dbName);
|
||
return false;
|
||
}
|
||
|
||
BYTE * pbData = new BYTE[file.Size()];
|
||
memcpy(pbData, pvData, file.Size());
|
||
|
||
CLZObject zObj;
|
||
|
||
if (!CLZO::Instance().CompressEncryptedMemory(zObj, pbData, file.Size(), s_adwEterPackKey))
|
||
{
|
||
TraceError("EncryptIndex: Cannot encrypt! %s", m_dbName);
|
||
SAFE_DELETE_ARRAY(pbData);
|
||
return false;
|
||
}
|
||
|
||
file.Destroy();
|
||
|
||
while (!DeleteFile(m_indexFileName));
|
||
|
||
FILE * fp;
|
||
|
||
fp = fopen(m_indexFileName, "wb");
|
||
|
||
if (!fp)
|
||
{
|
||
TraceError("EncryptIndex: Cannot open file for writing! %s", m_dbName);
|
||
SAFE_DELETE_ARRAY(pbData);
|
||
return false;
|
||
}
|
||
|
||
if (1 != fwrite(zObj.GetBuffer(), zObj.GetSize(), 1, fp))
|
||
{
|
||
TraceError("Encryptindex: Cannot write to file! %s", m_indexFileName);
|
||
SAFE_DELETE_ARRAY(pbData);
|
||
fclose(fp);
|
||
return false;
|
||
}
|
||
|
||
fclose(fp);
|
||
|
||
m_bEncrypted = true;
|
||
delete [] pbData;
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::__BuildIndex(CEterFileDict& rkFileDict, bool bOverwrite)
|
||
{
|
||
//DWORD dwBeginTime = ELTimer_GetMSec();
|
||
CMappedFile file;
|
||
LPCVOID pvData;
|
||
CLZObject zObj;
|
||
|
||
if (NULL == file.Create(m_indexFileName, &pvData, 0, 0))
|
||
{
|
||
TraceError("Cannot open pack index file! %s", m_dbName);
|
||
return false;
|
||
}
|
||
|
||
if (file.Size() < eterpack::c_HeaderSize)
|
||
{
|
||
TraceError("Pack index file header error! %s", m_dbName);
|
||
return false;
|
||
}
|
||
|
||
DWORD fourcc = *(DWORD *) pvData;
|
||
|
||
BYTE * pbData;
|
||
UINT uiFileSize;
|
||
|
||
if (fourcc == eterpack::c_IndexCC)
|
||
{
|
||
pbData = (BYTE *) pvData;
|
||
uiFileSize = file.Size();
|
||
}
|
||
else if (fourcc == CLZObject::ms_dwFourCC)
|
||
{
|
||
m_bEncrypted = true;
|
||
|
||
if (!CLZO::Instance().Decompress(zObj, (const BYTE *) pvData, s_adwEterPackKey))
|
||
return false;
|
||
|
||
if (zObj.GetSize() < eterpack::c_HeaderSize)
|
||
return false;
|
||
|
||
pbData = zObj.GetBuffer();
|
||
uiFileSize = zObj.GetSize();
|
||
}
|
||
else
|
||
{
|
||
TraceError("Pack index file fourcc error! %s", m_dbName);
|
||
return false;
|
||
}
|
||
|
||
pbData += sizeof(DWORD);
|
||
|
||
DWORD ver = *(DWORD *) pbData;
|
||
pbData += sizeof(DWORD);
|
||
|
||
if (ver != eterpack::c_Version)
|
||
{
|
||
TraceError("Pack index file version error! %s", m_dbName);
|
||
return false;
|
||
}
|
||
|
||
m_indexCount = *(long *) pbData;
|
||
pbData += sizeof(long);
|
||
|
||
if (uiFileSize < eterpack::c_HeaderSize + sizeof(TEterPackIndex) * m_indexCount)
|
||
{
|
||
TraceError("Pack index file size error! %s, indexCount %d", m_dbName, m_indexCount);
|
||
return false;
|
||
}
|
||
|
||
//Tracef("Loading Pack file %s elements: %d ... ", m_dbName, m_indexCount);
|
||
|
||
m_indexData = new TEterPackIndex[m_indexCount];
|
||
memcpy(m_indexData, pbData, sizeof(TEterPackIndex) * m_indexCount);
|
||
|
||
TEterPackIndex * index = m_indexData;
|
||
|
||
for (int i = 0; i < m_indexCount; ++i, ++index)
|
||
{
|
||
if (!index->filename_crc)
|
||
{
|
||
PushFreeIndex(index);
|
||
}
|
||
else
|
||
{
|
||
if (index->real_data_size > index->data_size)
|
||
m_FragmentSize += index->real_data_size - index->data_size;
|
||
|
||
m_DataPositionMap.insert(TDataPositionMap::value_type(index->filename_crc, index));
|
||
|
||
if (bOverwrite) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE>Ѵ<EFBFBD>
|
||
rkFileDict.UpdateItem(this, index);
|
||
else
|
||
rkFileDict.InsertItem(this, index);
|
||
}
|
||
}
|
||
|
||
//Tracef("Done. (spent %dms)\n", ELTimer_GetMSec() - dwBeginTime);
|
||
return true;
|
||
}
|
||
//
|
||
//void CEterPack::UpdateLastAccessTime()
|
||
//{
|
||
// m_tLastAccessTime = time(NULL);
|
||
//}
|
||
//
|
||
//void CEterPack::ClearDataMemoryMap()
|
||
//{
|
||
// // m_file<6C><65> data file<6C>̴<EFBFBD>...
|
||
// m_file.Destroy();
|
||
// m_tLastAccessTime = 0;
|
||
// m_bIsDataLoaded = false;
|
||
//}
|
||
|
||
bool CEterPack::Get(CMappedFile& out_file, const char * filename, LPCVOID * data)
|
||
{
|
||
TEterPackIndex * index = FindIndex(filename);
|
||
|
||
if (!index)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
//UpdateLastAccessTime();
|
||
//if (!m_bIsDataLoaded)
|
||
//{
|
||
// if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0))
|
||
// return false;
|
||
//
|
||
// m_bIsDataLoaded = true;
|
||
//}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CEterPack<63><6B><EFBFBD><EFBFBD> epk<70><6B> memory map<61><70> <20>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>, <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD> <20><> <20>κ<EFBFBD><CEBA><EFBFBD> <20><>ũ<EFBFBD>ؼ<EFBFBD> <20>Ѱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>,
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD>, <20>ʿ<EFBFBD><CABF><EFBFBD> <20>κи<CEBA> memory map<61><70> <20>ø<EFBFBD><C3B8><EFBFBD>, <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><>.
|
||
out_file.Create(m_stDataFileName.c_str(), data, index->data_position, index->data_size);
|
||
|
||
bool bIsSecurityCheckRequired = ( index->compressed_type == COMPRESSED_TYPE_SECURITY ||
|
||
index->compressed_type == COMPRESSED_TYPE_PANAMA );
|
||
|
||
if( bIsSecurityCheckRequired )
|
||
{
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
MD5_CTX context;
|
||
GenerateMD5Hash( (BYTE*)(*data), index->data_size, context );
|
||
|
||
if( memcmp( index->MD5Digest, context.digest, 16 ) != 0 )
|
||
{
|
||
return false;
|
||
}
|
||
#else
|
||
DWORD dwCrc32 = GetCRC32((const char*)(*data), index->data_size);
|
||
|
||
if( index->data_crc != dwCrc32 )
|
||
{
|
||
return false;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
if (COMPRESSED_TYPE_COMPRESS == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data)))
|
||
{
|
||
TraceError("Failed to decompress : %s", filename);
|
||
delete zObj;
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObject(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_SECURITY == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), s_adwEterPackSecurityKey))
|
||
{
|
||
TraceError("Failed to encrypt : %s", filename);
|
||
delete zObj;
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObject(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_PANAMA == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
__Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj);
|
||
out_file.BindLZObjectWithBufferedSize(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
#ifdef __THEMIDA__
|
||
VM_START
|
||
#endif
|
||
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if( !m_pCSHybridCryptPolicy->DecryptMemory( std::string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObjectWithBufferedSize(zObj);
|
||
if( COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
BYTE* pSDBData;
|
||
int iSDBSize;
|
||
|
||
if( !m_pCSHybridCryptPolicy->GetSupplementaryDataBlock( std::string(filename), pSDBData, iSDBSize) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
*data = out_file.AppendDataBlock( pSDBData, iSDBSize );
|
||
}
|
||
else
|
||
{
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
#ifdef __THEMIDA__
|
||
VM_END
|
||
#endif
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::Get2(CMappedFile& out_file, const char * filename, TEterPackIndex * index, LPCVOID * data)
|
||
{
|
||
if (!index)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
//UpdateLastAccessTime();
|
||
//if (!m_bIsDataLoaded)
|
||
//{
|
||
// if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0))
|
||
// return false;
|
||
//
|
||
// m_bIsDataLoaded = true;
|
||
//}
|
||
out_file.Create(m_stDataFileName.c_str(), data, index->data_position, index->data_size);
|
||
|
||
bool bIsSecurityCheckRequired = ( index->compressed_type == COMPRESSED_TYPE_SECURITY ||
|
||
index->compressed_type == COMPRESSED_TYPE_PANAMA );
|
||
|
||
if( bIsSecurityCheckRequired )
|
||
{
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
MD5_CTX context;
|
||
GenerateMD5Hash( (BYTE*)(*data), index->data_size, context );
|
||
|
||
if( memcmp( index->MD5Digest, context.digest, 16 ) != 0 )
|
||
{
|
||
return false;
|
||
}
|
||
#else
|
||
DWORD dwCrc32 = GetCRC32((const char*)(*data), index->data_size);
|
||
|
||
if( index->data_crc != dwCrc32 )
|
||
{
|
||
return false;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
if (COMPRESSED_TYPE_COMPRESS == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data)))
|
||
{
|
||
TraceError("Failed to decompress : %s", filename);
|
||
delete zObj;
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObject(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_SECURITY == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), s_adwEterPackSecurityKey))
|
||
{
|
||
TraceError("Failed to encrypt : %s", filename);
|
||
delete zObj;
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObject(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_PANAMA == index->compressed_type)
|
||
{
|
||
CLZObject * zObj = new CLZObject;
|
||
__Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj);
|
||
out_file.BindLZObjectWithBufferedSize(zObj);
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
#ifdef __THEMIDA__
|
||
VM_START
|
||
#endif
|
||
|
||
CLZObject * zObj = new CLZObject;
|
||
|
||
if( !m_pCSHybridCryptPolicy->DecryptMemory( std::string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
out_file.BindLZObjectWithBufferedSize(zObj);
|
||
|
||
if( COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
BYTE* pSDBData;
|
||
int iSDBSize;
|
||
|
||
if( !m_pCSHybridCryptPolicy->GetSupplementaryDataBlock( std::string(filename), pSDBData, iSDBSize) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
*data = out_file.AppendDataBlock( pSDBData, iSDBSize );
|
||
}
|
||
else
|
||
{
|
||
*data = zObj->GetBuffer();
|
||
}
|
||
#ifdef __THEMIDA__
|
||
VM_END
|
||
#endif
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
bool CEterPack::Delete(TEterPackIndex * pIndex)
|
||
{
|
||
CFileBase fileIndex;
|
||
|
||
if (!fileIndex.Create(m_indexFileName, CFileBase::FILEMODE_WRITE))
|
||
return false;
|
||
|
||
PushFreeIndex(pIndex);
|
||
WriteIndex(fileIndex, pIndex);
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::Delete(const char * filename)
|
||
{
|
||
TEterPackIndex * pIndex = FindIndex(filename);
|
||
|
||
if (!pIndex)
|
||
return false;
|
||
|
||
return Delete(pIndex);
|
||
}
|
||
|
||
bool CEterPack::Extract()
|
||
{
|
||
CMappedFile dataMapFile;
|
||
LPCVOID data;
|
||
|
||
if (!dataMapFile.Create(m_stDataFileName.c_str(), &data, 0, 0))
|
||
return false;
|
||
|
||
CLZObject zObj;
|
||
|
||
for (TDataPositionMap::iterator i = m_DataPositionMap.begin();
|
||
i != m_DataPositionMap.end();
|
||
++i)
|
||
{
|
||
TEterPackIndex* index = i->second;
|
||
CFileBase writeFile;
|
||
|
||
inlinePathCreate(index->filename);
|
||
printf("%s\n", index->filename);
|
||
|
||
writeFile.Create(index->filename, CFileBase::FILEMODE_WRITE);
|
||
|
||
if (COMPRESSED_TYPE_COMPRESS == index->compressed_type)
|
||
{
|
||
if (!CLZO::Instance().Decompress(zObj, (const BYTE *) data + index->data_position))
|
||
{
|
||
printf("cannot decompress");
|
||
return false;
|
||
}
|
||
|
||
writeFile.Write(zObj.GetBuffer(), zObj.GetSize());
|
||
zObj.Clear();
|
||
}
|
||
else if (COMPRESSED_TYPE_SECURITY == index->compressed_type)
|
||
{
|
||
if (!CLZO::Instance().Decompress(zObj, (const BYTE *) data + index->data_position, s_adwEterPackSecurityKey))
|
||
{
|
||
printf("cannot decompress");
|
||
return false;
|
||
}
|
||
|
||
writeFile.Write(zObj.GetBuffer(), zObj.GetSize());
|
||
zObj.Clear();
|
||
}
|
||
else if (COMPRESSED_TYPE_PANAMA == index->compressed_type)
|
||
{
|
||
__Decrypt_Panama(index->filename, (const BYTE *) data + index->data_position, index->data_size, zObj);
|
||
writeFile.Write(zObj.GetBuffer(), zObj.GetBufferSize());
|
||
zObj.Clear();
|
||
}
|
||
else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
#ifdef __THEMIDA__
|
||
VM_START
|
||
#endif
|
||
if( !m_pCSHybridCryptPolicy->DecryptMemory( std::string(index->filename), (const BYTE *) data + index->data_position, index->data_size, zObj) )
|
||
return false;
|
||
|
||
if( COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type)
|
||
{
|
||
dataMapFile.BindLZObjectWithBufferedSize(&zObj);
|
||
|
||
BYTE* pSDBData;
|
||
int iSDBSize;
|
||
|
||
if( !m_pCSHybridCryptPolicy->GetSupplementaryDataBlock( std::string(index->filename), pSDBData, iSDBSize) )
|
||
return false;
|
||
|
||
dataMapFile.AppendDataBlock( pSDBData, iSDBSize );
|
||
writeFile.Write(dataMapFile.AppendDataBlock( pSDBData, iSDBSize ),dataMapFile.Size());
|
||
}
|
||
else
|
||
{
|
||
writeFile.Write(zObj.GetBuffer(), zObj.GetBufferSize());
|
||
}
|
||
zObj.Clear();
|
||
#ifdef __THEMIDA__
|
||
VM_END
|
||
#endif
|
||
}
|
||
else if (COMPRESSED_TYPE_NONE == index->compressed_type)
|
||
writeFile.Write((const char *) data + index->data_position, index->data_size);
|
||
|
||
writeFile.Destroy();
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::GetNames(std::vector<std::string>* retNames)
|
||
{
|
||
CMappedFile dataMapFile;
|
||
LPCVOID data;
|
||
|
||
if (!dataMapFile.Create(m_stDataFileName.c_str(), &data, 0, 0))
|
||
return false;
|
||
|
||
CLZObject zObj;
|
||
|
||
for (TDataPositionMap::iterator i = m_DataPositionMap.begin();
|
||
i != m_DataPositionMap.end();
|
||
++i)
|
||
{
|
||
TEterPackIndex* index = i->second;
|
||
|
||
inlinePathCreate(index->filename);
|
||
|
||
retNames->push_back(index->filename);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::Put(const char * filename, const char * sourceFilename, BYTE packType, const std::string& strRelateMapName )
|
||
{
|
||
CMappedFile mapFile;
|
||
LPCVOID data;
|
||
|
||
if (sourceFilename)
|
||
{
|
||
if (!mapFile.Create(sourceFilename, &data, 0, 0))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
else if (!mapFile.Create(filename, &data, 0, 0))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
BYTE* pMappedData = (BYTE*)data;
|
||
int iMappedDataSize = mapFile.Size();
|
||
|
||
if( packType == COMPRESSED_TYPE_HYBRIDCRYPT || packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB )
|
||
{
|
||
#ifdef __THEMIDA__
|
||
VM_START
|
||
#endif
|
||
m_pCSHybridCryptPolicy->GenerateCryptKey( std::string(filename) );
|
||
|
||
if( packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB )
|
||
{
|
||
if( !m_pCSHybridCryptPolicy->GenerateSupplementaryDataBlock( std::string(filename), strRelateMapName, (const BYTE*)data, mapFile.Size(), pMappedData, iMappedDataSize ))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
#ifdef __THEMIDA__
|
||
VM_END
|
||
#endif
|
||
}
|
||
|
||
return Put(filename, pMappedData, iMappedDataSize, packType);
|
||
}
|
||
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
void CEterPack::GenerateMD5Hash( BYTE* pData, int nLength, IN OUT MD5_CTX& mdContext )
|
||
{
|
||
MD5Init (&mdContext);
|
||
|
||
const int nBlockSize = 1024;
|
||
|
||
int nLoopCnt = nLength / nBlockSize;
|
||
int nRemainder = nLength % nBlockSize;
|
||
int i;
|
||
|
||
for(i = 0; i < nLoopCnt; ++i )
|
||
{
|
||
MD5Update (&mdContext, reinterpret_cast<BYTE*>(pData + i*nBlockSize), nBlockSize);
|
||
}
|
||
|
||
if( nRemainder > 0 )
|
||
MD5Update (&mdContext, reinterpret_cast<BYTE*>(pData + i*nBlockSize), nRemainder);
|
||
|
||
MD5Final (&mdContext);
|
||
}
|
||
#endif
|
||
bool CEterPack::Put(const char * filename, LPCVOID data, long len, BYTE packType)
|
||
{
|
||
if (m_bEncrypted)
|
||
{
|
||
TraceError("EterPack::Put : Cannot put to encrypted pack (filename: %s, DB: %s)", filename, m_dbName);
|
||
return false;
|
||
}
|
||
|
||
CFileBase fileIndex;
|
||
|
||
if (!fileIndex.Create(m_indexFileName, CFileBase::FILEMODE_WRITE))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
CFileBase fileData;
|
||
|
||
if (!fileData.Create(m_stDataFileName.c_str(), CFileBase::FILEMODE_WRITE))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
TEterPackIndex * pIndex;
|
||
pIndex = FindIndex(filename);
|
||
|
||
CLZObject zObj;
|
||
std::string encryptStr;
|
||
|
||
if (packType == COMPRESSED_TYPE_SECURITY ||
|
||
packType == COMPRESSED_TYPE_COMPRESS)
|
||
{
|
||
if (packType == COMPRESSED_TYPE_SECURITY)
|
||
{
|
||
if (!CLZO::Instance().CompressEncryptedMemory(zObj, data, len, s_adwEterPackSecurityKey))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!CLZO::Instance().CompressMemory(zObj, data, len))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
data = zObj.GetBuffer();
|
||
len = zObj.GetSize();
|
||
}
|
||
else if (packType == COMPRESSED_TYPE_PANAMA)
|
||
{
|
||
if (!__Encrypt_Panama(filename, (const BYTE *) data, len, zObj))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
data = zObj.GetBuffer();
|
||
len = zObj.GetBufferSize();
|
||
}
|
||
else if (packType == COMPRESSED_TYPE_HYBRIDCRYPT || packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB )
|
||
{
|
||
#ifdef __THEMIDA__
|
||
VM_START
|
||
#endif
|
||
|
||
if( !m_pCSHybridCryptPolicy->EncryptMemory( std::string(filename), (const BYTE *)data, len, zObj ) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
data = zObj.GetBuffer();
|
||
len = zObj.GetBufferSize();
|
||
#ifdef __THEMIDA__
|
||
VM_END
|
||
#endif
|
||
|
||
}
|
||
|
||
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
MD5_CTX context;
|
||
GenerateMD5Hash( (BYTE*)(data), len, context );
|
||
#else
|
||
DWORD data_crc;
|
||
data_crc = GetCRC32((const char *) data, len);
|
||
#endif
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..
|
||
if (pIndex)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD> data ũ<>Ⱑ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<>⸦ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִٸ<D6B4>
|
||
if (pIndex->real_data_size >= len)
|
||
{
|
||
++m_map_indexRefCount[pIndex->id];
|
||
|
||
// <20><><EFBFBD>̰<EFBFBD> Ʋ<><C6B2><EFBFBD>ų<EFBFBD>, checksum<75><6D> Ʋ<><C6B2> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
||
if ( (pIndex->data_size != len) ||
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
(memcmp( pIndex->MD5Digest, context.digest, 16 ) != 0) )
|
||
#else
|
||
(pIndex->data_crc != data_crc) )
|
||
#endif
|
||
{
|
||
#ifdef __MAKE_PACK__
|
||
if (ms_PackLogFile)
|
||
fprintf(ms_PackLogFile, "Overwrite[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename);
|
||
printf("Overwrite[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename);
|
||
#endif
|
||
pIndex->data_size = len;
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
memcpy( pIndex->MD5Digest, context.digest, 16 );
|
||
|
||
#else
|
||
pIndex->data_crc = data_crc;
|
||
#endif
|
||
|
||
pIndex->compressed_type = packType;
|
||
|
||
CMakePackLog::GetSingleton().Writef("Overwrite[type:%u] %s\n", pIndex->compressed_type, pIndex->filename);
|
||
|
||
WriteIndex(fileIndex, pIndex);
|
||
WriteData(fileData, pIndex, data);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<>Ⱑ <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>Ҵ<EFBFBD><D2B4><EFBFBD>
|
||
// <20>־<EFBFBD><D6BE><EFBFBD> <20>Ѵ<EFBFBD>. <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>д<EFBFBD>.
|
||
PushFreeIndex(pIndex);
|
||
WriteIndex(fileIndex, pIndex);
|
||
}
|
||
|
||
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
pIndex = NewIndex(fileIndex, filename, len);
|
||
pIndex->data_size = len;
|
||
|
||
#ifdef CHECKSUM_CHECK_MD5
|
||
memcpy( pIndex->MD5Digest, context.digest, 16 );
|
||
#else
|
||
pIndex->data_crc = data_crc;
|
||
#endif
|
||
|
||
|
||
pIndex->data_position = GetNewDataPosition(fileData);
|
||
pIndex->compressed_type = packType;
|
||
|
||
WriteIndex(fileIndex, pIndex);
|
||
WriteNewData(fileData, pIndex, data);
|
||
|
||
++m_map_indexRefCount[pIndex->id];
|
||
|
||
#ifdef __MAKE_PACK__
|
||
if (ms_PackLogFile)
|
||
fprintf(ms_PackLogFile, "Write[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename);
|
||
printf("Write[%d/%d] %s, position %ld realsize %ld size %ld\n",
|
||
bCompress, bSecurity, pIndex->filename, pIndex->data_position, pIndex->real_data_size, pIndex->data_size);
|
||
#endif
|
||
CMakePackLog::GetSingleton().Writef("Write[type:%u] %s\n", pIndex->compressed_type, pIndex->filename);
|
||
|
||
return true;
|
||
}
|
||
|
||
long CEterPack::GetFragmentSize()
|
||
{
|
||
return m_FragmentSize;
|
||
}
|
||
|
||
// Private methods
|
||
bool CEterPack::CreateIndexFile()
|
||
{
|
||
FILE * fp;
|
||
|
||
if (NULL != (fp = fopen(m_indexFileName, "rb")))
|
||
{
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
else if (m_bReadOnly)
|
||
return false;
|
||
|
||
//
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
//
|
||
fp = fopen(m_indexFileName, "wb");
|
||
|
||
if (!fp)
|
||
return false;
|
||
|
||
fwrite(&eterpack::c_IndexCC, sizeof(DWORD), 1, fp);
|
||
fwrite(&eterpack::c_Version, sizeof(DWORD), 1, fp);
|
||
fwrite(&m_indexCount, sizeof(long), 1, fp);
|
||
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
|
||
|
||
void CEterPack::WriteIndex(CFileBase & file, TEterPackIndex * index)
|
||
{
|
||
file.Seek(sizeof(DWORD) + sizeof(DWORD));
|
||
file.Write(&m_indexCount, sizeof(long));
|
||
file.Seek(eterpack::c_HeaderSize + (index->id * sizeof(TEterPackIndex)));
|
||
|
||
if (!file.Write(index, sizeof(TEterPackIndex)))
|
||
{
|
||
assert(!"WriteIndex: fwrite failed");
|
||
return;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Free Block <20>̶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>κ<EFBFBD><CEBA><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
||
* Free Block <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> FREE_INDEX_BLOCK_SIZE (32768) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* <09><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>.
|
||
*
|
||
* <09><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 128k <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>
|
||
* 128 * 1024 / FREE_INDEX_BLOCK_SIZE = 4 <20>̹Ƿ<CCB9>
|
||
* <09><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD> m_FreeIndexList[4] <20><> <20><><EFBFBD><EFBFBD><EEB0A3>.
|
||
*
|
||
* FREE_INDEX_BLOCK_SIZE <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> FREE_INDEX_MAX_SIZE(512) <20>̴<EFBFBD>.
|
||
* <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 16MB <20>̻<EFBFBD><CCBB><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>迭<EFBFBD><E8BFAD> 512 <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EEB0A3>.
|
||
*/
|
||
int CEterPack::GetFreeBlockIndex(long size)
|
||
{
|
||
return min(FREE_INDEX_MAX_SIZE, size / FREE_INDEX_BLOCK_SIZE);
|
||
}
|
||
|
||
void CEterPack::PushFreeIndex(TEterPackIndex* index)
|
||
{
|
||
if (index->filename_crc != 0)
|
||
{
|
||
TDataPositionMap::iterator i = m_DataPositionMap.find(index->filename_crc);
|
||
|
||
if (i != m_DataPositionMap.end())
|
||
m_DataPositionMap.erase(i);
|
||
|
||
index->filename_crc = 0;
|
||
memset(index->filename, 0, sizeof(index->filename));
|
||
}
|
||
|
||
int blockidx = GetFreeBlockIndex(index->real_data_size);
|
||
m_FreeIndexList[blockidx].push_back(index);
|
||
m_FragmentSize += index->real_data_size;
|
||
//printf("FreeIndex: size %d: blockidx: %d\n", index->real_data_size, blockidx);
|
||
}
|
||
|
||
long CEterPack::GetNewIndexPosition(CFileBase & file)
|
||
{
|
||
long pos = (file.Size() - eterpack::c_HeaderSize) / sizeof(TEterPackIndex);
|
||
++m_indexCount;
|
||
return (pos);
|
||
}
|
||
|
||
TEterPackIndex* CEterPack::NewIndex(CFileBase& file, const char* filename, long size)
|
||
{
|
||
TEterPackIndex* index = NULL;
|
||
int block_size = size + (DATA_BLOCK_SIZE - (size % DATA_BLOCK_SIZE));
|
||
// if ((index = FindIndex(filename))) // <20>̹<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>
|
||
// return index;
|
||
|
||
int blockidx = GetFreeBlockIndex(block_size);
|
||
|
||
for (TFreeIndexList::iterator i = m_FreeIndexList[blockidx].begin();
|
||
i != m_FreeIndexList[blockidx].end();
|
||
++i)
|
||
{
|
||
if ((*i)->real_data_size >= size)
|
||
{
|
||
index = *i;
|
||
m_FreeIndexList[blockidx].erase(i);
|
||
|
||
assert(index->filename_crc == 0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!index)
|
||
{
|
||
index = new TEterPackIndex;
|
||
index->real_data_size = block_size;
|
||
index->id = GetNewIndexPosition(file);
|
||
}
|
||
|
||
strncpy(index->filename, filename, FILENAME_MAX_LEN);
|
||
index->filename[FILENAME_MAX_LEN] = '\0';
|
||
inlineConvertPackFilename(index->filename);
|
||
|
||
index->filename_crc = GetCRC32(index->filename, strlen(index->filename));
|
||
|
||
m_DataPositionMap.insert(TDataPositionMap::value_type(index->filename_crc, index));
|
||
return index;
|
||
}
|
||
|
||
TEterPackIndex* CEterPack::FindIndex(const char * filename)
|
||
{
|
||
static char tmpFilename[MAX_PATH + 1];
|
||
strncpy(tmpFilename, filename, MAX_PATH);
|
||
inlineConvertPackFilename(tmpFilename);
|
||
|
||
DWORD filename_crc = GetCRC32(tmpFilename, strlen(tmpFilename));
|
||
TDataPositionMap::iterator i = m_DataPositionMap.find(filename_crc);
|
||
|
||
if (i == m_DataPositionMap.end())
|
||
return NULL;
|
||
|
||
return (i->second);
|
||
}
|
||
|
||
bool CEterPack::IsExist(const char * filename)
|
||
{
|
||
return FindIndex(filename) ? true : false;
|
||
}
|
||
|
||
bool CEterPack::CreateDataFile()
|
||
{
|
||
FILE * fp;
|
||
|
||
if (NULL != (fp = fopen(m_stDataFileName.c_str(), "rb")))
|
||
{
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
else if (m_bReadOnly)
|
||
return false;
|
||
|
||
fp = fopen(m_stDataFileName.c_str(), "wb");
|
||
|
||
if (!fp)
|
||
return false;
|
||
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
|
||
long CEterPack::GetNewDataPosition(CFileBase& file)
|
||
{
|
||
return file.Size();
|
||
}
|
||
|
||
bool CEterPack::ReadData(CFileBase & file, TEterPackIndex* index, LPVOID data, long maxsize)
|
||
{
|
||
if (index->data_size > maxsize)
|
||
return false;
|
||
|
||
file.Seek(index->data_position);
|
||
file.Read(data, index->data_size);
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::WriteData(CFileBase & file, TEterPackIndex* index, LPCVOID data)
|
||
{
|
||
file.Seek(index->data_position);
|
||
|
||
if (!file.Write(data, index->data_size))
|
||
{
|
||
assert(!"WriteData: fwrite data failed");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::WriteNewData(CFileBase& file, TEterPackIndex* index, LPCVOID data)
|
||
{
|
||
file.Seek(index->data_position);
|
||
|
||
if (!file.Write(data, index->data_size))
|
||
{
|
||
assert(!"WriteData: fwrite data failed");
|
||
return false;
|
||
}
|
||
|
||
int empty_size = index->real_data_size - index->data_size;
|
||
|
||
if (empty_size < 0)
|
||
{
|
||
printf("SYSERR: WriteNewData(): CRITICAL ERROR: empty_size lower than 0!\n");
|
||
exit(1);
|
||
}
|
||
|
||
if (empty_size == 0)
|
||
return true;
|
||
|
||
char * empty_buf = (char *) calloc(empty_size, sizeof(char));
|
||
|
||
if (!file.Write(empty_buf, empty_size))
|
||
{
|
||
assert(!"WriteData: fwrite empty data failed");
|
||
return false;
|
||
}
|
||
|
||
free(empty_buf);
|
||
return true;
|
||
}
|
||
|
||
TDataPositionMap & CEterPack::GetIndexMap()
|
||
{
|
||
return m_DataPositionMap;
|
||
}
|
||
|
||
DWORD CEterPack::DeleteUnreferencedData()
|
||
{
|
||
TDataPositionMap::iterator i = m_DataPositionMap.begin();
|
||
DWORD dwCount = 0;
|
||
|
||
while (i != m_DataPositionMap.end())
|
||
{
|
||
TEterPackIndex * pIndex = (i++)->second;
|
||
|
||
if (0 == m_map_indexRefCount[pIndex->id])
|
||
{
|
||
printf("Unref File %s\n", pIndex->filename);
|
||
Delete(pIndex);
|
||
++dwCount;
|
||
}
|
||
}
|
||
|
||
return dwCount;
|
||
}
|
||
|
||
const char * CEterPack::GetDBName()
|
||
{
|
||
return m_dbName;
|
||
}
|
||
|
||
void CEterPack::__CreateFileNameKey_Panama(const char * filename, BYTE * key, unsigned int keySize)
|
||
{
|
||
// Ű <20><>ȣȭ
|
||
if (keySize != 32)
|
||
return;
|
||
|
||
std::string SrcStringForKey(filename);
|
||
unsigned int idx = GetCRC32(SrcStringForKey.c_str(), SrcStringForKey.length()) & 3;
|
||
|
||
CryptoPP::HashTransformation* hm1 = NULL;
|
||
CryptoPP::HashTransformation* hm2 = NULL;
|
||
|
||
static CryptoPP::Tiger tiger;
|
||
static CryptoPP::SHA1 sha1;
|
||
static CryptoPP::RIPEMD128 ripemd128;
|
||
static CryptoPP::Whirlpool whirlpool;
|
||
|
||
switch (idx & 3)
|
||
{
|
||
case 0:
|
||
hm1 = &whirlpool;
|
||
break;
|
||
|
||
case 1:
|
||
hm1 = &tiger;
|
||
break;
|
||
|
||
case 2:
|
||
hm1 = &sha1;
|
||
break;
|
||
|
||
case 3:
|
||
hm1 = &ripemd128;
|
||
break;
|
||
}
|
||
|
||
CryptoPP::StringSource(SrcStringForKey, true,
|
||
new CryptoPP::HashFilter(*hm1,
|
||
//new CryptoPP::HexEncoder(
|
||
new CryptoPP::ArraySink(key, 16)
|
||
//) // HexEncoder
|
||
) // HashFilter
|
||
); // StringSource
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ű<><C5B0> ù<><C3B9>° 4<><34><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> 16<31><36><EFBFBD><EFBFBD>Ʈ Ű <20><><EFBFBD><EFBFBD> <20>˰<EFBFBD><CBB0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
unsigned int idx2 = *(unsigned int*) key;
|
||
|
||
switch (idx2 & 3)
|
||
{
|
||
case 0:
|
||
hm2 = &sha1;
|
||
break;
|
||
|
||
case 1:
|
||
hm2 = &ripemd128;
|
||
break;
|
||
|
||
case 2:
|
||
hm2 = &whirlpool;
|
||
break;
|
||
|
||
case 3:
|
||
hm2 = &tiger;
|
||
break;
|
||
}
|
||
|
||
CryptoPP::StringSource(SrcStringForKey, true,
|
||
new CryptoPP::HashFilter(*hm2,
|
||
//new CryptoPP::HexEncoder(
|
||
new CryptoPP::ArraySink(key + 16, 16)
|
||
//) // HexEncoder
|
||
) // HashFilter
|
||
); // StringSource
|
||
// Ű <20><><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD>
|
||
}
|
||
|
||
bool CEterPack::__Encrypt_Panama(const char* filename, const BYTE* data, SIZE_T dataSize, CLZObject& zObj)
|
||
{
|
||
if (32 != m_stIV_Panama.length())
|
||
{
|
||
// <20><>Ŀ<EFBFBD><C4BF> <20><> <20><EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
#ifdef _DEBUG
|
||
TraceError("IV not set (filename: %s)", filename);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
CryptoPP::PanamaCipher<CryptoPP::LittleEndian>::Encryption Encryptor;
|
||
|
||
if (dataSize < Encryptor.MandatoryBlockSize())
|
||
{
|
||
#ifdef _DEBUG
|
||
TraceError("Type 3 pack file must be bigger than %u bytes (filename: %s)", Encryptor.MandatoryBlockSize(), filename);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
BYTE key[32];
|
||
|
||
__CreateFileNameKey_Panama(filename, key, sizeof(key));
|
||
Encryptor.SetKeyWithIV(key, sizeof(key), (const BYTE*) m_stIV_Panama.c_str(), 32);
|
||
|
||
// MandatoryBlockSize<7A><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> 2048 <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE>
|
||
DWORD cryptSize = dataSize - (dataSize % Encryptor.MandatoryBlockSize());
|
||
cryptSize = cryptSize > 2048 ? 2048 : cryptSize;
|
||
|
||
std::string tmp;
|
||
|
||
tmp.reserve(cryptSize);
|
||
|
||
CryptoPP::ArraySource(data, cryptSize, true,
|
||
new CryptoPP::StreamTransformationFilter(Encryptor,
|
||
new CryptoPP::StringSink(tmp)
|
||
)
|
||
);
|
||
|
||
if (tmp.length() != cryptSize)
|
||
{
|
||
#ifdef _DEBUG
|
||
TraceError("Type 3 pack crypt buffer size error (out %u should be %u)", tmp.length(), cryptSize);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
zObj.AllocBuffer(dataSize);
|
||
memcpy(zObj.GetBuffer(), tmp.c_str(), cryptSize);
|
||
|
||
if (dataSize - cryptSize > 0)
|
||
memcpy(zObj.GetBuffer() + cryptSize, data + cryptSize, dataSize - cryptSize);
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CEterPack::__Decrypt_Panama(const char* filename, const BYTE* data, SIZE_T dataSize, CLZObject& zObj)
|
||
{
|
||
if (32 != m_stIV_Panama.length())
|
||
{
|
||
// <20><>Ŀ<EFBFBD><C4BF> <20><> <20><EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
#ifdef _DEBUG
|
||
TraceError("IV not set (filename: %s)", filename);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
CryptoPP::PanamaCipher<CryptoPP::LittleEndian>::Decryption Decryptor;
|
||
|
||
BYTE key[32];
|
||
|
||
__CreateFileNameKey_Panama(filename, key, sizeof(key));
|
||
Decryptor.SetKeyWithIV(key, sizeof(key), (const BYTE*) m_stIV_Panama.c_str(), 32);
|
||
|
||
// MandatoryBlockSize<7A><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> 2048 <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE>
|
||
DWORD cryptSize = dataSize - (dataSize % Decryptor.MandatoryBlockSize());
|
||
cryptSize = cryptSize > 2048 ? 2048 : cryptSize;
|
||
|
||
std::string tmp;
|
||
|
||
tmp.reserve(cryptSize);
|
||
|
||
CryptoPP::ArraySource(data, cryptSize, true,
|
||
new CryptoPP::StreamTransformationFilter(Decryptor,
|
||
new CryptoPP::StringSink(tmp)
|
||
)
|
||
);
|
||
|
||
if (tmp.length() != cryptSize)
|
||
{
|
||
#ifdef _DEBUG
|
||
TraceError("Type 3 pack crypt buffer size error (out %u should be %u)", tmp.length(), cryptSize);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
zObj.AllocBuffer(dataSize);
|
||
memcpy(zObj.GetBuffer(), tmp.c_str(), cryptSize);
|
||
|
||
if (dataSize - cryptSize > 0)
|
||
memcpy(zObj.GetBuffer() + cryptSize, data + cryptSize, dataSize - cryptSize);
|
||
|
||
return true;
|
||
}
|
||
|
||
EterPackPolicy_CSHybridCrypt* CEterPack::GetPackPolicy_HybridCrypt() const
|
||
{
|
||
return m_pCSHybridCryptPolicy;
|
||
}
|
||
|
||
|
||
/////////////////////////
|
||
|
||
void CEterFileDict::InsertItem(CEterPack* pkPack, TEterPackIndex* pkInfo)
|
||
{
|
||
Item item;
|
||
|
||
item.pkPack = pkPack;
|
||
item.pkInfo = pkInfo;
|
||
|
||
m_dict.insert(TDict::value_type(pkInfo->filename_crc, item));
|
||
}
|
||
|
||
void CEterFileDict::UpdateItem(CEterPack* pkPack, TEterPackIndex* pkInfo)
|
||
{
|
||
Item item;
|
||
|
||
item.pkPack = pkPack;
|
||
item.pkInfo = pkInfo;
|
||
|
||
TDict::iterator f = m_dict.find(pkInfo->filename_crc);
|
||
if (f == m_dict.end())
|
||
m_dict.insert(TDict::value_type(pkInfo->filename_crc, item));
|
||
else
|
||
{
|
||
if (strcmp(f->second.pkInfo->filename, item.pkInfo->filename) == 0)
|
||
{
|
||
f->second = item;
|
||
}
|
||
else
|
||
{
|
||
TraceError("NAME_COLLISION: OLD: %s NEW: %s", f->second.pkInfo->filename, item.pkInfo->filename);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
CEterFileDict::Item* CEterFileDict::GetItem(DWORD dwFileNameHash, const char * c_pszFileName)
|
||
{
|
||
std::pair<TDict::iterator, TDict::iterator> iter_pair = m_dict.equal_range(dwFileNameHash);
|
||
|
||
TDict::iterator iter = iter_pair.first;
|
||
|
||
while (iter != iter_pair.second)
|
||
{
|
||
Item& item = iter->second;
|
||
|
||
if (0 == strcmp(c_pszFileName, item.pkInfo->filename))
|
||
return &item;
|
||
|
||
++iter;
|
||
}
|
||
|
||
return NULL;
|
||
}
|