add isync functions
follow clippy suggestions
This commit is contained in:
parent
26aeb75bd1
commit
faa09e64f6
977
Cargo.lock
generated
977
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,8 @@ aes-gcm = { features = ["alloc", "aes"], default-features = false, version = "0.
|
|||||||
sha2 = { default-features = false, version = "0.10.6" }
|
sha2 = { default-features = false, version = "0.10.6" }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
brotli = { features = ["std"], default-features = false, version = "3.3.4" }
|
brotli = { features = ["std"], default-features = false, version = "3.3.4" }
|
||||||
|
reqwest = { features = ["json"], version = "0.11.14"}
|
||||||
|
serde = { features = ["serde_derive"], version = "1.0.158"}
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 'z' # Optimize for size
|
opt-level = 'z' # Optimize for size
|
||||||
|
178
src/lib.rs
178
src/lib.rs
@ -19,20 +19,59 @@ pub fn get_args() -> Vec<String> {
|
|||||||
std::env::args().collect()
|
std::env::args().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn isync_upload() {
|
#[derive(serde::Deserialize, Debug)]
|
||||||
// todo!("Post request");
|
struct Saved {
|
||||||
// }
|
success: bool,
|
||||||
|
_status: u16,
|
||||||
|
data: Vec<u8>,
|
||||||
|
_errorcode: u64
|
||||||
|
}
|
||||||
|
|
||||||
// pub fn isync_download() -> String {
|
fn get_token() -> String {
|
||||||
// todo!("Get request");
|
let mut token: String = String::new();
|
||||||
// }
|
File::open(get_ipass_folder()+"token.ipasst").unwrap().read_to_string(&mut token).unwrap();
|
||||||
|
token
|
||||||
|
}
|
||||||
|
|
||||||
pub fn import_file(file_path:&String) -> bool {
|
|
||||||
if std::path::Path::new(file_path).exists() {
|
pub async fn isync_get() -> bool {
|
||||||
let mut reader = brotli::Decompressor::new(
|
let token = get_token();
|
||||||
File::open(file_path).unwrap(),
|
let client = reqwest::Client::builder().https_only(true).build().unwrap();
|
||||||
4096, // buffer size
|
let req = client.get("https://ipass.ipost.rocks/saved").header("ipass-auth-token", token).build().unwrap();
|
||||||
);
|
let res = client.execute(req).await.unwrap();
|
||||||
|
let body = res.json::<Saved>().await.unwrap();
|
||||||
|
if body.success {
|
||||||
|
File::create(get_ipass_folder()+"temp.ipassx").unwrap().write_all(&body.data).unwrap();
|
||||||
|
import_file(&(get_ipass_folder()+"temp.ipassx"));
|
||||||
|
std::fs::remove_file(get_ipass_folder()+"temp.ipassx").unwrap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn isync_save() -> bool {
|
||||||
|
let possible_data = export_data();
|
||||||
|
match possible_data {
|
||||||
|
Some(data) => {
|
||||||
|
let token = get_token();
|
||||||
|
let client = reqwest::Client::builder().https_only(true).build().unwrap();
|
||||||
|
let req = client.post("https://ipass.ipost.rocks/saved")
|
||||||
|
.header("ipass-auth-token", token)
|
||||||
|
.body(data)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let _res = client.execute(req).await.unwrap();
|
||||||
|
//sent data
|
||||||
|
true
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn import_data<R: Read>(mut reader: brotli::Decompressor<R>) {
|
||||||
let mut content: String = String::new();
|
let mut content: String = String::new();
|
||||||
let mut buf = [0u8; 4096];
|
let mut buf = [0u8; 4096];
|
||||||
loop {
|
loop {
|
||||||
@ -47,7 +86,7 @@ pub fn import_file(file_path:&String) -> bool {
|
|||||||
if size == 0 {
|
if size == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
content += &std::str::from_utf8(&buf[..size]).unwrap();
|
content += std::str::from_utf8(&buf[..size]).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +94,7 @@ pub fn import_file(file_path:&String) -> bool {
|
|||||||
let lines = content.lines();
|
let lines = content.lines();
|
||||||
let mut name = "";
|
let mut name = "";
|
||||||
for i in lines {
|
for i in lines {
|
||||||
if name == "" {
|
if name.is_empty() {
|
||||||
name = i;
|
name = i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -64,40 +103,62 @@ pub fn import_file(file_path:&String) -> bool {
|
|||||||
file.write_all(i.as_bytes()).unwrap();
|
file.write_all(i.as_bytes()).unwrap();
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
pub fn import_file(file_path:&String) -> bool {
|
||||||
|
if std::path::Path::new(file_path).exists() {
|
||||||
|
let reader = brotli::Decompressor::new(
|
||||||
|
File::open(file_path).unwrap(),
|
||||||
|
4096, // buffer size
|
||||||
|
);
|
||||||
|
import_data(reader);
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn export_data() -> Option<Vec<u8>> {
|
||||||
|
let mut collected_data = String::new();
|
||||||
|
let paths = std::fs::read_dir(get_ipass_folder()).ok()?;
|
||||||
|
|
||||||
|
for path in paths.flatten() {
|
||||||
|
let file_name = path.file_name().into_string().ok()?.replace(".ipass", "");
|
||||||
|
let content = std::fs::read_to_string(get_ipass_folder() + &path.file_name().to_string_lossy()).ok()?;
|
||||||
|
collected_data += format!("{}\n{}\n", file_name, content).as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut compressed_data = Vec::new();
|
||||||
|
{
|
||||||
|
let mut compressor = brotli::CompressorWriter::new(&mut compressed_data, 4096, 11, 22);
|
||||||
|
compressor.write_all(collected_data.as_bytes()).ok()?;
|
||||||
|
compressor.flush().ok()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(compressed_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn export_file(file_path: &String) -> bool {
|
pub fn export_file(file_path: &String) -> bool {
|
||||||
let mut collected_data: String = String::new();
|
match export_data() {
|
||||||
|
Some(compressed_data) => {
|
||||||
let paths = read_dir(get_ipass_folder()).unwrap();
|
if let Ok(mut file) = std::fs::File::create(file_path) {
|
||||||
|
if let Err(e) = file.write_all(&compressed_data) {
|
||||||
for p in paths {
|
eprintln!("Failed to write compressed data to file: {}", e);
|
||||||
if let Ok(path) = p {
|
|
||||||
let content = &mut read_to_string(get_ipass_folder()+&path.file_name().into_string().unwrap()).expect("Should have been able to read the file");
|
|
||||||
collected_data += format!("{}\n{}\n", path.file_name().into_string().unwrap().replace(".ipass", ""),content).as_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(file) = File::create(file_path) {
|
|
||||||
let mut writer = brotli::CompressorWriter::new(
|
|
||||||
file,
|
|
||||||
4096,
|
|
||||||
11,
|
|
||||||
22);
|
|
||||||
|
|
||||||
match writer.write_all(collected_data.as_bytes()) {
|
|
||||||
Err(e) => panic!("{}", e),
|
|
||||||
Ok(_) => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
eprintln!("Failed to create file at path: {}", file_path);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
eprintln!("Failed to export data");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vecu8_to_string(vec: Vec<u8>) -> String {
|
fn vecu8_to_string(vec: Vec<u8>) -> String {
|
||||||
@ -117,7 +178,7 @@ fn vecu8_to_string(vec: Vec<u8>) -> String {
|
|||||||
if do_print_warning {
|
if do_print_warning {
|
||||||
println!("[WARNING] Output may be corrupt");
|
println!("[WARNING] Output may be corrupt");
|
||||||
}
|
}
|
||||||
return out;
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encrypt_pass(nonce_arg:String, pass: String,mpw: String) -> String {
|
fn encrypt_pass(nonce_arg:String, pass: String,mpw: String) -> String {
|
||||||
@ -143,7 +204,7 @@ fn encrypt_pass(nonce_arg:String, pass: String,mpw: String) -> String {
|
|||||||
let cipher = Aes256Gcm::new(master_pw);
|
let cipher = Aes256Gcm::new(master_pw);
|
||||||
let nonce = Nonce::from_slice(nonce_final); // 96-bits; unique per message
|
let nonce = Nonce::from_slice(nonce_final); // 96-bits; unique per message
|
||||||
let ciphertext = cipher.encrypt(nonce, pass.as_ref()).unwrap();
|
let ciphertext = cipher.encrypt(nonce, pass.as_ref()).unwrap();
|
||||||
return hex::encode(ciphertext);
|
hex::encode(ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -172,10 +233,10 @@ fn decrypt_pass(nonce_arg:String, pass: Vec<u8>,mpw: String) -> Result<String,St
|
|||||||
let plaintext = cipher.decrypt(nonce, pass.as_ref());
|
let plaintext = cipher.decrypt(nonce, pass.as_ref());
|
||||||
match plaintext {
|
match plaintext {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
return Ok(vecu8_to_string(res));
|
Ok(vecu8_to_string(res))
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err("[ERROR] Error decrypting data, check your master password".to_string());
|
Err("[ERROR] Error decrypting data, check your master password".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,18 +246,18 @@ pub fn get_home_folder_str() -> String {
|
|||||||
Some(path) => {
|
Some(path) => {
|
||||||
let p = path.to_str();
|
let p = path.to_str();
|
||||||
match p {
|
match p {
|
||||||
Some(pa) => return pa.to_owned(),
|
Some(pa) => pa.to_owned(),
|
||||||
None => return "".to_owned(),
|
None => "".to_owned(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => return "".to_owned(),
|
None => "".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ipass_folder() -> String {
|
pub fn get_ipass_folder() -> String {
|
||||||
let path = get_home_folder_str()+"/.IPass/";
|
let path = get_home_folder_str()+"/.IPass/";
|
||||||
std::fs::create_dir_all(&path).unwrap();
|
std::fs::create_dir_all(&path).unwrap();
|
||||||
return path;
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_entry(name: &String, pw: String, mpw: String) -> bool {
|
pub fn create_entry(name: &String, pw: String, mpw: String) -> bool {
|
||||||
@ -207,7 +268,7 @@ pub fn create_entry(name: &String, pw: String, mpw: String) -> bool {
|
|||||||
let pw = encrypt_pass(name.to_owned(), pw,mpw);
|
let pw = encrypt_pass(name.to_owned(), pw,mpw);
|
||||||
let mut file = File::create(get_ipass_folder()+name+".ipass").unwrap();
|
let mut file = File::create(get_ipass_folder()+name+".ipass").unwrap();
|
||||||
file.write_all(pw.as_bytes()).unwrap();
|
file.write_all(pw.as_bytes()).unwrap();
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_entry(name:&String,mpw:String) -> Result<String,String> {
|
fn read_entry(name:&String,mpw:String) -> Result<String,String> {
|
||||||
@ -216,14 +277,14 @@ fn read_entry(name:&String,mpw:String) -> Result<String,String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_entry(name:&String, mpw: String) -> Result<String,String> {
|
pub fn get_entry(name:&String, mpw: String) -> Result<String,String> {
|
||||||
return read_entry(name,mpw);
|
read_entry(name,mpw)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_password(name:&String, password:String, mpw: String) -> bool {
|
pub fn edit_password(name:&String, password:String, mpw: String) -> bool {
|
||||||
let entry_result = read_entry(name, mpw.clone());
|
let entry_result = read_entry(name, mpw.clone());
|
||||||
if let Ok(entry) = entry_result {
|
if let Ok(entry) = entry_result {
|
||||||
// println!("entry: {entry}");
|
// println!("entry: {entry}");
|
||||||
let mut parts = entry.split(";");
|
let mut parts = entry.split(';');
|
||||||
let username = parts.next().unwrap().to_string();
|
let username = parts.next().unwrap().to_string();
|
||||||
let _old_password = parts.next().unwrap();
|
let _old_password = parts.next().unwrap();
|
||||||
let data = encrypt_pass(name.to_owned(), username+";"+password.as_str(),mpw);
|
let data = encrypt_pass(name.to_owned(), username+";"+password.as_str(),mpw);
|
||||||
@ -231,14 +292,14 @@ pub fn edit_password(name:&String, password:String, mpw: String) -> bool {
|
|||||||
file.write_all(data.as_bytes()).unwrap();
|
file.write_all(data.as_bytes()).unwrap();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_username(name:&String, username: String, mpw: String) -> bool {
|
pub fn edit_username(name:&String, username: String, mpw: String) -> bool {
|
||||||
let entry_result = read_entry(name, mpw.clone());
|
let entry_result = read_entry(name, mpw.clone());
|
||||||
if let Ok(entry) = entry_result {
|
if let Ok(entry) = entry_result {
|
||||||
// println!("entry: {entry}");
|
// println!("entry: {entry}");
|
||||||
let mut parts = entry.split(";");
|
let mut parts = entry.split(';');
|
||||||
let _old_username = parts.next().unwrap();
|
let _old_username = parts.next().unwrap();
|
||||||
let password = parts.next().unwrap();
|
let password = parts.next().unwrap();
|
||||||
let data = encrypt_pass(name.to_owned(), username+";"+password,mpw);
|
let data = encrypt_pass(name.to_owned(), username+";"+password,mpw);
|
||||||
@ -246,7 +307,7 @@ pub fn edit_username(name:&String, username: String, mpw: String) -> bool {
|
|||||||
file.write_all(data.as_bytes()).unwrap();
|
file.write_all(data.as_bytes()).unwrap();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prompt_answer(toprint: String) -> String {
|
pub fn prompt_answer(toprint: String) -> String {
|
||||||
@ -270,14 +331,13 @@ pub fn rename(name: &String, new_name: &String, mpw: String) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let content = &mut read_to_string(get_ipass_folder()+name+".ipass").expect("Should have been able to read the file");
|
let content = &mut read_to_string(get_ipass_folder()+name+".ipass").expect("Should have been able to read the file");
|
||||||
let data_result = decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw.clone()).to_owned();
|
if let Ok(mut data) = decrypt_pass(name.to_owned(),hex::decode(content).unwrap(),mpw.clone()) {
|
||||||
if let Ok(mut data) = data_result {
|
|
||||||
data = encrypt_pass(new_name.to_owned(), data,mpw);
|
data = encrypt_pass(new_name.to_owned(), data,mpw);
|
||||||
let mut file = File::create(get_ipass_folder()+new_name+".ipass").unwrap();
|
let mut file = File::create(get_ipass_folder()+new_name+".ipass").unwrap();
|
||||||
file.write_all(data.as_bytes()).unwrap();
|
file.write_all(data.as_bytes()).unwrap();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_entries() -> std::fs::ReadDir {
|
pub fn get_entries() -> std::fs::ReadDir {
|
||||||
@ -296,5 +356,5 @@ pub fn random_password() -> String {
|
|||||||
// println!("{} - {} - {}",index,(index as usize)%(alph_len-1),alph_len);
|
// println!("{} - {} - {}",index,(index as usize)%(alph_len-1),alph_len);
|
||||||
chars += &char_set[(index as usize)%(alph_len-1)].to_string();
|
chars += &char_set[(index as usize)%(alph_len-1)].to_string();
|
||||||
}
|
}
|
||||||
return chars;
|
chars
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user