diff options
author | Hugues Ross <hugues.ross@gmail.com> | 2020-07-28 13:16:57 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-28 19:16:57 +0200 |
commit | 3ce03d1c2a63d261c83f5962cd13212697f19472 (patch) | |
tree | f7c7db205866254865d18c711682c984c062b9cc /src/util | |
parent | f948e2c58570df6bc77226b6066fec5ed90051ee (diff) | |
download | minetest-3ce03d1c2a63d261c83f5962cd13212697f19472.tar.gz minetest-3ce03d1c2a63d261c83f5962cd13212697f19472.tar.bz2 minetest-3ce03d1c2a63d261c83f5962cd13212697f19472.zip |
Sanitize world directory names on create. Keep original name separate (#9432)
Blacklisted characters are replaced by '_' in the path. The display name is stored in world.mt, and duplicate file names are resolved by adding an incrementing suffix (_1, _2, _3, etc).
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/string.cpp | 68 | ||||
-rw-r--r-- | src/util/string.h | 8 |
2 files changed, 76 insertions, 0 deletions
diff --git a/src/util/string.cpp b/src/util/string.cpp index 6e1db798c..8381a29c5 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "translation.h" #include <algorithm> +#include <array> #include <sstream> #include <iomanip> #include <map> @@ -889,3 +890,70 @@ std::wstring translate_string(const std::wstring &s) return translate_string(s, g_client_translations); #endif } + +static const std::array<std::wstring, 22> disallowed_dir_names = { + // Problematic filenames from here: + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#file-and-directory-names + L"CON", + L"PRN", + L"AUX", + L"NUL", + L"COM1", + L"COM2", + L"COM3", + L"COM4", + L"COM5", + L"COM6", + L"COM7", + L"COM8", + L"COM9", + L"LPT1", + L"LPT2", + L"LPT3", + L"LPT4", + L"LPT5", + L"LPT6", + L"LPT7", + L"LPT8", + L"LPT9", +}; + +/** + * List of characters that are blacklisted from created directories + */ +static const std::wstring disallowed_path_chars = L"<>:\"/\\|?*."; + +/** + * 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); + + for (std::wstring disallowed_name : disallowed_dir_names) { + 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++) { + bool is_valid = true; + + // Unlikely, but control characters should always be blacklisted + if (safe_name[i] < 32) { + is_valid = false; + } else if (safe_name[i] < 128) { + is_valid = disallowed_path_chars.find_first_of(safe_name[i]) + == std::wstring::npos; + } + + if (!is_valid) + safe_name[i] = '_'; + } + + return wide_to_utf8(safe_name); +} diff --git a/src/util/string.h b/src/util/string.h index 185fb55e2..6fd11fadc 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -746,3 +746,11 @@ inline irr::core::stringw utf8_to_stringw(const std::string &input) std::wstring str = utf8_to_wide(input); return irr::core::stringw(str.c_str()); } + +/** + * 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 + * 2. Remove 'unsafe' characters from the name by replacing them with '_' + */ +std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix); |