From 5ede9c31db245cc3c3354d9c16200545fa5255db Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 7 Jan 2019 22:21:27 +0000 Subject: Implement name query using dialog crate --- src/main.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'src/main.rs') 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 +// 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 for Error { + fn from(error: dialog::Error) -> Error { + Error::DialogError(error) + } +} + impl From for Error { fn from(error: io::Error) -> Error { Error::IoError(error) @@ -211,6 +224,30 @@ fn parse_url(url: &str) -> Result { } } +fn query_name(label: &str, issuer: Option<&str>) -> Result { + 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)?; } -- cgit v1.2.1