Rev 276 | Rev 305 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <spk.h>
#include <StringList.h>
Utils::WString g_dir;
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
//#include <shlobj.h>
#else
#include <dirent.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
void PrintError ( int err )
{
switch ( err )
{
case CATERR_NODATFILE:
printf ( "No dat file found\n" );
break;
case CATERR_NOCATFILE:
printf ( "Unable to open cat file\n" );
break;
case CATERR_FILEEMPTY:
printf ( "Cat file is empty\n" );
break;
case CATERR_READCAT:
printf ( "Unable to read cat file\n" );
break;
case CATERR_DECRYPT:
printf ( "Unable to decrypt cat file\n" );
break;
case CATERR_MISMATCH:
printf ( "Dat file size mismatch\n" );
break;
}
}
void ListFiles (const Utils::WString &filename, const Utils::WString &searchmask )
{
wprintf(L"Listing files in %s...", filename.c_str() );
if (!searchmask.empty())
wprintf(L"(%s)", searchmask.c_str() );
printf("\n");
CCatFile catfile;
int err = catfile.open(filename, L"", CATREAD_CATDECRYPT);
if ( err == CATERR_NONE )
{
printf ( "Opened file\n" );
for (unsigned int i = 0; i < catfile.GetNumFiles(); i++)
{
SInCatFile *file = catfile.GetFile ( i );
if (!searchmask.empty())
{
if (!searchmask.match(file->sFile))
continue;
}
wprintf(L"[%9s] %s\n", SPK::GetSizeString(file->lSize).c_str(), file->sFile.c_str() );
}
}
else
PrintError ( err );
}
bool findFiles(Utils::WStringList &files, const Utils::WString &filepattern)
{
CFileIO File((filepattern.contains(L":")) ? filepattern : g_dir + L"/" + filepattern);
return File.GetDirIO().dirList(files, Utils::WString::Null(), File.filename());
}
void ExtractFile (const Utils::WString &filename, const Utils::WString &to, bool preserve )
{
if ( !filename.contains(L"::") ) return;
Utils::WString catfile = filename.token(L"::", 1);
Utils::WString filemask = filename.token(L"::", 2);
CCatFile cat;
int err = cat.open(catfile, L"", CATREAD_DAT);
if ( err )
{
PrintError ( err );
return;
}
// all files
if ( filemask == L"*" )
{
for (unsigned int i = 0; i < cat.GetNumFiles(); i++)
{
SInCatFile *f = cat.GetFile(i);
if (!cat.extractFile(f, to))
wprintf(L"Error: %s\n", cat.getErrorString().c_str() );
else
wprintf(L"File has been written (%s)\n", cat.errorString().c_str() );
}
return;
}
//TODO: add proper file mask for extracting
Utils::WStringList fileList;
fileList.pushBack(filemask);
if (fileList.empty())
{
wprintf(L"Error: unable to find any files matching: %s\n", filemask.c_str() );
return;
}
for (auto itr = fileList.begin(); itr != fileList.end(); itr++)
{
Utils::WString file = (*itr)->str;
if (!cat.extractFile(file, to, preserve))
wprintf(L"Error: %s\n", cat.getErrorString().c_str() );
else
wprintf(L"File has been written (%s)\n", cat.errorString().c_str() );
}
}
void AppendFile (const Utils::WString &sFile, const Utils::WString &filepattern )
{
Utils::WString catfile;
Utils::WString file;
Utils::WString C_File = sFile.findReplace(L"\\", L"/");
bool doFile = false;
if ( !C_File.contains(L"::"))
{
catfile = C_File;
doFile = true;
}
else
{
catfile = C_File.token(L"::", 1);
file = C_File.token(L"::", 1);
}
Utils::WStringList list;
findFiles(list, filepattern);
if (!list.size())
{
wprintf(L"Error: no files found to add: %s\n", filepattern.c_str());
return;
}
CCatFile cat;
int err = cat.open(catfile, L"", CATREAD_CATDECRYPT);
if ( err )
{
PrintError ( err );
return;
}
for (auto itr = list.begin(); itr != list.end(); itr++)
{
Utils::WString filename = (*itr)->str;
if (doFile)
file = filename;
if (!file.contains(L"."))
{
if (file[file.length() - 1] != L'/')
file += L"/";
file += CFileIO(filename).filename();
}
if (cat.appendFile(filename, file))
wprintf(L"File %s has beed added to: %s::%s\n", filename.c_str(), catfile.c_str(), file.c_str());
else
wprintf(L"Error: Unable to add file: %s\n", filename.c_str());
}
}
void RemoveFile (const Utils::WString &C_File, const Utils::WString &remfile )
{
// first open the cat file
CCatFile cat;
int err = cat.open(C_File, L"", CATREAD_CATDECRYPT);
if ( err )
{
PrintError ( err );
return;
}
SInCatFile *f = cat.findData(remfile);
if ( !f )
{
wprintf(L"Unable to find %s in cat file\n", remfile.c_str() );
return;
}
if (cat.removeFile(f))
printf ( "File has been removed from archive\n" );
}
void UnpackFile(const Utils::WString &file, const Utils::WString &tofile, const Utils::WString &ext)
{
Utils::WStringList list;
if(!findFiles(list, file) || !list.size())
{
wprintf(L"Error: no files found to unpack: %s\n", file.c_str());
return;
}
for(auto itr = list.first(); itr; itr = list.next())
{
Utils::WString filename = CFileIO(file).dir() + L"/" + itr->str;
C_File f(filename);
if (!f.CheckValidFilePointer())
{
CFileIO File((file.contains(L":")) ? file : g_dir + L"/" + file);
filename = File.GetDirIO().file(itr->str);
f.setFilename(filename);
}
Utils::WString oldFilename = f.filename();
if ( !f.CheckValidFilePointer() )
wprintf(L"Error: %s doesn't exists\n", filename.c_str() );
else if ( !f.ReadFromFile() )
wprintf(L"Error: unable to open file: %s\n", filename.c_str() );
else
{
f.UnPCKFile();
if (tofile.empty())
f.changeFileExt(ext.empty() ? L"xml" : ext);
else if ( tofile.left(2) == L"*." )
f.changeFileExt(CFileIO(tofile).extension().toString());
else
f.setFilename(tofile);
if ( !f.writeFilePointer() )
wprintf(L"Error: unable to write file: %s\n", tofile.c_str() );
else
wprintf(L"%s has been unpacked to %s\n", oldFilename.c_str(), f.filename().c_str() );
}
}
}
void PackFile(const Utils::WString &file, const Utils::WString &tofile)
{
Utils::WStringList list;
if(!findFiles(list, file) || !list.size())
{
wprintf(L"Error: no files found to pack: %s\n", file.c_str());
return;
}
for(auto itr = list.first(); itr; itr = list.next())
{
Utils::WString filename = CFileIO(file).dir() + L"/" + itr->str;
C_File f(filename);
if ( !f.CheckValidFilePointer() )
wprintf(L"Error: %s doesn't exists\n", filename.c_str() );
else if ( !f.ReadFromFile() )
wprintf(L"Error: unable to open file: %s\n", filename.c_str() );
else if ( !f.PCKFile() )
wprintf(L"Error: unable to pack file: %s\n", filename.c_str() );
else
{
if ( tofile.empty() )
{
if ( f.checkFileExt(L"bob") )
f.changeFileExt(L"pbb");
else if ( f.checkFileExt(L"bod") )
f.changeFileExt(L"pbd");
else
f.changeFileExt(L"pck");
}
else if ( tofile.left(2) == L"*." )
f.changeFileExt(tofile.right(3));
else
f.setFilename(tofile);
if ( !f.writeFilePointer() )
wprintf(L"Error: unable to write file: %s\n", tofile.c_str() );
else
wprintf(L"%s has been packed to %s\n", file.c_str(), f.filename().c_str() );
}
}
}
void PrintSyntax(const Utils::WString &cmd)
{
wprintf(L"Syntax: %s <flags> [arguments]\n", cmd.c_str() );
wprintf(L"Flags:\n");
wprintf(L"\t-l <filename> [filemask]\n");
wprintf(L"\t\tLists the contents of a cat file, with optional search mask\n");
wprintf(L"\t-x <catfile::filename> [dir]\n");
wprintf(L"\t\textracts a file from a cat file to the optional directory\n");
wprintf(L"\t-xp <catfile::filename> [dir]\n");
wprintf(L"\t\textracts a file from a cat file to the optional directory, preserves directory structure\n");
wprintf(L"\t-xa <catfile> [dir]\n");
wprintf(L"\t\textracts all files to optional directory\n");
wprintf(L"\t-a <filename> <catfile::tofile>\n");
wprintf(L"\t\tAdds the file into a cat archive, saves it as <tofile>\n");
wprintf(L"\t-r <catfile> <file>\n");
wprintf(L"\t\tRemoves a file from an archive\n");
wprintf(L"\t[--ext:EXTENSION] -u <filename> [tofile]\n");
wprintf(L"\t\tUnpacks a file, ie from pck to xml/txt\n");
wprintf(L"\t-p <filename> <tofile>\n");
wprintf(L"\t\tPacks a file, ie from xml/txt to pck\n");
}
int main ( int argc, char **argv )
{
printf ( "\nCATPCK Tool V1.21 27/03/2011 (SPK: %.2f) Created by Cycrow\n\n", GetLibraryVersion() );
// parse the cmd name
Utils::WString cmd (argv[0]);
cmd = cmd.findReplace(L"\\", L"/");
g_dir = cmd.tokens(L"/", 1, cmd.countToken(L"/") - 1);
cmd = cmd.token (L"/", -1);
if (g_dir.empty() || !g_dir.contains("/"))
{
#ifdef _WIN32
g_dir = Utils::WString(_getcwd(NULL, 0));
#else
g_dir = Utils::WString(getcwd(NULL, 0));
#endif
if (g_dir.empty())
g_dir = L"./";
}
if ( argc < 2 )
PrintSyntax(cmd);
else
{
Utils::WString sCommand;
for (int i = 1; i < argc; ++i)
sCommand = sCommand.addToken(L" ", Utils::WString(argv[i]));
sCommand.toLower();
Utils::WStringList flags;
while (sCommand.contains(L"--"))
{
long pos = 0;
pos = sCommand.findPos(L"--", pos);
if (pos > -1)
{
long nextPos = sCommand.findPos(L" ", pos);
if (nextPos > -1)
{
Utils::WString sFlag = sCommand.mid(pos, nextPos);
std::vector<Utils::WString> split;
if (sFlag.tokenise(L":", split))
flags.pushBack(split[0], split[1]);
sCommand = sCommand.findRemove(sFlag);
}
}
}
std::vector<Utils::WString> args;
sCommand.removeFirstSpace();
sCommand.removeEndSpace();
sCommand.tokenise(L" ", args);
Utils::WString command(args[0]);
if ( (command == L"-l") || (command == L"-list") )
{
if ( args.size() < 2 )
wprintf(L"Syntax: %s -l <filename> [filemask]\n\tLists the contents of the cat file\n", cmd.c_str() );
else if ( args.size() < 3)
ListFiles(args[1], Utils::WString(L""));
else
ListFiles(args[1], args[2]);
}
else if ( (command == L"-x") || (command == L"-extract") || (command == L"-xp") || (command == L"-extractpreserve") )
{
if ( args.size() < 2 )
wprintf(L"Syntax: %s %s <catfile::filename> [dir]\n\tExtracts a file from the cat archive\n", cmd.c_str(), command.c_str() );
else if ( args.size() < 3)
ExtractFile (args[1], L"", (command == L"-xp" || command == L"-extractpreserve") ? true : false );
else
ExtractFile (args[1], args[2], (command == L"-xp" || command == L"-extractpreserve") ? true : false );
}
else if ( (command == L"-xa") || (command == L"-extractall") )
{
if ( args.size() < 2)
wprintf(L"Syntax: %s %s <catfile> [dir]\n\tExtracts all files from the cat archive\n", cmd.c_str(), command.c_str() );
else if ( args.size() < 3)
ExtractFile(args[1] + L"::*", L"", true );
else
ExtractFile(args[1] + L"::*", args[2], true );
}
else if ( (command == L"-a") || (command == L"-append") )
{
if (args.size() < 3 )
wprintf(L"Syntax: %s -a <filename> <catfile::tofile>\n\tAppends a file into the archive\n", cmd.c_str() );
else
AppendFile(args[2], args[1]);
}
else if ( (command == L"-r") || (command == L"-remove") )
{
if ( args.size() < 3 )
wprintf(L"Syntax: %s -r <catfile> <filename>\n\tRemoves a file from the archive\n", cmd.c_str() );
else
RemoveFile (args[1], args[2]);
}
else if ( (command == L"-u") || (command == L"-unpack") )
{
Utils::WString ext = flags.findString(L"--ext");
if ( args.size() < 2 )
wprintf(L"Syntax: %s [--ext:EXTENSION] -u <filename> [to]\n\tUnpacks a file", cmd.c_str() );
else if ( args.size() < 3)
UnpackFile(args[1], L"", ext);
else
UnpackFile(args[1], args[2], ext);
}
else if ( (command == L"-p") || (command == L"-pack") )
{
if ( args.size() < 2 )
wprintf(L"Syntax: %s -p <filename> [to]\n\tPacks a file to .pck", cmd.c_str() );
else if ( args.size() < 3)
PackFile(args[1], L"");
else
PackFile(args[1], args[2]);
}
else
{
wprintf(L"Invalaid flag: %s\n\n", command.c_str());
PrintSyntax(cmd);
}
}
#ifdef _DEBUG
char pause;
printf ( "\n\nPress a key to end\n" );
scanf ( "%c", &pause );
#endif
return 0;
}