Added enc and pass commands, change names of commands back to full.

This commit is contained in:
Oleksandr Kozachuk
2022-12-13 22:39:41 +01:00
parent a291aafcf9
commit 85ac2a0420
5 changed files with 122 additions and 26 deletions
+1
View File
@@ -18,3 +18,4 @@ anyerror = "0.1.7"
home = "0.5.4" home = "0.5.4"
sha1 = "0.10.5" sha1 = "0.10.5"
base64 = "0.20.0" base64 = "0.20.0"
rpassword = "7.2.0"
+2
View File
@@ -6,6 +6,7 @@ use std::collections::HashMap;
pub struct LK { pub struct LK {
pub db: HashMap<NameRef, PasswordRef>, pub db: HashMap<NameRef, PasswordRef>,
pub ls: HashMap<String, PasswordRef>, pub ls: HashMap<String, PasswordRef>,
pub secrets: HashMap<NameRef, String>,
} }
impl LK { impl LK {
@@ -13,6 +14,7 @@ impl LK {
Self { Self {
db: HashMap::new(), db: HashMap::new(),
ls: HashMap::new(), ls: HashMap::new(),
secrets: HashMap::new(),
} }
} }
+18 -10
View File
@@ -16,6 +16,8 @@ peg::parser! {
/ ls_cmd() / ls_cmd()
/ mv_cmd() / mv_cmd()
/ rm_cmd() / rm_cmd()
/ enc_cmd()
/ pass_cmd()
/ comment_cmd() / comment_cmd()
) { c } ) { c }
@@ -32,9 +34,13 @@ peg::parser! {
{ Password::new(Some(pr), pn, pl, pm, 99, pd, pc) } { Password::new(Some(pr), pn, pl, pm, 99, pd, pc) }
rule sname() -> Password = &(word() _ num()? mode() _ date()) pn:word() _ pl:num()? pm:mode() _ pd:date() pc:comment()? rule sname() -> Password = &(word() _ num()? mode() _ date()) pn:word() _ pl:num()? pm:mode() _ pd:date() pc:comment()?
{ Password::new(None, pn, pl, pm, 99, pd, pc) } { Password::new(None, pn, pl, pm, 99, pd, pc) }
rule ssname() -> Password = &(word()) pn:word() rule nname() -> Password = &(word() _ num()? mode()) pn:word() _ pl:num()? pm:mode()
{ Password::new(None, pn, pl, pm, 99, Local::now().naive_local().date(), None) }
rule qname() -> Password = &(word()) pn:word()
{ Password::new(None, pn, None, Mode::NoSpaceCamel, 99, Local::now().naive_local().date(), None) } { Password::new(None, pn, None, Mode::NoSpaceCamel, 99, Local::now().naive_local().date(), None) }
pub rule name() -> Password = name:(jname() / pname() / mname() / sname() / ssname())? {? match name { Some(n) => Ok(n), None => Err("failed to parse password description") } } pub rule name() -> Password = name:(jname() / pname() / mname() / sname() / nname() / qname())? {?
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 date() -> 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") };
@@ -51,7 +57,7 @@ peg::parser! {
_ => Err("unknown mode"), _ => Err("unknown mode"),
} }
} }
rule rmode() -> Mode = m:$("R" / "r" / "U" / "u" / "N" / "n" / "C" / "H" / "h" / "B" / "b" / "D" / "d") {? rule rmode() -> Mode = m:$("R" / "r" / "U" / "u" / "N" / "n" / "C" / "c" / "H" / "h" / "B" / "b" / "D" / "d") {?
match m.to_uppercase().as_str() { match m.to_uppercase().as_str() {
"R" => Ok(Mode::Regular), "R" => Ok(Mode::Regular),
"N" => Ok(Mode::NoSpace), "N" => Ok(Mode::NoSpace),
@@ -64,14 +70,16 @@ peg::parser! {
} }
} }
rule mode() -> Mode = m:(umode() / rmode()) { m } rule mode() -> Mode = m:(umode() / rmode()) { m }
rule help_cmd() -> Command<'input> = "h" { Command::Help } rule help_cmd() -> Command<'input> = "help" { Command::Help }
rule quit_cmd() -> Command<'input> = "q" { Command::Quit } rule quit_cmd() -> Command<'input> = "quit" { Command::Quit }
rule ls_cmd() -> Command<'input> = "l" { Command::Ls } rule ls_cmd() -> Command<'input> = "ls" { Command::Ls }
rule add_cmd() -> Command<'input> = "a" _ 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 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> = "m" _ name:word() _ folder:word() { Command::Mv(name, folder) } rule mv_cmd() -> Command<'input> = "mv" _ name:word() _ folder:word() { Command::Mv(name, folder) }
rule rm_cmd() -> Command<'input> = "r" _ name:word() { Command::Rm(name) } rule pass_cmd() -> Command<'input> = "pass" _ name:word() { Command::Pass(name) }
rule comment_cmd() -> Command<'input> = "c" _ name:word() c:comment()? { Command::Comment(name, c) } rule enc_cmd() -> Command<'input> = "enc" _ name:word() { Command::Enc(name) }
rule rm_cmd() -> Command<'input> = "rm" _ name:word() { Command::Rm(name) }
rule comment_cmd() -> Command<'input> = "comment" _ name:word() c:comment()? { Command::Comment(name, c) }
} }
} }
+81 -16
View File
@@ -1,4 +1,5 @@
use home::home_dir; use home::home_dir;
use rpassword::prompt_password;
use rustyline::Editor; use rustyline::Editor;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
@@ -84,7 +85,60 @@ impl<'a> LKEval<'a> {
} }
} }
fn cmd_ls(&mut self, out: &mut Vec<String>) { fn read_master(&self, pwd: PasswordRef) -> String {
let parent = match &pwd.borrow().parent {
Some(p) => p.borrow().name.clone(),
None => Rc::new("/".to_string()),
};
let secret = match self.state.borrow().secrets.get(&parent) {
Some(p) => Some(p.clone()),
None => None,
};
match (pwd.borrow().parent.clone(), secret) {
(_, Some(s)) => s.to_string(),
(None, None) => {
let password = prompt_password("Master: ").unwrap();
self.state.borrow_mut().secrets.insert(Rc::new("/".to_string()), password.clone());
password
}
(Some(pn), None) => {
let password = prompt_password(format!("Password for {}: ", pn.borrow().name)).unwrap();
if password.len() > 0 {
self.state.borrow_mut().secrets.insert(pn.borrow().name.clone(), password.clone());
password
} else {
let master = self.read_master(pn.clone());
let password = pn.borrow().encode(master.as_str());
self.state.borrow_mut().secrets.insert(pn.borrow().name.clone(), password.clone());
password
}
}
}
}
fn cmd_enc(&self, out: &mut Vec<String>, name: &String) {
let root_folder = Rc::new("/".to_string());
if name == "/" && self.state.borrow().secrets.contains_key(&root_folder) {
out.push(self.state.borrow().secrets.get(&root_folder).unwrap().to_string());
return;
}
let pwd = match self.get_password(name) {
Some(p) => p.clone(),
None => {
out.push(format!("error: name {} not found", name));
return;
}
};
let name = pwd.borrow().name.clone();
if self.state.borrow().secrets.contains_key(&name) {
out.push(self.state.borrow().secrets.get(&name).unwrap().to_string());
return;
}
let sec = self.read_master(pwd.clone());
out.push(pwd.borrow().encode(sec.as_str()));
}
fn cmd_ls(&self, out: &mut Vec<String>) {
let mut tmp: Vec<PasswordRef> = vec![]; let mut tmp: Vec<PasswordRef> = vec![];
for (_, name) in &self.state.borrow().db { for (_, name) in &self.state.borrow().db {
tmp.push(name.clone()); tmp.push(name.clone());
@@ -100,7 +154,7 @@ impl<'a> LKEval<'a> {
} }
} }
pub fn eval(&mut self) -> LKPrint { pub fn eval(&self) -> LKPrint {
let mut out: Vec<String> = vec![]; let mut out: Vec<String> = vec![];
let mut quit: bool = false; let mut quit: bool = false;
@@ -134,27 +188,38 @@ impl<'a> LKEval<'a> {
} }
None => out.push("error: password not found".to_string()), None => out.push("error: password not found".to_string()),
}, },
Command::Enc(name) => self.cmd_enc(&mut out, name),
Command::Pass(name) => match self.get_password(name) {
Some(p) => {
self.state.borrow_mut().secrets.insert(p.borrow().name.clone(), prompt_password(format!("Password for {}: ", p.borrow().name)).unwrap());
}
None => {
if name == "/" {
self.state.borrow_mut().secrets.insert(Rc::new("/".to_string()), prompt_password("Master: ").unwrap());
} else {
out.push(format!("error: password with name {} not found", name));
}
}
},
Command::Help => { Command::Help => {
out.push("HELP".to_string()); out.push("HELP".to_string());
} }
Command::Mv(name, folder) => { Command::Mv(name, folder) => match self.get_password(name) {
for (_, tmp) in &self.state.borrow().db { Some(pwd) => {
if *tmp.borrow().name == *name { if folder == "/" {
if folder == "/" { pwd.borrow_mut().parent = None
tmp.borrow_mut().parent = None } else {
} else { match self.get_password(folder) {
for (_, fld) in &self.state.borrow().db { Some(fld) => {
if *fld.borrow().name == *folder { pwd.borrow_mut().parent = Some(fld.clone());
tmp.borrow_mut().parent = Some(fld.clone()); fix_password_recursion(pwd.clone());
fix_password_recursion(tmp.clone());
break;
}
} }
None => out.push(format!("error: folder {} not found", folder)),
} }
break;
} }
} }
} None => out.push(format!("error: password with name {} not found", name)),
},
Command::Error(err) => match err { Command::Error(err) => match err {
LKErr::ParseError(e) => out.push(e.to_string()), LKErr::ParseError(e) => out.push(e.to_string()),
LKErr::ReadError(e) => out.push(e.to_string()), LKErr::ReadError(e) => out.push(e.to_string()),
+20
View File
@@ -17,6 +17,8 @@ pub enum Command<'a> {
Ls, Ls,
Mv(Name, Name), Mv(Name, Name),
Rm(Name), Rm(Name),
Enc(Name),
Pass(Name),
Comment(Name, Comment), Comment(Name, Comment),
Error(LKErr<'a>), Error(LKErr<'a>),
Help, Help,
@@ -108,3 +110,21 @@ impl fmt::Display for Radix {
Ok(()) Ok(())
} }
} }
/*
impl fmt::Display for Radix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let sign = if self.x < 0 { '-' } else { ' ' };
let mut x: u32 = self.x.abs() as u32;
write!(f, "{}{}", sign, (0..).map(|_| {
let m = x % self.radix;
x /= self.radix;
(x, std::char::from_digit(m, self.radix).unwrap())
})
.take_while(|a| a.0 > 0).map(|b| b.1).collect::<String>()
.chars().rev().collect::<String>()
)?;
Ok(())
}
}
*/