mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-08-17 19:07:12 +02:00
fix(fs)!: use tauri::scope::fs::Scope (#2070)
This commit is contained in:
+63
-20
@@ -16,13 +16,13 @@ use std::{
|
||||
borrow::Cow,
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Read, Write},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
sync::Mutex,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use crate::{scope::Entry, Error, FsExt, SafeFilePath};
|
||||
use crate::{scope::Entry, Error, SafeFilePath};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CommandError {
|
||||
@@ -942,6 +942,8 @@ pub fn resolve_file<R: Runtime>(
|
||||
path: SafeFilePath,
|
||||
open_options: OpenOptions,
|
||||
) -> CommandResult<(File, PathBuf)> {
|
||||
use crate::FsExt;
|
||||
|
||||
match path {
|
||||
SafeFilePath::Url(url) => {
|
||||
let path = url.as_str().into();
|
||||
@@ -974,40 +976,81 @@ pub fn resolve_path<R: Runtime>(
|
||||
path
|
||||
};
|
||||
|
||||
let fs_scope = webview.state::<crate::Scope>();
|
||||
|
||||
let scope = tauri::scope::fs::Scope::new(
|
||||
webview,
|
||||
&FsScope::Scope {
|
||||
allow: webview
|
||||
.fs_scope()
|
||||
.allowed
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.chain(global_scope.allows().iter().filter_map(|e| e.path.clone()))
|
||||
allow: global_scope
|
||||
.allows()
|
||||
.iter()
|
||||
.filter_map(|e| e.path.clone())
|
||||
.chain(command_scope.allows().iter().filter_map(|e| e.path.clone()))
|
||||
.collect(),
|
||||
deny: webview
|
||||
.fs_scope()
|
||||
.denied
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.chain(global_scope.denies().iter().filter_map(|e| e.path.clone()))
|
||||
deny: global_scope
|
||||
.denies()
|
||||
.iter()
|
||||
.filter_map(|e| e.path.clone())
|
||||
.chain(command_scope.denies().iter().filter_map(|e| e.path.clone()))
|
||||
.collect(),
|
||||
require_literal_leading_dot: webview.fs_scope().require_literal_leading_dot,
|
||||
require_literal_leading_dot: fs_scope.require_literal_leading_dot,
|
||||
},
|
||||
)?;
|
||||
|
||||
if scope.is_allowed(&path) {
|
||||
let require_literal_leading_dot = fs_scope.require_literal_leading_dot.unwrap_or(cfg!(unix));
|
||||
|
||||
if is_forbidden(&fs_scope.scope, &path, require_literal_leading_dot)
|
||||
|| is_forbidden(&scope, &path, require_literal_leading_dot)
|
||||
{
|
||||
return Err(CommandError::Plugin(Error::PathForbidden(path)));
|
||||
}
|
||||
|
||||
if fs_scope.scope.is_allowed(&path) || scope.is_allowed(&path) {
|
||||
Ok(path)
|
||||
} else {
|
||||
Err(CommandError::Plugin(Error::PathForbidden(path)))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_forbidden<P: AsRef<Path>>(
|
||||
scope: &tauri::fs::Scope,
|
||||
path: P,
|
||||
require_literal_leading_dot: bool,
|
||||
) -> bool {
|
||||
let path = path.as_ref();
|
||||
let path = if path.is_symlink() {
|
||||
match std::fs::read_link(path) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
};
|
||||
let path = if !path.exists() {
|
||||
crate::Result::Ok(path)
|
||||
} else {
|
||||
std::fs::canonicalize(path).map_err(Into::into)
|
||||
};
|
||||
|
||||
if let Ok(path) = path {
|
||||
let path: PathBuf = path.components().collect();
|
||||
scope.forbidden_patterns().iter().any(|p| {
|
||||
p.matches_path_with(
|
||||
&path,
|
||||
glob::MatchOptions {
|
||||
// this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt`
|
||||
// see: <https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5>
|
||||
require_literal_separator: true,
|
||||
require_literal_leading_dot,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct StdFileResource(Mutex<File>);
|
||||
|
||||
impl StdFileResource {
|
||||
|
||||
Reference in New Issue
Block a user