فهرست منبع

fix(core): scope checks on Android (#8420)

* fix(core): scope checks on Android

On Android, when we call canonicalize() on "/data/user/0/appid" (which is the data dir), the result is a "/data/data/appid" path, so we need to adjust our scope for that.

* clarify code

* apply the logic to all targets
Lucas Fernandes Nogueira 1 سال پیش
والد
کامیت
effe5871af
2فایلهای تغییر یافته به همراه50 افزوده شده و 5 حذف شده
  1. 5 0
      .changes/fix-android-scope.md
  2. 45 5
      core/tauri/src/scope/fs.rs

+ 5 - 0
.changes/fix-android-scope.md

@@ -0,0 +1,5 @@
+---
+"tauri": patch:bug
+---
+
+Fixes file scope checks on Android.

+ 45 - 5
core/tauri/src/scope/fs.rs

@@ -79,14 +79,54 @@ fn push_pattern<P: AsRef<Path>, F: Fn(&str) -> Result<Pattern, glob::PatternErro
 ) -> crate::Result<()> {
   let path: PathBuf = pattern.as_ref().components().collect();
   list.insert(f(&path.to_string_lossy())?);
-  #[cfg(windows)]
-  {
-    if let Ok(p) = std::fs::canonicalize(&path) {
-      list.insert(f(&p.to_string_lossy())?);
+
+  let mut path = path;
+  let mut checked_path = None;
+
+  // attempt to canonicalize parents in case we have a path like `/data/user/0/appid/**`
+  // where `**` obviously does not exist but we need to canonicalize the parent
+  //
+  // example: given the `/data/user/0/appid/assets/*` path,
+  // it's a glob pattern so it won't exist (canonicalize() fails);
+  //
+  // the second iteration needs to check `/data/user/0/appid/assets` and save the `*` component to append later.
+  //
+  // if it also does not exist, a third iteration is required to check `/data/user/0/appid`
+  // with `assets/*` as the cached value (`checked_path` variable)
+  // on Android that gets canonicalized to `/data/data/appid` so the final value will be `/data/data/appid/assets/*`
+  // which is the value we want to check when we execute the `is_allowed` function
+  let canonicalized = loop {
+    if let Ok(path) = path.canonicalize() {
+      break Some(if let Some(p) = checked_path {
+        path.join(p)
+      } else {
+        path
+      });
+    }
+
+    // get the last component of the path as an OsStr
+    let last = path.iter().next_back().map(PathBuf::from);
+    if let Some(mut p) = last {
+      // remove the last component of the path
+      // so the next iteration checks its parent
+      path.pop();
+      // append the already checked path to the last component
+      if let Some(checked_path) = &checked_path {
+        p.push(checked_path);
+      }
+      // replace the checked path with the current value
+      checked_path.replace(p);
     } else {
-      list.insert(f(&format!("\\\\?\\{}", path.display()))?);
+      break None;
     }
+  };
+
+  if let Some(p) = canonicalized {
+    list.insert(f(&p.to_string_lossy())?);
+  } else if cfg!(windows) {
+    list.insert(f(&format!("\\\\?\\{}", path.display()))?);
   }
+
   Ok(())
 }