use std::convert::TryFrom;
use std::path::PathBuf;
use clap::Parser;
use openpgp_card_tool_git::Armor;
#[derive(Parser, Debug, Default)]
pub struct Args {
#[clap(long, value_names = ["SIGNATURE_FILE"])]
pub verify: Option<PathBuf>,
#[clap(long, short = 'b')]
pub detach_sign: bool,
#[clap(long, short = 's', hide = true)]
pub sign: bool,
#[clap(long, short = 'a')]
pub armor: bool,
#[clap(long, short = 'u', value_names = ["SIGNING_KEY_FINGERPRINT"])]
pub user_id: Option<String>,
#[clap(long, hide = true)]
pub keyid_format: Option<String>,
#[clap(long, hide = true)]
pub status_fd: Option<String>,
pub file_to_verify: Option<String>,
#[clap(short, long, env = "PGP_CERT_D", value_names = ["STORE_PATH"])]
pub cert_store: Option<PathBuf>,
#[clap(long)]
pub store_card_pin: bool,
#[clap(long, value_names = ["CERTIFICATE_FILE"])]
pub import: Option<PathBuf>,
}
pub enum Mode {
Verify {
signature: PathBuf,
cert_store: Option<PathBuf>,
},
Sign {
id: String,
armor: Armor,
cert_store: Option<PathBuf>,
},
StoreCardPin,
Import {
cert_file: PathBuf,
cert_store: Option<PathBuf>,
},
None,
}
impl TryFrom<Args> for Mode {
type Error = String;
fn try_from(value: Args) -> Result<Self, Self::Error> {
if value.store_card_pin {
Ok(Mode::StoreCardPin)
} else if let Some(cert) = value.import {
Ok(Mode::Import {
cert_file: cert,
cert_store: value.cert_store,
})
} else if let Some(signature) = value.verify {
if Some("-".into()) == value.file_to_verify {
Ok(Mode::Verify {
signature,
cert_store: value.cert_store,
})
} else {
Err("Verification of files other than stdin is unsupported. Use -".into())
}
} else if value.detach_sign {
if let Some(user_id) = value.user_id {
Ok(Mode::Sign {
id: user_id,
armor: if value.armor {
Armor::Armor
} else {
Armor::NoArmor
},
cert_store: value.cert_store,
})
} else {
Err("The -u parameter is required. Please provide a hex-encoded signing subkey fingerprint with no spaces".into())
}
} else if value.sign {
Err("Inline signing is not supported. Use --detach-sign".into())
} else {
Ok(Mode::None)
}
}
}