Subversion Repositories spk

Rev

Rev 222 | Rev 298 | 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 ( CyString filename, Utils::WString &searchmask )
{
        printf ( "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.ToString(), 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 ( CyString C_File, const Utils::WString &filepattern )
{
        Utils::WString catfile;
        Utils::WString file;

        C_File = C_File.FindReplace("\\", "/");

        bool doFile = false;
        if ( !C_File.IsIn ( "::" ) )
        {
                catfile = C_File.ToString();
                doFile = true;
        }
        else
        {
                catfile = C_File.GetToken ( "::", 1, 1 ).ToString();
                file = C_File.GetToken ( "::", 2, 2 ).ToString();
        }

        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 )
{
        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; 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
                {
                        f.UnPCKFile();
                        if ( tofile.empty() )
                                f.changeFileExt(L"xml");
                        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", file.c_str(), f.filename().c_str() );
                }
        }
}

void PackFile(const Utils::String &file, const Utils::String &tofile)
{
        Utils::WStringList list;
        if(!findFiles(list, file) || !list.size())
        {
                printf("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() )
                                printf("Error: unable to write file: %s\n", tofile.c_str() );
                        else
                                wprintf(L"%hs has been packed to %s\n", file.c_str(), f.filename().c_str() );
                }
        }
}

void PrintSyntax(CyString cmd)
{
        printf ( "Syntax: %s <flags> [arguments]\n", cmd.c_str() );
        printf ( "Flags:\n");
        printf ( "\t-l <filename> [filemask]\n");
        printf ( "\t\tLists the contents of a cat file, with optional search mask\n");
        printf ( "\t-x <catfile::filename> [dir]\n");
        printf ( "\t\textracts a file from a cat file to the optional directory\n");
        printf ( "\t-xp <catfile::filename> [dir]\n");
        printf ( "\t\textracts a file from a cat file to the optional directory, preserves directory structure\n");
        printf ( "\t-xa <catfile> [dir]\n");
        printf ( "\t\textracts all files to optional directory\n");
        printf ( "\t-a <filename> <catfile::tofile>\n");
        printf ( "\t\tAdds the file into a cat archive, saves it as <tofile>\n");
        printf ( "\t-r <catfile> <file>\n");
        printf ( "\t\tRemoves a file from an archive\n");
        printf ( "\t-u <filename> <tofile>\n");
        printf ( "\t\tUnpacks a file, ie from pck to xml/txt\n");
        printf ( "\t-p <filename> <tofile>\n");
        printf ( "\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())
        {
            #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(CyString(cmd.toString()));
        else
        {
                CyString command ( argv[1] );
                command.ToLower();

                if ( (command == "-l") || (command == "-list") )
                {
                        if ( argc < 3 )
                                wprintf(L"Syntax: %s -l <filename> [filemask]\n\tLists the contents of the cat file\n", cmd.c_str() );
                        else if ( argc < 4 )
                                ListFiles ( CyString(argv[2]), Utils::WString(L""));
                        else
                                ListFiles ( CyString(argv[2]), Utils::WString(argv[3]));
                }
                else if ( (command == "-x") || (command == "-extract") || (command == "-xp") || (command == "-extractpreserve") )
                {
                        if ( argc < 3 )
                                wprintf(L"Syntax: %s %hs <catfile::filename> [dir]\n\tExtracts a file from the cat archive\n", cmd.c_str(), command.c_str() );
                        else if ( argc < 4 )
                                ExtractFile (Utils::WString(argv[2]), L"", (command == "-xp" || command == "-extractpreserve") ? true : false );
                        else
                                ExtractFile (Utils::WString(argv[2]), Utils::WString(argv[3]), (command == "-xp" || command == "-extractpreserve") ? true : false );
                }
                else if ( (command == "-xa") || (command == "-extractall") )
                {
                        if ( argc < 3 )
                                wprintf(L"Syntax: %s %hs <catfile> [dir]\n\tExtracts all files from the cat archive\n", cmd.c_str(), command.c_str() );
                        else if ( argc < 4 )
                                ExtractFile(Utils::WString::FromString(argv[2]) + L"::*", L"", true );
                        else
                                ExtractFile(Utils::WString::FromString(argv[2]) + L"::*", Utils::WString(argv[3]), true );
                }
                else if ( (command == "-a") || (command == "-append") )
                {
                        if ( argc < 4 )
                                wprintf(L"Syntax: %s -a <filename> <catfile::tofile>\n\tAppends a file into the archive\n", cmd.c_str() );
                        else
                                AppendFile ( CyString(argv[3]), Utils::WString(argv[2]));
                }
                else if ( (command == "-r") || (command == "-remove") )
                {
                        if ( argc < 4 )
                                wprintf(L"Syntax: %s -r <catfile> <filename>\n\tRemoves a file from the archive\n", cmd.c_str() );
                        else
                                RemoveFile (Utils::WString::FromString(argv[2]), Utils::WString::FromString(argv[3]));
                }
                else if ( (command == "-u") || (command == "-unpack") )
                {
                        if ( argc < 3 )
                                wprintf(L"Syntax: %s -u <filename> [to]\n\tUnpacks a file", cmd.c_str() );
                        else if ( argc < 4 )
                                UnpackFile(Utils::WString::FromString(argv[2]), L"");
                        else
                                UnpackFile(Utils::WString::FromString(argv[2]), Utils::WString::FromString(argv[3]));
                }
                else if ( (command == "-p") || (command == "-pack") )
                {
                        if ( argc < 3 )
                                wprintf(L"Syntax: %s -p <filename> [to]\n\tPacks a file to .pck", cmd.c_str() );
                        else if ( argc < 4 )
                                PackFile(argv[2], "");
                        else
                                PackFile(argv[2], argv[3]);
                }
                else
                {
                        printf("Invalaid flag: %s\n\n", command.c_str());
                        PrintSyntax(CyString(cmd.toString()));
                }
        }

#ifdef _DEBUG
        char pause;
        printf ( "\n\nPress a key to end\n" );
        scanf ( "%c", &pause );
#endif

        return 0;
}