Refresh data management dialogs

This commit is contained in:
Alexander Sellite 2026-09-02 07:19:25 -04:00
parent 3a61056ce5
commit cab313d69d
7 changed files with 720 additions and 103 deletions

View file

@ -117,6 +117,18 @@ func resolve() -> bool:
var expected: String = str(bootstrap.get("expected_root_id", ""))
if selected.is_empty():
return _fail("The data-folder pointer is incomplete.")
if not _validate_persistent_root_path(selected):
# A historical direct validation could leave a real bootstrap pointer
# aimed at /tmp. Do not keep retrying an unsafe location on every
# launch: leave its files alone, remove only the pointer, and return to
# the normal first-run persistent-folder choice.
_clear_bootstrap_pointer()
requires_selection = true
error_message = (
"A temporary data folder was ignored. Choose a persistent folder."
)
status_changed.emit(error_message)
return false
mode = (
Mode.APP_DATA
if selected == ProjectSettings.globalize_path(APP_DATA_PORTABLE_PATH)
@ -213,6 +225,8 @@ func select_new_root(path: String, app_data: bool = false) -> bool:
var normalized: String = _normalize(path)
if app_data:
normalized = ProjectSettings.globalize_path(APP_DATA_PORTABLE_PATH)
if not _validate_persistent_root_path(normalized):
return false
if not _validate_candidate(normalized, true):
return false
var manifest_path: String = _existing_manifest_path(normalized)
@ -277,6 +291,8 @@ func use_existing_root(path: String) -> bool:
if device_id.length() != 32:
device_id = Crypto.new().generate_random_bytes(16).hex_encode()
var normalized: String = _normalize(path)
if not _validate_persistent_root_path(normalized):
return false
if not _activate_existing(normalized, "", true):
return false
if not _write_bootstrap(root_path, root_id):
@ -370,6 +386,34 @@ func _activate_existing(path: String, expected_id: String, permit_creation: bool
return true
func _validate_persistent_root_path(path: String) -> bool:
# Test fixtures intentionally use temporary folders, but they must only be
# process-local. A real saved data-root pointer should never target a
# temporary directory that the operating system can purge at any time.
if _isolated_validation_requested():
return true
if _is_temporary_directory(path):
return _fail(
"Temporary folders cannot be used for persistent straywild data."
)
return true
static func _is_temporary_directory(path: String) -> bool:
var case_insensitive: bool = OS.get_name() == "Windows"
var normalized: String = _normalize_comparison_path(
path, case_insensitive
)
var temporary: String = _normalize_comparison_path(
OS.get_temp_dir(), case_insensitive
)
return (
not normalized.is_empty()
and not temporary.is_empty()
and (normalized == temporary or normalized.begins_with(temporary + "/"))
)
func _validate_candidate(path: String, create: bool) -> bool:
var normalized: String = _normalize(path)
if normalized.is_empty() or not normalized.is_absolute_path():
@ -512,6 +556,17 @@ func _write_bootstrap(path: String, id: String) -> bool:
)
func _clear_bootstrap_pointer() -> void:
for path: String in [
BOOTSTRAP_PATH,
BOOTSTRAP_PATH + ".backup",
BOOTSTRAP_TEMP_PATH,
]:
var absolute: String = ProjectSettings.globalize_path(path)
if FileAccess.file_exists(absolute):
DirAccess.remove_absolute(absolute)
func _load_bootstrap_identity() -> void:
var data: Dictionary = _read_json(BOOTSTRAP_PATH, 64 * 1024)
if data.is_empty():