GameList: URL encode custom properties paths with brackets

Fixes custom properties not applying on restart to games with
brackets in their paths.
This commit is contained in:
Stenzek 2025-01-20 21:59:22 +10:00
parent 4b20fc6922
commit 17b0da7283
No known key found for this signature in database

View File

@ -118,6 +118,7 @@ static PlayedTimeEntry UpdatePlayedTimeFile(const std::string& path, const std::
std::time_t add_time); std::time_t add_time);
static std::string GetCustomPropertiesFile(); static std::string GetCustomPropertiesFile();
static const std::string& GetCustomPropertiesSection(const std::string& path, std::string* temp_path);
static bool PutCustomPropertiesField(INISettingsInterface& ini, const std::string& path, const char* field, static bool PutCustomPropertiesField(INISettingsInterface& ini, const std::string& path, const char* field,
const char* value); const char* value);
@ -624,14 +625,17 @@ bool GameList::RescanCustomAttributesForPath(const std::string& path, const INIS
void GameList::ApplyCustomAttributes(const std::string& path, Entry* entry, void GameList::ApplyCustomAttributes(const std::string& path, Entry* entry,
const INISettingsInterface& custom_attributes_ini) const INISettingsInterface& custom_attributes_ini)
{ {
std::optional<std::string> custom_title = custom_attributes_ini.GetOptionalStringValue(path.c_str(), "Title"); std::string temp_path;
const std::string& section = GetCustomPropertiesSection(path, &temp_path);
std::optional<std::string> custom_title = custom_attributes_ini.GetOptionalStringValue(section.c_str(), "Title");
if (custom_title.has_value()) if (custom_title.has_value())
{ {
entry->title = std::move(custom_title.value()); entry->title = std::move(custom_title.value());
entry->has_custom_title = true; entry->has_custom_title = true;
} }
const std::optional<SmallString> custom_region_str = const std::optional<SmallString> custom_region_str =
custom_attributes_ini.GetOptionalSmallStringValue(path.c_str(), "Region"); custom_attributes_ini.GetOptionalSmallStringValue(section.c_str(), "Region");
if (custom_region_str.has_value()) if (custom_region_str.has_value())
{ {
const std::optional<DiscRegion> custom_region = Settings::ParseDiscRegionName(custom_region_str.value()); const std::optional<DiscRegion> custom_region = Settings::ParseDiscRegionName(custom_region_str.value());
@ -646,7 +650,7 @@ void GameList::ApplyCustomAttributes(const std::string& path, Entry* entry,
} }
} }
const std::optional<TinyString> custom_language_str = const std::optional<TinyString> custom_language_str =
custom_attributes_ini.GetOptionalTinyStringValue(path.c_str(), "Language"); custom_attributes_ini.GetOptionalTinyStringValue(section.c_str(), "Language");
if (custom_language_str.has_value()) if (custom_language_str.has_value())
{ {
const std::optional<GameDatabase::Language> custom_region = const std::optional<GameDatabase::Language> custom_region =
@ -1550,18 +1554,31 @@ std::string GameList::GetCustomPropertiesFile()
return Path::Combine(EmuFolders::DataRoot, "custom_properties.ini"); return Path::Combine(EmuFolders::DataRoot, "custom_properties.ini");
} }
const std::string& GameList::GetCustomPropertiesSection(const std::string& path, std::string* temp_path)
{
// pretty much everything is fine in an ini section, except for square brackets.
if (path.find_first_of("[]") == std::string::npos)
return path;
// otherwise, URLencode it
return (*temp_path = Path::URLEncode(path));
}
bool GameList::PutCustomPropertiesField(INISettingsInterface& ini, const std::string& path, const char* field, bool GameList::PutCustomPropertiesField(INISettingsInterface& ini, const std::string& path, const char* field,
const char* value) const char* value)
{ {
ini.Load(); ini.Load();
std::string temp_path;
const std::string& section = GetCustomPropertiesSection(path, &temp_path);
if (value && *value != '\0') if (value && *value != '\0')
{ {
ini.SetStringValue(path.c_str(), field, value); ini.SetStringValue(section.c_str(), field, value);
} }
else else
{ {
ini.DeleteValue(path.c_str(), field); ini.DeleteValue(section.c_str(), field);
ini.RemoveEmptySections(); ini.RemoveEmptySections();
} }