summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2022-10-17 17:40:25 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2022-10-17 17:40:25 +0300
commitdd0baa82e9789da23c8f9b06925776c7f80e2568 (patch)
tree7a1cf3c7ef6dc49464c5b3382a08695b66565a67
parent0ef4dde9392452f7cf7f18294f747fc6e0babb8d (diff)
downloadmeli-dd0baa82e9789da23c8f9b06925776c7f80e2568.zip
Spawn user-given command strings with sh -c ".."
If given string contains arguments, Command::new(string) will fail. Reported in #159 https://git.meli.delivery/meli/meli/issues/159
-rw-r--r--src/components/mail/view.rs87
-rw-r--r--src/components/mail/view/envelope.rs10
-rw-r--r--src/components/mail/view/html.rs10
-rw-r--r--src/mailcap.rs3
-rw-r--r--src/main.rs13
5 files changed, 71 insertions, 52 deletions
diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs
index 36bae497..e7ec7a7b 100644
--- a/src/components/mail/view.rs
+++ b/src/components/mail/view.rs
@@ -2223,13 +2223,13 @@ impl Component for MailView {
None,
true,
);
- let (exec_cmd, argument) = desktop_exec_to_command(
+ let exec_cmd = desktop_exec_to_command(
&command,
p.path.display().to_string(),
false,
);
- match Command::new(&exec_cmd)
- .arg(&argument)
+ match Command::new("sh")
+ .args(&["-c", &exec_cmd])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
@@ -2241,8 +2241,8 @@ impl Component for MailView {
Err(err) => {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
- "Failed to start `{} {}`: {}",
- &exec_cmd, &argument, err
+ "Failed to start `{}`: {}",
+ &exec_cmd, err
)),
));
}
@@ -2790,49 +2790,66 @@ fn save_attachment(path: &std::path::Path, bytes: &[u8]) -> Result<()> {
Ok(())
}
-fn desktop_exec_to_command(command: &str, path: String, is_url: bool) -> (String, String) {
+fn desktop_exec_to_command(command: &str, path: String, is_url: bool) -> String {
/* Purge unused field codes */
let command = command
.replace("%i", "")
.replace("%c", "")
.replace("%k", "");
- if let Some(pos) = command.find("%f").or_else(|| command.find("%F")) {
- (command[0..pos].trim().to_string(), path)
- } else if let Some(pos) = command.find("%u").or_else(|| command.find("%U")) {
+ if command.contains("%f") {
+ command.replacen("%f", &path.replace(' ', "\\ "), 1)
+ } else if command.contains("%F") {
+ command.replacen("%F", &path.replace(' ', "\\ "), 1)
+ } else if command.contains("%u") || command.contains("%U") {
+ let from_pattern = if command.contains("%u") { "%u" } else { "%U" };
if is_url {
- (command[0..pos].trim().to_string(), path)
+ command.replacen(from_pattern, &path, 1)
} else {
- (
- command[0..pos].trim().to_string(),
- format!("file://{}", path),
+ command.replacen(
+ from_pattern,
+ &format!("file://{}", path).replace(' ', "\\ "),
+ 1,
)
}
+ } else if is_url {
+ format!("{} {}", command, path)
} else {
- (command, path)
+ format!("{} {}", command, path.replace(' ', "\\ "))
}
}
-/*
#[test]
fn test_desktop_exec() {
- for cmd in [
- "ristretto %F",
- "/usr/lib/firefox-esr/firefox-esr %u",
- "/usr/bin/vlc --started-from-file %U",
- "zathura %U",
- ]
- .iter()
- {
- println!(
- "cmd = {} output = {:?}, is_url = false",
- cmd,
- desktop_exec_to_command(cmd, "/tmp/file".to_string(), false)
- );
- println!(
- "cmd = {} output = {:?}, is_url = true",
- cmd,
- desktop_exec_to_command(cmd, "www.example.com".to_string(), true)
- );
- }
+ assert_eq!(
+ "ristretto /tmp/file".to_string(),
+ desktop_exec_to_command("ristretto %F", "/tmp/file".to_string(), false)
+ );
+ assert_eq!(
+ "/usr/lib/firefox-esr/firefox-esr file:///tmp/file".to_string(),
+ desktop_exec_to_command(
+ "/usr/lib/firefox-esr/firefox-esr %u",
+ "/tmp/file".to_string(),
+ false
+ )
+ );
+ assert_eq!(
+ "/usr/lib/firefox-esr/firefox-esr www.example.com".to_string(),
+ desktop_exec_to_command(
+ "/usr/lib/firefox-esr/firefox-esr %u",
+ "www.example.com".to_string(),
+ true
+ )
+ );
+ assert_eq!(
+ "/usr/bin/vlc --started-from-file www.example.com".to_string(),
+ desktop_exec_to_command(
+ "/usr/bin/vlc --started-from-file %U",
+ "www.example.com".to_string(),
+ true
+ )
+ );
+ assert_eq!(
+ "zathura --fork file:///tmp/file".to_string(),
+ desktop_exec_to_command("zathura --fork %U", "file:///tmp/file".to_string(), true)
+ );
}
-*/
diff --git a/src/components/mail/view/envelope.rs b/src/components/mail/view/envelope.rs
index 9b810935..bb968459 100644
--- a/src/components/mail/view/envelope.rs
+++ b/src/components/mail/view/envelope.rs
@@ -403,13 +403,13 @@ impl Component for EnvelopeView {
None,
true,
);
- let (exec_cmd, argument) = super::desktop_exec_to_command(
+ let exec_cmd = super::desktop_exec_to_command(
&command,
p.path.display().to_string(),
false,
);
- match Command::new(&exec_cmd)
- .arg(&argument)
+ match Command::new("sh")
+ .args(&["-c", &exec_cmd])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
@@ -421,8 +421,8 @@ impl Component for EnvelopeView {
Err(err) => {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
- "Failed to start `{} {}`: {}",
- &exec_cmd, &argument, err
+ "Failed to start `{}`: {}",
+ &exec_cmd, err
)),
));
}
diff --git a/src/components/mail/view/html.rs b/src/components/mail/view/html.rs
index 34f28fcf..d5334561 100644
--- a/src/components/mail/view/html.rs
+++ b/src/components/mail/view/html.rs
@@ -151,10 +151,10 @@ impl Component for HtmlView {
};
if let Some(command) = command {
let p = create_temp_file(&self.bytes, None, None, true);
- let (exec_cmd, argument) =
+ let exec_cmd =
super::desktop_exec_to_command(&command, p.path.display().to_string(), false);
- match Command::new(&exec_cmd)
- .arg(&argument)
+ match Command::new("sh")
+ .args(&["-c", &exec_cmd])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
@@ -166,8 +166,8 @@ impl Component for HtmlView {
Err(err) => {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
- "Failed to start `{} {}`: {}",
- &exec_cmd, &argument, err
+ "Failed to start `{}`: {}",
+ &exec_cmd, err
)),
));
}
diff --git a/src/mailcap.rs b/src/mailcap.rs
index c581d26d..c3caa55f 100644
--- a/src/mailcap.rs
+++ b/src/mailcap.rs
@@ -214,7 +214,8 @@ impl MailcapEntry {
std::borrow::Cow::from("less")
};
- let mut pager = Command::new(pager_cmd.as_ref())
+ let mut pager = Command::new("sh")
+ .args(["-c", pager_cmd.as_ref()])
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.spawn()?;
diff --git a/src/main.rs b/src/main.rs
index 9a13ec77..391bef2d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -233,12 +233,13 @@ fn run_app(opt: Opt) -> Result<()> {
}
use std::process::{Command, Stdio};
- let mut handle =
- Command::new(std::env::var("PAGER").unwrap_or_else(|_| "more".to_string()))
- .stdin(Stdio::piped())
- .stdout(Stdio::inherit())
- .stderr(Stdio::inherit())
- .spawn()?;
+ let mut handle = Command::new("sh")
+ .arg("-c")
+ .arg(std::env::var("PAGER").unwrap_or_else(|_| "more".to_string()))
+ .stdin(Stdio::piped())
+ .stdout(Stdio::inherit())
+ .stderr(Stdio::inherit())
+ .spawn()?;
handle.stdin.take().unwrap().write_all(v.as_bytes())?;
handle.wait()?;