"Fossies" - the Fresh Open Source Software archive 
Member "lrc-1.0/src/lib/ResourceManager.cxx" of archive lrc-1.0.tar.gz:
// ResourceManager.cxx
//
// Copyright 2011, 2012 Andreas Tscharner <andy@vis.ethz.ch>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser 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 Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301, USA.
#include <cstring>
#include <cstdio>
#include "../Utils.hxx"
#include "../StatusCodes.hxx"
#include "../Factories.hxx"
#include "../include/ResourceManager.hxx"
int lrc::ResourceManager::load_from_file(void)
{
const char WHOLE_FILE[] = "Whole file";
FILE *rdfFile;
size_t rdfFileSize;
size_t decompSize;
size_t decryptSize;
int retVal;
unsigned int numEntries;
size_t readItems;
unsigned char *rdfData;
unsigned char *decompData;
unsigned char *decryptData;
unsigned char *bufferPos;
CompressDecompress *decompressor;
EncryptDecrypt *decryptor;
DEBUG_PRINT(("Checking current data and entries\n"))
if (m_resData) {
delete[] m_resData;
};
if (m_resEntries) {
delete[] m_resEntries;
};
DEBUG_PRINT(("Getting file size of %s: ", m_resourceFile))
rdfFileSize = file_size(m_resourceFile);
if (rdfFileSize <= 0) {
return ERROR_FILE_READ;
};
DEBUG_PRINT((": %d bytes\n", rdfFileSize))
rdfFile = fopen(m_resourceFile, "rb");
if (!rdfFile) {
return ERROR_FILE_OPEN;
};
rdfData = new unsigned char[rdfFileSize];
DEBUG_PRINT(("Reading %d bytes from file %s (complete file)\n", rdfFileSize, m_resourceFile))
readItems = fread(rdfData, sizeof(unsigned char), rdfFileSize, rdfFile);
fclose(rdfFile);
if (readItems != rdfFileSize) {
DEBUG_PRINT(("Error reading file. Read %d; expected: %d\n", readItems, rdfFileSize))
delete[] rdfData;
return ERROR_FILE_READ;
};
DEBUG_PRINT(("Decrypting data with decryption type %d.", m_encType))
try {
decryptor = EncryptionFactory::get_encryption_class(m_encType, const_cast<char *>(WHOLE_FILE));
} catch (lrcEncryptionDisabledException const &encDisEx) {
delete[] rdfData;
return ERROR_ENCRYPTION_NOT_AVAILABLE;
};
retVal = decryptor->decrypt(m_password, rdfData, rdfFileSize, &decryptData, decryptSize);
delete decryptor;
delete[] rdfData;
if (!success(retVal)) {
DEBUG_PRINT((" Decrypting failed with error code: %d\n", retVal))
return ERROR_ENCRYPTION_DECRYPT;
};
DEBUG_PRINT(("\n"))
DEBUG_PRINT(("Decompressing data with decompressor type %d. ", m_compType))
decompressor = CompressionFactory::get_compression_class(m_compType);
retVal = decompressor->decompress(decryptData, decryptSize, &decompData, decompSize);
delete decompressor;
delete[] decryptData;
if (! success(retVal)) {
DEBUG_PRINT(("Decompression failed with error code: %d\n", retVal))
return ERROR_COMPRESSION_DECOMPRESS;
};
DEBUG_PRINT(("Old size: %d; new size: %d\n", decryptSize, decompSize))
bufferPos = decompData;
DEBUG_PRINT(("Getting number of entries..."))
memcpy(&numEntries, bufferPos, sizeof(unsigned int));
bufferPos += sizeof(unsigned int);
DEBUG_PRINT(("done (%d).\n", numEntries))
DEBUG_PRINT(("Getting all %d entries ", numEntries))
m_resEntries = new resEntry[numEntries];
for (int i=0; i<numEntries; i++) {
memcpy(&m_resEntries[i], bufferPos, sizeof(resEntry));
bufferPos += sizeof(resEntry);
DEBUG_PRINT(("."))
};
DEBUG_PRINT(("done.\n"))
m_resDataSize = decompSize - sizeof(unsigned int) - (numEntries * sizeof(resEntry));
DEBUG_PRINT(("Getting data for all entries (total: %d bytes)\n", m_resDataSize))
m_resData = new unsigned char[m_resDataSize];
memset(m_resData, 0, m_resDataSize);
memcpy(m_resData, bufferPos, m_resDataSize);
m_numResEntries = numEntries;
delete[] decompData;
return NO_ERROR;
}
lrc::ResourceManager::ResourceManager(const char *p_resFilename,
const lrc::CompressionType p_compress,
const lrc::EncryptionType p_encrypt,
const unsigned char *p_key) throw (lrcFileNotFoundException)
{
size_t len;
if (!file_exists((char *)p_resFilename)) {
throw(lrcFileNotFoundException((char *)p_resFilename));
};
len = strlen(p_resFilename);
m_resourceFile = new char[len+1];
memset(m_resourceFile, 0, (len+1));
strncpy(m_resourceFile, p_resFilename, len);
m_resEntries = nullptr;
m_numResEntries = -1;
m_resData = nullptr;
m_resDataSize = -1;
m_compType = p_compress;
m_encType = p_encrypt;
m_password = const_cast<unsigned char *>(p_key);
}
lrc::ResourceManager::~ResourceManager(void)
{
delete[] m_resourceFile;
}
char **lrc::ResourceManager::get_resource_ids(int &p_numRes)
{
int retVal, sLen, i;
char **retIDs = nullptr;
DEBUG_PRINT(("Checking number of entries: %d\n", m_numResEntries))
if (m_numResEntries < 0) {
retVal = this->load_from_file();
DEBUG_PRINT(("Reading the file returned %d\n", retVal))
if (!success(retVal)) {
return nullptr;
};
};
DEBUG_PRINT(("Number of entries after loading the file: %d\n", m_numResEntries))
retIDs = new char*[m_numResEntries];
for(i=0; i<m_numResEntries; i++) {
sLen = strlen(m_resEntries[i].resID);
retIDs[i] = new char[sLen + 1];
memset(retIDs[i], 0, (sLen+1));
strncpy(retIDs[i], m_resEntries[i].resID, sLen);
};
p_numRes = m_numResEntries;
return retIDs;
}
lrc::Resource *lrc::ResourceManager::get_resource(const char *p_resID, const unsigned char *p_password)
{
int retVal, i, foundID;
ResourceData *retEntry = nullptr;
unsigned char *dataStart;
DEBUG_PRINT(("Checking number of entries: %d\n", m_numResEntries))
if (m_numResEntries < 0) {
retVal = this->load_from_file();
DEBUG_PRINT(("Reading the file returned %d\n", retVal))
if (!success(retVal)) {
return nullptr;
};
};
foundID = -1;
for (i=0; i<m_numResEntries; i++) {
if (strcmp(m_resEntries[i].resID, p_resID) == 0) {
foundID = i;
break;
};
};
if (foundID < 0) {
return retEntry;
};
retEntry = new ResourceData();
dataStart = m_resData + m_resEntries[foundID].startOffset;
retVal = retEntry->get_data_from_memory(dataStart, m_resEntries[foundID], p_password);
if (!success(retVal)) {
delete retEntry;
retEntry = nullptr;
};
return retEntry;
}
lrc::Resource *lrc::ResourceManager::get_resource(unsigned int p_resIdx, const unsigned char *p_password)
{
int retVal;
ResourceData *retEntry;
unsigned char *dataStart;
DEBUG_PRINT(("Checking the number of entries: %d\n", m_numResEntries))
if (m_numResEntries < 0) {
retVal = this->load_from_file();
DEBUG_PRINT(("Resing the file returned %d\n", retVal))
if (!success(retVal)) {
return nullptr;
};
};
if ((p_resIdx < 0) || (p_resIdx > (m_numResEntries-1))) {
return nullptr;
};
retEntry = new ResourceData();
dataStart = m_resData + m_resEntries[p_resIdx].startOffset;
retVal = retEntry->get_data_from_memory(dataStart, m_resEntries[p_resIdx], p_password);
if (!success(retVal)) {
delete retEntry;
retEntry = nullptr;
};
return retEntry;
}