diff options
author | Igor Matuszewski <igor@sequoia-pgp.org> | 2020-10-24 02:20:50 +0200 |
---|---|---|
committer | Igor Matuszewski <igor@sequoia-pgp.org> | 2020-11-01 19:08:00 +0100 |
commit | a0da43702413524e4a8a37def96fea0645e10cd8 (patch) | |
tree | 5313ebfa6f1dd783a5dc293d0ef9079686e9d687 /ipc | |
parent | 4ea6fb50f5a83aeb9661ff8e523ea698211f3924 (diff) |
ipc: Percent-decode gpgconf directory listings under Windows
Almost every Windows path contains a (percent-encoded) colon coupled
with a drive letter (e.g. C:), so this needs to be done to properly decode
a path.
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/src/gnupg.rs | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/ipc/src/gnupg.rs b/ipc/src/gnupg.rs index fc81a07b..ee355319 100644 --- a/ipc/src/gnupg.rs +++ b/ipc/src/gnupg.rs @@ -64,29 +64,27 @@ impl Context { let mut directories: BTreeMap<String, PathBuf> = Default::default(); let mut sockets: BTreeMap<String, PathBuf> = Default::default(); - let homedir: Option<PathBuf> = - ephemeral.as_ref().map(|tmp| tmp.path()).or(homedir) - .map(|p| p.into()); + let ephemeral_dir = ephemeral.as_ref().map(|tmp| tmp.path()); + let homedir = ephemeral_dir.or(homedir).map(PathBuf::from); - for fields in Self::gpgconf( - &homedir, &["--list-components"], 3)?.into_iter() - { + for fields in Self::gpgconf(&homedir, &["--list-components"], 3)? { components.insert(String::from_utf8(fields[0].clone())?, String::from_utf8(fields[2].clone())?.into()); } - for fields in Self::gpgconf(&homedir, &["--list-dirs"], 2)?.into_iter() - { - let (mut key, value) = (fields[0].clone(), fields[1].clone()); - if key.ends_with(b"-socket") { - let l = key.len(); - key.truncate(l - b"-socket".len()); - sockets.insert(String::from_utf8(key)?, - String::from_utf8(value)?.into()); - } else { - directories.insert(String::from_utf8(key)?, - String::from_utf8(value)?.into()); - } + for fields in Self::gpgconf(&homedir, &["--list-dirs"], 2)? { + // NOTE: Directories and socket paths are percent-encoded if no + // argument to "--list-dirs" is given + let key = std::str::from_utf8(&fields[0])?; + let mut value = std::str::from_utf8(&fields[1])?.to_owned(); + // FIXME: Percent-decode everything, but for now at least decode + // colons to support Windows drive letters + value = value.replace("%3a", ":"); + + match key.strip_suffix("-socket") { + None => directories.insert(key.into(), value.into()), + Some(key) => sockets.insert(key.into(), value.into()), + }; } Ok(Context { @@ -111,21 +109,25 @@ impl Context { gpgconf.env("GNUPGHOME", homedir); } - for argument in arguments { - gpgconf.arg(argument); - } - let output = gpgconf.output().map_err(|e| -> anyhow::Error { - Error::GPGConf(e.to_string()).into() + gpgconf.args(arguments); + + let output = gpgconf.output().map_err(|e| { + Error::GPGConf(e.to_string()) })?; if output.status.success() { let mut result = Vec::new(); - for line in output.stdout.split(nl) { + for mut line in output.stdout.split(nl) { if line.len() == 0 { // EOF. break; } + // Make sure to also skip \r on Windows + if line[line.len() - 1] == b'\r' { + line = &line[..line.len() - 1]; + } + let fields = line.splitn(nfields, colon).map(|f| f.to_vec()) .collect::<Vec<_>>(); |