Implement gen command, to generate samples.
This commit is contained in:
@@ -22,3 +22,4 @@ rpassword = "7.2.0"
|
|||||||
shlex = "1.1.0"
|
shlex = "1.1.0"
|
||||||
shellexpand = "3.0.0"
|
shellexpand = "3.0.0"
|
||||||
scopeguard = "1.1.0"
|
scopeguard = "1.1.0"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|||||||
+47
-1
@@ -5,10 +5,13 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cmp::min;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::parser::command_parser;
|
use crate::parser::command_parser;
|
||||||
use crate::password::fix_password_recursion;
|
use crate::password::fix_password_recursion;
|
||||||
use crate::password::{Name, PasswordRef};
|
use crate::password::{Name, Password, PasswordRef};
|
||||||
use crate::repl::LKEval;
|
use crate::repl::LKEval;
|
||||||
use crate::structs::{LKOut, Radix, CORRECT_FILE, DUMP_FILE};
|
use crate::structs::{LKOut, Radix, CORRECT_FILE, DUMP_FILE};
|
||||||
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env};
|
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env};
|
||||||
@@ -409,4 +412,47 @@ impl<'a> LKEval<'a> {
|
|||||||
Err(e) => out.e(format!("error: failed to write: {}", e.to_string())),
|
Err(e) => out.e(format!("error: failed to write: {}", e.to_string())),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cmd_gen(&self, out: &LKOut, num: &u32, name: &PasswordRef) {
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new(r"^.+?(G+|X+)$").unwrap();
|
||||||
|
}
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
let num: usize = (*num).try_into().unwrap();
|
||||||
|
let pwd = name.borrow();
|
||||||
|
let secret = "a".to_string();
|
||||||
|
let mut genpwds: Vec<(PasswordRef, String)> = Vec::new();
|
||||||
|
match RE.captures(pwd.name.as_ref()) {
|
||||||
|
Some(caps) => {
|
||||||
|
let gen = &caps[1];
|
||||||
|
if gen.starts_with("G") {
|
||||||
|
let name = pwd.name.trim_end_matches('G');
|
||||||
|
for num in 1..10_u32.pow(gen.len().try_into().unwrap()) {
|
||||||
|
let npwd = Password::from_password(&pwd);
|
||||||
|
npwd.borrow_mut().name = Rc::new(format!("{}{}", name, num).to_string());
|
||||||
|
let pass = npwd.borrow().encode(&secret);
|
||||||
|
genpwds.push((npwd, pass));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let name = gen.trim_end_matches('X');
|
||||||
|
let num = rng.gen_range(1..10_u32.pow(gen.len().try_into().unwrap()));
|
||||||
|
let npwd = Password::from_password(&pwd);
|
||||||
|
npwd.borrow_mut().name = Rc::new(format!("{}{}", name, num).to_string());
|
||||||
|
let pass = npwd.borrow().encode(&secret);
|
||||||
|
genpwds.push((npwd, pass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let npwd = Password::from_password(&pwd);
|
||||||
|
let pass = npwd.borrow().encode(&secret);
|
||||||
|
genpwds.push((npwd, pass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genpwds.sort_by(|a, b| b.1.len().cmp(&a.1.len()));
|
||||||
|
out.o(format!("{:>30}{:>4} {}", "Name", "Len", "Password"));
|
||||||
|
for num in (genpwds.len()-min(genpwds.len(), num))..genpwds.len() {
|
||||||
|
let (pwd, pass) = (genpwds[num].0.borrow(), genpwds[num].1.to_string());
|
||||||
|
out.o(format!("{:>30}{:>4} {}", pwd.to_string(), pass.len(), pass));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -21,6 +21,7 @@ peg::parser! {
|
|||||||
/ dump_cmd()
|
/ dump_cmd()
|
||||||
/ dump_def_cmd()
|
/ dump_def_cmd()
|
||||||
/ enc_cmd()
|
/ enc_cmd()
|
||||||
|
/ gen_cmd()
|
||||||
/ pass_cmd()
|
/ pass_cmd()
|
||||||
/ unpass_cmd()
|
/ unpass_cmd()
|
||||||
/ correct_cmd()
|
/ correct_cmd()
|
||||||
@@ -51,12 +52,14 @@ peg::parser! {
|
|||||||
match name { Some(n) => Ok(n), None => Err("failed to parse password description") }
|
match name { Some(n) => Ok(n), None => Err("failed to parse password description") }
|
||||||
}
|
}
|
||||||
|
|
||||||
rule date() -> NaiveDate = y:$("-"? ['0'..='9']*<1,4>) "-" m:$(['0'..='9']*<1,2>) "-" d:$(['0'..='9']*<1,2>) {?
|
rule ndate() -> NaiveDate = y:$("-"? ['0'..='9']*<1,4>) "-" m:$(['0'..='9']*<1,2>) "-" d:$(['0'..='9']*<1,2>) {?
|
||||||
let year: i32 = match y.parse() { Ok(n) => n, Err(_) => return Err("year") };
|
let year: i32 = match y.parse() { Ok(n) => n, Err(_) => return Err("year") };
|
||||||
let month: u32 = match m.parse() { Ok(n) => n, Err(_) => return Err("month") };
|
let month: u32 = match m.parse() { Ok(n) => n, Err(_) => return Err("month") };
|
||||||
let day: u32 = match d.parse() { Ok(n) => n, Err(_) => return Err("day") };
|
let day: u32 = match d.parse() { Ok(n) => n, Err(_) => return Err("day") };
|
||||||
NaiveDate::from_ymd_opt(year, month, day).ok_or("date")
|
NaiveDate::from_ymd_opt(year, month, day).ok_or("date")
|
||||||
}
|
}
|
||||||
|
rule cdate() -> NaiveDate = "now" { Local::now().naive_local().date() }
|
||||||
|
rule date() -> NaiveDate = d:(ndate() / cdate()) { d }
|
||||||
rule umode() -> Mode = ("U" / "u") m:$("R" / "r" / "N" / "n" / "H" / "h" / "B" / "b") {?
|
rule umode() -> Mode = ("U" / "u") m:$("R" / "r" / "N" / "n" / "H" / "h" / "B" / "b") {?
|
||||||
match m.to_uppercase().as_str() {
|
match m.to_uppercase().as_str() {
|
||||||
"R" => Ok(Mode::RegularUpcase),
|
"R" => Ok(Mode::RegularUpcase),
|
||||||
@@ -88,6 +91,9 @@ peg::parser! {
|
|||||||
rule source_cmd() -> Command<'input> = "source" _ s:$(([' '..='~'])+) { Command::Source(s.to_string()) }
|
rule source_cmd() -> Command<'input> = "source" _ s:$(([' '..='~'])+) { Command::Source(s.to_string()) }
|
||||||
rule ls_cmd() -> Command<'input> = "ls" f:comment()? { Command::Ls(f.unwrap_or(".".to_string())) }
|
rule ls_cmd() -> Command<'input> = "ls" f:comment()? { Command::Ls(f.unwrap_or(".".to_string())) }
|
||||||
rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) }
|
rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) }
|
||||||
|
rule gen_cmd() -> Command<'input> = "gen" n:num()? _ name:name() {
|
||||||
|
Command::Gen(match n { Some(n) => n, None => 10_u32 }, Rc::new(RefCell::new(name)))
|
||||||
|
}
|
||||||
rule error_cmd() -> Command<'input> = "error" _ e:$(([' '..='~'])+) { Command::Error(LKErr::Error(e)) }
|
rule error_cmd() -> Command<'input> = "error" _ e:$(([' '..='~'])+) { Command::Error(LKErr::Error(e)) }
|
||||||
rule mv_cmd() -> Command<'input> = "mv" _ name:word() _ folder:word() { Command::Mv(name, folder) }
|
rule mv_cmd() -> Command<'input> = "mv" _ name:word() _ folder:word() { Command::Mv(name, folder) }
|
||||||
rule pass_cmd() -> Command<'input> = "pass" _ name:word() { Command::Pass(name) }
|
rule pass_cmd() -> Command<'input> = "pass" _ name:word() { Command::Pass(name) }
|
||||||
|
|||||||
@@ -47,6 +47,19 @@ impl Password {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_password(password: &Password) -> PasswordRef {
|
||||||
|
Rc::new(RefCell::new(Self {
|
||||||
|
parent: password.parent.clone(),
|
||||||
|
prefix: password.prefix.clone(),
|
||||||
|
name: password.name.clone(),
|
||||||
|
length: password.length.clone(),
|
||||||
|
mode: password.mode.clone(),
|
||||||
|
seq: password.seq,
|
||||||
|
date: password.date.clone(),
|
||||||
|
comment: password.comment.clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn encode(&self, secret: &str) -> String {
|
pub fn encode(&self, secret: &str) -> String {
|
||||||
let skey = SKey::new(&self.name, self.seq, secret);
|
let skey = SKey::new(&self.name, self.seq, secret);
|
||||||
let (sep, len) = match (&self.length, &self.mode) {
|
let (sep, len) = match (&self.length, &self.mode) {
|
||||||
|
|||||||
+2
-3
@@ -106,9 +106,8 @@ impl<'a> LKEval<'a> {
|
|||||||
}
|
}
|
||||||
None => out.e(format!("error: password {} not found", name)),
|
None => out.e(format!("error: password {} not found", name)),
|
||||||
},
|
},
|
||||||
Command::Enc(name) => {
|
Command::Enc(name) => { self.cmd_enc(&out, name); }
|
||||||
self.cmd_enc(&out, name);
|
Command::Gen(num, name) => self.cmd_gen(&out, &num, &name),
|
||||||
}
|
|
||||||
Command::PasteBuffer(command) => self.cmd_pb(&out, command),
|
Command::PasteBuffer(command) => self.cmd_pb(&out, command),
|
||||||
Command::Source(script) => self.cmd_source(&out, script),
|
Command::Source(script) => self.cmd_source(&out, script),
|
||||||
Command::Dump(script) => self.cmd_dump(&out, script),
|
Command::Dump(script) => self.cmd_dump(&out, script),
|
||||||
|
|||||||
+2
-1
@@ -60,6 +60,7 @@ pub enum Command<'a> {
|
|||||||
Mv(Name, Name),
|
Mv(Name, Name),
|
||||||
Rm(Name),
|
Rm(Name),
|
||||||
Enc(Name),
|
Enc(Name),
|
||||||
|
Gen(u32, PasswordRef),
|
||||||
Pass(Name),
|
Pass(Name),
|
||||||
UnPass(Name),
|
UnPass(Name),
|
||||||
Correct(Name),
|
Correct(Name),
|
||||||
@@ -74,7 +75,7 @@ pub enum Command<'a> {
|
|||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Regular,
|
Regular,
|
||||||
RegularUpcase,
|
RegularUpcase,
|
||||||
|
|||||||
Reference in New Issue
Block a user