diff options
Diffstat (limited to 'src/ipc')
| -rw-r--r-- | src/ipc/client.rs | 35 | ||||
| -rw-r--r-- | src/ipc/server.rs | 25 |
2 files changed, 53 insertions, 7 deletions
diff --git a/src/ipc/client.rs b/src/ipc/client.rs index 094bb636..4c356355 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -1,20 +1,34 @@ use std::io::ErrorKind; use std::iter::Peekable; -use std::slice; +use std::path::Path; +use std::{env, slice}; use anyhow::{anyhow, bail, Context}; use niri_config::OutputName; use niri_ipc::socket::Socket; use niri_ipc::{ - Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview, Request, - Response, Transform, Window, WindowLayout, + Action, Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview, + Request, Response, Transform, Window, WindowLayout, }; use serde_json::json; use crate::cli::Msg; use crate::utils::version; -pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { +pub fn handle_msg(mut msg: Msg, json: bool) -> anyhow::Result<()> { + // For actions taking paths, prepend the niri CLI's working directory. + if let Msg::Action { + action: + Action::Screenshot { path, .. } + | Action::ScreenshotScreen { path, .. } + | Action::ScreenshotWindow { path, .. }, + } = &mut msg + { + if let Some(path) = path { + ensure_absolute_path(path).context("error making the path absolute")?; + } + } + let request = match &msg { Msg::Version => Request::Version, Msg::Outputs => Request::Outputs, @@ -668,6 +682,19 @@ fn fmt_rounded(x: f64) -> String { } } +fn ensure_absolute_path(path: &mut String) -> anyhow::Result<()> { + let p = Path::new(path); + if p.is_relative() { + let mut cwd = env::current_dir().context("error getting current working directory")?; + cwd.push(p); + match cwd.into_os_string().into_string() { + Ok(absolute) => *path = absolute, + Err(cwd) => bail!("couldn't convert absolute path to string: {cwd:?}"), + } + } + Ok(()) +} + #[cfg(test)] mod tests { use insta::assert_snapshot; diff --git a/src/ipc/server.rs b/src/ipc/server.rs index 051bccab..354023b7 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::collections::HashSet; use std::ffi::OsStr; use std::os::unix::net::{UnixListener, UnixStream}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::{env, io, process}; @@ -17,8 +17,8 @@ use futures_util::{select_biased, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, Fu use niri_config::OutputName; use niri_ipc::state::{EventStreamState, EventStreamStatePart as _}; use niri_ipc::{ - Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response, WindowLayout, - Workspace, + Action, Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response, + WindowLayout, Workspace, }; use smithay::desktop::layer_map_for_output; use smithay::input::pointer::{ @@ -379,6 +379,8 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply { Response::PickedColor(color) } Request::Action(action) => { + validate_action(&action)?; + let (tx, rx) = async_channel::bounded(1); let action = niri_config::Action::from(action); @@ -451,6 +453,23 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply { Ok(response) } +fn validate_action(action: &Action) -> Result<(), String> { + if let Action::Screenshot { path, .. } + | Action::ScreenshotScreen { path, .. } + | Action::ScreenshotWindow { path, .. } = action + { + if let Some(path) = path { + // Relative paths are resolved against the niri compositor's working directory, which + // is almost certainly not what you want. + if !Path::new(path).is_absolute() { + return Err(format!("path must be absolute: {path}")); + } + } + } + + Ok(()) +} + async fn handle_event_stream_client(client: EventStreamClient) -> anyhow::Result<()> { let EventStreamClient { events, |
