Rev 130 | Rev 160 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "OriginalFiles.h"
#include "File.h"
#include "Logging/Log.h"
#include "BaseFile.h"
#include "spk.h"
//#include "ProgressInfo.h"
namespace SPK {
void AddLogEntry(int type, CyString args, CyStringList *errors)
{
if ( errors ) errors->PushBack(args, ERRORLOG_OLD(type));
}
COriginalFiles::COriginalFiles(const Utils::String &dir) : _sDir(dir)
{
}
COriginalFiles::~COriginalFiles(void)
{
reset();
}
int COriginalFiles::count() const
{
return _lFiles.size();
}
/**
* Check for original file
*
* Checks if the file is an original file or not
*/
bool COriginalFiles::isOriginal(C_File *f) const
{
if ( _getFile(f) )
return true;
return false;
}
void COriginalFiles::installed(CBaseFile *package)
{
for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
{
C_File *of = oNode->Data();
for ( CListNode<C_File> *checkNode = package->GetFileList()->Front(); checkNode; checkNode = checkNode->next() )
{
C_File *f = checkNode->Data();
// match the same filetype
if ( of->GetFileType() != f->GetFileType() )
continue;
// same file
if ( of->GetFilename().Compare(f->GetFilename()) )
_storeOverride(f);
}
}
}
void COriginalFiles::backup(CBaseFile *package, CyStringList *errors)
{
// backup any original files before installing
CLog::log(CLog::Log_Install, 3, "Checking for any original files to backup");
CDirIO oDir(_sDir + "/PluginManager/Original");
for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
{
C_File *of = oNode->Data();
for ( CListNode<C_File> *checkNode = package->GetFileList()->Front(); checkNode; checkNode = checkNode->next() )
{
C_File *f = checkNode->Data();
// match the same filetype
if ( of->GetFileType() != f->GetFileType() )
continue;
// same file
if ( of->GetFilename().Compare(f->GetFilename()) )
{
// check if original file already exists (assume already backed up)
if ( !backupFile(of, errors) )
continue;
break;
}
}
}
}
bool COriginalFiles::backupFile(C_File *f, CyStringList *errors)
{
Utils::String newDir = "PluginManager/Original/" + f->getDirectory(NULL);
CDirIO oDir(_sDir);
if ( oDir.exists(newDir + "/" + f->GetFilename().ToString()) )
return true;
// make sure the directory exissts
if ( !oDir.exists(newDir) )
{
if ( !oDir.Create(newDir) )
{
CLog::logf(CLog::Log_Install, 2, "Unable to create directory to backup original files, %s", newDir.c_str());
AddLogEntry(SPKINSTALL_CREATEDIRECTORY_FAIL, newDir, errors);
return false;
}
CLog::logf(CLog::Log_Install, 2, "Created new directory, %s", newDir.c_str());
AddLogEntry(SPKINSTALL_CREATEDIRECTORY, newDir, errors);
}
// now lets copy the file
CFileIO CopyFile(f->filePointer());
if ( CopyFile.copy(oDir.File(newDir + "/" + f->GetFilename().ToString()).ToString()) )
{
CLog::logf(CLog::Log_Install, 2, "Original file: %s has been backed up", f->GetNameDirectory(NULL).c_str());
AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP, f->GetNameDirectory(NULL), errors);
return true;
}
else
{
CLog::logf(CLog::Log_Install, 2, "Failed to backup the original file: %s", f->GetNameDirectory(NULL).c_str());
AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP_FAIL, f->GetNameDirectory(NULL), errors);
return false;
}
}
bool COriginalFiles::doBackup(C_File *f, CyStringList *errors)
{
bool backed = false;
C_File *of = this->_getFile(f);
if ( of ) {
// check if the orignal file is already backed up
if ( !CFileIO::Exists(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString()) )
{
// lets back up the file now
backed = this->backupFile(of, errors);
}
}
return backed;
}
int COriginalFiles::restoreAll(CProgressInfo *info, int files, int max)
{
for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
{
// update the progress
if ( info ) info->UpdateProgress(files, max);
++files;
C_File *f = oNode->Data();
CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
if ( of.exists() )
of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString());
delete oNode->Data();
}
_lFiles.clear();
return files;
}
bool COriginalFiles::restoreFile(C_File *f, CyStringList *errors)
{
bool original = false;
// check if its an original file and restore
if ( this->isOriginal(f) )
{
CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
if ( of.exists() )
{
original = true;
if ( of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString()) )
AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE, f->GetNameDirectory(NULL), errors);
else
AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE_FAIL, f->GetNameDirectory(NULL), errors);
CFileIO backupFile(_sDir + "/PluginManager/Original/Replacements/" + f->GetNameDirectory(NULL).ToString());
if ( backupFile.exists() ) backupFile.remove();
}
}
return original;
}
void COriginalFiles::parse(const Utils::String &data)
{
C_File *uf = new C_File();
uf->setFileType((FileType)data.token(" ", 1).toLong());
// Extra files also contain a directory, so make sure we split that up
if (uf->fileType() == FILETYPE_EXTRA )
{
uf->SetDir(data.tokens(" ", 2).tokens(":", 2));
uf->SetFilename(data.tokens(" ", 2).token(":", 1));
}
else
uf->SetFilename(data.tokens(" ", 2));
// set the complete filename, GetNameDirectory returns the directory based on the file type
uf->SetFilename(_sDir + "/" + uf->GetNameDirectory(NULL).ToString());
_lFiles.push_back(uf);
}
void COriginalFiles::update(bool bForce, const CLinkList<C_File> *pFiles)
{
if ( _lFiles.empty() || bForce )
{
_storeFiles(FILETYPE_SCRIPT, "scripts", pFiles);
_storeFiles(FILETYPE_TEXT, "t", pFiles);
_storeFiles(FILETYPE_SOUND, "soundtrack", pFiles);
_storeFiles(FILETYPE_EXTRA, "mov", pFiles);
}
}
bool COriginalFiles::writeData(CyStringList *lines)
{
bool addAny = false;
if ( !_lFiles.empty() )
{
for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
{
C_File *uf = node->Data();
Utils::String uString = "Original: ";
uString += Utils::String::Number((long)uf->GetFileType()) + " ";
uString += uf->GetFilename().ToString();
// add the directory for Extra files
if ( uf->GetFileType() == FILETYPE_EXTRA && !uf->GetDir().Empty())
{
uString += ":";
uString += uf->GetDir().ToString();
}
lines->PushBack(CyString(uString));
addAny = true;
}
}
return addAny;
}
void COriginalFiles::reset()
{
_lFiles.MemoryClear();
}
/**
* Update original files list
*
* Scan the current directory for any fiels that are already there, ie ones that have not been installed
* Original files should be all the scripts/sounds, etc that are in an unmodified game directory
*
* Save list of files and check if any packages overright these files
* Any file that gets overrighten from this list will automatically be backed up, and restored once the packages are removed
*/
void COriginalFiles::_storeFiles(FileType filetype, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
{
Utils::String ext = "pck";
switch ( filetype )
{
case FILETYPE_SOUND:
ext = "mp3";
break;
}
CDirIO Dir(_sDir + "/" + searchPath);
CyStringList *files = Dir.DirList();
if ( !files )
return;
for ( SStringList *node = files->Head(); node; node = node->next )
{
CFileIO File(Dir.File(node->str));
if ( File.extension().Compare(ext) )
_add(filetype, File.filename(), searchPath, pFiles);
}
delete files;
}
/**
* Get original file
*
* Finds a matching original file entry and returns it
*/
C_File *COriginalFiles::_getFile(C_File *file) const
{
if ( !file ) return NULL;
for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
{
C_File *of = node->Data();
// not of the same file type
if ( of->GetFileType() != file->GetFileType() )
continue;
// same file name, must be the same file
if ( of->GetFilename().Compare(file->GetFilename()) )
return of;
}
return NULL;
}
/**
* Adds a file onto the original files list
*
* Checks if it already exists so we dont create multiples
*/
void COriginalFiles::_add(FileType filetype, const Utils::String &filename, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
{
// dont add plugin manager as original files
if ( filetype == FILETYPE_SCRIPT && filename.isin("!init.pmanager") )
return;
// first check if a matching one exists
for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
{
C_File *file = node->Data();
if ( file->GetFileType() != filetype )
continue;
if ( file->GetFilename().Compare(CyString(filename)) )
return;
}
// check that no packages are currently using them either, not original if being used already
for ( CListNode<C_File> *node = pFiles->Front(); node; node = node->next() )
{
C_File *file = node->Data();
if ( file->GetFileType() != filetype )
continue;
if ( file->GetFilename().Compare(CyString(filename)) )
return;
}
// add the file entry to the list
C_File *of = new C_File(filename);
of->setFileType(filetype);
if (filetype == FILETYPE_EXTRA)
of->SetDir(searchPath);
of->SetFilename(_sDir + "/" + of->GetNameDirectory(NULL).ToString());
_lFiles.push_back(of);
}
void COriginalFiles::_storeOverride(C_File *f)
{
CDirIO oDir(_sDir + "/PluginManager/Original/Replacements");
if ( !oDir.exists() ) oDir.Create();
CFileIO file(oDir.file(f->GetNameDirectory(NULL).ToString()));
if ( !file.GetDirIO().exists() ) file.GetDirIO().Create();
CFileIO fromFile(f->GetFilePointer());
fromFile.copy(file.fullFilename(), true);
}
}