aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api.rs12
-rw-r--r--src/locked.rs6
-rw-r--r--src/pwgen.rs44
3 files changed, 55 insertions, 7 deletions
diff --git a/src/api.rs b/src/api.rs
index 99e12fd..0ecc7fa 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -252,14 +252,18 @@ impl SyncResCipher {
let history = if let Some(history) = &self.password_history {
history
.iter()
- .map(|entry| crate::db::HistoryEntry {
- last_used_date: entry.last_used_date.clone(),
- password: entry.password.clone(),
+ .filter_map(|entry| {
+ // Gets rid of entries with a non-existent password
+ entry.password.clone().map(|p| crate::db::HistoryEntry {
+ last_used_date: entry.last_used_date.clone(),
+ password: p,
+ })
})
.collect()
} else {
vec![]
};
+
let (folder, folder_id) = if let Some(folder_id) = &self.folder_id {
let mut folder_name = None;
for folder in folders {
@@ -459,7 +463,7 @@ struct SyncResPasswordHistory {
#[serde(rename = "LastUsedDate")]
last_used_date: String,
#[serde(rename = "Password")]
- password: String,
+ password: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
diff --git a/src/locked.rs b/src/locked.rs
index 3cad927..aecc54d 100644
--- a/src/locked.rs
+++ b/src/locked.rs
@@ -1,13 +1,15 @@
use zeroize::Zeroize;
+const LEN: usize = 4096;
+
pub struct Vec {
- data: Box<arrayvec::ArrayVec<[u8; 4096]>>,
+ data: Box<arrayvec::ArrayVec<u8, LEN>>,
_lock: region::LockGuard,
}
impl Default for Vec {
fn default() -> Self {
- let data = Box::new(arrayvec::ArrayVec::<_>::new());
+ let data = Box::new(arrayvec::ArrayVec::<_, LEN>::new());
// XXX it'd be nice to handle this better than .unwrap(), but it'd be
// a lot of effort
let lock = region::lock(data.as_ptr(), data.capacity()).unwrap();
diff --git a/src/pwgen.rs b/src/pwgen.rs
index dc6808f..cf63bb2 100644
--- a/src/pwgen.rs
+++ b/src/pwgen.rs
@@ -56,8 +56,50 @@ pub fn pwgen(ty: Type, len: usize) -> String {
let mut rng = rand::thread_rng();
let mut pass = vec![];
- pass.extend(alphabet.choose_multiple(&mut rng, len).copied());
+ pass.extend(
+ std::iter::repeat_with(|| alphabet.choose(&mut rng).unwrap())
+ .take(len),
+ );
// unwrap is safe because the method of generating passwords guarantees
// valid utf8
String::from_utf8(pass).unwrap()
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_pwgen() {
+ let pw = pwgen(Type::AllChars, 50);
+ assert_eq!(pw.len(), 50);
+ // technically this could fail, but the chances are incredibly low
+ // (around 0.000009%)
+ assert_duplicates(&pw);
+
+ let pw = pwgen(Type::AllChars, 100);
+ assert_eq!(pw.len(), 100);
+ assert_duplicates(&pw);
+
+ let pw = pwgen(Type::NoSymbols, 100);
+ assert_eq!(pw.len(), 100);
+ assert_duplicates(&pw);
+
+ let pw = pwgen(Type::Numbers, 100);
+ assert_eq!(pw.len(), 100);
+ assert_duplicates(&pw);
+
+ let pw = pwgen(Type::NonConfusables, 100);
+ assert_eq!(pw.len(), 100);
+ assert_duplicates(&pw);
+ }
+
+ #[track_caller]
+ fn assert_duplicates(s: &str) {
+ let mut set = std::collections::HashSet::new();
+ for c in s.chars() {
+ set.insert(c);
+ }
+ assert!(set.len() < s.len())
+ }
+}