cargo-cryptile 0.2.0

A CLI Tool to Encrypt and Decrypt files with a secure password.
Documentation
use cargo_cryptile as cryptile;
use std::env;
use std::process;
use std::io::{self, ErrorKind, Write};
use dialoguer::Password;

mod config;
use config::{Config, Operation, Pass};


impl<'a> Config<'a> {
    fn get_args(&self) -> ([u8; 32], &str, bool) {
        let key = match self.get_key() {
            Ok(k) => k,
            Err(m) => {
                eprintln!("{}", m);
                process::exit(1)
            }
        };
        let filename = self.file().unwrap();
        let replace = self.replace();

        (key, filename, replace)
    }
}

fn get_pass_input() -> String {
    let password = Password::new().with_prompt("Enter a password")
        .with_confirmation("Confirm password", "Passwords mismatching")
        .interact();

    match password {
        Err(_) => {
            eprintln!("Cannot read from the stdin");
            process::exit(1)
        }
        Ok(password) => password
    }
}

fn get_input(s: &str) -> String {
    print!("{}", s);
    io::stdout().flush().unwrap();

    let mut input = String::new();

    if let Err(_) = io::stdin().read_line(&mut input) {
        eprintln!("Cannot read from the stdin");
        process::exit(1)
    }
    input.trim().to_owned()
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut config = match Config::parse(&args) {
        Ok(c) => c,
        Err(m) => {
            eprintln!("{}", m);
            process::exit(1);
        }
    };

    match config.operation {
        Operation::Help(text) => {
            println!("{text}");
            process::exit(0);
        },
        Operation::Encrypt => {
            let (key, filename, replace) = config.get_args();

            if let Err(e) = cryptile::encrypt(filename, &key) {
                let new_name = filename.to_owned() + cryptile::FILE_EXTENSION;
                match e.kind() {
                    ErrorKind::NotFound => {
                        eprintln!("Error: File Not Found!");
                        process::exit(1);
                    }
                    ErrorKind::PermissionDenied => {
                        eprintln!("Error: Permission Denied");
                        process::exit(1);
                    }
                    _ => {
                        cryptile::delete(&new_name);
                        eprintln!("{}", e);
                        process::exit(1)
                    }
                }
            }
            println!("Successfully Encrypted the file");
            if replace {
                cryptile::delete(filename);
            }
        }
        Operation::Decrypt => {
            let (key, filename, replace) = config.get_args();

            if let Err(e) = cryptile::decrypt(filename, &key) {
                let new_name = filename.replace(cryptile::FILE_EXTENSION, "");
                match e.kind() {
                    ErrorKind::Unsupported => {
                        eprintln!("Error: Unsupported File type");
                        process::exit(1)
                    }
                    ErrorKind::PermissionDenied => {
                        eprintln!("Error: Permission Denied");
                        process::exit(1);
                    }
                    ErrorKind::InvalidInput => {
                        eprintln!("Error: Wrong key given");
                        process::exit(1)
                    }
                    ErrorKind::NotFound => {
                        eprintln!("Error: File Not Found!");
                        process::exit(1);
                    }
                    ErrorKind::UnexpectedEof => {
                        eprintln!("Error: Unexpected End of File");
                        process::exit(1)
                    }
                    _ => {
                        cryptile::delete(&new_name);
                        eprintln!("{}", e);
                        process::exit(1)
                    }
                }
            }
            println!("Successfully Decrypted the file");
            if replace {
                cryptile::delete(filename);
            }
        }
        Operation::Set => {
            match config.pass.as_ref().unwrap() {
                Pass::Master => {
                    let pass = get_pass_input();
                    config.set_pass(pass, None);
                }
                Pass::Saved { identifier: _ } => {
                    let pass = get_pass_input();
                    let id = get_input("Enter an identifier: ");
                    config.set_pass(pass, Some(id));
                }
                _ => ()
            }
        }
    }
}



#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_pw_input() {
        let p = get_pass_input();

        println!("start->{}<-end", p);
    }
}