sheetkit_core/
protection.rs1#[derive(Debug, Clone, Default)]
5pub struct WorkbookProtectionConfig {
6 pub password: Option<String>,
8 pub lock_structure: bool,
10 pub lock_windows: bool,
12 pub lock_revision: bool,
14}
15
16pub fn legacy_password_hash(password: &str) -> u16 {
22 if password.is_empty() {
23 return 0;
24 }
25 let mut hash: u16 = 0;
26 let bytes = password.as_bytes();
27 for (i, &byte) in bytes.iter().enumerate() {
28 let mut intermediate = byte as u16;
29 intermediate = (intermediate << (i + 1)) | (intermediate >> (15 - i));
30 hash ^= intermediate;
31 }
32 hash ^= bytes.len() as u16;
33 hash ^= 0xCE4B;
34 hash
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn test_legacy_password_hash_empty() {
43 assert_eq!(legacy_password_hash(""), 0);
44 }
45
46 #[test]
47 fn test_legacy_password_hash_known_values() {
48 let h = legacy_password_hash("password");
50 assert_ne!(h, 0);
51 assert_eq!(h, legacy_password_hash("password"));
53
54 let h2 = legacy_password_hash("test");
56 assert_ne!(h2, 0);
57 assert_ne!(h, h2);
58
59 let h3 = legacy_password_hash("a");
61 assert_ne!(h3, 0);
62 }
63
64 #[test]
65 fn test_legacy_password_hash_format() {
66 let h = legacy_password_hash("password");
68 let hex = format!("{:04X}", h);
69 assert_eq!(hex.len(), 4);
70 }
71
72 #[test]
73 fn test_workbook_protection_config_default() {
74 let config = WorkbookProtectionConfig::default();
75 assert!(config.password.is_none());
76 assert!(!config.lock_structure);
77 assert!(!config.lock_windows);
78 assert!(!config.lock_revision);
79 }
80}