Added enc and pass commands, change names of commands back to full.
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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()),
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user