aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs43
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)?;
}