Improve subdir filepath template handling

Adds new templates for subdir options
%title%
%title_stripped%
%dlc_title%
%dlc_title_stripped%
This commit is contained in:
Sude 2025-02-16 15:35:37 +02:00
parent 5d6640de88
commit 367b57ca89
13 changed files with 246 additions and 104 deletions

View File

@ -29,7 +29,6 @@ class Blacklist
void initialize(const std::vector<std::string>& lines);
bool isBlacklisted(const std::string& path);
bool isBlacklisted(const std::string& path, const std::string& gamename, std::string subdirectory = "");
std::vector<BlacklistItem>::size_type size() const { return blacklist_.size(); }
bool empty() { return blacklist_.empty(); }

View File

@ -27,8 +27,10 @@ class gameDetails
std::vector<gameFile> languagepacks;
std::vector<gameDetails> dlcs;
std::string gamename;
std::string gamename_basegame;
std::string product_id;
std::string title;
std::string title_basegame;
std::string icon;
std::string serials;
std::string changelog;
@ -51,6 +53,8 @@ class gameDetails
protected:
void filterListWithPriorities(std::vector<gameFile>& list, const gameSpecificConfig& config);
void filterListWithType(std::vector<gameFile>& list, const unsigned int& iType);
std::string makeFilepath(const gameFile& gf, const DirectoryConfig& dirConf);
std::string makeCustomFilepath(const std::string& filename, const gameDetails& gd, const DirectoryConfig& dirConf);
private:
std::string serialsFilepath;
std::string logoFilepath;

View File

@ -26,13 +26,16 @@ class gameFile
std::string size;
std::string galaxy_downlink_json_url;
std::string version;
std::string title;
std::string gamename_basegame = "";
std::string title_basegame = "";
unsigned int platform;
unsigned int language;
unsigned int type;
int score;
int silent;
void setFilepath(const std::string& path);
std::string getFilepath();
std::string getFilepath() const;
Json::Value getAsJson();
virtual ~gameFile();
protected:

View File

@ -12,7 +12,7 @@
namespace GlobalConstants
{
const int GAMEDETAILS_CACHE_VERSION = 5;
const int GAMEDETAILS_CACHE_VERSION = 6;
const int ZLIB_WINDOW_SIZE = 15;
struct optionsStruct {const unsigned int id; const std::string code; const std::string str; const std::string regexp;};
@ -129,14 +129,19 @@ namespace GlobalConstants
const unsigned int GFTYPE_DLC_EXTRA = 1 << 5;
const unsigned int GFTYPE_DLC_PATCH = 1 << 6;
const unsigned int GFTYPE_DLC_LANGPACK = 1 << 7;
const unsigned int GFTYPE_CUSTOM_BASE = 1 << 8;
const unsigned int GFTYPE_CUSTOM_DLC = 1 << 9;
const unsigned int GFTYPE_DLC = GFTYPE_DLC_INSTALLER | GFTYPE_DLC_EXTRA |
GFTYPE_DLC_PATCH | GFTYPE_DLC_LANGPACK;
GFTYPE_DLC_PATCH | GFTYPE_DLC_LANGPACK |
GFTYPE_CUSTOM_DLC;
const unsigned int GFTYPE_BASE = GFTYPE_BASE_INSTALLER | GFTYPE_BASE_EXTRA |
GFTYPE_BASE_PATCH | GFTYPE_BASE_LANGPACK;
GFTYPE_BASE_PATCH | GFTYPE_BASE_LANGPACK |
GFTYPE_CUSTOM_BASE;
const unsigned int GFTYPE_INSTALLER = GFTYPE_BASE_INSTALLER | GFTYPE_DLC_INSTALLER;
const unsigned int GFTYPE_EXTRA = GFTYPE_BASE_EXTRA | GFTYPE_DLC_EXTRA;
const unsigned int GFTYPE_PATCH = GFTYPE_BASE_PATCH | GFTYPE_DLC_PATCH;
const unsigned int GFTYPE_LANGPACK = GFTYPE_BASE_LANGPACK | GFTYPE_DLC_LANGPACK;
const unsigned int GFTYPE_CUSTOM = GFTYPE_CUSTOM_BASE | GFTYPE_CUSTOM_DLC;
const std::vector<GlobalConstants::optionsStruct> INCLUDE_OPTIONS =
{

View File

@ -60,8 +60,6 @@ struct wishlistItem
namespace Util
{
std::string makeFilepath(const std::string& directory, const std::string& path, const std::string& gamename, std::string subdirectory = "", const unsigned int& platformId = 0, const std::string& dlcname = "");
std::string makeRelativeFilepath(const std::string& path, const std::string& gamename, std::string subdirectory = "");
std::string getFileHash(const std::string& filename, unsigned hash_id);
std::string getFileHashRange(const std::string& filepath, unsigned hash_id, off_t range_start = 0, off_t range_end = 0);
std::string getChunkHash(unsigned char* chunk, uintmax_t chunk_size, unsigned hash_id);

View File

@ -133,7 +133,17 @@ int main(int argc, char *argv[])
std::string check_orphans_text = "Check for orphaned files (files found on local filesystem that are not found on GOG servers). Sets regular expression filter (Perl syntax) for files to check. If no argument is given then the regex defaults to '" + orphans_regex_default + "'";
// Help text for subdir options
std::string subdir_help_text = "\nTemplates:\n- %platform%\n- %gamename%\n- %gamename_firstletter%\n- %dlcname%\n- %gamename_transformed%\n- %gamename_transformed_firstletter%";
std::string subdir_help_text = "\nTemplates:\n"
"- %platform%\n"
"- %gamename%\n"
"- %gamename_firstletter%\n"
"- %dlcname%\n"
"- %gamename_transformed%\n"
"- %gamename_transformed_firstletter%\n"
"- %title%\n"
"- %title_stripped%\n"
"- %dlc_title%\n"
"- %dlc_title_stripped%";
// Help text for include and exclude options
std::string include_options_text;

View File

@ -296,6 +296,14 @@ Templates:
\- %gamename_transformed%
.br
\- %gamename_transformed_firstletter%
.br
\- %title%
.br
\- %title_stripped%
.br
\- %dlc_title%
.br
\- %dlc_title_stripped%
.TP
\fB\-\-subdir\-extras\fR arg (=extras)
Set subdirectory for extras

View File

@ -70,10 +70,3 @@ bool Blacklist::isBlacklisted(const std::string& path) {
}
return false;
}
bool Blacklist::isBlacklisted(const std::string& path, const std::string& gamename, std::string subdirectory)
{
std::string filepath = Util::makeRelativeFilepath(path, gamename, subdirectory);
return isBlacklisted(filepath);
}

View File

@ -2173,6 +2173,9 @@ std::vector<gameDetails> Downloader::getGameDetailsFromJsonNode(Json::Value root
fileDetails.language = fileDetailsNode["language"].asUInt();
fileDetails.silent = fileDetailsNode["silent"].asInt();
fileDetails.gamename = fileDetailsNode["gamename"].asString();
fileDetails.title = fileDetailsNode["title"].asString();
fileDetails.gamename_basegame = fileDetailsNode["gamename_basegame"].asString();
fileDetails.title_basegame = fileDetailsNode["title_basegame"].asString();
fileDetails.type = fileDetailsNode["type"].asUInt();
fileDetails.galaxy_downlink_json_url = fileDetailsNode["galaxy_downlink_json_url"].asString();
if (!fileDetailsNode["version"].empty())
@ -2446,6 +2449,7 @@ int Downloader::downloadFileWithId(const std::string& fileid_string, const std::
}
gameDetails gd = gogGalaxy->productInfoJsonToGameDetails(productInfo, dlConf);
gd.makeFilepaths(Globals::globalConfig.dirConf);
auto vFiles = gd.getGameFileVector();
gameFile gf;
@ -2517,7 +2521,7 @@ int Downloader::downloadFileWithId(const std::string& fileid_string, const std::
std::string filename, filepath;
filename = gogGalaxy->getPathFromDownlinkUrl(url, gf.gamename);
if (output_filepath.empty())
filepath = Util::makeFilepath(Globals::globalConfig.dirConf.sDirectory, filename, gf.gamename);
filepath = gf.getFilepath();
else
filepath = output_filepath;
std::cout << "Downloading: " << filepath << std::endl;

View File

@ -376,21 +376,29 @@ gameDetails galaxyAPI::productInfoJsonToGameDetails(const Json::Value& json, con
if (dlConf.iInclude & GlobalConstants::GFTYPE_INSTALLER)
{
gamedetails.installers = this->fileJsonNodeToGameFileVector(gamedetails.gamename, json["downloads"]["installers"], GlobalConstants::GFTYPE_BASE_INSTALLER, dlConf);
for (auto &item : gamedetails.installers)
item.title = gamedetails.title;
}
if (dlConf.iInclude & GlobalConstants::GFTYPE_EXTRA)
{
gamedetails.extras = this->fileJsonNodeToGameFileVector(gamedetails.gamename, json["downloads"]["bonus_content"], GlobalConstants::GFTYPE_BASE_EXTRA, dlConf);
for (auto &item : gamedetails.extras)
item.title = gamedetails.title;
}
if (dlConf.iInclude & GlobalConstants::GFTYPE_PATCH)
{
gamedetails.patches = this->fileJsonNodeToGameFileVector(gamedetails.gamename, json["downloads"]["patches"], GlobalConstants::GFTYPE_BASE_PATCH, dlConf);
for (auto &item : gamedetails.patches)
item.title = gamedetails.title;
}
if (dlConf.iInclude & GlobalConstants::GFTYPE_LANGPACK)
{
gamedetails.languagepacks = this->fileJsonNodeToGameFileVector(gamedetails.gamename, json["downloads"]["language_packs"], GlobalConstants::GFTYPE_BASE_LANGPACK, dlConf);
for (auto &item : gamedetails.languagepacks)
item.title = gamedetails.title;
}
if (dlConf.iInclude & GlobalConstants::GFTYPE_DLC)
@ -408,16 +416,34 @@ gameDetails galaxyAPI::productInfoJsonToGameDetails(const Json::Value& json, con
}
gameDetails dlc_gamedetails = this->productInfoJsonToGameDetails(json["expanded_dlcs"][i], dlConf);
dlc_gamedetails.title_basegame = gamedetails.title;
dlc_gamedetails.gamename_basegame = gamedetails.gamename;
// Add DLC type to all DLC files
for (unsigned int j = 0; j < dlc_gamedetails.installers.size(); ++j)
{
dlc_gamedetails.installers[j].type = GlobalConstants::GFTYPE_DLC_INSTALLER;
dlc_gamedetails.installers[j].title_basegame = dlc_gamedetails.title_basegame;
dlc_gamedetails.installers[j].gamename_basegame = dlc_gamedetails.gamename_basegame;
}
for (unsigned int j = 0; j < dlc_gamedetails.extras.size(); ++j)
{
dlc_gamedetails.extras[j].type = GlobalConstants::GFTYPE_DLC_EXTRA;
dlc_gamedetails.extras[j].title_basegame = dlc_gamedetails.title_basegame;
dlc_gamedetails.extras[j].gamename_basegame = dlc_gamedetails.gamename_basegame;
}
for (unsigned int j = 0; j < dlc_gamedetails.patches.size(); ++j)
{
dlc_gamedetails.patches[j].type = GlobalConstants::GFTYPE_DLC_PATCH;
dlc_gamedetails.patches[j].title_basegame = dlc_gamedetails.title_basegame;
dlc_gamedetails.patches[j].gamename_basegame = dlc_gamedetails.gamename_basegame;
}
for (unsigned int j = 0; j < dlc_gamedetails.languagepacks.size(); ++j)
{
dlc_gamedetails.languagepacks[j].type = GlobalConstants::GFTYPE_DLC_LANGPACK;
dlc_gamedetails.languagepacks[j].title_basegame = dlc_gamedetails.title_basegame;
dlc_gamedetails.languagepacks[j].gamename_basegame = dlc_gamedetails.gamename_basegame;
}
// Add DLC only if it has any files
if (!dlc_gamedetails.installers.empty() || !dlc_gamedetails.extras.empty() || !dlc_gamedetails.patches.empty() || !dlc_gamedetails.languagepacks.empty())

View File

@ -91,75 +91,67 @@ void gameDetails::makeFilepaths(const DirectoryConfig& config)
if (this->icon.rfind(".") != std::string::npos)
icon_ext = this->icon.substr(this->icon.rfind("."));
this->serialsFilepath = Util::makeFilepath(directory, "serials.txt", this->gamename, subdir, 0);
this->logoFilepath = Util::makeFilepath(directory, "logo" + logo_ext, this->gamename, subdir, 0);
this->iconFilepath = Util::makeFilepath(directory, "icon" + icon_ext, this->gamename, subdir, 0);
this->changelogFilepath = Util::makeFilepath(directory, "changelog_" + gamename + ".html", this->gamename, subdir, 0);
this->gameDetailsJsonFilepath = Util::makeFilepath(directory, "game-details.json", this->gamename, subdir, 0);
this->productJsonFilepath = Util::makeFilepath(directory, "product.json", this->gamename, subdir, 0);
this->serialsFilepath = this->makeCustomFilepath(std::string("serials.txt"), *this, config);
this->logoFilepath = this->makeCustomFilepath(std::string("logo") + logo_ext, *this, config);
this->iconFilepath = this->makeCustomFilepath(std::string("icon") + icon_ext, *this, config);
this->changelogFilepath = this->makeCustomFilepath(std::string("changelog_") + gamename + ".html", *this, config);
this->gameDetailsJsonFilepath = this->makeCustomFilepath(std::string("game-details.json"), *this, config);
this->productJsonFilepath = this->makeCustomFilepath(std::string("product.json"), *this, config);
for (unsigned int i = 0; i < this->installers.size(); ++i)
for (auto &installer : this->installers)
{
subdir = config.bSubDirectories ? config.sInstallersSubdir : "";
filepath = Util::makeFilepath(directory, this->installers[i].path, this->gamename, subdir, this->installers[i].platform);
this->installers[i].setFilepath(filepath);
filepath = this->makeFilepath(installer, config);
installer.setFilepath(filepath);
}
for (unsigned int i = 0; i < this->extras.size(); ++i)
for (auto &extra : this->extras)
{
subdir = config.bSubDirectories ? config.sExtrasSubdir : "";
filepath = Util::makeFilepath(directory, this->extras[i].path, this->gamename, subdir, 0);
this->extras[i].setFilepath(filepath);
filepath = this->makeFilepath(extra, config);
extra.setFilepath(filepath);
}
for (unsigned int i = 0; i < this->patches.size(); ++i)
for (auto &patch : this->patches)
{
subdir = config.bSubDirectories ? config.sPatchesSubdir : "";
filepath = Util::makeFilepath(directory, this->patches[i].path, this->gamename, subdir, this->patches[i].platform);
this->patches[i].setFilepath(filepath);
filepath = this->makeFilepath(patch, config);
patch.setFilepath(filepath);
}
for (unsigned int i = 0; i < this->languagepacks.size(); ++i)
for (auto &languagepack : this->languagepacks)
{
subdir = config.bSubDirectories ? config.sLanguagePackSubdir : "";
filepath = Util::makeFilepath(directory, this->languagepacks[i].path, this->gamename, subdir, 0);
this->languagepacks[i].setFilepath(filepath);
filepath = this->makeFilepath(languagepack, config);
languagepack.setFilepath(filepath);
}
for (unsigned int i = 0; i < this->dlcs.size(); ++i)
{
subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sInstallersSubdir : "";
this->dlcs[i].serialsFilepath = Util::makeFilepath(directory, "serials.txt", this->gamename, subdir, 0);
this->dlcs[i].logoFilepath = Util::makeFilepath(directory, "logo" + logo_ext, this->gamename, subdir, 0, this->dlcs[i].gamename);
this->dlcs[i].iconFilepath = Util::makeFilepath(directory, "icon" + icon_ext, this->gamename, subdir, 0, this->dlcs[i].gamename);
this->dlcs[i].changelogFilepath = Util::makeFilepath(directory, "changelog_" + this->dlcs[i].gamename + ".html", this->gamename, subdir, 0);
this->dlcs[i].productJsonFilepath = Util::makeFilepath(directory, "product.json", this->gamename, subdir, 0, this->dlcs[i].gamename);
for (unsigned int j = 0; j < this->dlcs[i].installers.size(); ++j)
this->dlcs[i].serialsFilepath = this->makeCustomFilepath(std::string("serials.txt"), this->dlcs[i], config);
this->dlcs[i].logoFilepath = this->makeCustomFilepath(std::string("logo") + logo_ext, this->dlcs[i], config);
this->dlcs[i].iconFilepath = this->makeCustomFilepath(std::string("icon") + icon_ext, this->dlcs[i], config);
this->dlcs[i].changelogFilepath = this->makeCustomFilepath(std::string("changelog_") + this->dlcs[i].gamename + ".html", this->dlcs[i], config);
this->dlcs[i].productJsonFilepath = this->makeCustomFilepath(std::string("product.json"), this->dlcs[i], config);
for (auto &installer : this->dlcs[i].installers)
{
subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sInstallersSubdir : "";
filepath = Util::makeFilepath(directory, this->dlcs[i].installers[j].path, this->gamename, subdir, this->dlcs[i].installers[j].platform, this->dlcs[i].gamename);
this->dlcs[i].installers[j].setFilepath(filepath);
filepath = this->makeFilepath(installer, config);
installer.setFilepath(filepath);
}
for (unsigned int j = 0; j < this->dlcs[i].patches.size(); ++j)
for (auto &extra : this->dlcs[i].extras)
{
subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sPatchesSubdir : "";
filepath = Util::makeFilepath(directory, this->dlcs[i].patches[j].path, this->gamename, subdir, this->dlcs[i].patches[j].platform, this->dlcs[i].gamename);
this->dlcs[i].patches[j].setFilepath(filepath);
filepath = this->makeFilepath(extra, config);
extra.setFilepath(filepath);
}
for (unsigned int j = 0; j < this->dlcs[i].extras.size(); ++j)
for (auto &patch : this->dlcs[i].patches)
{
subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sExtrasSubdir : "";
filepath = Util::makeFilepath(directory, this->dlcs[i].extras[j].path, this->gamename, subdir, 0, this->dlcs[i].gamename);
this->dlcs[i].extras[j].setFilepath(filepath);
filepath = this->makeFilepath(patch, config);
patch.setFilepath(filepath);
}
for (unsigned int j = 0; j < this->dlcs[i].languagepacks.size(); ++j)
for (auto &languagepack : this->dlcs[i].languagepacks)
{
subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sLanguagePackSubdir : "";
filepath = Util::makeFilepath(directory, this->dlcs[i].languagepacks[j].path, this->gamename, subdir, 0, this->dlcs[i].gamename);
this->dlcs[i].languagepacks[j].setFilepath(filepath);
filepath = this->makeFilepath(languagepack, config);
languagepack.setFilepath(filepath);
}
}
}
@ -286,3 +278,143 @@ void gameDetails::filterListWithType(std::vector<gameFile>& list, const unsigned
gf++;
}
}
std::string gameDetails::makeFilepath(const gameFile& gf, const DirectoryConfig& dirConf)
{
std::map<std::string, std::string> templates;
std::string path = gf.path;
std::string filename = path;
if (path.find_last_of("/") != std::string::npos)
filename = path.substr(path.find_last_of("/")+1, path.length());
std::string subdir;
if (dirConf.bSubDirectories)
{
if (gf.type & GlobalConstants::GFTYPE_INSTALLER)
{
subdir = dirConf.sInstallersSubdir;
}
else if (gf.type & GlobalConstants::GFTYPE_EXTRA)
{
subdir = dirConf.sExtrasSubdir;
}
else if (gf.type & GlobalConstants::GFTYPE_PATCH)
{
subdir = dirConf.sPatchesSubdir;
}
else if (gf.type & GlobalConstants::GFTYPE_LANGPACK)
{
subdir = dirConf.sLanguagePackSubdir;
}
if (gf.type & GlobalConstants::GFTYPE_DLC)
{
subdir = dirConf.sDLCSubdir + "/" + subdir;
}
if (!dirConf.sGameSubdir.empty())
{
subdir = dirConf.sGameSubdir + "/" + subdir;
}
}
std::string gamename = gf.gamename;
std::string title = gf.title;
std::string dlc_gamename;
std::string dlc_title;
if (gf.type & GlobalConstants::GFTYPE_DLC)
{
gamename = gf.gamename_basegame;
title = gf.title_basegame;
dlc_gamename = gf.gamename;
dlc_title = gf.title;
}
std::string filepath = dirConf.sDirectory + "/" + subdir + "/" + filename;
std::string platform;
for (unsigned int i = 0; i < GlobalConstants::PLATFORMS.size(); ++i)
{
if ((gf.platform & GlobalConstants::PLATFORMS[i].id) == GlobalConstants::PLATFORMS[i].id)
{
platform = boost::algorithm::to_lower_copy(GlobalConstants::PLATFORMS[i].str);
break;
}
}
if (platform.empty())
{
if (filepath.find("%gamename%/%platform%") != std::string::npos)
platform = "";
else
platform = "no_platform";
}
// Don't save certain files in "no_platform" folder
if (
filepath.rfind("/icon.png") != std::string::npos
|| filepath.rfind("/logo.jpg") != std::string::npos
|| filepath.rfind("/product.json") != std::string::npos
)
platform = "";
std::string gamename_firstletter;
if (!gamename.empty())
{
if (std::isdigit(gamename.front()))
gamename_firstletter = "0";
else
gamename_firstletter = gamename.front();
}
std::string gamename_transformed;
std::string gamename_transformed_firstletter;
if (filepath.find("%gamename_transformed%") != std::string::npos || filepath.find("%gamename_transformed_firstletter%") != std::string::npos)
{
gamename_transformed = Util::transformGamename(gamename);
if (!gamename_transformed.empty())
{
if (std::isdigit(gamename_transformed.front()))
gamename_transformed_firstletter = "0";
else
gamename_transformed_firstletter = gamename_transformed.front();
}
}
templates["%gamename%"] = gamename;
templates["%gamename_firstletter%"] = gamename_firstletter;
templates["%title%"] = title;
templates["%title_stripped%"] = Util::getStrippedString(title);
templates["%dlcname%"] = dlc_gamename;
templates["%dlc_title%"] = dlc_title;
templates["%dlc_title_stripped%"] = Util::getStrippedString(dlc_title);
templates["%platform%"] = platform;
templates["%gamename_transformed%"] = gamename_transformed;
templates["%gamename_transformed_firstletter%"] = gamename_transformed_firstletter;
for (auto t : templates)
Util::replaceAllString(filepath, t.first, t.second);
Util::replaceAllString(filepath, "//", "/"); // Replace any double slashes with single slash
return filepath;
}
std::string gameDetails::makeCustomFilepath(const std::string& filename, const gameDetails& gd, const DirectoryConfig& dirConf)
{
gameFile gf;
gf.gamename = gd.gamename;
gf.path = "/" + filename;
gf.title = gd.title;
gf.gamename_basegame = gd.gamename_basegame;
gf.title_basegame = gd.title_basegame;
if (gf.gamename_basegame.empty())
gf.type = GlobalConstants::GFTYPE_CUSTOM_BASE;
else
gf.type = GlobalConstants::GFTYPE_CUSTOM_DLC;
std::string filepath;
filepath = this->makeFilepath(gf, dirConf);
return filepath;
}

View File

@ -25,7 +25,7 @@ void gameFile::setFilepath(const std::string& path)
this->filepath = path;
}
std::string gameFile::getFilepath()
std::string gameFile::getFilepath() const
{
return this->filepath;
}
@ -43,6 +43,9 @@ Json::Value gameFile::getAsJson()
json["language"] = this->language;
json["silent"] = this->silent;
json["gamename"] = this->gamename;
json["title"] = this->title;
json["gamename_basegame"] = this->gamename_basegame;
json["title_basegame"] = this->title_basegame;
json["type"] = this->type;
json["galaxy_downlink_json_url"] = this->galaxy_downlink_json_url;
if (!this->version.empty())

View File

@ -17,49 +17,6 @@
#include <tidy.h>
#include <tidybuffio.h>
/*
Create filepath from specified directory and path
Remove the leading slash from path if needed
Use gamename as base directory if specified
*/
std::string Util::makeFilepath(const std::string& directory, const std::string& path, const std::string& gamename, std::string subdirectory, const unsigned int& platformId, const std::string& dlcname)
{
std::string dir = directory + makeRelativeFilepath(path, gamename, subdirectory);
Util::filepathReplaceReservedStrings(dir, gamename, platformId, dlcname);
return dir;
}
/* Create filepath relative to download base directory specified in config.
*/
std::string Util::makeRelativeFilepath(const std::string& path, const std::string& gamename, std::string subdirectory)
{
std::string filepath;
if (gamename.empty())
{
if (path.at(0)=='/')
{
std::string tmp_path = path.substr(1,path.length());
filepath = tmp_path;
}
else
{
filepath = path;
}
}
else
{
std::string filename = path.substr(path.find_last_of("/")+1, path.length());
if (!subdirectory.empty())
{
subdirectory = "/" + subdirectory;
}
filepath = subdirectory + "/" + filename;
}
return filepath;
}
std::string Util::getFileHash(const std::string& filename, unsigned hash_id)
{
unsigned char digest[rhash_get_digest_size(hash_id)];