This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new d68078d9f fix(services/webdav): decode path before set Entry (#3020)
d68078d9f is described below

commit d68078d9f568c3d56f0600abcbac998b32ff4404
Author: G-XD <[email protected]>
AuthorDate: Thu Sep 7 19:08:00 2023 +0800

    fix(services/webdav): decode path before set Entry (#3020)
---
 core/src/raw/http_util/mod.rs     |  1 +
 core/src/raw/http_util/uri.rs     | 50 +++++++++++++++++++++++++++++++++++++++
 core/src/services/webdav/pager.rs |  6 +++--
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/core/src/raw/http_util/mod.rs b/core/src/raw/http_util/mod.rs
index 2d6946db7..0bf62ee93 100644
--- a/core/src/raw/http_util/mod.rs
+++ b/core/src/raw/http_util/mod.rs
@@ -45,6 +45,7 @@ pub use header::parse_last_modified;
 pub use header::parse_location;
 
 mod uri;
+pub use uri::percent_decode_path;
 pub use uri::percent_encode_path;
 
 mod error;
diff --git a/core/src/raw/http_util/uri.rs b/core/src/raw/http_util/uri.rs
index e40349642..1f3b893e0 100644
--- a/core/src/raw/http_util/uri.rs
+++ b/core/src/raw/http_util/uri.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use percent_encoding::percent_decode_str;
 use percent_encoding::utf8_percent_encode;
 use percent_encoding::AsciiSet;
 use percent_encoding::NON_ALPHANUMERIC;
@@ -47,6 +48,16 @@ pub fn percent_encode_path(path: &str) -> String {
     utf8_percent_encode(path, &PATH_ENCODE_SET).to_string()
 }
 
+/// percent_decode_path will do percent decoding for http decode path.
+///
+/// If the input is not percent encoded or not valid utf8, return the input.
+pub fn percent_decode_path(path: &str) -> String {
+    match percent_decode_str(path).decode_utf8() {
+        Ok(v) => v.to_string(),
+        Err(_) => path.to_string(),
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -79,4 +90,43 @@ mod tests {
             assert_eq!(actual, expected, "{name}");
         }
     }
+
+    #[test]
+    fn test_percent_decode_path() {
+        let cases = vec![
+            (
+                "Reserved Characters",
+                "%3B%2C/%3F%3A%40%26%3D%2B%24",
+                ";,/?:@&=+$",
+            ),
+            ("Unescaped Characters", "-_.!~*'()", "-_.!~*'()"),
+            ("Number Sign", "%23", "#"),
+            (
+                "Alphanumeric Characters + Space",
+                "ABC%20abc%20123",
+                "ABC abc 123",
+            ),
+            (
+                "Unicode Characters",
+                
"%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C%EF%BC%81%E2%9D%A4",
+                "你好,世界!❤",
+            ),
+            (
+                "Double Encoded Characters",
+                "Double%2520Encoded",
+                "Double%20Encoded",
+            ),
+            (
+                "Not Percent Encoded Characters",
+                "/not percent encoded/path;,/?:@&=+$-",
+                "/not percent encoded/path;,/?:@&=+$-",
+            ),
+        ];
+
+        for (name, input, expected) in cases {
+            let actual = percent_decode_path(input);
+
+            assert_eq!(actual, expected, "{name}");
+        }
+    }
 }
diff --git a/core/src/services/webdav/pager.rs 
b/core/src/services/webdav/pager.rs
index 03195c069..519cae33f 100644
--- a/core/src/services/webdav/pager.rs
+++ b/core/src/services/webdav/pager.rs
@@ -62,13 +62,15 @@ impl oio::Page for WebdavPager {
             }
 
             let normalized_path = build_rel_path(&self.root, path);
-            if normalized_path == self.path {
+            let decoded_path = percent_decode_path(normalized_path.as_str());
+
+            if normalized_path == self.path || decoded_path == self.path {
                 // WebDav server may return the current path as an entry.
                 continue;
             }
 
             let meta = res.parse_into_metadata()?;
-            entries.push(oio::Entry::new(&normalized_path, meta))
+            entries.push(oio::Entry::new(&decoded_path, meta))
         }
 
         Ok(Some(entries))

Reply via email to