From 377a8c837957c38ed228e5063a169ac2ddfe2482 Mon Sep 17 00:00:00 2001 From: WangTongchao Date: Sat, 7 Nov 2026 23:45:21 +0800 Subject: [PATCH] feat(plugins): let a plugin read files outside the project (#2006) Adds the API 1.3 `fs` import behind the existing `fs.read:` capability: `read-file` (decoded like the editor, unsaved contents win), `read-bytes`, `stat` and `read-dir` (sorted, at most 4096), all at most 16 MiB. Paths are absolute or `~/`; the requested path and the grant are both resolved to their real location before the prefix check, so `..`, symlinks and name-prefix siblings can't climb out, and a whole-file-system grant is refused. A refusal is `denied` naming the `fs.read:` to declare. Reuses `workspace.file-kind` / `file-stat`; SDK `host::fs`. Closes #1822, closes #1825. Co-authored-by: chaoes <26876656+chaoes@users.noreply.github.com> --- crates/ide-host/src/plugins/api.rs | 32 +++ crates/ide-host/tests/plugins.rs | 73 ++++++- crates/ide-plugin/src/runtime.rs | 4 + crates/ide-plugin/src/sandbox.rs | 194 ++++++++++++++++++ crates/ide-plugin/src/wit_host.rs | 129 ++++++++++-- .../tests/fixtures/commit/dist/plugin.wasm | Bin 100258 -> 100266 bytes .../fixtures/commit/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/endpoints/dist/plugin.wasm | Bin 81461 -> 81469 bytes .../endpoints/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/hello/dist/plugin.wasm | Bin 143251 -> 143259 bytes .../fixtures/hello/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/hover/dist/plugin.wasm | Bin 89604 -> 89612 bytes .../fixtures/hover/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/indexer/dist/plugin.wasm | Bin 83031 -> 83039 bytes .../fixtures/indexer/dist/plugin.wasm.sources | 2 +- .../fixtures/inlay-hints/dist/plugin.wasm | Bin 91551 -> 91551 bytes .../inlay-hints/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/jobs/dist/plugin.wasm | Bin 150169 -> 150177 bytes .../fixtures/jobs/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/misbehave/dist/plugin.wasm | Bin 109143 -> 112135 bytes .../misbehave/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/misbehave/plugin.toml | 8 + .../tests/fixtures/misbehave/src/lib.rs | 20 ++ .../fixtures/path-events/dist/plugin.wasm | Bin 92727 -> 92735 bytes .../path-events/dist/plugin.wasm.sources | 2 +- .../fixtures/semantic-tokens/dist/plugin.wasm | Bin 91835 -> 91835 bytes .../semantic-tokens/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/storage/dist/plugin.wasm | Bin 73966 -> 73974 bytes .../fixtures/storage/dist/plugin.wasm.sources | 2 +- .../tests/fixtures/tables/dist/plugin.wasm | Bin 119171 -> 119179 bytes .../fixtures/tables/dist/plugin.wasm.sources | 2 +- plugins/README.md | 13 +- .../official/ai-completion/dist/plugin.wasm | Bin 173110 -> 173110 bytes .../ai-completion/dist/plugin.wasm.sources | 2 +- plugins/official/checkstyle/dist/plugin.wasm | Bin 169558 -> 169566 bytes .../checkstyle/dist/plugin.wasm.sources | 2 +- plugins/official/csv-editor/dist/plugin.wasm | Bin 133421 -> 133429 bytes .../csv-editor/dist/plugin.wasm.sources | 2 +- plugins/official/git-toolbox/dist/plugin.wasm | Bin 110095 -> 110103 bytes .../git-toolbox/dist/plugin.wasm.sources | 2 +- plugins/official/graphviz/dist/plugin.wasm | Bin 129129 -> 129137 bytes .../graphviz/dist/plugin.wasm.sources | 2 +- .../official/key-promoter/dist/plugin.wasm | Bin 100211 -> 100219 bytes .../key-promoter/dist/plugin.wasm.sources | 2 +- .../official/license-header/dist/plugin.wasm | Bin 152629 -> 152637 bytes .../license-header/dist/plugin.wasm.sources | 2 +- plugins/official/mybatis/dist/plugin.wasm | Bin 168370 -> 168378 bytes .../official/mybatis/dist/plugin.wasm.sources | 2 +- .../official/regex-tester/dist/plugin.wasm | Bin 931754 -> 931762 bytes .../regex-tester/dist/plugin.wasm.sources | 2 +- plugins/official/solidity/dist/plugin.wasm | Bin 108053 -> 108053 bytes .../solidity/dist/plugin.wasm.sources | 2 +- .../official/string-tools/dist/plugin.wasm | Bin 165811 -> 165819 bytes .../string-tools/dist/plugin.wasm.sources | 2 +- sdk/rust/openidea-plugin/src/host.rs | 83 ++++++-- sdk/rust/openidea-plugin/src/mock.rs | 130 ++++++++++++ sdk/rust/openidea-plugin/wit/fs.wit | 37 ++++ sdk/rust/openidea-plugin/wit/plugin.wit | 10 +- wit/fs.wit | 37 ++++ wit/plugin.wit | 10 +- 60 files changed, 760 insertions(+), 66 deletions(-) create mode 100644 sdk/rust/openidea-plugin/wit/fs.wit create mode 100644 wit/fs.wit diff --git a/crates/ide-host/src/plugins/api.rs b/crates/ide-host/src/plugins/api.rs index 418ace365..e4f6d961a 100644 --- a/crates/ide-host/src/plugins/api.rs +++ b/crates/ide-host/src/plugins/api.rs @@ -1287,6 +1287,38 @@ impl HostApi for PluginApi { let value = user.get(key).filter(|v| setting.accepts(v)).cloned().unwrap_or(setting.default); serde_json::to_string(&value).ok() } + + fn read_text_file(&self, real: &Path, max: usize) -> Result { + // Unsaved editor contents win, as they do for project files. + if let Some(text) = self.shared.workspace().and_then(|w| w.buffer_text(real)) { + return Ok(text); + } + let meta = std::fs::metadata(real).map_err(|e| not_a_file(real, e))?; + if !meta.is_file() { + return Err(HostError::Invalid(format!("{}: not a file", real.display()))); + } + if meta.len() > max as u64 { + return Err(too_large(real, max)); + } + let loaded = ide_vfs::load_text(real).map_err(failed)?; + if loaded.binary { + return Err(HostError::Invalid(format!("{}: not text; read it as bytes", real.display()))); + } + Ok(loaded.text) + } +} + +/// A file that is not there, or cannot be read, as the plugin sees it. +fn not_a_file(path: &Path, e: std::io::Error) -> HostError { + match e.kind() { + std::io::ErrorKind::NotFound => HostError::NotFound(format!("{}: no such file", path.display())), + std::io::ErrorKind::PermissionDenied => HostError::Denied(format!("{}: {}", path.display(), "not readable")), + _ => failed(e), + } +} + +fn too_large(path: &Path, max: usize) -> HostError { + HostError::Invalid(format!("{}: file is larger than {} MiB", path.display(), max >> 20)) } /// [`PluginWorkspace`] over the desktop host's open projects. diff --git a/crates/ide-host/tests/plugins.rs b/crates/ide-host/tests/plugins.rs index e961f51b7..a34dec395 100644 --- a/crates/ide-host/tests/plugins.rs +++ b/crates/ide-host/tests/plugins.rs @@ -126,6 +126,19 @@ fn misbehave_pkg() -> PathBuf { repo().join("crates/ide-plugin/tests/fixtures/misbehave") } +/// `misbehave` with `fs.read:` added to its capabilities. +fn misbehave_granted(dir: &Path, granted: &Path) -> PathBuf { + let pkg = dir.join("misbehave-granted"); + copy_dir(&misbehave_pkg(), &pkg); + let manifest = pkg.join("plugin.toml"); + let text = std::fs::read_to_string(&manifest).unwrap(); + let path = granted.to_string_lossy().replace('\\', "/"); + let required = format!("required = [\"project.read\", \"fs.read:{path}\"]"); + let text = text.replace("required = [\"project.read\"]", &required); + std::fs::write(&manifest, text).unwrap(); + pkg +} + /// Whether `f` holds within 5 s. A call a slow runner keeps waiting behind /// another (or behind a new instance starting) holds once it caught up. fn eventually(mut f: impl FnMut() -> bool) -> bool { @@ -374,6 +387,64 @@ fn read_file_is_confined_to_the_project() { assert_eq!(f.status("misbehave"), PluginStatus::Active); } +/// `fs.read` reaches the granted paths and nothing else, through the real +/// component: the same checks the runtime makes, against a real file system. +#[test] +fn fs_read_reaches_only_the_granted_paths() { + let f = fixture(Limits::default()); + let shared = f._tmp.path().join("shared"); + std::fs::create_dir_all(&shared).unwrap(); + let notes = shared.join("notes.txt"); + std::fs::write(¬es, "outside the project\n").unwrap(); + // A sibling whose name starts with the grant's: not covered by it. + let sibling = f._tmp.path().join("shared-other"); + std::fs::create_dir_all(&sibling).unwrap(); + let other = sibling.join("notes.txt"); + std::fs::write(&other, "not the same directory\n").unwrap(); + let secret = f._tmp.path().join("secret.txt"); + f.install(&misbehave_granted(f._tmp.path(), &shared)); + + assert_eq!(f.run("misbehave", "fsread", Some(notes.to_str().unwrap())).unwrap().unwrap(), "outside the project\n"); + let err = f.run("misbehave", "fsread", Some(secret.to_str().unwrap())).unwrap_err(); + assert!(err.contains("fs.read:"), "the refusal names what to grant: {err}"); + let err = f.run("misbehave", "fsread", Some(other.to_str().unwrap())).unwrap_err(); + assert!(err.contains("fs.read:"), "a name prefix grants nothing: {err}"); + let err = f.run("misbehave", "fsread", Some("notes.txt")).unwrap_err(); + assert!(err.contains("absolute"), "{err}"); + let err = f.run("misbehave", "fsread", Some(shared.to_str().unwrap())).unwrap_err(); + assert!(err.contains("not a file"), "{err}"); + let missing = shared.join("gone.txt"); + let err = f.run("misbehave", "fsread", Some(missing.to_str().unwrap())).unwrap_err(); + assert!(err.contains("no such file"), "{err}"); + // A refusal is the plugin's to handle, like any other error it gets. + let info = f.host.info_of("misbehave").unwrap(); + assert_eq!((info.status, info.stats.crashes, info.stats.errors), (PluginStatus::Active, 0, 0), "{info:?}"); +} + +/// `fs.read-dir` lists a granted directory, sorted, and refuses the rest. +#[test] +fn fs_read_dir_lists_a_granted_directory() { + let f = fixture(Limits::default()); + let shared = f._tmp.path().join("shared"); + std::fs::create_dir_all(shared.join("zeta")).unwrap(); + std::fs::write(shared.join("beta.txt"), "b").unwrap(); + std::fs::write(shared.join("alpha.txt"), "a").unwrap(); + f.install(&misbehave_granted(f._tmp.path(), &shared)); + + let listing = f.run("misbehave", "read-dir", Some(shared.to_str().unwrap())).unwrap().unwrap(); + let lines: Vec<&str> = listing.lines().collect(); + assert_eq!(lines, vec!["file alpha.txt", "file beta.txt", "dir zeta"], "{listing}"); + + // A file is not a directory, and a path outside the grant is refused. + let file = shared.join("alpha.txt"); + let err = f.run("misbehave", "read-dir", Some(file.to_str().unwrap())).unwrap_err(); + assert!(err.contains("not a directory"), "{err}"); + let err = f.run("misbehave", "read-dir", Some(f._tmp.path().to_str().unwrap())).unwrap_err(); + assert!(err.contains("fs.read:"), "{err}"); + let info = f.host.info_of("misbehave").unwrap(); + assert_eq!((info.status, info.stats.crashes, info.stats.errors), (PluginStatus::Active, 0, 0), "{info:?}"); +} + /// A missing capability is an error the plugin can handle, not a trap. #[test] fn ungranted_capabilities_are_denied_not_trapped() { @@ -650,7 +721,7 @@ fn idle_instances_are_reclaimed_and_schedules_reactivate() { assert_eq!(f.host.instances(), 0); let info = f.host.info_of("misbehave").unwrap(); assert_eq!((info.status, info.stats.reclaims), (PluginStatus::Inactive, 1)); - assert_eq!(f.command_titles("misbehave").len(), 10, "contributions stay"); + assert_eq!(f.command_titles("misbehave").len(), 12, "contributions stay"); assert_eq!(f.run("misbehave", "echo", Some("y")).unwrap().as_deref(), Some("y")); assert_eq!(f.host.info_of("misbehave").unwrap().stats.activations, 2); diff --git a/crates/ide-plugin/src/runtime.rs b/crates/ide-plugin/src/runtime.rs index 35f154751..80dbf6df5 100644 --- a/crates/ide-plugin/src/runtime.rs +++ b/crates/ide-plugin/src/runtime.rs @@ -206,6 +206,10 @@ pub trait HostApi: Send + Sync { fn locale(&self) -> String; /// A setting of the plugin as JSON (project over global over the schema default). fn setting(&self, root: Option<&Path>, key: &str) -> Option; + /// Reads and decodes a text file outside the project, whose real path an + /// `fs.read` grant already covers: the unsaved buffer wins, then the disk. + /// `max` bounds the bytes read. + fn read_text_file(&self, real: &Path, max: usize) -> Result; } /// Shared compilation engine plus an epoch ticker thread for wall-clock limits. diff --git a/crates/ide-plugin/src/sandbox.rs b/crates/ide-plugin/src/sandbox.rs index 71a03d615..523a2b2f4 100644 --- a/crates/ide-plugin/src/sandbox.rs +++ b/crates/ide-plugin/src/sandbox.rs @@ -1,8 +1,12 @@ //! Capability checks for host functions that touch the file system. +use ide_extension::Capability; use std::path::{Path, PathBuf}; /// Largest file `read-file` returns. +/// The most entries `fs.read-dir` hands over: the same cap as `find-files`. +pub const MAX_LIST_ENTRIES: usize = 4096; + pub const MAX_READ_BYTES: u64 = 16 << 20; /// The canonical `root` and the absolute form of `path` (absolute, or @@ -124,6 +128,72 @@ pub fn read_text(real: &Path) -> Result { String::from_utf8(bytes).map_err(|_| format!("{}: not valid UTF-8 text", real.display())) } +/// Why a read outside the project was refused. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Refusal { + /// No `fs.read:` grant covers the file; names the capability to declare. + Denied(String), + /// The path cannot be read as asked. + Invalid(String), +} + +/// Expands a leading `~` or `~/` to the user's home; everything else as written. +fn expand_tilde(path: &str) -> PathBuf { + let rest = if path == "~" { + Some("") + } else if let Some(rest) = path.strip_prefix("~/") { + Some(rest) + } else { + path.strip_prefix("~\\") + }; + match rest { + Some(rest) => std::env::var_os("HOME") + .or_else(|| std::env::var_os("USERPROFILE")) + .map(|home| PathBuf::from(home).join(rest)) + .unwrap_or_else(|| PathBuf::from(path)), + None => PathBuf::from(path), + } +} + +/// The real path of `path` when an `fs.read:` grant covers it. +/// +/// The grant is compared with the **real** path, so a symlink pointing out of +/// a granted tree is refused, and `fs.read:/srv/app` covers `/srv/app/x` but +/// not `/srv/application`. Windows' `\\?\` prefix (what `canonicalize` adds) +/// is stripped from the file side so a manifest may spell `C:\Program Files\X`. +pub fn resolve_granted(granted: &[Capability], path: &str) -> Result { + let asked = expand_tilde(path); + if !asked.is_absolute() { + return Err(Refusal::Invalid(format!("{path}: use an absolute path (or ~/…)"))); + } + let real = asked.canonicalize().map_err(|_| Refusal::Invalid(format!("{path}: no such file")))?; + let plain = strip_verbatim(&real); + let cap = Capability::FsRead(plain.clone()); + let mut covered = false; + for grant in granted { + let Capability::FsRead(base) = grant else { continue }; + // The grant is compared where it really is too: `/tmp/x` is `/private/tmp/x` on macOS. + let base_real = expand_tilde(base).canonicalize().map(|p| strip_verbatim(&p)).unwrap_or_else(|_| base.clone()); + if !Capability::FsRead(base_real).covers(&cap) { + continue; + } + // A directory that is its own parent is a root: `/`, `C:\`. + if Path::new(base).parent().is_none() { + return Err(Refusal::Invalid(format!( + "{plain}: fs.read:{base} covers a whole file system; declare a directory" + ))); + } + covered = true; + } + if covered { Ok(real) } else { Err(Refusal::Denied(cap.to_string())) } +} + +/// `\\?\C:\…` (what `canonicalize` returns on Windows) as `C:\…`. +fn strip_verbatim(path: &Path) -> String { + let text = path.to_string_lossy(); + text.strip_prefix(r"\\?\").unwrap_or(&text).to_owned() +} + #[cfg(test)] mod tests { use super::*; @@ -226,4 +296,128 @@ mod tests { let p = resolve_in_root(tmp.path(), "b.bin").unwrap(); assert!(read_text(&p).unwrap_err().contains("UTF-8")); } + + /// The grant a manifest author would write for `dir`: the plain path, no + /// `\\?\` prefix. + fn grant_for(dir: &Path) -> Capability { + Capability::FsRead(strip_verbatim(&dir.canonicalize().unwrap())) + } + + fn text_at(dir: &Path, name: &str, body: &str) -> PathBuf { + let file = dir.join(name); + std::fs::write(&file, body).unwrap(); + file.canonicalize().unwrap() + } + + #[test] + fn a_file_outside_every_grant_is_denied_naming_the_capability() { + let tmp = tempfile::tempdir().unwrap(); + let file = text_at(tmp.path(), "app.properties", "name=YonBIP\n"); + let err = resolve_granted(&[], file.to_str().unwrap()).unwrap_err(); + match err { + Refusal::Denied(cap) => assert!(cap.starts_with("fs.read:"), "{cap}"), + other => panic!("expected denied, got {other:?}"), + } + // A grant on another tree does not cover it either. + let elsewhere = tempfile::tempdir().unwrap(); + let err = resolve_granted(&[grant_for(elsewhere.path())], file.to_str().unwrap()).unwrap_err(); + assert!(matches!(err, Refusal::Denied(_)), "{err:?}"); + } + + #[test] + fn a_grant_covers_what_is_under_it_but_not_a_sibling_with_its_prefix() { + let tmp = tempfile::tempdir().unwrap(); + let granted = tmp.path().join("seeyon"); + std::fs::create_dir_all(granted.join("conf")).unwrap(); + let file = text_at(&granted.join("conf"), "server.xml", ""); + let cap = grant_for(&granted); + + assert_eq!(resolve_granted(std::slice::from_ref(&cap), file.to_str().unwrap()).unwrap(), file); + // The directory itself, asked for explicitly, is covered too. + assert!(resolve_granted(std::slice::from_ref(&cap), granted.to_str().unwrap()).is_ok()); + + // `/x/seeyon` must not cover `/x/seeyon-old/app.properties`. + let sibling = tmp.path().join("seeyon-old"); + std::fs::create_dir_all(&sibling).unwrap(); + let other = text_at(&sibling, "app.properties", "x=1"); + assert!(matches!(resolve_granted(&[cap], other.to_str().unwrap()), Err(Refusal::Denied(_)))); + } + + #[cfg(unix)] + #[test] + fn a_grant_declared_through_a_symlinked_directory_covers_its_files() { + // `/tmp/tool` on macOS is `/private/tmp/tool`: the grant is resolved too. + let tmp = tempfile::tempdir().unwrap(); + let real = tmp.path().join("real"); + std::fs::create_dir_all(&real).unwrap(); + let file = text_at(&real, "a.txt", "a"); + let link = tmp.path().join("link"); + std::os::unix::fs::symlink(&real, &link).unwrap(); + let cap = Capability::FsRead(link.to_string_lossy().into_owned()); + assert!(resolve_granted(std::slice::from_ref(&cap), link.join("a.txt").to_str().unwrap()).is_ok()); + assert!(resolve_granted(&[cap], file.to_str().unwrap()).is_ok()); + } + + #[test] + fn a_granted_symlink_target_must_still_be_covered() { + // The grant is compared with the real path, so a link inside a granted + // tree cannot be used to read outside it. + let tmp = tempfile::tempdir().unwrap(); + let granted = tmp.path().join("granted"); + std::fs::create_dir_all(&granted).unwrap(); + let secret = text_at(tmp.path(), "secret.txt", "s"); + #[cfg(unix)] + { + std::os::unix::fs::symlink(&secret, granted.join("link")).unwrap(); + let cap = grant_for(&granted); + let err = resolve_granted(&[cap], granted.join("link").to_str().unwrap()).unwrap_err(); + assert!(matches!(err, Refusal::Denied(_)), "{err:?}"); + } + #[cfg(windows)] + { + // Creating symlinks needs a privilege tests do not have; hard links + // to the same file are covered by the parent directory anyway, so + // only the textual check is exercised here. + let _ = secret; + assert!(resolve_granted(&[grant_for(&granted)], granted.to_str().unwrap()).is_ok()); + } + } + + #[test] + fn a_path_must_be_absolute_and_exist() { + let tmp = tempfile::tempdir().unwrap(); + let cap = grant_for(tmp.path()); + let err = resolve_granted(std::slice::from_ref(&cap), "app.properties").unwrap_err(); + assert!(matches!(err, Refusal::Invalid(ref m) if m.contains("absolute")), "{err:?}"); + let err = resolve_granted(&[cap], tmp.path().join("missing").to_str().unwrap()).unwrap_err(); + assert!(matches!(err, Refusal::Invalid(ref m) if m.contains("no such file")), "{err:?}"); + } + + #[test] + fn a_root_grant_is_refused() { + let tmp = tempfile::tempdir().unwrap(); + let file = text_at(tmp.path(), "a.txt", "hi"); + #[cfg(windows)] + let cap = Capability::FsRead(format!("{}\\", std::env::var("SystemDrive").unwrap_or_else(|_| "C:".into()))); + #[cfg(unix)] + let cap = Capability::FsRead("/".into()); + let err = resolve_granted(&[cap], file.to_str().unwrap()).unwrap_err(); + assert!(matches!(err, Refusal::Invalid(ref m) if m.contains("whole file system")), "{err:?}"); + } + + #[test] + fn a_tilde_starts_at_the_users_home() { + let home = std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE")); + if home.is_none() { + return; + } + let expanded = expand_tilde("~/app.properties"); + assert!(expanded.is_absolute(), "{}", expanded.display()); + assert!(expanded.starts_with(home.unwrap())); + assert_eq!( + expand_tilde("~"), + PathBuf::from(std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE")).unwrap()) + ); + assert_eq!(expand_tilde("relative/x"), PathBuf::from("relative/x")); + } } diff --git a/crates/ide-plugin/src/wit_host.rs b/crates/ide-plugin/src/wit_host.rs index bf9d92b09..caa8b2517 100644 --- a/crates/ide-plugin/src/wit_host.rs +++ b/crates/ide-plugin/src/wit_host.rs @@ -49,6 +49,7 @@ pub(crate) mod syntax_bindings { "openidea:plugin/net": super::bindings::openidea::plugin::net, "openidea:plugin/secrets": super::bindings::openidea::plugin::secrets, "openidea:plugin/process": super::bindings::openidea::plugin::process, + "openidea:plugin/fs": super::bindings::openidea::plugin::fs, "openidea:plugin/views": super::bindings::openidea::plugin::views, "openidea:plugin/settings": super::bindings::openidea::plugin::settings, }, @@ -77,6 +78,7 @@ pub(crate) mod providers_bindings { "openidea:plugin/net": super::bindings::openidea::plugin::net, "openidea:plugin/secrets": super::bindings::openidea::plugin::secrets, "openidea:plugin/process": super::bindings::openidea::plugin::process, + "openidea:plugin/fs": super::bindings::openidea::plugin::fs, "openidea:plugin/views": super::bindings::openidea::plugin::views, "openidea:plugin/settings": super::bindings::openidea::plugin::settings, }, @@ -105,6 +107,7 @@ pub(crate) mod views_bindings { "openidea:plugin/net": super::bindings::openidea::plugin::net, "openidea:plugin/secrets": super::bindings::openidea::plugin::secrets, "openidea:plugin/process": super::bindings::openidea::plugin::process, + "openidea:plugin/fs": super::bindings::openidea::plugin::fs, "openidea:plugin/views": super::bindings::openidea::plugin::views, "openidea:plugin/settings": super::bindings::openidea::plugin::settings, }, @@ -112,7 +115,7 @@ pub(crate) mod views_bindings { } use bindings::openidea::plugin::{ - commit, diagnostics, editor, events, invocation, log, net, process, secrets, settings, storage, tasks, + commit, diagnostics, editor, events, fs, invocation, log, net, process, secrets, settings, storage, tasks, types as wit, ui, vcs, views, workspace, }; @@ -193,6 +196,12 @@ impl StoreData { if self.granted.iter().any(|g| g.covers(&cap)) { Ok(()) } else { Err(wit::Error::Denied(cap.to_string())) } } + /// `path` as the real path an `fs.read:…` grant covers, or what the plugin + /// should be told instead (`denied` naming the capability to declare). + fn granted_file(&self, path: &str) -> Result { + sandbox::resolve_granted(&self.granted, path).map_err(Into::into) + } + fn client(&self) -> Option<&str> { self.invocation.client.as_deref() } @@ -533,25 +542,7 @@ impl workspace::HostProject for StoreData { return Ok(Err(e)); } }; - let meta = match std::fs::symlink_metadata(&real) { - Ok(m) => m, - Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - return Ok(Err(wit::Error::NotFound(format!("{path}: no such file")))); - } - Err(e) => return Ok(Err(wit::Error::Failed(e.to_string()))), - }; - let kind = if meta.is_file() { - workspace::FileKind::File - } else if meta.is_dir() { - workspace::FileKind::Directory - } else if meta.is_symlink() { - workspace::FileKind::Symlink - } else { - workspace::FileKind::Other - }; - let modified = - meta.modified().ok().and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()).map(|d| d.as_secs()); - Ok(Ok(workspace::FileStat { kind, size: meta.len(), modified })) + Ok(file_stat(&real, &path)) } fn find_files(&mut self, this: Resource, glob: String, limit: u32) -> Fallible> { @@ -991,6 +982,104 @@ impl settings::Host for StoreData { impl views_bindings::openidea::plugin::view_types::Host for StoreData {} +fn file_kind(t: std::fs::FileType) -> workspace::FileKind { + if t.is_file() { + workspace::FileKind::File + } else if t.is_dir() { + workspace::FileKind::Directory + } else if t.is_symlink() { + workspace::FileKind::Symlink + } else { + workspace::FileKind::Other + } +} + +/// `project.stat` and `fs.stat`: the metadata of `real`, named `shown` in errors. +fn file_stat(real: &Path, shown: &str) -> Result { + let meta = std::fs::symlink_metadata(real).map_err(|e| match e.kind() { + std::io::ErrorKind::NotFound => wit::Error::NotFound(format!("{shown}: no such file")), + _ => wit::Error::Failed(e.to_string()), + })?; + let modified = meta.modified().ok().and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()).map(|d| d.as_secs()); + Ok(workspace::FileStat { kind: file_kind(meta.file_type()), size: meta.len(), modified }) +} + +/// A refused `fs.read` as the plugin sees it: `denied` carries the capability +/// string, so the plugin can say exactly what its manifest lacks. +impl From for wit::Error { + fn from(refusal: sandbox::Refusal) -> Self { + match refusal { + sandbox::Refusal::Denied(cap) => Self::Denied(cap), + sandbox::Refusal::Invalid(message) => Self::Invalid(message), + } + } +} + +/// Files outside the open projects, gated by `fs.read:` grants. +impl fs::Host for StoreData { + fn read_file(&mut self, path: String) -> Fallible { + let real = match self.granted_file(&path) { + Ok(real) => real, + Err(e) => return Ok(Err(e)), + }; + Ok(self.host.read_text_file(&real, sandbox::MAX_READ_BYTES as usize).map_err(to_wit)) + } + + fn read_bytes(&mut self, path: String) -> Fallible> { + use std::io::Read; + let real = match self.granted_file(&path) { + Ok(real) => real, + Err(e) => return Ok(Err(e)), + }; + let max = sandbox::MAX_READ_BYTES; + let read = std::fs::File::open(&real).and_then(|file| { + let mut bytes = Vec::new(); + // One byte over: a file that grew past the limit is refused, not truncated. + file.take(max + 1).read_to_end(&mut bytes).map(|_| bytes) + }); + Ok(match read { + Ok(bytes) if bytes.len() as u64 > max => { + Err(wit::Error::Invalid(format!("{path}: larger than {} MiB", max >> 20))) + } + Ok(bytes) => Ok(bytes), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { + Err(wit::Error::NotFound(format!("{path}: no such file"))) + } + Err(e) => Err(wit::Error::Failed(format!("{path}: {e}"))), + }) + } + + fn stat(&mut self, path: String) -> Fallible { + Ok(self.granted_file(&path).and_then(|real| file_stat(&real, &path))) + } + + fn read_dir(&mut self, path: String) -> Fallible> { + let real = match self.granted_file(&path) { + Ok(real) => real, + Err(e) => return Ok(Err(e)), + }; + let read = match std::fs::read_dir(&real) { + Ok(read) => read, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { + return Ok(Err(wit::Error::NotFound(format!("{path}: no such directory")))); + } + Err(_) if real.is_file() => return Ok(Err(wit::Error::Invalid(format!("{path}: not a directory")))), + Err(e) => return Ok(Err(wit::Error::Failed(format!("{path}: {e}")))), + }; + let mut entries: Vec = read + .flatten() + .take(sandbox::MAX_LIST_ENTRIES) + .map(|e| fs::DirEntry { + name: e.file_name().to_string_lossy().into_owned(), + kind: e.file_type().map_or(workspace::FileKind::Other, file_kind), + }) + .collect(); + // Sorted, so what a plugin picks doesn't depend on the disk's order. + entries.sort_by(|a, b| a.name.cmp(&b.name)); + Ok(Ok(entries)) + } +} + /// Largest message between a plugin and its view's frame. const MAX_VIEW_MESSAGE: usize = 1 << 20; diff --git a/crates/ide-plugin/tests/fixtures/commit/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/commit/dist/plugin.wasm index 610b9b9e781e898cd92fc232e87d41676d1c7d2b..06b81cb175faa8282bb2ee7baf5111bf86cef660 100644 GIT binary patch delta 2419 zcmZvd2~ZPf6oB__Vgv$;^=L#WOTY^CL=>&!v7IVb#{!DjYU?q!!Z5Tt#e)&SsHjlU zp#LZeQt$*71iMocBx*$DGC+WUpx_{2bw)?&Xh&+J_WfZKu*wYI|L=S6f7kzZb3!dU zrj0`W38M!MTn;bD^r#WYrBUC)BXTinGCUFuDF_AtJ#zQKZ%}Kx57UINu zZda*P46hX?Y;**4J7ZHYFF*=u-rNp)K^L=#1p^rv8w=OT-q=7$CiStN zxPKXY7{l$~IvxFpXh2hVLd`aXw%qU&oCb*=?ZFoe2hHI0?^C3zqL| z&!YYDxHo8@75}9riy4A)Tbcx`yRu^*K(Zi902tJDi#nR?#E7|f35s0`fJEZEyBtkl z?LPhi8z?!h(IO55;NOABk}S)dY@_yXt7jB|#}Jpd*nM?n>DJ-Q-nD1ai%R6|Aa~ z+&J*`{gTK^GK0K581%kISV<;JT@tG;=}7qP$LNN)$5uK(`HLO?4F&YTa}{}ovYkR^0vsUY7=$7ePUHvGSVyn$q%33M}BUH`cmXfMD2ncFE9%0bB@ZOg*fCdN3P9Z3N6Cb{GGC)ZI)QxtU?L4 z7;Qq>r3`kg*`{Kh71Lc~J;5ugD!)RWuXns9S~%*ZCpSb%E}p11ZP&vqLy3C-Z0R z90$n7WXuGv3<0w+>0_=h#fGB0CSMBZ#s46n*0Q%Hh@^T8UDM2W{;#6PMzN=y_o=hy1xX z7$@Lb@!Vln`vQrFw2$$K8@tiq#Eq?J>|U}8sVbp~oi7<-JEBm^dQ&r#mXgo?tlpe0 z!MXmNG|0)CDBq*x`unra*4$;hnasQCGs0RJHrI<+#e2vk)@wGCyvVFyuPWW zVVH@!)CV&xEcG2?3mRl=l$pFK9gaqdvKh#*vi-dt9MD5oSuTn*%4tK4<(rZ7DyAa0 zS5zZ|D~BP&EB7FuRgOox-)ctwbBo%KF~lLy8O9=;46VpZRn+FsDigA(nhwmf>er=m5EYolp6ces)*ZD(=kb$_OvI7$q8+u@BO?@n51 zoX!0^Me^;m$e8xtA}_SlBAq*Ek=-5CyLV^0_=a-ok=D6V={Hiy!)c z7Ju*oy@av{;r&1-jDNfg@E7&hCu1Bsjh2tOlz$=UpL9u3da>&#$Q9iG3LM5J)M_I7 zLx%(1Ec^(r^n+umas`~lAF@4-FA?ix^gt&kZLB4fnAcp36}F5aIEts>O(Fs z(-_9XJx_R~IlmZuAazwJNK;LrkZ8}~AB+Dnn$=5S6hM|HDGZ`naMis222PLr554~6 A=l}o! delta 2410 zcmZvdeN;?o9LMkP&NR{#S!t(eyG>cOUJ{C>aQ7@(j;*}pV3&35s_nGP+46Fv8WdSp z@gQp3LX?*@_F5xFBh&koq*BC5FUvVPw8!kx+Lrx2Gk2yO{`ox5JiqV#y*{$2h zDwT@i)xyM$wg8t%z@}ixCUxmfLe3^1fF#ngxgD+uMOzlJpd&+LVxWNRjR}MVawo3$h zi~8fSud%GGxX+DQ1PIFbGznIBZO1%-1VNSnFziV+bu`zG5p#bcC=wL_D&n)N0;R8Z z9eBQQ>2GJ!+nesUC+5tQPLjg2reF(n#$$g7laeVY>4qPSt+b86wx$RdQpd1(;k(n^$jf6s zkVU-GzBc~O$Nkjw#jwxRUZF01C%`^oNk$}=LvH*Q0+)p0nezerzbY#MjtU)F$rAh# zl^qOPL6<#(TJD|l$Buk>dgE}N@umkfkk^sS(}6A(#&e~_la(s*qCHvbKy!=v3L?pw zf%7oS$e0{A+-Ky3zt@){cM@6`t_{{z~M!{AJJ}T+iPr8_{fx<;g0P zV2RNzgkH{I#~Umr){bFki?gD?OWWniGD?a00i~4J6RyAm$9PUb7&5P5A@bjXWLuLD zr4>gdN3Jfz<7Zd>kfRHIkt+*Bka>l!$eO~LNZXH>SJ8o#WBgbLPRhyr zSZmuMaxobLfol$65FD@Jt7jnY*Owr-TrWe;Dvm&&EzVS!>#)W&Bwv`5<_%6gbBsH6K~KNo_%lJ)r0lHDgItj)rTCzwT?XP@G6_8|Ea8wp zmIUJj6qn3(H0#w8H|YTJ$eX)RaN_1R6uauaL8^2#v2(hSmPZsyS$}E<(yIG(ve}!x zF*rAflLpzD6Xi`tZjc{qZ_ZuD8_2v;uaV}$u(=+*D$Y$NF<-NR>?_SOU!Rndz8h2aby_HCK6MY3To9IYrn{a?hW78Vs z)Vq(7uFWPV>9~K|?1CKJLi6x%p;J-NG977XsRYBx>-XpfrTBi_`@@8^dZ9F?)z4yn ztLoC$WHc{*@D=j+2ekIshZtGNd#Iu{PH3ZP*msN~Tiedy&g0QcYjKnq@}|QRk32hR zp|KYCZxzY6(;~OD_ZNAgofc`|L5u9|px!+@)5SNO1AMWE%GufY2k{0L44A0)PFnnk zE?WG-E_w;&U13)ErS*Qg0`MR8=k9Sft#!taxs>k~wB0=tJiXZS17r)Xe+4?SeRZ1f zLC|4CHw!<2YgTY5Rjz6V-E`YRE+0?oc8$=i_VMt0u zdyRk$GOU6Q%WzrkV1N$Bw$#v~4gP3@l~#UCf=$s-#ir-ZCZ?2x@7;IKxo5q1Ui-AT zXIk9S=K@;V?;>-`ZENl2B)Obmv_9`!pY_(~r1j~*jHazGT58$k!i27Nlvu?*Us=>r zrYW)RX|pOd)~Adqjdc6Gg!M2+ZbW(^??mo_5h9OT3nMf>s*#6!B19{Qf3z1EaWw@~ zG$cmP!&73~nG7Zp8LLE-qp|zpA{mZdi*$+0@~)@7DlQ{H#3{t0P`NlPH%7+$o>Qq* zoKR0I;-r9kbn($pLN;Z4(uKPMfmi9shr1s^3thfv2M-34lW+#~(>@>cBM0x(T84*<*?)iFomGR~U(C{-Wy0GJ}$l)Gq}o?1DJ z4e?4(11-r*-vC{tFa5CZ(^lqXCCAzPC_%8ugVI7*<9Y&~`oH01WNMcz6~@m1%scupdBlsn0ttm*5>maE``?UiO=s|%>l=Sz4z z1<$h-Bqb{lTU(NqWPWePb={erpt7`_Zp!`wr+$+f&mO`W$ve3*P*2b2ZUr3552`%4 zNOzoz7vZUE$cu(9`XX-u;EP-S25eJQe&&3GdHgfFDj3Lv{0Q9bqxM3sQ?Ey6nyFVS za6PO}n|0Urf*{nMEAWF}T31l&2!kZFC;_P{+69AjvgixP1w-a&OL-3^*rq59(ZVa` z{M#nGikESGsI}Kd5?ZdV zvbD%dWibkyTW6(nlnnS#xx;4W-X6e2M4I=}HcYb@S*}@w{81Bu^ep#TXxlATx^9+% zH765|EXTWNB73gIBAc$=L1tEDAV(`IkSgs$WU=-zQe3$hxx8{2GQKisxv`UtdMVFg z8nzm(B4>qI3KEM@$ttoGJyMzMY0INaq!gR;x1~a&tAdmk?Mlud62!-44y-yXlz$z; zL~5#{v5U{D!tEush!o-(U5Kg9M}v{-Y|JyR=3`_>4a@majhB6khthGT&$nvVp+RJ= zx79%I6wJHX@^=(WB&RmO%U*9V?XicQQR%;ufST4bWKdXyJj{|i9n94+5 z;3`|$ZXem3Wf56I;hmIZC~R#sk?q$v;`YMp7hZdHMX!tNbtoRL4?;RNoJQs}yoc;; zxaVPuAXSRxqNvwVNcjyln)u&bjf}hb5V=~%9DJ%fiyYOhM9yja1!-zzHr`G5k$*O^ z^W)zficD!vbGNzoh?wE}x8^l=h5JlJK+6f-r)l{PnW|@Ai}eO%Y%7bbZe@`j=(}K| zA=HN*z};=W$m}*|s%slSo@i%>S>MhikJ=mTao$MaS_iu$4?5)b$+{~YXC@-)`~(e- zbUtymwp&EBeV!zNW3Dhs ze;@x@I)Bn)33A>|%f2@fNhiJcEXN(XilbcN@8U2C6uNNu$K(Ha=dc8p0JwF&l)_&C L($0xF5Wf0fKlYsH delta 2317 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 pg*GJg;dcQ_9!>pvD+`7{o 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 delta 2445 zcmZvd2~1Q+7=YjZmR*nqr9la($g)@k4@6MBEl;abj{;r@t+y14XoFO+6m$_(qF4=s zu*eN6qKmH1qoA$`t+iMc5vkBt4Kbu@dVnd3*r4q{yKfh4$xFVu{{NrOiOL1Dfaw+uZ~mh;e?E4Q=2cf?b5tK8Y`I4b!h->@Jt%mvH{P~F3r?yO}6aV zWRqm5S6b|lT6?zG3ym~v$Q>VOqhkZ+^YDypoi`17XxY5+0O|DZ{8#`j6&C!+yXuY>ga<_B?HKi^es^s`-?5J zF?R2W7>}C&W?2n_X-;MI3j~o~jVJ@qkd2Xkw(UmORUmZH!pL-BW&Bh#&^|TM(YTMt zRsz>a_0~8{>-d=ABRh;fJ7n&~GIC0lLS?P8HWgRsARA*ohhp*|CJOo9wsoK*h1)v+ zA0{c>o-yF;9J=eX9?TMnjdR8X9E=;wLj&0y?@sRToQy@0$FDVx&tu;)VFhoHl8XhO zL!T!s1TavaFJdq#Qjiz|9kerXF|ZQMN=k(WdM#3Y+q+ZA|sA1L(*eM>`XS)aupN#Fgp~dPi6ZfA7xKPI_88RBXZo3`*P+Y zujhm#-L!tTCRMELAfi9xM0RLBaUoCZ>SXrIN^QHq9wfI!+Nj05Cz4-sS0a6m-$1@R z9*x|TSLAHgu|Zd4ADA5%MB^7$06JDeTQ0tTwoE+AfpPLz#M0I!Fm_7 z%^I273gs*r5=nD`FB*~;s*qy}gHbD?aG}L-z0BRJpYZ*{{U{J#l!U^qMH`UQi^us& z(JTCUQKsYrOrJScOJNj!{)r^3cm^sr7LSy6Qd#@+4oZ`bS|Ny;C0-*ef%)^J1NSaFL zp!(plullUoqSe!7I-Fj0f~6?^L;{GJC#Pd~#>qxYmF(13D%rBWO^Dm611M5{Y7(;b z)KAC@cc9)V-4Dp;I%d_S(tvzW$#x!ej_rKl+!Xwc8qT@0llSv^59FKkOw?Qd9kN?L z*G9?^kjIoAU~AEpXf9+}wtUMM)kStSLNBs&6H+@AdHCW+Waq`F$X3cMTZ?&al1P27kzE;HHoHKE(T8pZ&RWp&gs+%B|#eWT0)r9KZ1A8*4#tTLL zYWywBZ{;Sr<_Ip^U-}pseTijg>Sc6}MqJjgO#FI
7rlK2`bu=miwuJ(wlY_|Ox zOMskgySmF_`>iCry2_H^Q`?t>Pik2b8fsY*^w&&A^01#&=ZZXD$LevXj@_Td^{gIy z>Lca&+kJW?9PqWB*D%30qlx{r@F$c{cQq8taMtDaHhc~b++O4aI(qj>hb=bZAGLCP zX5#*;K)QBULN~qD9Vr{0c8_UWUK=}=m2?qX$kHBXeD6)%jr|sy(-Xl%7JdD96Kfh@ z_t=1#^SuIE;6!!4HSCi)>P*gnig!559x$b{vwDgW=6Zm>I?fxsAg6c|w8?pn<3?Af W_`q0z!0L+05XZyyYS$^y>GdzvxWS|V diff --git a/crates/ide-plugin/tests/fixtures/hover/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/hover/dist/plugin.wasm.sources index f07847b94..3db54b4e0 100644 --- a/crates/ide-plugin/tests/fixtures/hover/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/hover/dist/plugin.wasm.sources @@ -1 +1 @@ -bb94b980261fc996c92bc8eceb5a89e8dbdaf26b5e4466223a86fe8abb9b63e0 +2a81c76cb9e2482f17a3cb080dbd1f9109c9305153cddcd232158c16b1a099c2 diff --git a/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/indexer/dist/plugin.wasm index 626ee3d8bb39f82e083c00cd0da78958e9f26408..9c353983a4aeac06674a545f8150d80dac12395e 100644 GIT binary patch delta 2319 zcmZvddrVVT7{Kp$TPjk}ZajhyVq4u5H(db1iH~?yKwaEK7wV9Q&L{<8bIP280&@yA zvhg@`f{zG-3R0kOfbtR%k%x-l!h*)Skxio}>PYwpGKc$4dt17VHvOG@&-ebmb9)DL z4!`Lf426!+LN7S_%Tj-=YUSjqoKPdK?c%Bv*T>>2V@fZ?o9t?fkrUgL+n^J-pXXS_ zE=)3Fu-p`j!c1|U!i2>%Y-&M>SASJ&8W*>K<6OAe-=?LdaVk#n6I+#>&`(@7pFurI z(D*|=Ez*?ppd+E-%b*ykB9-9-aGz#ut>R&jEQyMSJ0w3!jVjGiJNUF}qKaO`7ESa) z$Rqcnr$Zin5$z19FuH9cjF7_EX>`YSA3*DqpZ^X8^uUfyJe(!BcP2w23E33_CX%&l zwqs#6OHsa!DAL_Y@2(`=ULUg_9h{6=Hg&|DzW{+8%lJMSjPZs7;-p>pPM4mUDUM@R zoKhliOoJEf^?B5f)Q+KkMC=+Ep@p#n60GQ8!dd_mZTkY?t=2N;B-q*i~UG#{;PoManxE$0A9Sa^VFzm9!6D6M6FVnVFW_^+&LFPOg+GCn+ac z#w%nJAvqDcNL{iPIqOgq^pTW9fBwHxl5#k6!rkR`OUei~ii95V#2&;QnajfvS$#}J z=usaW%afy#=KD zM32A1o!2v8&AkUrxKzgK^+gp^Il_k(A>bK}UO!uLqpM^b<#6 zh@L;OTY@J{p0yE5XhfDf;LYCbW!Rd^?5|z*=EGojUIjf_oD%{DlA1FEc_wEma==X2 zToqpX=V~XkGUWQA^pD&*V4#j9Uj}+|A%81!EMEh98g}|SnR}}_+C1J<4R%N1Rlzxa zfypM~T{wQF*xi~sHo18`r+OL)y5H1k*u>OE||#Zm3UOyRrW6O`?C4S z`Z8ZPTaiIF)fzHZ<^k3^1NG6>kcDV85bb;7#|@&u4g(a_5H}r4SvXshLy;! z2CbX50M8IR*J~R6YyvlX!HLGbXgAh)3)$VoypA?CBkP)3(BV6k7zOrHvior)^$jTWh8*qA*V(hN_&Pf{K0R*8gzMXp zz1N>2jcv^F)3!6SM3-Cu?>H4t2fi2Hz(;l^72fc*hLw_`W=}GFBN9zR+XIoA?cHE1 z3cCq7RZU0Ago%*n9p0$w+8JOI|Eo2TomnV;*%^Uc-^Ci_-i^u8pzbu*h>lw<(~_Q< z*-}XHq5ALugD0;@55ZuF>P}0MikbT$Uc9F}^)M|lugS=C_-QdBgJ~xn_TH_A7$sB%o a{H-xOF5r-tb3#GcoHD1N(76g2 z*(jVjMKOXr1SwFsK+8h~L=XXCOBW>SMmCL_Oh5Fb7O}=yQ`QQJ4ZqF|{ z4kI}Zx)L!o^B2VaqRia-4n~s6a9YdSZdp~9^{!?(hM$KKb#laGF23a|;XKk^WujP)I@&LcmD! z5iB+an-DGQ~n$TGBo31GM4BKr-`F-=^GtdY9>97 zRWWh_$50KHv)5-)KSnu;nI+U^zz{q!f3h=6-nmP%#Hit9t#?NE` zW8}%+8!*N|daq)=F34i_+f;yr7a7lR^=ckqd>}k&}gyP{v1``C8;=FhyI$$`oLC1fCY3 zW0x3hBG#E<*IK%(ZKji3#4-wj)j%QSw8T*Ag~#?@X(BSHY%`LS-QeWodaN zZfBJTATO8uBPYtkkwFy;kh?0@Aj>MEkS{Cz9L=UU*H?(9Wj5JzaS;mAFS^gR<|R}( z204QzEhArh5x+bmX{-DYDXr>3j#MQh*IhagV5~|-sep9^| zX{h#fwG|m;Q`M5m>e*neGf*2h$LiA{PzX`a)*&Nl(E6gI2URDMR1TDJm?YwPA)BFSe2 zuu_THMj_&iWUS76o~^O~){9eRc!&hn!5WE|uGl&-p^?KbyeSUT~syAKFc}-bD7bQLiuB+L6ueH1gwi8aeUuGW;hky6jHR zUh5T4ddRxk;bcQ#FiETxza_C@WU>565o+)3u&KAK_~q-mUq&F<1^@rOzGT# z9O`_C)OS(G54+ATu()IbSn(`89e6Lig!k-9D!Jxs4J#z$?J_cPEe1`)y91HA-F;vz zjkpdt)ySTVX%iujd%RKAr8mGP{#R>adh<~Hq&FHFdV@B|tq+sqgZfmo5j{6)rj>*9 z$!q;p_|)D{zwN*J>2Aj@TE7F?JaEwF+r9^6bbvNNIylvY;6d7i%0b!$%`LN&v-li6 z@mqT{F;q94%WVLFbu;Y0`g)9w8!3h=g7jJ)lr)tT-aA=l1t8yOei?xs5_cp>WV z{Otq-eAA=*j<}qeXmfHIFsp)`m0qH^i$p@2l)$=z=G1Oi7(KPo4RRb0EGXa%LSjy1+ec)0hqJ!NpS%IsIy{Aq5}b>vjtC!2?6wzkyuaxWJIbl7sVSYvd0nD?gf4%_$^s{GyN&x|k dv$BH1vz9gi1ebI+0jLE60000qw5HJC;!FE-1#wtAk)BG^e diff --git a/crates/ide-plugin/tests/fixtures/inlay-hints/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/inlay-hints/dist/plugin.wasm.sources index ac690f4be..e4c12ad55 100644 --- a/crates/ide-plugin/tests/fixtures/inlay-hints/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/inlay-hints/dist/plugin.wasm.sources @@ -1 +1 @@ -17137e31b7997f20beee8ddc1c30918428c4083cb7284ad505a4b888b1ba34c0 +072674781078ba19d74b8f2ceb023edc23a822ddfd32eb8865084d42fbeb2b71 diff --git a/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/jobs/dist/plugin.wasm index ec949d20b1971fd4c7e71d2d0e94909df1363148..cdb25003e049eadf3c06ddddc9d0de7d999db50c 100644 GIT binary patch delta 2588 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 N{~JAN7Traa{|lrIRd)aY delta 23829 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 ctx.project().map(|p| p.root()).transpose(), + // The `fs.read` grants: the text of `arg`, or the refusal naming what it needs. + "fsread" => openidea::plugin::fs::read_file(&arg.unwrap_or_default()).map(Some), + // The `fs.read-dir` listing: "name kind" lines. + "read-dir" => { + use openidea::plugin::workspace::FileKind; + let entries = openidea::plugin::fs::read_dir(&arg.unwrap_or_default())?; + let lines: Vec = entries + .iter() + .map(|e| { + let kind = match e.kind { + FileKind::File => "file", + FileKind::Directory => "dir", + FileKind::Symlink => "link", + FileKind::Other => "other", + }; + format!("{kind} {}", e.name) + }) + .collect(); + Ok(Some(lines.join("\n"))) + } // `editor.write` is not granted: an error, not a trap. "insert" => { let editor = ctx.editor().ok_or_else(|| failed("no editor"))?; diff --git a/crates/ide-plugin/tests/fixtures/path-events/dist/plugin.wasm b/crates/ide-plugin/tests/fixtures/path-events/dist/plugin.wasm index 043a98de0a31ec29e20d39564fcc002cf39e5e92..ab5f37c09c648518d651fe4f86075ed9c6760de0 100644 GIT binary patch delta 2268 zcmZ{l3s96*6oB{qyFBC}D5$K0{w$_QqscQwVAy^8)d4|&fOO{5i@-E-gC}9&kMg+u;>sh z8iH)#EL~|+VU>|{vr}Z7A(Gb^*UQFLX7&_w@UAI9Ml968?#`pM>v^NU z8X8l}fr^a29}H@wJBj#U2yRnZY$FG^iLfOe?fv3pXtF782aJ=}IDh2hxI>UnlDE!< ze0pN59iaMjd=x5z6Q%Tdyf?r-vV7ZpD5Or?-{GK`C=w1s5xJib4#UK2rw8sMcb)-( zJlGilV`RA^*kSBur&5$8hai!N$12HT#S$nb6^doA^z<=}V_v3GDdNR)5wqarlkGXQ zA6Gm_`)9jW!#E9291>#@&dKWlhH2bxfEk^=%*k4Nkq5d_isYR%WseI>Q+=G+Km+%c18B%_ny-yY$D;Be zFQn4_DnMVf{F98SBKaOnVv$M?o`O;0lfKXOAAQ1(m7ig@B3s^?7xQ9c?m6U2`dr8% z!|7?zL!u8QA}<}<3WG#?_>ccqN~A|}rj&-zCr8GyQDju<0>4s=%*7lICg4J&&__9yLX+8?^>mwatKX0wieq*tB)tMvWQd_1uB}PiU6EK^XJ(xMuWbH z5#ysOI2i?{^!~|NfQRwiU~G+l-hLFdF+ypgrxG>9dR*OEC zC+8vqbBq?6R`LzER4}VJdl46A?0k*DlJ?|8GO_7`Od_u#p=As4G4Ckbh18Y3jg*$> z*%^GuEO=(pRK5wtcIp7+Dz!f{T^)_osTUw0sY8)o6|u-;6~4%e72!xY=Qi7vibQ6! z#vY8B2-NQ!{@n>ge*Qh=ne*3>ahfD#kEX=MbjKQ_i{CWmDi=sbWipzKRxUz1Re2#p zt9)KH*R{rMY7$wyOYFeb5Oq?momKI8m#?0K46OD+eq7BXbE>1T$9JpOn$vC&yGzUs z6v&F2<7m)Xa|De;YClANTg%eut(|AS;v%!0NJJoi)vlOtD#%eLK^1SsOE%b>(vk}# zy3QGWDC(A=@BBI`?yKrbO#_hdwm5*8`WO_~)-#i#dT(d5#|`G11>)Mk?gli3Ak!Lh zCp_4ohv|(qC~j?J)&Aai0I9eTh%C7P>IVXqU3Oz{Calc^nb5{ePq%d=W82yLD{5zw-B;YmFYP(zST7}U zyn{X9whrDrEN7YJ2s!g=F9_ws zR{_Uz_lKiXM@{Kof~G~?0cQ0}4fwe`57qmwZ9xuRV{JHl9V1iSbtNnJtzMSKvVK=m z*jtIaH~LtynSD&!*!Q*B=Szjg>sX;@bpKmuzm65UtpB04;U)1LDQ%aMfEx~aw{B#| zjiU>UDhS}L9c;NU{1Uu?^%L*y)BtOT?*MB@!vLGmgMkVOK|uwDyeyVTBgr#FVAy<6SO}F^=t?Rg5lVxYq9#kMN~t_N zj6qTmEXte33oVK~L{VU`$V}^?GuSky$&6GwI>uC^{mwovIMF|!d(ZiO&+mEmZkNGI zXRy+S*Z|>|+f-R+sjqi4wpolqV}7=npW}n3eS>*zO+_Q-1<-|R$fU5P3p)|xW=(dn z$vlHv`pn*n%xC^FiyZ8!we*@v+RdlV%3B6n{_iyrEIvY`U$TbFWW&1o$UW-{poPfd z0?`m2*T8~`jC~LarAQAF_2DoK@$&d)7KVsnV*=^}lya1;S8j!eq+J<^e5Bk5xg>Sd zJjmsbY_bDTlcIzectS#xUHNATz5qAL(#?0EfOp#RE(=8@DRDm(k~@i!U?ASxJn=nx z+er|}y=_r2N|q*tI*eZLRxv3G2w@lwt0eoA7DF+qO7eNRdw^OT^RrbdhLb25s$dn9 z^(^Yglb&G(e{Nq1Px#Q}VF?!Docbn!fmiMTnAz4(ovgNJJkgDcQMB=CJ6&j+xoLfH zlaKxM`zbU;lAg?t50D+{%b|eOq^Eig8M9o%FcwF0P?+{OV_u*T_~2cY0Oe#P!{0`w zr%^dj6!5OQa{+zvm7irz70G{Z3XN2@_XOM}ewn-6o){B$toZ`7Wo$VaC*dUK+|}e_ z<~(fqNM;6flh}R9$n*O)VLM&-|MA~SiR*!5Q|^ZGj}MGvqsW-b1%BqOvKO&9jGuBm zNOX=bPFaD7Gdrf45WV5N*w*PAW=CM}DMxxp7}E@nWTN9Jd!M zi?sAwQBFJxmg9M)ktGEl_}*TSJf*LoLO-;AT(}U*`MkoCX`mrq#T$_7;`N~6M~ZW% z&DI)Yd9f~X5MyZhjIwXpC4y*T?HM-0+S5H zLn<~NV^91!QPDjhxm_BmdSO00J++;7;#MM29Cbv4cvBI(m`uo%H^dbkdz27v0IPoyWvj zFC=lei(cT4E>0YlvwYg*WFB{IM!~x7`^d11CV!{!eR_{Oa#0UWDZYnJf4C zxRK)i8hm?WfEJrQKzEx5z7c)CP-udl7J5?uzl92VTBwh3UuL>V981bOT}jY22cuhe zvh~`*1!fZju`&l+HUj?%p2M1n`*vcGw!?prwnIBeCv_|m4J#7^1H+%~t1TD>^Z@B{GTHzD delta 126 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 delta 2607 zcmZ`*eQ*@z8QWkW97UWLqU7Dp0Bn3JR7=1Qn;&sRfjy zWQ@uwv@g1R95DBDmHIa_GzmHW=7##P@zU61VF`4&6XE zZAO_>cRCGcz`${OP}I#8BXT}8(#4|(n~m1N?ual!4_q^<#_LX%`nL)1GW4n&_TCPH zL;I@5>@Dq)fUwdt_=iA15L^-@QL;*6?uG#Qa)2$Z&q6JGk?a+9NBuK)w6OTbOtSfn zix6V#8%wcGJ<#}pC|>*v+ubCws-{d-vD&5qG^^VWG>T|tbDAGR1AD*OkBh9m`B!91 z4wjOwJh&z+(5;UzvIst_rChT9Z2f$(D&(u$ta<_4z}^K!ojU`3A43 zuO0q{C=Pb8v!ATNt87uEf>`a2TId&JPF;l&AY=?!mx9PKcfEKm0 z6&PRJp*Nc477XQT)e9%mfDShNc`G{9)<5qaqlT^dqLL`~eKA8EIK_PJt8!a8(msKwK^{1%{;{K4Kh*S7fw3mlf4Pz-rF1g1vG+Qk zqm6jGGP0tawWrTGe7oe39L5HsY(dv=QO8=lD#;d~eiTh?%jtjq|3=xCGr=*VGu4&d z1D1^DQ@S!F?uNJZA96eioS^%y>bjl+ktBNXA3k>cY%#jozt1k={zvrN*1JH|+S%%3 zKSz&R)4LJSRR1?m(H`06zWIo%U-#V$I+k0{SCPPt=Qmr(kuS}|7WGe;QuIvScQZ(* z^WQz6w3XkoQL@Tg+0&ORyxVx(Zz&Y5emeg`F|Hyeyu6K_y!=yaWA3PKXGeWxS4Atw z>~$epLfQ2GJbD=J?B8xjkahp?2-)e^79ywyuWhua)bUw`VwxZ3j5;;%zq`aKnwb*a zf>>^xK&VI8t56jDme>NnRSvQ5ujkS2P8wQ4cJ0vpWKRrjP8jLow@G@*^5KOPZW%5k z`@?W4v^R?|pX^%Xkll$p$^I1&LsLqDX#`IK6$FidH#Nq_>UZAlhCxOPp9AP=)RcdT z_$9$C3qB=qTd|Vh1uNc8i!F>J7M9sD&a$RVwc#l$3fVA;;Ft}Q3BI?Xf{S*P5M(+a5zKI49zx3N4$LxlvESmenv!bDB?n%n zl4s+vju!OCVJX1_@to1`H+n~p9r5rsh*17H&MOjneL^5?t zb)twylsl15-osAR#tz3Sx#W;yci|yQEOGI&Y8Q%=&Bk+088oHM#T#63VJ4O5CE$%4 zeVo+i;{-HNVwIaqP~*n$$V(lEpAgI)hjxPOM5GdwCZd|)a3ZD>^e5sgg3mmB-G4lI zk-QhiV+z6E@%TGI)dXJIGy$FDy_&@D$l)ZElQ)!vN|SKfjps#E)+A$^nModDI*ya)%+N2e zGCP9@yIZy(KWPbQX8i7gA?67*-q+U_LpAay4= zi5?&gcLXMA4n)v!qW)|Ee5A$I&73BJ{m>}Ti zD$U8&d4$*IBA_cVn8#_IEkKrXPd?tG(A9jdL-8b@SvCnf%=R})kXXPam{suO609rW z5>WSV<3=u{Br5YVkgi-PL?X?i?p`IS2ruOrX_Sd^i7v66K0d>kGwRyzFXB@56>+JS zPUh$N=47m}AsW6umEJnyV5hRE7`HgLcJWVxRemS@Mls^8dSZJiy(`+n_A*qYqAC2q zeK_YNoVE}j+t8+5T})eVQ$kDdfjHO|p7SW4u-q3st@klMV+oSgcx(0W0iJ&2`$jKE zBN6@4gmQfu($Eu5eH_0Q5elzcjt(8~UxC-+&=T%mjao}m(+G3=x8(U+Z|-tk4sUu6 p_4$Z|%eG@Sl#M&kZ4(7SXb3Ogi30j75Dtd0K*X)#-Wt4L@;}wCv_t>^ diff --git a/crates/ide-plugin/tests/fixtures/tables/dist/plugin.wasm.sources b/crates/ide-plugin/tests/fixtures/tables/dist/plugin.wasm.sources index 0f9e3ec65..e532820fb 100644 --- a/crates/ide-plugin/tests/fixtures/tables/dist/plugin.wasm.sources +++ b/crates/ide-plugin/tests/fixtures/tables/dist/plugin.wasm.sources @@ -1 +1 @@ -92654b80a977c272264c15d8b608e8bdac6c5d5612a5da2707bab156e655f615 +768198dc62d18f2c6d6c0aec57116df79ebc5a608abbff3d9912bdb24c893787 diff --git a/plugins/README.md b/plugins/README.md index fa14654b0..4aefec7f5 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -250,6 +250,7 @@ machine. Users can revoke optional capabilities in Settings › Plugins. | Capability | Risk | Unlocks today | | ------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------- | | `project.read` | low | `Project::root`, `read_file`, `find_files`, `host::projects`, `publish_diagnostics` | +| `fs.read:` | high | `host::fs::read_file`, `read_bytes`, `stat`, `read_dir` — files outside the projects, under the grant's directory | | `editor.read` | low | `TextEditor::document`, `selections` | | `editor.write` | medium | `TextEditor::apply_edits` | | `vcs.read` | low | `Project::vcs_status` (branch, upstream, ahead/behind, changes), `vcs_remotes`, `host::pending_commit`, before-commit checks | @@ -269,8 +270,16 @@ working. On grant the program is resolved to an absolute path and its content hash is recorded; it is checked again right before every start, and a replaced file is refused until the user approves it again. In a remote project the server resolves and pins the program on its own machine (see _Remote -projects_). `fs.read:` can be declared and granted; it unlocks nothing -yet. +projects_). + +`fs.read:` grants reading outside the open projects: a directory (its +files, at any depth) or one file. The path is resolved to its real location +before it is compared, so a symlink pointing out of the granted directory is +refused, and a sibling whose name merely starts with the granted one (`/opt/see` +vs `/opt/seeyon`) is not covered. Granting a whole file system (`/`, `C:\`) is +refused when the manifest is read: declare the directories you need. Reads are +capped — text over the limit fails rather than truncating, and files that are +not text have to be read as bytes. Logging, notifications, status bar items, tasks and run-time contributions are always available. Calling a gated function without its capability returns diff --git a/plugins/official/ai-completion/dist/plugin.wasm b/plugins/official/ai-completion/dist/plugin.wasm index 41b13eb14bdcdb428cbe881e3e6e76da738f47d5..157cdf6436d6b3b5831c4bf106e5dae03ec5ba60 100644 GIT binary patch delta 147 zcmdmXf@|9eu7)j)Dte3)wyWwfIx{gYn4W3CXwJA{`$7Z8mm-X7ws*TSuHj_-Gu^_U zF@W*S^atULlG_*gGyY&_oHBiOIHL>Wo9#fcJ3@>{w(reiJi*CyWy171;f&4@wYJ+i zN*Uc48Lw>jFJs)t$oOYFUj?HVBjc3qk(G>xo=z8!XWGNc#K6F?XZxLarYIKx)^9dc delta 151 zcmdmXf@|9eu7)j)Dte4P+g0@#otYTtOwTl6G-q71eW3y4OA*Eu+q+#E*Kjiam~P?E z7{K^q`h##r$?c2$8Go=dPMAJBoY95x#de_B9U;a8+xKQMp5SDZxRDG0h6fp zh0GF6LYO~Zo6~Zn+j5*}GP`VV`)pyAjd#VF(%{XIYM*a(k{q3c&y#S9MrGh;@_Us% zUS-WRMTt`;S9-l(B~^((Y@(* ze)+&$#De|Lorfafy-L3?g;Iggvw)2l*JFKjdIC zQ&)1(#L?>)pa6q(egU$^4qEl;n5~!<_0g1EOhr2_$;JJ5_g(MiWa2My-HPVW6;ns( zBP|45wC3U_TLkj3z)mVldh*fi;Ie;SfQ7(-jCvTrSI%5B{pE!_sh^SV#c%@`DSZjf zu==$nXuX3P1&dIQS{h%>eGSkf#aKJ}+!yEKfga*%R-Vue`L|*m0=lUBQDiv%H_YG~ z^niT(QPcvpa?#`P-YH!FQmo-{`OB~im+3Fd@SLc+PDRU+ghpDk91|F-m*WTMqif4K zvpy<)0#EUD-+ls@zFZ}(T!FbX{3Hs$ER!sINS$yol$=99*=}a3$8eux*Kp4V$r}Myz01y%EcBT%O(tU)1;$R@5}%_8=1Ngj~7>En=Dxk%>4(WZQ=(SYw{2G@*DL zVGEC{2T7~oUYEhXYI(Cf9&deZGBLRj?tTs=zL6f)P zF^1>2;a3dvYj_6@>Zrj1ceu1@&dTwva2>iqCABk-Bpu z>S0!Nsu~MBi;=xJ_!3qog+rZicvLox^wFRR+j&X`E#3}|VcmA#nIQdQJMt34HeHTX zb%eph9oWVy2Y2AdY>-li?=pDntQ?QkVPeG2?TNaTr9u65n3WOs8E>Vbjn>q{xNy>X zNT`j@6!GCYqI826zKp38!&P$6r|8}-sZoybDi~DvG6LcGs+x=EJF^~3Ije?xzVw20 zvL5LPk;sLS&KY#Gp3lBP?gq?dSlWR4TYjAEXRrZ57PR=S9`*ULk*S5RU?xMwEBJt+ zXeSaG%66iL;nGfggCS)X&NE!yW!c@=h|NrOG-4XVxkg-I_~~v-^B=omF!i%0Yrifv zA)BcO2<4H4-M3DlK|w-BM3OL4@+sl_Y`XeY{DvWYkLA5&4^A=l)n+S?;$|z4-!)@8 z@29#K$>x4~_VF8HP~JYv;z#@N4pUhz*7k2|v6zJcBvaQ>jH35jP!oxNTW00^t+RAs zzqLo*`^_^zf837}h8YL&F+)lq>}@Yo|6->MF|Af^S*_MOoovNyW?pW^yD(lmeUP6Q z-o``Na_6AMZ9HIuHnkx$qHtSR-f2SvD?EOf?^T0-a@cCl<|AevvhxT(6U@E8-AXI| z7$(t+?KsM;DMv9c+FnP6hL0hQnQ6gL7dA&i-PQoT!)n0u9U~j?dWY2j_H8y`=$I9W z9qqMm5ezSHW<&Q5D)zwSgr0{;u>@4+NA%Bwy6X7MeW z@Jqg=&`axkai6n)*m@9E{onF%FJe^Yzi|f7@@t*^F7gvmCs%!l0ViX@KXG~#dy5(5 zqTA@LL3DCkO8$#7$EpFZdBMh4S9!gP;?iO@)xO`3hXf6_fbUaV(EEQ1M!1sGKEo=3 z%W~Hh^qKg~H4H`bEBqaYFho^_%uvNyvp`prXmsEP1!Bao2~NTHwmj<;FF3~4S#dRJ zBHm{v<#G+n(lO%0S^W0pEEL}plwBZH3Kob!jKUwm-#%HqNZbQ{EMIt79OC~~GPzL9 G%Ksm<+{kqR delta 2747 zcma)8eNYtV8Q5~s~nIxzzwRQl}R-ieKW^q>9B z^Zoh0@BSrV|8v0Jo;4c%udAbH+qYjY>y#YZCDmUZ#5XLwYVjS0u*YJ?8APu|z#!b7 zpjo^@2;(zgiJMMzn2r++W{c&m&Qc$;lecR>ix{Aq=FUTb7#g5I6vL^#JP&EWU+L0(e2U%L*(^LH&`4vlu?2f*S2ps{OMlG9 zB&PbaQP0t97GM#s(xnB+9COvIPsMD>sHmGJ=U^&)v@{3zOzHlngOiE7%ymnOO_dBC zp^mf=Y|)&98(gg~7YnSUGBsBo8f;wl+l#Oe=+z=01n`}XLBn5esFP}k=3D|NaFNoM zqMOwRm!kPLY7{6yDcm%!ko$Uo9xBB8N$3A}E-t7+o?_++RoDJjh+{wtRX&V#yLZS4 zu0TDYz56h{fLmMqDBQOT*SiesI9%Rx?86uI@p3#Th6br%1roXW>sDYqL*)wm1l=^a zf-~!;;+1#;J@oEMT>EyFw0afh((q%*|F%qH*#q+Ui^1e<>X{ZJOEsGN9J7vlepP#A zHSQF=9#v2AHuV=FO$-dtT~FchAn#R!oLS66zcN70xya@jXuKHZz!mM0HCWGuQs-I} zqFNhU!gJ?QJyD7Z^l5)DMXim==hmYD2ehvB7-vX7dWO5)LU(MyPscWz>o{Wj)kZq9 z0eMM2Q{b|t3faZGkt(9{!ejN3Z6oIJ63q|7mW@bZs%axiZ|l&x3HP&n@g_`$PusK! z2O|+6`(~_SSi2d^5zx+Uh9`1dyBRfAI9&)wYuA=-Lz9@Mhh-vG5?R)v@mCq=DOE@= zTgbvCtA0|-IG9d3Whh~2E5j0oZ^}>`6ZGSXPz<&Da*nRkzsixpFvY_MRi{-R?j{>~ zkj(Ib2lE(WD)1OXNd?jw4pks8+43YSQih0EWF;~~M8%ADSefaBO2k9g5-N>Tt<$6( zc!c5k9r!iF{3_l-om#7K#2G3rinFr)FjR-CQ<0bFtJ8;Ge2?KPFYaPcUc~+157(U& zRu8eFQsfv|S&Zz((HF5gF%;^w%_XyGxQ{xG-^o+bX~|9~3>$Xx&iLt_oybiH*|ghI zn7U#)Pn)(-nC$OPzYFF)KafGtNvy8Kubiv7w~Z zpimi=A>u-HM5;P1dY-VcV9?WDY+k+1o z3icv_p=2+r7_RNby$s3waEamTeWu;rb=b;OYaOOBT&%-ohBx<{nxE}Q4^wZ|oBMUG z9$8G?M<@*^?7VpbbqWyD!;<)sk}nC*vgz6b_$@=)LDPHDL7ZjkyA5U@g$-sNzi+^F z-cR`ul8pUyHS!yxQ*NVa@v}y}$5dvMx&2$3OlH0hNz{H45%fV5s>1Pa$*lCSd6teG zHutFGuyF?HPlr*&Fyjb5XGr#iyd7fdpX`(&y4lPvv)NpyGtHRI%AS9SX3akDvFPZ)V(h)hpWZE=0@Bf3+LW@N1p)KJpS!p{@A@SL}?7{(*B5>@B*F zi*BUX`_RU1Df%}`Y-@Vm#swQ!S>bj|l0%76Wb1wl1O>I0fbUaFaQ6QcjBuq*`wD9W zzR>pdRSCttJ}Hoz|U-qtSI#m{YHE6lhG z6cOh!l5#luwc^p@lUe-sWiJ#z7Sz5-_#%WPNxHUjvA7fbMwUG&j`8o5HYH!o%KI-x Cgu_t) diff --git a/plugins/official/checkstyle/dist/plugin.wasm.sources b/plugins/official/checkstyle/dist/plugin.wasm.sources index 3937291d0..d11c3807d 100644 --- a/plugins/official/checkstyle/dist/plugin.wasm.sources +++ b/plugins/official/checkstyle/dist/plugin.wasm.sources @@ -1 +1 @@ -7e6d23a7ac4da5429c453ec33dae8ce4e19ca87114a741b289cd4041b05fb59f +8713c59c1e6d8c8210bcd19c33e0b306df4fb3bed1d55da8058625d52b9af7e1 diff --git a/plugins/official/csv-editor/dist/plugin.wasm b/plugins/official/csv-editor/dist/plugin.wasm index 46f165e97e390a9de54bd6832f98e5993964dad4..3668c9b519787259df820ae16721982de8c8f216 100644 GIT binary patch delta 2670 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 X$N!)~k5L8Wm|`+A0?6?y3l@ zp&a>%imVkYQmk4RM@7`65V@4$MqDlhwMr=hX``h9Yu~>YkV3-u|MT9Pcl_`DJAb8F z4X0V@>TIA;thbppS(VpR!pK#OaK*G9H?7U4)rKlNOb_a2qp>{|auh=*P4Nk%#=#(L zG(KdR%tuT{j#Qb|U{sdq=_-Efv}7xkkze19|8s9&iIQg3=y}4FgB}( zOi$oRe8PRG5~C6eS*RzV+z7YGW~Bmcl9XFukn|`+kTX;X9-8J7H4_`aG2SvRoR=+D zEw^WV_N&!uM$m{?RCa*xl&YhlN1U>MDWJ2M1CJm>3_rMng;YWgB|;`~NR9-FtWNg9 zePZ%a+)qha3OytyCCs6xiTW2{0mJZ&P(=z-0w9Alrp$)x1T@pe=~>jz)cnh4NW?M! zeGIwd@O=);5WfEqKoXCn0XXSusJ{q%#+0N^)TX-v=*iWLD$t9{%+nLtkhx?#)|*Yj zKtozcoKL+Wt3ZY^`%!>kl<^GB6a-1!nso-?II%ezY&%p-gQ8R;MjX`u42pHf)Dy+o zlpTw4sv-b;o+l&ct$B{;Oo@+>{u9$-gxKVKgGZsv*^YdcvjIv- zgm&QnWs-=KsS`>Uiu?~l-1MqCLyDYmPfIs~4bKX8u{#*C1DL{;W*F@VHnf$;-0UDE_286nUsT1bMT3Inutu3mI6k2pLzg4p~_dj2y0r^fEb+@k}V| z%*%MIP}bV+4Y?^9iEOTP#%bSEiFZ#T2dh>g^;H$fQ+HyKws%jtn(MH}G`NqXsjd!s%TnMHi>X;;?JctdQ|vKCv(iR4bCBztLWVC|j!Pm5QV@E+ zDDlWzDH`&KS51VA*!&(L;3O1r)z(qz5v$DIQtS zG#}aBREyL#yC5r@Q;<>j<{(w~T9Ip8sC{b7KBVpaK;-=Uok$lwwTaL-Bi&o+z(lo% zBQsjJTXJ(9y*U!GYYVn0oX09wwta=~RkYnjX0}tWrR}$n$_^U2u!BaP)A8}Q}{FhP1~P_ zTGZpJp7|^t)mNW=j-1j%YwzsA$fEu4YFcAjFHK|Da}Uzidk%L=e=M>#jS@pP_WPqq z(@zWCXK_ES$kTnaNPXXEk#9VwMece|i(J!By=(e&OgEedyx0zMHXJ`3uVLAkiCR2B zi{Cv!i~nla% zl}_-)7S{_Nu+SPhih6yap2hX19~`lUk)nvXkjqUiGdcmDbu6aeAi4Z}(Lcd(1b;q@ nlGcC#$4b{isttpGEdI|gTCooN05%mRtOt&TxFTf?ya@OYz@Vr> delta 2309 zcmZvdeNa?Y6u{qkZ&?=>0{j{fkjH`{7Jh&*X5jEFm(nRPEfw=?)KQUUoJujs-4zkg zA;7tef~={j1c?bgbyJxM$LE5Ie6G5HC@3iz0#j%jd+^N&)7(pkV)w%)YUe%z1FoDUsjMP`(HM>F*=z-)%$8KH`lWQIT%Y08`mSKoA%t{ungh54*(=_Zw`QG$xZ4{?Z()WED`m&UH}c`TwV<{h?;#zN3bE&$wsWV zkVJuw+$KqZHI}SG8OH8M1%g$^Gc;2WByoNIF@QYcyg%Hfzm5h)sZLby&jRQc>ksHg zinF>f5#!t_Bw!+|4u0j^Wy#j#VjA|7QSu6&<2hU61Elxh1Z=Kz(bw1tP0>c=Bn81hZf!$`b)3_4o`t zms7`ASe{Sg{?ds>P)pp4--j-;X-~AcuUHLGE1G{y!ZOLc(uFV}9w^0=&n6FkN(ZyJ z;pAoxADVxThdeRp^f;=ST^@yd%b4i)Rhuraoy(3@$?CbNu+v%jE{33{Tt5`?pS;>rf3oAeQK zxs>Z_^`Ua&smXI`35q|y8j0L}H3E6*>O!QO(H|LVoP$g(p+Oi9=?`{bh&=m%U*{9)8Ia|CoM?i z^7SM%nR??*`)&oJxi-I@%?Xl-e-# ze5#g5*44&?p7`HXkGI>Ga{;m;#;G?m(15M`7LB!atC1abG%;npkK+|Dm3%NYiA2@E z6K?nBVF}KU;$?Ae_Cy7%k{=bxdf0Q93lb@*5Am@VhRqEUbeaG;XFq0%^wb}*AD@g@ z;_($Ue1@6yHH2V>-iCMT= zlIB^+&gME~xoJGI+LVcmyEP4|z14zTcAMH~-`;_Axf6<zM_>h*G4B~o*jMy|L^BTs9eiG#MT z-H#4h+Py$z@jYsK``%Tg{yv@Fw)<3a`hg$u=y4*U9hr`J!xE|KpjY5^2OSB%69?_bpFDrtMc-ukpv#0Zk^j4&L#gM>FCbmizKk6Y zm4<3h=yJie%om~+U@|-jf(91XOTn;L0Rsm0bU4C|skAx)p7ppu|3OOSF~dLMuopj{ mhV-Q%z=3PaAj^qm7-ps+ApwE`mKxHQ1INNTL&get7V;mt2cX~p diff --git a/plugins/official/key-promoter/dist/plugin.wasm.sources b/plugins/official/key-promoter/dist/plugin.wasm.sources index 37f95f763..dfdaa2126 100644 --- a/plugins/official/key-promoter/dist/plugin.wasm.sources +++ b/plugins/official/key-promoter/dist/plugin.wasm.sources @@ -1 +1 @@ -d2992f8f58b131ba05e70262d4c825f61449c3b45f6c9543eb90f27bf8ef8748 +d558d709d79c09dd1d8745ed65d3ce4b2c4083e1922522c2b2328c46f0d9e54a diff --git a/plugins/official/license-header/dist/plugin.wasm b/plugins/official/license-header/dist/plugin.wasm index 2397657683d747789b0fa8ae44239d5fb7df6532..d7c80ac1805ce09572422ba988dd374103a13d14 100644 GIT binary patch delta 2804 zcmZuz4Nz3q6@K5_x3I7fmV(a0LVYYoQKJSyGz!Sek5p5u2%?~{C@M%0#As9ky2iiF zlq!kDYsa+W*a_50TQX`cNnSeJNl3OCjik*G)FuH7iA^-6oi;I(8PoIb{$%aI41An( z&;L31o_Dc3>do$`o;7j!=zLk+Ppqzyzk4O?K1u5s@#Aj-Xfl|J@nM#qPyCAdupbYO`tjEBnT{0PJipXoA5Fb5;&n@PGbJfj zO5g8xyQMVAcFsUm(k{HP5AEn-HefF9@Wp^nmfhEwO~FF>MS&{Ys^BB^^T*71MTVDs z6A2gE*=h@%@UdnKsxibqv5V`zq^=#&V1?R|1lFniZMA zAS;f+4cR@)=f$E(Ce>%-@U*;tlttLE7@cgH4e8PQM~%>}RlxDIM-tgl8}>kFmUt{R z48$WhZcrqrVS!|%)60Gxk7*cTzIe>KzwK{^w(Z4dj9g8cWXQ-`xQ0v`jvwJJPO{_# zJc=<+Ay%8v%io%ay`ZEYwxb*IzH5f1#lZqV)R! zsUlHmI=`jjEO3*xJCPOb6V*_m4f4xQcmOXioecMQ?moXCb>wd46db47_-qQEB&vKW zl2iJxi;}*3fJ!P^)d)3Gjr0$d*3a6fVh23ToI$~QSVIOXDYMHN_~$tFyF3kT`YYnsWf&z6Gw^l@EjD&gM-YGfJgjemdEW` zG)5TYu58p(uI$oW8Z-A*J}C!FK*qPs!$I8SU(LfVh0JZv#R_;h&&33zVwdx%(zjT2 zK6WOwi6IQTKUy1mJ|Bg22d?GALGX1x781-^B%omt(uitbgxYa+tp%7v=lKPgjCNjK zfX^Z*=%s~NOYl-5R?`^XEyRI{37x`ohHQ5tGYDlLD3$RmzbQRYi@+ku5RzSp$*jOk0IS=)80l zJqn~#U5XNd-cr0nux~YuoX);jjnnpEY8Hyhv?Q2^rn56^sFymsuMATN=9XbPK~)*% z%n0TESV%m`vZN_72t*NHiyLKdB?Vpenw$!$hU%!Z@^b2u&VEr2mEiZ~G#(x7`*JLv z7}V)8r72+wYuDm1iQHI=7E*AnLluE{orv+vb#R3A?9PZEqSRSR1s=)@+O&x<=vFDq zV}n6!{zEk~N45p?h|qNAslYTxFiWcWWX-)dEy5HW1)W{0KxeSOifX0)?yf{BMRlc; z-l`7vZ6z`jL!Ot1DyOr27m`SBjSG1MCtNuCgPmxy^I#QTrh|{GM2&3gv5P3rddw&I z(|Wv5(7pi^3A#4m2*K=X%qDPE<0`>J8--r|Mzj+3#YW5|uy4Z01Yd6wl2bP0L!!Rh zEaq!=4GM_bR)gA5!1lthfN#|xD|C_=ev(y-?WForE#4z&+9Ir<*#e!Y$~qCpb9Ew) zxF?WJ^ZDo#NHykjLp{<74%Z8fSL@M7RLfQ|{cmg)%wyY-%EtD<%wijGB;@~|$hsTE zUHY`an4=So#uZ=_8nK>WS0g?raBT}3J4MutCUUQ{B~2o zZl`5J!}uijj_>oi9n@c)y|Dv1A%S~}V%~{kB=EvctRwjMPEngTpEBa$x1XY=K-`Ai zBCHipBZa-b8^0yi#y!Zl1g249i&~ID%-R-z5n4m8?#X|Dv&g@*!SR^Q|Cus%CmMOjw0in9ErRdg(JFKW!Rs~Zo{n?zp{?;XSg z(RV&IUP5}+Jg*+Yn2Ff`@?a~iV%M`MoQRXW>oi893ER%$k7inPkM~fHJ?y_d_#KA$ z*;i0wN*)_BjM#$fE=E-XubG$SU8LpIFCe+!FZMxTD~5^j#*5fQUsS_AR}Rj9J9 z&oE}Se#vVGuwVvy_*uwFU@K%DSAbnB+zvo4=;WyJV8gjFgpS{{yBs B!?*wd delta 2794 zcmZuzdr(x@8Na`~yRfhjmV(a0LcO~f#dj3NM*z8bNHw*JAPNeLqJjiLj7BA(n~1uZ zP$e<(m@%z7b^>*5OU7%?HZh&eM3QYrgJ~T~j7h+dgr=I(PMhGwG5zk@N7fGi>~FvC ze9zzc&N=t3&Y1I^FR)AR2U~QUAFTv^byzEG`5s z%=+TRpa5MM3JP($AT<3i*ppMPe;RPq1_F2|Xf}9cnmrBu=a$%QU!i*}r4R$vZ>`69qC%Of8#s}T?4MV4TMgKaV5Z}9U+O?XX) zmwguv7d&j08BX|ElNnX$W1pJIzmFxypb5k5a12r@+L;){LB7++ys=n@o6MDj6z;HK zCUAun#o>lLGRWt~qfjQ-XA|(0e0z{ZS+NMm*itJpVsDGeEtS9#$HU3&kQKY3F>@l8 z=m8RulW;{?s8}HB-E^^ECt?z=Gk+qc-`{#&@7wyyGkU8ARnl!_HPS;S5BpDWmpV;N z!XvoJsl+M+y7)U|v4^gAQsImZ z>xbBLso0NWJkbt}5{74_!3JV6CmnwHxap@jHHsPI<4{A)D++R`@p1)q8Q%ZjR43Gc zP7#el)%Z;Xr-6Rf?nG9sPq3jty}~a$;Q_q7WIWuXrTglB)KaSyf}u^nz^%A{i5tUePJxX3PN;-91NcX<-pMpx(Z zj>#A?pq-tZPUM{Af1HkqGIcTV09K%j&7O(!faGB3X5tX39-4(B`D!1tC*k41nB{U? z7L5_Ea@TCsQLpUM92&DbeSBOt7K8SC^IWu|pMNtKJB<`>Qx2BH&3O*S=!{*?C8h^i zY#w$bwSJ-Z9C3WqR`x<33g`@6%Y&WZ+dMif9yV*Cfck}Skkq~qHKY1k@-d6n^YSqs z9$uA?FQYKTmK0zO!K(#Wg&}^o0Q;iG921!{Wt$V>(L2VE{sO;}r)l9eIbM?UgPYLy zcfHn3S#lae9!{g$#wrUbna1`PqMG1VA(j$6xB`dc0&$!sMK|kRLD@Any$IO^8;j^n zYwUOt3JGo%VH`nxG4cq0UW_t=j$&jHd|ZrzaluGNMaq_w6{8ZBEt})+vji*Cn7R_l z(0Iv8x)jK#sszOZ-V(e^uy+-WoW{Ohg%h?=Yi6p-usGC*s4NfDuhI!OjSsCq;#(r4_h2ZyPG#+j2 zhcYZ08}jKgIE)bvYu4ZZncP@|W^!;yE~Jp%Y8P?|j=FH@$2hSR=YdL`rG-x_1xMC(*h!LS z9p(|dy$&A`w6Dilf{yh#NHC)cGYDK&_=sTs2H{t?0WBnby#dn*Y#Z?j!M7WQ<%CVR zO49e6#C*-DMm|Yft5Fj!*j5lx@Xcyug;$azSF&obja*-?!TSV_n?>|fn{k1pids>} z^R=RmgvT+P=JS!qk*?3@`Z{C~9Huh*fQq~oel4XiN)9BU^xFh zm37vOv-DZLK1W9z^drE=G+-UU&IWu%;My7rcATUsjg($viyK90&5dH3ZZ~29DQ9oP zpP_Z!-A0cI4dWBoGkVVFx6}S=?9J`S4jbGQHx zwBG-`W|4^E91q?h3h3%cu*muJTK#~>BKFzYB4}CJB53(bi`cQ~J*YO(Tivja?j-t> zc)t}>V~0P}Z$i4&+^_G)uz}S7@?Z-+#ja;jFc$5+;{*m{3ER%#PbPZi9_ykWJK2A` z@H_PJ)32f0kUG?_2eF2pyEw%dyv@8U_dGpLegUcefZ2z^S24njH=M^t`k?CPy&OH_ zPsbbh&P*RTC*Gk6_pt33X|TL(K{q`pe)dc^rc(Albkhxo->}|y@iM{I_t2Z}9}u12C1pZIpM)WH3KkHZJ`imVmyK diff --git a/plugins/official/license-header/dist/plugin.wasm.sources b/plugins/official/license-header/dist/plugin.wasm.sources index f8e01f0aa..b1653a867 100644 --- a/plugins/official/license-header/dist/plugin.wasm.sources +++ b/plugins/official/license-header/dist/plugin.wasm.sources @@ -1 +1 @@ -582fb1f8b6c24e54c70b1f6028cd4cdfed067482f4a4635d6e7720608bca3584 +2bb41b4e45f335141e7d257cd81a0cdcd767d77441d0fd2d12235735881f124c diff --git a/plugins/official/mybatis/dist/plugin.wasm b/plugins/official/mybatis/dist/plugin.wasm index d2663a440f321ff5402c6ca7276807a7981919ee..4174e6a1acc4f83b9f708fd53d3b7eb8fffa0a0b 100644 GIT binary patch delta 2951 zcmZ`*3s6+&72fZ^D=Z5PJAi@&#><+fCKdzQLLNrF7(sDBv=L%rf|?MNp^f4LlPK&2 z5=rYQ2+7Y=RzO9Ihza@w1J<;pL1!mJr%c4wjwD0sV~C;kqASfLJ@@Vd%}{pOZ_oM9 z`<(yrag({b$=v?B8FxO(HlH=Esk?u{;9q1=9B#boMoD9qxry)HXwsM^6E2MwHwI|T zK<}5mA}=Iz-q>B2P>)-v*^L%W?nbj~u}*d2Sn;_KaV`W)BhV@)Vz88a#d1MUCFSU^C>#7z}}i+3(tHHbb<*Qm>(GP)51D80&C@zr7g0 zLc3^RjDChr{#GIuVo-x%_LW$} z$j+Tqyn`UPn{Io7(cQW^UPH`pB!}Z zD{Jut_H$zftdr~(9-D#EsnjoJOsa#_S*ETYlR2plrA4gEgcDTbHS4e(7!tKF0hq#` zXnPr9V73YV`Fea#D9T=eeJV+wn1vkb*2yetWEsDng}m9$pALc*ii;;3v;sm=#jXu# z0_;3u6Bd|l|Iz9}{4$Zb38jEj48I23l>YLwv4#9y%|-={)7CezJ<_R{%`#q0vu5y@ zO|m3Q?l~ysKfZwol=6ri?7#(nFbA6noH=-v*>3X}H{GK!2;P?NBzfi>G!YM@z zxMG%+%S~GFil5AsfLvKphQ-p~;^&NVi`+(2y?-m>sPE^uf-0!7P7~$WhF?>)T(iMx zHl7oW`ADJx6*spdj|#vuc49RRYRgV-ZU^|CT_}NF>@Glokp^$<9h&M3LfM1qATo0= zRo~7l_hM&ApFXM&Y(u4wM;0PEs$XBQN^_XeYLE#`$=(U<=e9yTOWUo-1HS& zvOu`wQpIqkcBZKO+Yj*qLE=aF3xOX;F2N3thH#IfiGq<oJogGwNaYw8bdOS&$oWVA8aiOm{b+l@@aBdKqf$C?G2M2%aKX zc?4g0yAohE%2Mj2GalE7eI(S?h$jhdHsT7wpPO_$cbl-6s2$CSA!uyIKM8C{b;