Rev 316 | Rev 320 | 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#include "Utils/CommandLine.h"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;case CATERR_CREATED:printf("Cat file does not exist\n");break;}}void ListFiles(const Utils::CommandLine &cmd){const Utils::WString& filename = cmd.arg(1);const Utils::WString& searchmask = cmd.arg(2);CFileIO File(!filename.contains(L":") ? CDirIO(g_dir).file(filename) : filename);if(!File.exists())File.open(filename);if (!File.exists()){wprintf(L"Error: Cat file: %s, does not exist", filename.c_str());return;}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(File.fullFilename(), L"", CATREAD_CATDECRYPT);int listed = 0;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 (!file->sFile.match(searchmask))continue;}wprintf(L"[%9s] %s\n", SPK::GetSizeString(static_cast<unsigned long>(file->lSize)).c_str(), file->sFile.c_str() );++listed;}if (!searchmask.empty())wprintf(L"\nListed Files: [%d/%d]", listed, static_cast<int>(catfile.GetNumFiles()));}elsePrintError ( err );}void findAllFiles(const CDirIO &dirIO, const Utils::WString& dir, const Utils::WString& filepattern, Utils::WStringList& list){Utils::WStringList dirList;if (dirIO.dirList(dirList, dir, filepattern, true)){for (auto itr = dirList.begin(); itr != dirList.end(); itr++){if (dirIO.isDir((*itr)->str))findAllFiles(dirIO, (*itr)->str, filepattern, list);elselist.pushBack((*itr)->str);}}}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(), true);}void ExtractFile (const Utils::CommandLine& cmd, const Utils::WString& fileMask, bool preserve){Utils::WString filename = cmd.arg(1) + fileMask;Utils::WString to = cmd.argCount() < 2 ? cmd.cmdDir() : cmd.arg(2);if (!to.contains(L":")) to = cmd.file()->dirIO().file(to);CDirIO destination(to);if (cmd.hasSwitch("preserve"))preserve = true;if ( !filename.contains(L"::") ) return;Utils::WString catfile = filename.token(L"::", 1);CFileIO File((catfile.contains(L":")) ? catfile : g_dir + L"/" + catfile);Utils::WString filemask = filename.token(L"::", 2);CCatFile cat;int err = cat.open(File.fullFilename(), L"", CATREAD_DAT);if ( err ){PrintError ( err );return;}Utils::WStringList fileList;if (filemask.containsAny(L"*?")){for (unsigned int i = 0; i < cat.GetNumFiles(); i++){SInCatFile* f = cat.GetFile(i);if(f->sFile.match(filemask))fileList.pushBack(f->sFile);}}elsefileList.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() );elsewprintf(L"File has been written: %s\n", preserve ? file.c_str() : CFileIO(file).filename().c_str());}}void AppendFile (const Utils::CommandLine& cmd){Utils::WString sFile = cmd.arg(2);Utils::WString filepattern = cmd.arg(1);Utils::WString catfile;Utils::WString file;bool recursive = cmd.hasSwitch(L"recursive");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"::", 2);}if (!catfile.contains(":"))catfile = g_dir + L"/" + catfile;Utils::WStringList list;CFileIO File((filepattern.contains(L":")) ? filepattern : g_dir + L"/" + filepattern);if (recursive)findAllFiles(File.dirIO(), L"", File.filename(), list);elsefindFiles(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 && err != CATERR_CREATED){PrintError ( err );return;}int added = 0;for (auto itr = list.begin(); itr != list.end(); itr++){if (File.dirIO().isDir((*itr)->str))continue;Utils::WString filename = (*itr)->str;Utils::WString toFile = file;if (doFile)toFile = File.dirIO().relativePath(filename);;if (!toFile.contains(L".")){if (toFile[static_cast<unsigned long>(toFile.length() - 1)] != L'/')toFile += L"/";toFile += CFileIO(filename).filename();}++added;if (cat.appendFile(filename, toFile))wprintf(L"File %s has beed added to: %s::%s\n", filename.c_str(), catfile.c_str(), toFile.c_str());elsewprintf(L"Error: Unable to add file: %s\n", filename.c_str());}if(!added)wprintf(L"Warning: Nothing to add: %s\n", filepattern.c_str());}void RemoveFile (const Utils::WString &C_File, const Utils::WString &remfile ){// first open the cat fileCCatFile 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 = 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{if(!f.UnPCKFile())wprintf(L"Error: unable to unpack file: %s\n", filename.c_str());else{if (tofile.empty())f.changeFileExt(ext.empty() ? L"xml" : ext);else if (tofile.left(2) == L"*.")f.changeFileExt(CFileIO(tofile).extension().toString());elsef.setFilename(tofile);if (!f.writeFilePointer())wprintf(L"Error: unable to write file: %s\n", tofile.c_str());elsewprintf(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 = 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");elsef.changeFileExt(L"pck");}else if ( tofile.left(2) == L"*." )f.changeFileExt(tofile.right(3));elsef.setFilename(tofile);if ( !f.writeFilePointer() )wprintf(L"Error: unable to write file: %s\n", tofile.c_str() );elsewprintf(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 [--preserve] <catfile::filemask> [dir]\n");wprintf(L"\t\textracts a file from a cat file to the optional directory\n\t--preverve: Preserves directory structure");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.22 17/05/2025 (SPK: %.2f) Created by Cycrow\n\n", GetLibraryVersion() );// parse the cmd nameUtils::CommandLine cmd(argc, argv);g_dir = cmd.cmdDir();if ( argc < 2 )PrintSyntax(cmd.cmdName());else{Utils::WString command(cmd.arg(0).lower());auto& args = cmd.args();if ( (command == L"-l") || (command == L"-list") ){if (cmd.argCount() < 2)wprintf(L"Syntax: %s -l <filename> [filemask]\n\tLists the contents of the cat file\n", cmd.cmdName().c_str());elseListFiles(cmd);}else if ((command == L"-x") || (command == L"-extract")){if (cmd.argCount() < 2 )wprintf(L"Syntax: %s %s [--preserve] <catfile::filemask> [dir]\n\tExtracts a file from the cat archive\n", cmd.cmdName().c_str(), command.c_str() );elseExtractFile (cmd, L"", false);}else if ( (command == L"-xa") || (command == L"-extractall") ){if (cmd.argCount() < 2)wprintf(L"Syntax: %s %s <catfile> [dir]\n\tExtracts all files from the cat archive\n", cmd.cmdName().c_str(), command.c_str() );elseExtractFile(cmd, L"::*", 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.cmdName().c_str() );elseAppendFile(cmd);}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.cmdName().c_str() );elseRemoveFile (args[1], args[2]);}else if ( (command == L"-u") || (command == L"-unpack") ){Utils::WString ext = cmd.switchData(L"--ext");if ( args.size() < 2 )wprintf(L"Syntax: %s [--ext:EXTENSION] -u <filename> [to]\n\tUnpacks a file", cmd.cmdName().c_str() );else if ( args.size() < 3)UnpackFile(args[1], L"", ext);elseUnpackFile(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.cmdName().c_str() );else if ( args.size() < 3)PackFile(args[1], L"");elsePackFile(args[1], args[2]);}else{wprintf(L"Invalaid flag: %s\n\n", command.c_str());PrintSyntax(cmd.cmdName());}}#ifdef _DEBUGchar pause;printf ( "\n\nPress a key to end\n" );scanf ( "%c", &pause );#endifreturn 0;}