dbus_server_address_parser/decode/
unixexec.rs1use super::{
2 guid::to_guid,
3 unescape::{unescape, UnescapeError},
4 GuidError,
5};
6use crate::{Guid, Unixexec};
7use std::convert::TryFrom;
8use thiserror::Error;
9
10#[derive(Debug, Clone, Error)]
11pub enum UnixexecError {
12 #[error("Could not unescape: {0}")]
13 UnescapeError(#[from] UnescapeError),
14 #[error("GUID error: {0}")]
15 GuidError(#[from] GuidError),
16 #[error("Unknown key")]
17 UnknownKey,
18 #[error("Missing path value")]
19 MissingPath,
20}
21
22impl Unixexec {
23 fn decode_value(server_address: &str, key: &str) -> Result<Option<String>, UnixexecError> {
24 for key_value in server_address.split(',') {
25 if let Some(value) = key_value.strip_prefix(key) {
26 let value = unescape(value)?;
27 return Ok(Some(value));
28 }
29 }
30 Ok(None)
31 }
32
33 fn decode_path(server_address: &str) -> Result<String, UnixexecError> {
34 if let Some(path) = Unixexec::decode_value(server_address, "path=")? {
35 Ok(path)
36 } else {
37 Err(UnixexecError::MissingPath)
38 }
39 }
40
41 fn decode_arg(server_address: &str, i: usize) -> Result<Option<String>, UnixexecError> {
42 let key = format!("argv{}=", i);
43 Unixexec::decode_value(server_address, &key)
44 }
45
46 fn decode_guid(server_address: &str) -> Result<Option<Guid>, UnixexecError> {
47 if let Some(guid) = Unixexec::decode_value(server_address, "guid=")? {
48 let guid = to_guid(&guid)?;
49 Ok(Some(guid))
50 } else {
51 Ok(None)
52 }
53 }
54
55 fn check_argv(&self, key: &str) -> Result<(), UnixexecError> {
56 if let Some(i) = key.strip_prefix("argv") {
57 match i.parse::<usize>() {
58 Ok(i) => {
59 if i <= self.argv.len() {
60 Ok(())
61 } else {
62 Err(UnixexecError::UnknownKey)
63 }
64 }
65 Err(_) => Err(UnixexecError::UnknownKey),
66 }
67 } else {
68 Err(UnixexecError::UnknownKey)
69 }
70 }
71
72 fn check_keys(&self, server_address: &str) -> Result<(), UnixexecError> {
73 for key_value in server_address.split(',') {
74 if let Some((key, _)) = key_value.split_once('=') {
75 if key != "path" && key != "guid" {
76 self.check_argv(key)?;
77 }
78 } else {
79 return Err(UnixexecError::UnknownKey);
80 }
81 }
82 Ok(())
83 }
84}
85
86impl TryFrom<&str> for Unixexec {
87 type Error = UnixexecError;
88
89 fn try_from(server_address: &str) -> Result<Self, Self::Error> {
90 let path = Unixexec::decode_path(server_address)?;
91
92 let argv0 = Unixexec::decode_arg(server_address, 0)?;
93
94 let mut argv = Vec::new();
95 let mut i = 1usize;
96 while let Some(value) = Unixexec::decode_arg(server_address, i)? {
97 argv.push(value);
98 i += 1;
99 }
100
101 let guid = Unixexec::decode_guid(server_address)?;
102
103 let unixexec = Unixexec {
104 path,
105 argv0,
106 argv,
107 guid,
108 };
109
110 unixexec.check_keys(server_address)?;
111
112 Ok(unixexec)
113 }
114}