Skip to content

Commit

Permalink
Update directory name sanitization
Browse files Browse the repository at this point in the history
Only ASCII spaces have to be handles specially, and leading spaces are
also disallowed.
  • Loading branch information
ShadowNinja authored and rubenwardy committed Apr 8, 2022
1 parent 65fdc7a commit dae6fe9
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 30 deletions.
12 changes: 8 additions & 4 deletions src/unittest/test_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,12 @@ void TestUtilities::testBase64()

void TestUtilities::testSanitizeDirName()
{
UASSERT(sanitizeDirName("a", "_") == "a");
UASSERT(sanitizeDirName("COM1", "_") == "_COM1");
UASSERT(sanitizeDirName("cOm\u00B2 .txt:a", "_") == "cOm\u00B2 _txt_a");
UASSERT(sanitizeDirName("cOnIn$ ", "_") == "_cOnIn$ ");
UASSERT(sanitizeDirName("a", "~") == "a");
UASSERT(sanitizeDirName(" ", "~") == "__");
UASSERT(sanitizeDirName(" a ", "~") == "_a_");
UASSERT(sanitizeDirName("COM1", "~") == "~COM1");
UASSERT(sanitizeDirName("COM1", ":") == "_COM1");
UASSERT(sanitizeDirName("cOm\u00B2", "~") == "~cOm\u00B2");
UASSERT(sanitizeDirName("cOnIn$", "~") == "~cOnIn$");
UASSERT(sanitizeDirName(" cOnIn$ ", "~") == "_cOnIn$_");
}
39 changes: 14 additions & 25 deletions src/util/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -864,40 +864,29 @@ static const std::array<std::wstring, 30> disallowed_dir_names = {
static const std::wstring disallowed_path_chars = L"<>:\"/\\|?*.";


/**
* @param str
* @return A copy of \p str with trailing whitespace removed.
*/
static std::wstring wrtrim(const std::wstring &str)
{
size_t back = str.size();
while (back > 0 && std::isspace(str[back - 1]))
--back;

return str.substr(0, back);
}


/**
* Sanitize the name of a new directory. This consists of two stages:
* 1. Check for 'reserved filenames' that can't be used on some filesystems
* and add a prefix to them
* 2. Remove 'unsafe' characters from the name by replacing them with '_'
*/
std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix)
{
std::wstring safe_name = utf8_to_wide(str);

std::wstring dev_name = wrtrim(safe_name);

for (std::wstring disallowed_name : disallowed_dir_names) {
if (str_equal(dev_name, disallowed_name, true)) {
if (str_equal(safe_name, disallowed_name, true)) {
safe_name = utf8_to_wide(optional_prefix) + safe_name;
break;
}
}

for (unsigned long i = 0; i < safe_name.length(); i++) {
// Replace leading and trailing spaces with underscores.
size_t start = safe_name.find_first_not_of(L' ');
size_t end = safe_name.find_last_not_of(L' ');
if (start == std::wstring::npos || end == std::wstring::npos)
start = end = safe_name.size();
for (size_t i = 0; i < start; i++)
safe_name[i] = L'_';
for (size_t i = end + 1; i < safe_name.size(); i++)
safe_name[i] = L'_';

// Replace other disallowed characters with underscores
for (size_t i = 0; i < safe_name.length(); i++) {
bool is_valid = true;

// Unlikely, but control characters should always be blacklisted
Expand All @@ -909,7 +898,7 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
}

if (!is_valid)
safe_name[i] = '_';
safe_name[i] = L'_';
}

return wide_to_utf8(safe_name);
Expand Down
2 changes: 1 addition & 1 deletion src/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ inline irr::core::stringw utf8_to_stringw(const std::string &input)
/**
* Sanitize the name of a new directory. This consists of two stages:
* 1. Check for 'reserved filenames' that can't be used on some filesystems
* and prefix them
* and add a prefix to them
* 2. Remove 'unsafe' characters from the name by replacing them with '_'
*/
std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix);
Expand Down

0 comments on commit dae6fe9

Please sign in to comment.