Browse Source

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.
Rémi Verschelde 7 years ago
parent
commit
af9c67db0c
6 changed files with 37 additions and 21 deletions
  1. 1 1
      core/error_macros.cpp
  2. 15 7
      core/os/os.cpp
  3. 1 1
      core/os/os.h
  4. 2 1
      core/project_settings.cpp
  5. 9 5
      drivers/unix/os_unix.cpp
  6. 9 6
      platform/windows/os_windows.cpp

+ 1 - 1
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) {
 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 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());
 	_err_print_error(p_function, p_file, p_line, err.utf8().get_data());
 }
 }

+ 15 - 7
core/os/os.cpp

@@ -279,14 +279,22 @@ String OS::get_locale() const {
 	return "en";
 	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<String> 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<String> 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("/");
+	}
+
+	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 an;
+	return safe_dir_name;
 }
 }
 
 
 // Path to data, config, cache, etc. OS-specific folders
 // Path to data, config, cache, etc. OS-specific folders

+ 1 - 1
core/os/os.h

@@ -338,7 +338,7 @@ public:
 
 
 	virtual String get_locale() const;
 	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_godot_dir_name() const;
 
 
 	virtual String get_data_path() const;
 	virtual String get_data_path() const;

+ 2 - 1
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");
 	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_stdout", false);
 	GLOBAL_DEF("application/run/disable_stderr", 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.instance();
 	key->set_scancode(KEY_ENTER);
 	key->set_scancode(KEY_ENTER);

+ 9 - 5
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 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 != "") {
 	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 {
 		} 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);
 		}
 		}
 	}
 	}
 
 

+ 9 - 6
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 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 != "") {
 	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 {
 		} 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("\\", "/");
 		}
 		}
 	}
 	}