dbus_server_address_parser/decode/
unixexec.rs

1use 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}