diff options
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)?;      }  | 
