|
|
|
@ -10,10 +10,10 @@ use std::{
|
|
|
|
|
iter,
|
|
|
|
|
};
|
|
|
|
|
use eyre::eyre;
|
|
|
|
|
use config::op::Password;
|
|
|
|
|
use config::op::{self, Password};
|
|
|
|
|
use error::ParseErrorKind;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
|
|
|
enum IsSigning
|
|
|
|
|
{
|
|
|
|
|
No,
|
|
|
|
@ -30,18 +30,17 @@ impl Default for IsSigning
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
|
|
|
enum KeyKind
|
|
|
|
|
{
|
|
|
|
|
Autodetect,
|
|
|
|
|
RsaPublic,
|
|
|
|
|
Autodetect(IsSigning),
|
|
|
|
|
RsaPublic(IsSigning),
|
|
|
|
|
RsaPrivate(IsSigning), // is signing key?
|
|
|
|
|
Aes,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum TranslationMode
|
|
|
|
|
{
|
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
|
|
|
enum TranslationMode {
|
|
|
|
|
Autodetect,
|
|
|
|
|
Encrypt,
|
|
|
|
|
Decrypt,
|
|
|
|
@ -57,20 +56,35 @@ impl Default for TranslationMode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
|
|
|
enum Atom
|
|
|
|
|
{
|
|
|
|
|
Key(KeyKind, String, Password),
|
|
|
|
|
|
|
|
|
|
NonSpecific,
|
|
|
|
|
FileAuto(String),
|
|
|
|
|
FileSpecific(String, String, TranslationMode),
|
|
|
|
|
//TODO:
|
|
|
|
|
SetMode(config::op::Mode),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Atom
|
|
|
|
|
{
|
|
|
|
|
pub fn hash_into(&self, map: &mut smallmap::Map<u64, ()>) -> bool
|
|
|
|
|
{
|
|
|
|
|
use std::hash::{Hash,Hasher,};
|
|
|
|
|
let hasher = std::collections::hash_map::DefaultHasher::new();
|
|
|
|
|
self.hash(&mut hasher);
|
|
|
|
|
let vl = hasher.finish();
|
|
|
|
|
if map.contains_key(&vl) {
|
|
|
|
|
true
|
|
|
|
|
} else {
|
|
|
|
|
map.insert(hasher.finish(),());
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[instrument]
|
|
|
|
|
pub async fn parse<I: IntoIterator<Item=String> + std::fmt::Debug>(args: I) -> Result<!/* TODO: What type do we make for this? */, eyre::Report>
|
|
|
|
|
pub async fn parse<I: IntoIterator<Item=String> + std::fmt::Debug>(args: I) -> Result<config::Operation, eyre::Report>
|
|
|
|
|
{
|
|
|
|
|
let (mut tx, mut rx) = mpsc::channel(1);
|
|
|
|
|
|
|
|
|
@ -89,13 +103,50 @@ pub async fn parse<I: IntoIterator<Item=String> + std::fmt::Debug>(args: I) -> R
|
|
|
|
|
"--stat" => todo!(),
|
|
|
|
|
_ => {
|
|
|
|
|
let handler = tokio::spawn(async move {
|
|
|
|
|
//TODO: What container type do we make for this?
|
|
|
|
|
let mut output = op::Normal::default();
|
|
|
|
|
let mut had = smallmap::Map::new();
|
|
|
|
|
while let Some(atom) = rx.recv().await {
|
|
|
|
|
debug!("[Normal] recv atom: {:?}", atom);
|
|
|
|
|
// Construct `Normal` with atoms
|
|
|
|
|
|
|
|
|
|
if Atom::hash_into(&atom, &mut had) {
|
|
|
|
|
return Err(error::ConstructError::AlreadyExists(format!("TODO: {:?}", atom)));
|
|
|
|
|
}
|
|
|
|
|
todo!()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
match atom {
|
|
|
|
|
Atom::NonSpecific => output.in_place = true,
|
|
|
|
|
Atom::SetMode(mode) => output.mode = Some(mode),
|
|
|
|
|
Atom::FileAuto(file) => output.files.push((file, None, None)),
|
|
|
|
|
Atom::FileSpecific(finput, foutput, mode) => {
|
|
|
|
|
let mode = match mode {
|
|
|
|
|
TranslationMode::Autodetect => resolve::find_file_mode(&finput).await?,
|
|
|
|
|
TranslationMode::Encrypt => op::Mode::Encrypt,
|
|
|
|
|
TranslationMode::Decrypt => op::Mode::Decrypt,
|
|
|
|
|
};
|
|
|
|
|
output.files.push((finput, Some(foutput), Some(mode)));
|
|
|
|
|
},
|
|
|
|
|
Atom::Key(kind, string, password) => {
|
|
|
|
|
let (kind, sign) = match kind {
|
|
|
|
|
KeyKind::Autodetect(s) => (resolve::find_key_mode(&string).await?, s),
|
|
|
|
|
KeyKind::RsaPrivate(s) => (config::KeyKind::RsaPrivate, s),
|
|
|
|
|
KeyKind::RsaPublic(s) => (config::KeyKind::RsaPublic, s),
|
|
|
|
|
KeyKind::Aes => (config::KeyKind::Aes, Default::default()),
|
|
|
|
|
};
|
|
|
|
|
if sign != IsSigning::No && kind == config::KeyKind::Aes {
|
|
|
|
|
warn!("Key was detected to not be RSA, option to sign is set and ignored.");
|
|
|
|
|
} else {
|
|
|
|
|
output.sign.push((string.clone(), password.clone()));
|
|
|
|
|
}
|
|
|
|
|
match kind {
|
|
|
|
|
config::KeyKind::Aes => output.aes.push((string, password)),
|
|
|
|
|
config::KeyKind::RsaPublic => output.rsa.push((string, password)),
|
|
|
|
|
config::KeyKind::RsaPrivate => output.rsa.push((string, password))
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(config::Operation::Normal(output))
|
|
|
|
|
}.instrument(tracing::info_span!("handler")));
|
|
|
|
|
match parse_normal(std::iter::once(arg)
|
|
|
|
|
.chain(args.map(Into::into)), &mut tx).await
|
|
|
|
|
{
|
|
|
|
@ -119,12 +170,11 @@ pub async fn parse<I: IntoIterator<Item=String> + std::fmt::Debug>(args: I) -> R
|
|
|
|
|
.wrap_err_with(|| eyre!("Failed to construct operation from arguments"))
|
|
|
|
|
.with_note(|| "In constructing of operation from spec");
|
|
|
|
|
},
|
|
|
|
|
Ok(result) => {
|
|
|
|
|
|
|
|
|
|
Ok(operation) => {
|
|
|
|
|
//TODO: Validate operation here?
|
|
|
|
|
Ok(operation)
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn parse_normal<I: IntoIterator<Item=String>>(args: I, atoms: &mut mpsc::Sender<Atom>) -> Result<(), error::Error>
|
|
|
|
@ -132,7 +182,7 @@ async fn parse_normal<I: IntoIterator<Item=String>>(args: I, atoms: &mut mpsc::S
|
|
|
|
|
let mut args = args.into_iter();
|
|
|
|
|
let mut reading=true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut mode_set=false;
|
|
|
|
|
while let Some(arg) = args.next()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
@ -146,7 +196,27 @@ async fn parse_normal<I: IntoIterator<Item=String>>(args: I, atoms: &mut mpsc::S
|
|
|
|
|
}
|
|
|
|
|
if reading && arg.starts_with("-") {
|
|
|
|
|
let mut opt = arg.chars().skip(1);
|
|
|
|
|
|
|
|
|
|
macro_rules! check_mode_set
|
|
|
|
|
{
|
|
|
|
|
() => {
|
|
|
|
|
if mode_set {
|
|
|
|
|
return Err((arg, error::ParseErrorKind::ModeSet).into());
|
|
|
|
|
} else {
|
|
|
|
|
mode_set=true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
match opt.next() {
|
|
|
|
|
Some('a') => check_mode_set!(),
|
|
|
|
|
Some('e') => {
|
|
|
|
|
check_mode_set!();
|
|
|
|
|
atoms.send(Atom::SetMode(config::op::Mode::Encrypt)).await?;
|
|
|
|
|
},
|
|
|
|
|
Some('d') => {
|
|
|
|
|
check_mode_set!();
|
|
|
|
|
atoms.send(Atom::SetMode(config::op::Mode::Decrypt)).await?;
|
|
|
|
|
},
|
|
|
|
|
Some('i') => match opt.next() {
|
|
|
|
|
None => atoms.send(Atom::NonSpecific).await?,
|
|
|
|
|
Some(r) => return Err((ParseErrorKind::BadTail('i', iter::once(r).chain(opt).collect()), arg).swap().into()),
|
|
|
|
@ -238,8 +308,8 @@ async fn parse_normal<I: IntoIterator<Item=String>>(args: I, atoms: &mut mpsc::S
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let kind = match kind {
|
|
|
|
|
KeySpec::Autodetect => KeyKind::Autodetect,
|
|
|
|
|
KeySpec::RsaPublic => KeyKind::RsaPublic,
|
|
|
|
|
KeySpec::Autodetect => KeyKind::Autodetect(signing),
|
|
|
|
|
KeySpec::RsaPublic => KeyKind::RsaPublic(signing),
|
|
|
|
|
KeySpec::RsaPrivate => KeyKind::RsaPrivate(signing),
|
|
|
|
|
KeySpec::Aes => KeyKind::Aes,
|
|
|
|
|
};
|
|
|
|
|