aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorHugues Ross <hugues.ross@gmail.com>2020-07-28 13:16:57 -0400
committerGitHub <noreply@github.com>2020-07-28 19:16:57 +0200
commit3ce03d1c2a63d261c83f5962cd13212697f19472 (patch)
treef7c7db205866254865d18c711682c984c062b9cc /src/util
parentf948e2c58570df6bc77226b6066fec5ed90051ee (diff)
downloadminetest-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.cpp68
-rw-r--r--src/util/string.h8
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);