diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2019-01-07 22:21:27 +0000 |
---|---|---|
committer | Robin Krahl <me@robin-krahl.de> | 2019-01-11 04:36:55 +0100 |
commit | 5ede9c31db245cc3c3354d9c16200545fa5255db (patch) | |
tree | bb38ef7a7d653a8d866f2fc0a00bfab3bab35eda /src | |
parent | 516ee5886f7ddcd60670aa5bdb2edc98cbec257d (diff) | |
download | nitrocli-otp-qr-5ede9c31db245cc3c3354d9c16200545fa5255db.tar.gz nitrocli-otp-qr-5ede9c31db245cc3c3354d9c16200545fa5255db.tar.bz2 |
Implement name query using dialog crate
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index 9fa1a72..331e22f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +// Copyright (C) 2019 Robin Krahl <robin.krahl@ireas.org> +// SPDX-License-Identifier: MIT + #![warn(missing_docs, rust_2018_compatibility, rust_2018_idioms, unused)] //! Reads OTP configuration from a QR code and writes it to an OTP slot on a Nitrokey device. @@ -10,8 +13,11 @@ use std::path; use std::process; use std::str; +use dialog::DialogBox; + #[derive(Debug)] enum Error { + DialogError(dialog::Error), IoError(io::Error), Error(String), UrlParseError(url::ParseError), @@ -21,6 +27,7 @@ enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { + Error::DialogError(ref err) => write!(f, "Dialog error: {:?}", err), Error::IoError(ref err) => write!(f, "IO error: {}", err), Error::Error(ref string) => write!(f, "Error: {}", string), Error::UrlParseError(ref err) => write!(f, "URL parse error: {}", err), @@ -35,6 +42,12 @@ impl From<&str> for Error { } } +impl From<dialog::Error> for Error { + fn from(error: dialog::Error) -> Error { + Error::DialogError(error) + } +} + impl From<io::Error> for Error { fn from(error: io::Error) -> Error { Error::IoError(error) @@ -211,6 +224,30 @@ fn parse_url(url: &str) -> Result<UrlData, Error> { } } +fn query_name(label: &str, issuer: Option<&str>) -> Result<String, Error> { + let title = "Enter OTP slot name"; + let mut text = "Please enter a name for the OTP secret:".to_string(); + text.push_str(&format!("\n\tlabel:\t{}", label)); + if let Some(issuer) = issuer { + text.push_str(&format!("\n\tissuer:\t{}", issuer)); + }; + let text = text; + let default = issuer.unwrap_or(label); + let name = dialog::Input::new(text) + .title(title) + .default(default) + .show()?; + if let Some(name) = name { + if name.is_empty() { + Err(Error::from("The OTP name may not be empty")) + } else { + Ok(name.trim_end_matches(&"\n").to_string()) + } + } else { + Err(Error::from("You canceled the name input dialog")) + } +} + fn run(options: Options) -> Result<(), Error> { let path = match options.file { Some(ref file) => path::PathBuf::from(file), @@ -218,7 +255,11 @@ fn run(options: Options) -> Result<(), Error> { }; let url = decode_qr_code(&path)?; let url_data = parse_url(&url)?; - println!("{:?}", url_data); + let name = match options.name { + Some(name) => name, + None => query_name(&url_data.label, url_data.issuer.as_ref().map(|x| &**x))?, + }; + println!("{}: {:?}", name, url_data); if options.file.is_none() { fs::remove_file(&path)?; } |