1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use std::{fmt, path::Path};

use glob::Pattern;
use tauri_utils::{
  config::{Config, FsAllowlistScope},
  Env, PackageInfo,
};

use crate::api::path::parse as parse_path;

/// Scope for filesystem access.
#[derive(Clone)]
pub struct Scope {
  allow_patterns: Vec<Pattern>,
}

impl fmt::Debug for Scope {
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    f.debug_struct("Scope")
      .field(
        "allow_patterns",
        &self
          .allow_patterns
          .iter()
          .map(|p| p.as_str())
          .collect::<Vec<&str>>(),
      )
      .finish()
  }
}

impl Scope {
  /// Creates a new scope from a `FsAllowlistScope` configuration.
  pub fn for_fs_api(
    config: &Config,
    package_info: &PackageInfo,
    env: &Env,
    scope: &FsAllowlistScope,
  ) -> Self {
    let mut allow_patterns = Vec::new();
    for path in &scope.0 {
      if let Ok(path) = parse_path(config, package_info, env, path) {
        allow_patterns.push(Pattern::new(&path.to_string_lossy()).expect("invalid glob pattern"));
        #[cfg(windows)]
        {
          allow_patterns.push(
            Pattern::new(&format!("\\\\?\\{}", path.display())).expect("invalid glob pattern"),
          );
        }
      }
    }
    Self { allow_patterns }
  }

  /// Determines if the given path is allowed on this scope.
  pub fn is_allowed<P: AsRef<Path>>(&self, path: P) -> bool {
    let path = path.as_ref();
    let path = if !path.exists() {
      crate::Result::Ok(path.to_path_buf())
    } else {
      std::fs::canonicalize(path).map_err(Into::into)
    };

    if let Ok(path) = path {
      let allowed = self.allow_patterns.iter().any(|p| p.matches_path(&path));
      allowed
    } else {
      false
    }
  }
}