Correct logic for sanitize_string_for_path. Fixes #286 and compatibility with Pokemon games from master branch.

This commit is contained in:
J-D-K 2025-09-06 20:14:28 -04:00
parent e658545a48
commit 8653e9b033
8 changed files with 44 additions and 37 deletions

@ -1 +1 @@
Subproject commit 30f56742733a350a1f4788d6fa2bcf26712ae669
Subproject commit 4fb3633139d4b259d63a2257ff7945b7ac542a5b

View File

@ -181,7 +181,7 @@ bool JKSV::initialize_sdl()
bool JKSV::create_directories()
{
// Working directory creation.
const fslib::Path workDir = config::get_working_directory();
const fslib::Path workDir{config::get_working_directory()};
const bool needsWorkDir = !fslib::directory_exists(workDir);
const bool workDirCreated = needsWorkDir && fslib::create_directories_recursively(workDir);
if (needsWorkDir && !workDirCreated) { return false; }

View File

@ -297,7 +297,7 @@ void BackupMenuState::confirm_restore()
{
const char *popBackupEmpty = strings::get_by_name(strings::names::BACKUPMENU_POPS, 1);
const fslib::Path target = m_directoryPath / m_directoryListing[entry.index];
const fslib::Path target{m_directoryPath / m_directoryListing[entry.index]};
const bool targetIsDirectory = fslib::directory_exists(target);
const bool backupIsGood = targetIsDirectory ? fs::directory_has_contents(target) : fs::zip_has_contents(target);
if (!backupIsGood)
@ -359,9 +359,8 @@ void BackupMenuState::upload_backup()
const MenuEntry &entry = m_menuEntries[selected];
if (entry.type != BackupMenuState::MenuEntryType::Local) { return; }
const char *targetName = m_directoryListing[entry.index].get_filename();
fslib::Path target = m_directoryPath / targetName;
const bool isDir = fslib::directory_exists(target);
fslib::Path target{m_directoryPath / m_directoryListing[entry.index]};
const bool isDir = fslib::directory_exists(target);
if (isDir)
{
const char *popNotZip = strings::get_by_name(strings::names::BACKUPMENU_POPS, 13);

View File

@ -172,11 +172,11 @@ void TitleOptionState::change_output_directory()
return;
}
const fslib::Path workDir = config::get_working_directory();
const fslib::Path oldPath = workDir / pathSafe;
const fslib::Path newPath = workDir / pathBuffer.data();
const bool oldExists = fslib::directory_exists(oldPath);
const bool renameFailed = oldExists && error::fslib(fslib::rename_directory(oldPath, newPath));
const fslib::Path workDir{config::get_working_directory()};
const fslib::Path oldPath{workDir / pathSafe};
const fslib::Path newPath{workDir / pathBuffer.data()};
const bool oldExists = fslib::directory_exists(oldPath);
const bool renameFailed = oldExists && error::fslib(fslib::rename_directory(oldPath, newPath));
if (oldExists && renameFailed) { ui::PopMessageManager::push_message(popTicks, popFailed); }
// Need to change WebDav to match.
@ -307,8 +307,8 @@ void TitleOptionState::export_svi_file()
const uint64_t applicationID = m_titleInfo->get_application_id();
const std::string titleIdHex = stringutil::get_formatted_string("%016llX", applicationID);
const fslib::Path sviDir = config::get_working_directory() / "svi";
const fslib::Path sviPath = sviDir / titleIdHex + ".svi";
const fslib::Path sviDir{config::get_working_directory() / "svi"};
const fslib::Path sviPath{sviDir / titleIdHex + ".svi"};
const bool dirExists = fslib::directory_exists(sviDir);
const bool createError = !dirExists && error::fslib(fslib::create_directory(sviDir));

View File

@ -106,7 +106,7 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
// This is needed to preserve empty directories.
if (sourceDir.get_count() <= 0)
{
const fslib::Path saveMe = source / NAME_SAVE_ME;
const fslib::Path saveMe{source / NAME_SAVE_ME};
dest.open_new_file(saveMe.get_path());
dest.close_current_file();
return;

View File

@ -51,30 +51,38 @@ void stringutil::strip_character(char c, std::string &target)
bool stringutil::sanitize_string_for_path(const char *stringIn, char *stringOut, size_t stringOutSize)
{
uint32_t codepoint{};
const size_t length = std::char_traits<char>::length(stringIn);
for (size_t i = 0, offset = 0; i < length;)
{
const uint8_t *point = reinterpret_cast<const uint8_t *>(&stringIn[i]);
const ssize_t count = decode_utf8(&codepoint, point);
const bool countCheck = count <= 0 || i + count >= stringOutSize;
const bool codeCheck = codepoint < 0x20 || codepoint > 0x7E;
if (countCheck) { break; }
else if (codepoint == L'é') { stringOut[offset++] = 'e'; }
else if (codeCheck) { return false; }
const int length = std::char_traits<char>::length(stringIn);
const bool forbidden = std::find(FORBIDDEN_PATH_CHARACTERS.begin(), FORBIDDEN_PATH_CHARACTERS.end(), codepoint) !=
FORBIDDEN_PATH_CHARACTERS.end();
if (forbidden) { stringOut[offset++] = 0x20; }
for (int i = 0, outOffset = 0; i < length;)
{
const uint8_t *point = reinterpret_cast<const uint8_t *>(&stringIn[i]);
const ssize_t count = decode_utf8(&codepoint, point);
if (count <= 0 || i + count >= static_cast<int>(stringOutSize)) { return false; }
if (codepoint == L'é')
{
stringOut[outOffset++] = 'e';
i += count;
continue;
}
const bool asciiCheck = codepoint < 0x0 || codepoint >= 0x7E;
if (asciiCheck) { return false; }
const bool isForbidden = std::find(FORBIDDEN_PATH_CHARACTERS.begin(), FORBIDDEN_PATH_CHARACTERS.end(), codepoint) !=
FORBIDDEN_PATH_CHARACTERS.end();
if (isForbidden) { stringOut[outOffset++] = 0x20; }
else
{
std::memcpy(&stringOut[offset], &stringIn[i], static_cast<size_t>(count));
offset += count;
std::memcpy(&stringOut[outOffset], &stringIn[i], static_cast<size_t>(count));
outOffset += count;
}
i += count;
}
const int outLength = std::char_traits<char>::length(stringOut) - 1;
for (int i = outLength; i > 0 && (stringOut[i] == ' ' || stringOut[i] == '.'); --i) { stringOut[i] = '\0'; }
for (int i = outLength; i-- > 0 && (stringOut[i] == ' ' || stringOut[i] == '.');) { stringOut[i] = '\0'; }
return true;
}

View File

@ -34,10 +34,10 @@ void tasks::mainmenu::backup_all_for_all_local(sys::ProgressTask *task, MainMenu
data::TitleInfo *titleInfo = data::get_title_info_by_id(applicationID);
if (error::is_null(titleInfo)) { continue; }
const fslib::Path workDir = config::get_working_directory();
const fslib::Path targetDir = workDir / titleInfo->get_path_safe_title();
const bool exists = fslib::directory_exists(targetDir);
const bool createError = !exists && error::fslib(fslib::create_directories_recursively(targetDir));
const fslib::Path workDir{config::get_working_directory()};
const fslib::Path targetDir{workDir / titleInfo->get_path_safe_title()};
const bool exists = fslib::directory_exists(targetDir);
const bool createError = !exists && error::fslib(fslib::create_directories_recursively(targetDir));
if (!exists && createError) { continue; }
const char *pathSafe = user->get_path_safe_nickname();

View File

@ -16,9 +16,9 @@ void tasks::useroptions::backup_all_for_user_local(sys::ProgressTask *task, User
data::User *user = taskData->user;
if (error::is_null(user)) { TASK_FINISH_RETURN(task); }
const fslib::Path workDir = config::get_working_directory();
const bool exportToZip = config::get_by_key(config::keys::EXPORT_TO_ZIP);
const int titleCount = user->get_total_data_entries();
const fslib::Path workDir{config::get_working_directory()};
const bool exportToZip = config::get_by_key(config::keys::EXPORT_TO_ZIP);
const int titleCount = user->get_total_data_entries();
for (int i = 0; i < titleCount; i++)
{
const FsSaveDataInfo *saveInfo = user->get_save_info_at(i);