From af9c67db0c998bbd6f0de1ab0af98f9e615e6029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 26 Nov 2017 19:00:53 +0100 Subject: [PATCH] Allow customizing user:// path (folder in OS::get_data_path()) This allows to specify any valid folder name (including with subfolders) to use as user:// on all platforms. The folder is constrained to the platform-specific OS::get_data_path() (typically what `XDG_DATA_HOME` resolves to). Fixes #13236. --- core/error_macros.cpp | 2 +- core/os/os.cpp | 22 +++++++++++++++------- core/os/os.h | 2 +- core/project_settings.cpp | 3 ++- drivers/unix/os_unix.cpp | 14 +++++++++----- platform/windows/os_windows.cpp | 15 +++++++++------ 6 files changed, 37 insertions(+), 21 deletions(-) diff --git a/core/error_macros.cpp b/core/error_macros.cpp index 7d85aa90015..a942b1dd2d5 100644 --- a/core/error_macros.cpp +++ b/core/error_macros.cpp @@ -101,6 +101,6 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal) { String fstr(fatal ? "FATAL: " : ""); - String err(fstr + "Index" + p_index_str + "=" + itos(p_index) + " out of size (" + p_size_str + "=" + itos(p_size) + ")"); + String err(fstr + "Index " + p_index_str + "=" + itos(p_index) + " out of size (" + p_size_str + "=" + itos(p_size) + ")"); _err_print_error(p_function, p_file, p_line, err.utf8().get_data()); } diff --git a/core/os/os.cpp b/core/os/os.cpp index a39dfcc003c..8088a6fa746 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -279,14 +279,22 @@ String OS::get_locale() const { return "en"; } -// Helper function used by OS_Unix and OS_Windows -String OS::get_safe_application_name() const { - String an = ProjectSettings::get_singleton()->get("application/config/name"); - Vector invalid_char = String("\\ / : * ? \" < > |").split(" "); - for (int i = 0; i < invalid_char.size(); i++) { - an = an.replace(invalid_char[i], "-"); +// Helper function to ensure that a dir name/path will be valid on the OS +String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const { + + Vector invalid_chars = String(": * ? \" < > |").split(" "); + if (p_allow_dir_separator) { + // Dir separators are allowed, but disallow ".." to avoid going up the filesystem + invalid_chars.push_back(".."); + } else { + invalid_chars.push_back("/"); } - return an; + + String safe_dir_name = p_dir_name.replace("\\", "/").strip_edges(); + for (int i = 0; i < invalid_chars.size(); i++) { + safe_dir_name = safe_dir_name.replace(invalid_chars[i], "-"); + } + return safe_dir_name; } // Path to data, config, cache, etc. OS-specific folders diff --git a/core/os/os.h b/core/os/os.h index d7a1512e39b..c72696fe373 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -338,7 +338,7 @@ public: virtual String get_locale() const; - String get_safe_application_name() const; + String get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator = false) const; virtual String get_godot_dir_name() const; virtual String get_data_path() const; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 13340535b52..67b081de34c 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -891,7 +891,8 @@ ProjectSettings::ProjectSettings() { custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "tscn,scn,res"); GLOBAL_DEF("application/run/disable_stdout", false); GLOBAL_DEF("application/run/disable_stderr", false); - GLOBAL_DEF("application/config/use_shared_user_dir", true); + GLOBAL_DEF("application/config/use_custom_user_dir", false); + GLOBAL_DEF("application/config/custom_user_dir_name", ""); key.instance(); key->set_scancode(KEY_ENTER); diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 0d102902e84..0b1aebaaabd 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -447,13 +447,17 @@ int OS_Unix::get_processor_count() const { String OS_Unix::get_user_data_dir() const { - String appname = get_safe_application_name(); + String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name")); if (appname != "") { - bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir"); - if (use_godot_dir) { - return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname); + bool use_custom_dir = ProjectSettings::get_singleton()->get("application/config/use_custom_user_dir"); + if (use_custom_dir) { + String custom_dir = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/custom_user_dir_name"), true); + if (custom_dir == "") { + custom_dir = appname; + } + return get_data_path().plus_file(custom_dir); } else { - return get_data_path().plus_file(appname); + return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname); } } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 827189bb4fe..284dfaf9048 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -2199,14 +2199,17 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const { String OS_Windows::get_user_data_dir() const { - String appname = get_safe_application_name(); + String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name")); if (appname != "") { - - bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir"); - if (use_godot_dir) { - return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname).replace("\\", "/"); + bool use_custom_dir = ProjectSettings::get_singleton()->get("application/config/use_custom_user_dir"); + if (use_custom_dir) { + String custom_dir = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/custom_user_dir_name"), true); + if (custom_dir == "") { + custom_dir = appname; + } + return get_data_path().plus_file(custom_dir).replace("\\", "/"); } else { - return get_data_path().plus_file(appname).replace("\\", "/"); + return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname).replace("\\", "/"); } }