Skip to content

Commit

Permalink
fix(plugins): allow loading relative urls (#2539)
Browse files Browse the repository at this point in the history
* fix(plugins): allow loading relative urls

* style(fmt): rustfmt
  • Loading branch information
imsnif authored Jun 14, 2023
1 parent 59239cc commit f193347
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
---
source: zellij-server/src/plugins/./unit/plugin_tests.rs
assertion_line: 2496
assertion_line: 2889
expression: "format!(\"{:#?}\", new_tab_event)"
---
Some(
StartOrReloadPluginPane(
File(
"/path/to/my/plugin.wasm",
),
RunPlugin {
_allow_exec_host_cmd: false,
location: File(
"/path/to/my/plugin.wasm",
),
},
None,
),
)
13 changes: 11 additions & 2 deletions zellij-server/src/plugins/zellij_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use zellij_utils::{
input::{
actions::Action,
command::{RunCommand, RunCommandAction, TerminalAction},
layout::Layout,
layout::{Layout, RunPlugin, RunPluginLocation},
plugins::PluginType,
},
serde,
Expand Down Expand Up @@ -946,10 +946,19 @@ fn host_start_or_reload_plugin(env: &ForeignFunctionEnv) {
env.plugin_env.name()
)
};
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
wasi_read_string(&env.plugin_env.wasi_env)
.and_then(|url| Url::parse(&url).map_err(|e| anyhow!("Failed to parse url: {}", e)))
.and_then(|url| {
let action = Action::StartOrReloadPlugin(url);
RunPluginLocation::parse(url.as_str(), Some(cwd))
.map_err(|e| anyhow!("Failed to parse plugin location: {}", e))
})
.and_then(|run_plugin_location| {
let run_plugin = RunPlugin {
location: run_plugin_location,
_allow_exec_host_cmd: false,
};
let action = Action::StartOrReloadPlugin(run_plugin);
apply_action!(action, error_msg, env);
Ok(())
})
Expand Down
11 changes: 3 additions & 8 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use zellij_utils::{
actions::{Action, SearchDirection, SearchOption},
command::TerminalAction,
get_mode_info,
layout::{Layout, RunPluginLocation},
layout::Layout,
},
ipc::{
ClientAttributes, ClientToServerMsg, ExitReason, IpcReceiverWithContext, ServerToClientMsg,
Expand Down Expand Up @@ -615,14 +615,9 @@ pub(crate) fn route_action(
))
.with_context(err_context)?;
},
Action::StartOrReloadPlugin(url) => {
let run_plugin_location =
RunPluginLocation::parse(url.as_str()).with_context(err_context)?;
Action::StartOrReloadPlugin(run_plugin) => {
senders
.send_to_screen(ScreenInstruction::StartOrReloadPluginPane(
run_plugin_location,
None,
))
.send_to_screen(ScreenInstruction::StartOrReloadPluginPane(run_plugin, None))
.with_context(err_context)?;
},
Action::LaunchOrFocusPlugin(run_plugin, should_float) => {
Expand Down
8 changes: 2 additions & 6 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub enum ScreenInstruction {
NewTiledPluginPane(RunPluginLocation, Option<String>, ClientId), // Option<String> is
// optional pane title
NewFloatingPluginPane(RunPluginLocation, Option<String>, ClientId), // Option<String> is an
StartOrReloadPluginPane(RunPluginLocation, Option<String>),
StartOrReloadPluginPane(RunPlugin, Option<String>),
// optional pane title
AddPlugin(
Option<bool>, // should_float
Expand Down Expand Up @@ -2573,14 +2573,10 @@ pub(crate) fn screen_thread_main(
size,
))?;
},
ScreenInstruction::StartOrReloadPluginPane(run_plugin_location, pane_title) => {
ScreenInstruction::StartOrReloadPluginPane(run_plugin, pane_title) => {
let tab_index = screen.active_tab_indices.values().next().unwrap_or(&1);
let size = Size::default();
let should_float = Some(false);
let run_plugin = RunPlugin {
_allow_exec_host_cmd: false,
location: run_plugin_location,
};
screen
.bus
.senders
Expand Down
2 changes: 1 addition & 1 deletion zellij-utils/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ pub enum CliAction {
/// Query all tab names
QueryTabNames,
StartOrReloadPlugin {
url: Url,
url: String,
},
LaunchOrFocusPlugin {
#[clap(short, long, value_parser)]
Expand Down
29 changes: 19 additions & 10 deletions zellij-utils/src/input/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use serde::{Deserialize, Serialize};

use std::path::PathBuf;
use std::str::FromStr;
use url::Url;

use crate::position::Position;

Expand Down Expand Up @@ -233,7 +232,7 @@ pub enum Action {
/// Open a new tiled (embedded, non-floating) plugin pane
NewTiledPluginPane(RunPluginLocation, Option<String>), // String is an optional name
NewFloatingPluginPane(RunPluginLocation, Option<String>), // String is an optional name
StartOrReloadPlugin(Url),
StartOrReloadPlugin(RunPlugin),
}

impl Action {
Expand Down Expand Up @@ -287,14 +286,18 @@ impl Action {
close_on_exit,
start_suspended,
} => {
let current_dir = get_current_dir();
let cwd = cwd
.map(|cwd| current_dir.join(cwd))
.or_else(|| Some(current_dir));
if let Some(plugin) = plugin {
if floating {
let plugin = RunPluginLocation::parse(&plugin).map_err(|e| {
let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| {
format!("Failed to parse plugin loction {plugin}: {}", e)
})?;
Ok(vec![Action::NewFloatingPluginPane(plugin, name)])
} else {
let plugin = RunPluginLocation::parse(&plugin).map_err(|e| {
let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| {
format!("Failed to parse plugin location {plugin}: {}", e)
})?;
// it is intentional that a new tiled plugin pane cannot include a
Expand All @@ -310,10 +313,6 @@ impl Action {
} else if !command.is_empty() {
let mut command = command.clone();
let (command, args) = (PathBuf::from(command.remove(0)), command);
let current_dir = get_current_dir();
let cwd = cwd
.map(|cwd| current_dir.join(cwd))
.or_else(|| Some(current_dir));
let hold_on_start = start_suspended;
let hold_on_close = !close_on_exit;
let run_command_action = RunCommandAction {
Expand Down Expand Up @@ -474,9 +473,19 @@ impl Action {
CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]),
CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]),
CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]),
CliAction::StartOrReloadPlugin { url } => Ok(vec![Action::StartOrReloadPlugin(url)]),
CliAction::StartOrReloadPlugin { url } => {
let current_dir = get_current_dir();
let run_plugin_location = RunPluginLocation::parse(&url, Some(current_dir))
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
let run_plugin = RunPlugin {
location: run_plugin_location,
_allow_exec_host_cmd: false,
};
Ok(vec![Action::StartOrReloadPlugin(run_plugin)])
},
CliAction::LaunchOrFocusPlugin { url, floating } => {
let run_plugin_location = RunPluginLocation::parse(url.as_str())
let current_dir = get_current_dir();
let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(current_dir))
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
let run_plugin = RunPlugin {
location: run_plugin_location,
Expand Down
23 changes: 18 additions & 5 deletions zellij-utils/src/input/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ pub enum RunPluginLocation {
}

impl RunPluginLocation {
pub fn parse(location: &str) -> Result<Self, PluginsConfigError> {
pub fn parse(location: &str, cwd: Option<PathBuf>) -> Result<Self, PluginsConfigError> {
let url = Url::parse(location)?;

let decoded_path = percent_encoding::percent_decode_str(url.path()).decode_utf8_lossy();
Expand All @@ -233,16 +233,29 @@ impl RunPluginLocation {
// Path is absolute, its safe to use URL path.
//
// This is the case if the scheme and : delimiter are followed by a / slash
decoded_path
PathBuf::from(decoded_path.as_ref())
} else if location.starts_with("file:~") {
// Unwrap is safe here since location is a valid URL
PathBuf::from(location.strip_prefix("file:").unwrap())
} else {
// URL dep doesn't handle relative paths with `file` schema properly,
// it always makes them absolute. Use raw location string instead.
//
// Unwrap is safe here since location is a valid URL
location.strip_prefix("file:").unwrap().into()
let stripped = location.strip_prefix("file:").unwrap();
match cwd {
Some(cwd) => cwd.join(stripped),
None => PathBuf::from(stripped),
}
};

Ok(Self::File(PathBuf::from(path.as_ref())))
let path = match shellexpand::full(&path.to_string_lossy().to_string()) {
Ok(s) => PathBuf::from(s.as_ref()),
Err(e) => {
log::error!("Failed to shell expand plugin path: {}", e);
path
},
};
Ok(Self::File(path))
},
_ => Err(PluginsConfigError::InvalidUrlScheme(url)),
}
Expand Down
15 changes: 8 additions & 7 deletions zellij-utils/src/kdl/kdl_layout_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,14 @@ impl<'a> KdlLayoutParser<'a> {
plugin_block.span().len(),
),
)?;
let location = RunPluginLocation::parse(&string_url).map_err(|e| {
ConfigError::new_layout_kdl_error(
e.to_string(),
url_node.span().offset(),
url_node.span().len(),
)
})?;
let location =
RunPluginLocation::parse(&string_url, self.cwd_prefix(None)?).map_err(|e| {
ConfigError::new_layout_kdl_error(
e.to_string(),
url_node.span().offset(),
url_node.span().len(),
)
})?;
Ok(Some(Run::Plugin(RunPlugin {
_allow_exec_host_cmd,
location,
Expand Down
7 changes: 4 additions & 3 deletions zellij-utils/src/kdl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,8 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
let should_float = command_metadata
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "floating"))
.unwrap_or(false);
let location = RunPluginLocation::parse(&plugin_path)?;
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?;
let run_plugin = RunPlugin {
location,
_allow_exec_host_cmd: false,
Expand Down Expand Up @@ -1402,7 +1403,7 @@ impl Options {
}

impl RunPlugin {
pub fn from_kdl(kdl_node: &KdlNode) -> Result<Self, ConfigError> {
pub fn from_kdl(kdl_node: &KdlNode, cwd: Option<PathBuf>) -> Result<Self, ConfigError> {
let _allow_exec_host_cmd =
kdl_get_child_entry_bool_value!(kdl_node, "_allow_exec_host_cmd").unwrap_or(false);
let string_url = kdl_get_child_entry_string_value!(kdl_node, "location").ok_or(
Expand All @@ -1412,7 +1413,7 @@ impl RunPlugin {
kdl_node.span().len(),
),
)?;
let location = RunPluginLocation::parse(string_url).map_err(|e| {
let location = RunPluginLocation::parse(string_url, cwd).map_err(|e| {
ConfigError::new_layout_kdl_error(
e.to_string(),
kdl_node.span().offset(),
Expand Down

0 comments on commit f193347

Please sign in to comment.