Skip to content

Commit

Permalink
Working auto-resume feature
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpclark committed Dec 6, 2017
1 parent fed5635 commit ab754c1
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 39 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "abrute"
version = "0.1.3"
version = "0.1.4"
authors = ["Daniel P. Clark <[email protected]>"]
description = "AESCrypt Brute force attempter."
documentation = "http:https://danielpclark.github.io/abrute/index.html"
Expand All @@ -15,6 +15,6 @@ categories = ["cryptography"]
array_tool = "^1.0"
tempdir = "0.3"
clap = "^2.26"
digits = "^1.0.0"
digits = "~1.1.0"
num_cpus = "^1.0"
rayon = "0.8.2"
23 changes: 21 additions & 2 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rayon::prelude::*;
use super::result::Error;
extern crate num_cpus;
extern crate tempdir;
use resume::{ResumeKey,ResumeFile};
use self::tempdir::TempDir;
use std::{fs,path,env};

Expand Down Expand Up @@ -74,12 +75,12 @@ fn has_reached_end<'a>(sequencer: &Digits, max: usize) -> Result<(), Error> {
}

pub fn aescrypt_core_loop<'a>(
characters: String,
max: usize,
mut sequencer: Digits,
target: &str,
adj: Option<&str>
) -> Result<(), Error> {

loop {
has_reached_end(&sequencer, max)?;
progress_report(&sequencer);
Expand Down Expand Up @@ -111,6 +112,15 @@ pub fn aescrypt_core_loop<'a>(

break;
}

ResumeFile::save(
ResumeKey::new(
characters.clone(),
adj.map(str::to_string),
sequencer.clone(),
target.to_string()
)
);
}

Ok(())
Expand All @@ -133,12 +143,12 @@ fn any_file_contents(dir: &TempDir, omit: &str) -> bool {
}

pub fn unzip_core_loop<'a>(
characters: String,
max: usize,
mut sequencer: Digits,
target: &str,
adj: Option<&str>
) -> Result<(), Error> {

if let Ok(dir) = TempDir::new("abrute") {
let cwd = env::current_dir().unwrap();
let working = path::Path::new(&dir.path().as_os_str()).join(&target);
Expand Down Expand Up @@ -182,6 +192,15 @@ pub fn unzip_core_loop<'a>(
if !code.is_empty() {
return code.pop().unwrap();
}

ResumeFile::save(
ResumeKey::new(
characters.clone(),
adj.map(str::to_string),
sequencer.clone(),
target.to_string()
)
);
}
} else {
return Err(Error::FailedTempDir);
Expand Down
21 changes: 19 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ USE OF THIS BINARY FALLS UNDER THE MIT LICENSE (c) 2017").
validate_start_string(&matches, max)?;

let mapping = derive_character_base(matches.value_of("CHARACTERS").unwrap());
let resume_key_chars = mapping_to_characters(&mapping);
let mut sequencer = Digits::new(mapping, matches.value_of("start").unwrap_or("").to_string());
sequencer.zero_fill(min as usize);

Expand All @@ -104,10 +105,26 @@ USE OF THIS BINARY FALLS UNDER THE MIT LICENSE (c) 2017").
validate_and_prep_sequencer_adjacent(&mut sequencer, adjacent)?;
validate_file_exists(&target)?;

// Begin Resume Feature
let starting = sequencer.to_s();
use ::resume::{ResumeKey,ResumeFile};
let cli_key = ResumeKey::new(
resume_key_chars.clone(),
adjacent.map(str::to_string),
sequencer,
target.to_string(),
);
let latest = cli_key.latest(ResumeFile::load());
let sequencer = latest.start;
if starting != sequencer.to_s() {
println!("Resuming from last save point: {}", sequencer.to_s());
}
// End Resume Feature

if matches.is_present("zip") {
unzip_core_loop(max, sequencer, target, adjacent)
unzip_core_loop(resume_key_chars, max, sequencer, target, adjacent)
} else {
aescrypt_core_loop(max, sequencer, target, adjacent)
aescrypt_core_loop(resume_key_chars, max, sequencer, target, adjacent)
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/process_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ pub fn derive_character_base(characters: &str) -> BaseCustom<char> {
BaseCustom::<char>::new(characters.chars().collect())
}

pub fn mapping_to_characters(m: &BaseCustom<char>) -> String {
let mut crs = String::new();
for x in 0..m.base as usize {
crs.push_str(&m.gen(x as u64)[..]);
}
crs
}
75 changes: 42 additions & 33 deletions src/resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,12 @@ extern crate array_tool;
use self::array_tool::vec::Shift;
extern crate digits;
use self::digits::prelude::*;
use std::cmp::Ordering;

struct ResumeKeyDB {
pub(crate) struct ResumeKeyDB {
rkeys: Vec<ResumeKey>,
}

impl ResumeKeyDB {
fn first(&self) -> Option<&ResumeKey> {
self.rkeys.iter().next()
}

fn get(f: String) -> ResumeKeyDB {
let file = File::open(f);
assert!(file.is_ok());
Expand All @@ -43,23 +38,38 @@ impl ResumeKeyDB {
}
}

#[derive(Debug,PartialEq)]
struct ResumeKey {
#[derive(Debug,Clone)]
pub(crate) struct ResumeKey {
characters: String,
adjacent: Option<u8>,
start: Digits,
adjacent: Option<String>,
pub(crate) start: Digits,
target: String,
}

impl PartialEq for ResumeKey {
fn eq(&self, other: &ResumeKey) -> bool {
self.start == other.start
}
}

impl ResumeKey {
fn latest(self, db: ResumeKeyDB) -> ResumeKey {
pub fn new(c: String,a: Option<String>,s: Digits,t: String) -> ResumeKey {
ResumeKey {
characters: c,
adjacent: a,
start: s,
target: t,
}
}

pub(crate) fn latest(self, db: ResumeKeyDB) -> ResumeKey {
db.
rkeys.
into_iter().
filter(|rk| rk.characters == self.characters).
filter(|rk| rk.target == self.target).
filter(|rk| rk.start >= self.start).
max_by(|_,_| Ordering::Greater).
max_by(|ref a, ref b| a.start.partial_cmp(&b.start).unwrap()).
unwrap_or(self)
}
}
Expand Down Expand Up @@ -89,7 +99,7 @@ impl TryFrom<String> for ResumeKey {
let c = values.shift().ok_or_else(|| return MalformedResumeKey)?;
let a = values.shift().ok_or_else(|| return MalformedResumeKey).unwrap();
let a = match a.parse::<u8>() {
Ok(v) => Some(v),
Ok(_) => Some(a),
_ => None,
};
Ok(ResumeKey {
Expand All @@ -106,11 +116,11 @@ impl TryFrom<String> for ResumeKey {

impl Display for ResumeKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let a = if self.adjacent.is_some() {
format!("{}", self.adjacent.unwrap())
} else {
"None".to_string()
};
let a: String;
match self.adjacent {
Some(ref v) => a = v.clone(),
_ => a = "None".to_string(),
}
write!(f,
"{}\n{}\n{}\n{}\n\n",
self.characters,
Expand All @@ -125,7 +135,7 @@ impl Display for ResumeKey {
fn input_and_output_for_resume_works() {
let r = ResumeKey {
characters: String::from("asdf"),
adjacent: Some(1),
adjacent: Some("1".to_string()),
start: Digits::new({BaseCustom::<char>::new("asdf".chars().collect())}, String::from("aaaa")),
target: String::from("thing.aes")
};
Expand All @@ -134,37 +144,37 @@ fn input_and_output_for_resume_works() {
file.write_all(&format!("{}", r).as_bytes()).ok();

let keys = ResumeKeyDB::get(".example.res".to_string());
let k = keys.first();
let k = keys.rkeys.iter().next();
assert_eq!(Some(&r), k);

let _a = fs::remove_file(".example.res");
assert!(!Path::new(".example.res").exists(), "`.example.res` cleanup failed!");
}

#[derive(Debug)]
struct ResumeFile;
pub(crate) struct ResumeFile;

impl ResumeFile {
pub(crate) fn save(&self, rk: &ResumeKey) {
pub(crate) fn save(rk: ResumeKey) {
let file = OpenOptions::new().append(true).create(true).open(".abrute");
assert!(file.is_ok(), "Failed to create or open file `.abrute` for resuming work!");

if let Ok(mut f) = file {
f.write_all(&format!("{}\n", rk).as_bytes()).ok();
f.write_all(&format!("{}", rk).as_bytes()).ok();
let _a = f.sync_data();
}

self.backup()
ResumeFile::backup()
}

fn backup(&self) {
fn backup() {
let file = ".abrute";
let backup = ".abrute.bak";
fs::copy(file, backup).
expect("Failed to backup `.abrute` to `.abrute.bak`!");
}

pub(crate) fn load(&self) -> ResumeKeyDB {
pub(crate) fn load() -> ResumeKeyDB {
let file = ".abrute";
if Path::new(file).exists() {
let db = ResumeKeyDB::get(file.to_owned());
Expand All @@ -180,35 +190,34 @@ impl ResumeFile {
return ResumeKeyDB { rkeys: vec![] };
}

pub(crate) fn purge(&self) {
#[allow(dead_code)]
pub(crate) fn purge() {
let _a = fs::remove_file(".abrute");
let _b = fs::remove_file(".abrute.bak");
}
}

#[test]
fn it_backup_system_works() {
let db_backup = ResumeFile {};

let bc = BaseCustom::<char>::new("asdf".chars().collect());
let aa = Digits::new(bc.clone(), "aaaa".to_string());
let ab = Digits::new(bc.clone(), "ssss".to_string());

let ra = ResumeKey { characters: "asdf".to_string(), adjacent: None, start: aa, target: "thing".to_string() };
let rb = ResumeKey { characters: "asdf".to_string(), adjacent: None, start: ab, target: "thing".to_string() };

db_backup.save(&ra);
db_backup.save(&rb);
ResumeFile::save(ra.clone());
ResumeFile::save(rb.clone());

assert!(Path::new(".abrute").exists(), "`.abrute` not found!");
assert!(Path::new(".abrute.bak").exists(), "`.abrute.bak` not found!");

let loaded_db = db_backup.load();
let loaded_db = ResumeFile::load();

assert!(loaded_db.rkeys.contains(&ra), "`.abrute` backup did not contain first key backup!");
assert!(loaded_db.rkeys.contains(&rb), "`.abrute` backup did not contain second key backup!");

db_backup.purge();
ResumeFile::purge();

assert!(!Path::new(".abrute").exists(), "`.abrute` cleanup failed!");
assert!(!Path::new(".abrute.bak").exists(), "`.abrute.bak` cleanup failed!");
Expand Down

0 comments on commit ab754c1

Please sign in to comment.