From 0fb307720c0bf70466935334facbe109a5a4d20a Mon Sep 17 00:00:00 2001
From: jpcerrone <jpcerronex@gmail.com>
Date: Mon, 22 May 2023 15:03:05 -0300
Subject: [PATCH] PCK file path improvements

Fixes godotengine#77317 (Inconsistent PCK file path behaviour).
Simplifies all PCK file paths so that paths with extra '/' symbols in them
still match to the same path.
Fixes various FileAccess methods that didn't work when using PCK paths that
contain extra '/' symbols.
---
 core/io/file_access_pack.cpp | 7 ++++---
 core/io/file_access_pack.h   | 5 +++--
 core/io/pck_packer.cpp       | 4 +++-
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 88a906a38e3..74c5c1c1910 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -48,7 +48,8 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t
 }
 
 void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) {
-	PathMD5 pmd5(p_path.md5_buffer());
+	String simplified_path = p_path.simplify_path();
+	PathMD5 pmd5(simplified_path.md5_buffer());
 
 	bool exists = files.has(pmd5);
 
@@ -68,7 +69,7 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64
 
 	if (!exists) {
 		//search for dir
-		String p = p_path.replace_first("res://", "");
+		String p = simplified_path.replace_first("res://", "");
 		PackedDir *cd = root;
 
 		if (p.contains("/")) { //in a subdir
@@ -87,7 +88,7 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64
 				}
 			}
 		}
-		String filename = p_path.get_file();
+		String filename = simplified_path.get_file();
 		// Don't add as a file if the path points to a directory
 		if (!filename.is_empty()) {
 			cd->files.insert(filename);
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 8bfabc9529c..1538b302c29 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -184,7 +184,8 @@ public:
 };
 
 Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
-	PathMD5 pmd5(p_path.md5_buffer());
+	String simplified_path = p_path.simplify_path();
+	PathMD5 pmd5(simplified_path.md5_buffer());
 	HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
 	if (!E) {
 		return nullptr; //not found
@@ -197,7 +198,7 @@ Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
 }
 
 bool PackedData::has_path(const String &p_path) {
-	return files.has(PathMD5(p_path.md5_buffer()));
+	return files.has(PathMD5(p_path.simplify_path().md5_buffer()));
 }
 
 bool PackedData::has_directory(const String &p_path) {
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index e7f4980e94a..9b49cc3d8c7 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -115,7 +115,9 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
 	}
 
 	File pf;
-	pf.path = p_file;
+	// Simplify path here and on every 'files' access so that paths that have extra '/'
+	// symbols in them still match to the MD5 hash for the saved path.
+	pf.path = p_file.simplify_path();
 	pf.src_path = p_src;
 	pf.ofs = ofs;
 	pf.size = f->get_length();