oxidize_pdf/encryption/
permissions.rs

1//! PDF permissions according to ISO 32000-1 Table 22
2
3/// Permission flags for encrypted PDFs
4#[derive(Debug, Clone, Copy)]
5pub struct Permissions {
6    /// Permission bits (32-bit value)
7    bits: u32,
8}
9
10/// Individual permission flags
11#[derive(Debug, Clone, Copy)]
12pub struct PermissionFlags {
13    /// Print the document
14    pub print: bool,
15    /// Modify document contents
16    pub modify_contents: bool,
17    /// Copy text and graphics
18    pub copy: bool,
19    /// Add or modify text annotations
20    pub modify_annotations: bool,
21    /// Fill in form fields
22    pub fill_forms: bool,
23    /// Extract text and graphics (accessibility)
24    pub accessibility: bool,
25    /// Assemble the document (insert, rotate, delete pages)
26    pub assemble: bool,
27    /// Print in high quality
28    pub print_high_quality: bool,
29}
30
31impl Default for PermissionFlags {
32    fn default() -> Self {
33        Self {
34            print: false,
35            modify_contents: false,
36            copy: false,
37            modify_annotations: false,
38            fill_forms: false,
39            accessibility: true, // Usually allowed for accessibility
40            assemble: false,
41            print_high_quality: false,
42        }
43    }
44}
45
46impl Permissions {
47    /// Create new permissions with all operations prohibited
48    pub fn new() -> Self {
49        // Bits 1-2 must be 0, bits 7-8 reserved (1), bits 13-32 must be 1
50        // This gives us 0xFFFFF0C0 as base
51        Self { bits: 0xFFFFF0C0 }
52    }
53
54    /// Create permissions from flags
55    pub fn from_flags(flags: PermissionFlags) -> Self {
56        let mut perm = Self::new();
57
58        if flags.print {
59            perm.set_print(true);
60        }
61        if flags.modify_contents {
62            perm.set_modify_contents(true);
63        }
64        if flags.copy {
65            perm.set_copy(true);
66        }
67        if flags.modify_annotations {
68            perm.set_modify_annotations(true);
69        }
70        if flags.fill_forms {
71            perm.set_fill_forms(true);
72        }
73        if flags.accessibility {
74            perm.set_accessibility(true);
75        }
76        if flags.assemble {
77            perm.set_assemble(true);
78        }
79        if flags.print_high_quality {
80            perm.set_print_high_quality(true);
81        }
82
83        perm
84    }
85
86    /// Create permissions allowing all operations
87    pub fn all() -> Self {
88        let mut perm = Self::new();
89        perm.bits |= 0x0F3C; // Set all permission bits
90        perm
91    }
92
93    /// Get raw permission bits
94    pub fn bits(&self) -> u32 {
95        self.bits
96    }
97
98    /// Create from raw bits
99    pub fn from_bits(bits: u32) -> Self {
100        Self { bits }
101    }
102
103    /// Check if contains all the specified permissions
104    pub fn contains(&self, other: Permissions) -> bool {
105        (self.bits & other.bits) == other.bits
106    }
107
108    /// Allow/disallow printing (bit 3)
109    pub fn set_print(&mut self, allow: bool) -> &mut Self {
110        if allow {
111            self.bits |= 1 << 2;
112        } else {
113            self.bits &= !(1 << 2);
114        }
115        self
116    }
117
118    /// Check if printing is allowed
119    pub fn can_print(&self) -> bool {
120        (self.bits & (1 << 2)) != 0
121    }
122
123    /// Allow/disallow modifying contents (bit 4)
124    pub fn set_modify_contents(&mut self, allow: bool) -> &mut Self {
125        if allow {
126            self.bits |= 1 << 3;
127        } else {
128            self.bits &= !(1 << 3);
129        }
130        self
131    }
132
133    /// Check if modifying contents is allowed
134    pub fn can_modify_contents(&self) -> bool {
135        (self.bits & (1 << 3)) != 0
136    }
137
138    /// Allow/disallow copying (bit 5)
139    pub fn set_copy(&mut self, allow: bool) -> &mut Self {
140        if allow {
141            self.bits |= 1 << 4;
142        } else {
143            self.bits &= !(1 << 4);
144        }
145        self
146    }
147
148    /// Check if copying is allowed
149    pub fn can_copy(&self) -> bool {
150        (self.bits & (1 << 4)) != 0
151    }
152
153    /// Allow/disallow modifying annotations (bit 6)
154    pub fn set_modify_annotations(&mut self, allow: bool) -> &mut Self {
155        if allow {
156            self.bits |= 1 << 5;
157        } else {
158            self.bits &= !(1 << 5);
159        }
160        self
161    }
162
163    /// Check if modifying annotations is allowed
164    pub fn can_modify_annotations(&self) -> bool {
165        (self.bits & (1 << 5)) != 0
166    }
167
168    /// Allow/disallow filling forms (bit 9)
169    pub fn set_fill_forms(&mut self, allow: bool) -> &mut Self {
170        if allow {
171            self.bits |= 1 << 8;
172        } else {
173            self.bits &= !(1 << 8);
174        }
175        self
176    }
177
178    /// Check if filling forms is allowed
179    pub fn can_fill_forms(&self) -> bool {
180        (self.bits & (1 << 8)) != 0
181    }
182
183    /// Allow/disallow accessibility (bit 10)
184    pub fn set_accessibility(&mut self, allow: bool) -> &mut Self {
185        if allow {
186            self.bits |= 1 << 9;
187        } else {
188            self.bits &= !(1 << 9);
189        }
190        self
191    }
192
193    /// Check if accessibility is allowed
194    pub fn can_access_for_accessibility(&self) -> bool {
195        (self.bits & (1 << 9)) != 0
196    }
197
198    /// Allow/disallow document assembly (bit 11)
199    pub fn set_assemble(&mut self, allow: bool) -> &mut Self {
200        if allow {
201            self.bits |= 1 << 10;
202        } else {
203            self.bits &= !(1 << 10);
204        }
205        self
206    }
207
208    /// Check if document assembly is allowed
209    pub fn can_assemble(&self) -> bool {
210        (self.bits & (1 << 10)) != 0
211    }
212
213    /// Allow/disallow high quality printing (bit 12)
214    pub fn set_print_high_quality(&mut self, allow: bool) -> &mut Self {
215        if allow {
216            self.bits |= 1 << 11;
217        } else {
218            self.bits &= !(1 << 11);
219        }
220        self
221    }
222
223    /// Check if high quality printing is allowed
224    pub fn can_print_high_quality(&self) -> bool {
225        (self.bits & (1 << 11)) != 0
226    }
227
228    /// Get permission flags
229    pub fn flags(&self) -> PermissionFlags {
230        PermissionFlags {
231            print: self.can_print(),
232            modify_contents: self.can_modify_contents(),
233            copy: self.can_copy(),
234            modify_annotations: self.can_modify_annotations(),
235            fill_forms: self.can_fill_forms(),
236            accessibility: self.can_access_for_accessibility(),
237            assemble: self.can_assemble(),
238            print_high_quality: self.can_print_high_quality(),
239        }
240    }
241}
242
243impl Default for Permissions {
244    fn default() -> Self {
245        Self::new()
246    }
247}
248
249#[cfg(test)]
250mod tests {
251    use super::*;
252
253    #[test]
254    fn test_permissions_new() {
255        let perm = Permissions::new();
256        assert_eq!(perm.bits(), 0xFFFFF0C0);
257
258        // All operations should be prohibited by default
259        assert!(!perm.can_print());
260        assert!(!perm.can_modify_contents());
261        assert!(!perm.can_copy());
262    }
263
264    #[test]
265    fn test_permissions_all() {
266        let perm = Permissions::all();
267
268        assert!(perm.can_print());
269        assert!(perm.can_modify_contents());
270        assert!(perm.can_copy());
271        assert!(perm.can_modify_annotations());
272        assert!(perm.can_fill_forms());
273        assert!(perm.can_access_for_accessibility());
274        assert!(perm.can_assemble());
275        assert!(perm.can_print_high_quality());
276    }
277
278    #[test]
279    fn test_permission_flags() {
280        let mut perm = Permissions::new();
281
282        // Test individual permissions
283        perm.set_print(true);
284        assert!(perm.can_print());
285        assert_eq!(perm.bits() & (1 << 2), 1 << 2);
286
287        perm.set_copy(true);
288        assert!(perm.can_copy());
289        assert_eq!(perm.bits() & (1 << 4), 1 << 4);
290
291        perm.set_print(false);
292        assert!(!perm.can_print());
293        assert_eq!(perm.bits() & (1 << 2), 0);
294    }
295
296    #[test]
297    fn test_from_flags() {
298        let flags = PermissionFlags {
299            print: true,
300            modify_contents: false,
301            copy: true,
302            modify_annotations: false,
303            fill_forms: true,
304            accessibility: true,
305            assemble: false,
306            print_high_quality: true,
307        };
308
309        let perm = Permissions::from_flags(flags);
310        assert!(perm.can_print());
311        assert!(!perm.can_modify_contents());
312        assert!(perm.can_copy());
313        assert!(!perm.can_modify_annotations());
314        assert!(perm.can_fill_forms());
315        assert!(perm.can_access_for_accessibility());
316        assert!(!perm.can_assemble());
317        assert!(perm.can_print_high_quality());
318    }
319
320    #[test]
321    fn test_get_flags() {
322        let mut perm = Permissions::new();
323        perm.set_print(true).set_copy(true).set_fill_forms(true);
324
325        let flags = perm.flags();
326        assert!(flags.print);
327        assert!(flags.copy);
328        assert!(flags.fill_forms);
329        assert!(!flags.modify_contents);
330        assert!(!flags.modify_annotations);
331    }
332
333    #[test]
334    fn test_permissions_default() {
335        let perm = Permissions::default();
336        assert_eq!(perm.bits(), Permissions::new().bits());
337    }
338
339    #[test]
340    fn test_permissions_bits_manipulation() {
341        let mut perm = Permissions::new();
342
343        // Test setting all permissions individually
344        perm.set_print(true);
345        perm.set_modify_contents(true);
346        perm.set_copy(true);
347        perm.set_modify_annotations(true);
348        perm.set_fill_forms(true);
349        perm.set_accessibility(true);
350        perm.set_assemble(true);
351        perm.set_print_high_quality(true);
352
353        assert!(perm.can_print());
354        assert!(perm.can_modify_contents());
355        assert!(perm.can_copy());
356        assert!(perm.can_modify_annotations());
357        assert!(perm.can_fill_forms());
358        assert!(perm.can_access_for_accessibility());
359        assert!(perm.can_assemble());
360        assert!(perm.can_print_high_quality());
361    }
362
363    #[test]
364    fn test_permissions_bits_clearing() {
365        let mut perm = Permissions::all();
366
367        // Test clearing all permissions individually
368        perm.set_print(false);
369        perm.set_modify_contents(false);
370        perm.set_copy(false);
371        perm.set_modify_annotations(false);
372        perm.set_fill_forms(false);
373        perm.set_accessibility(false);
374        perm.set_assemble(false);
375        perm.set_print_high_quality(false);
376
377        assert!(!perm.can_print());
378        assert!(!perm.can_modify_contents());
379        assert!(!perm.can_copy());
380        assert!(!perm.can_modify_annotations());
381        assert!(!perm.can_fill_forms());
382        assert!(!perm.can_access_for_accessibility());
383        assert!(!perm.can_assemble());
384        assert!(!perm.can_print_high_quality());
385    }
386
387    #[test]
388    fn test_permissions_chaining() {
389        let mut perm = Permissions::new();
390        perm.set_print(true).set_copy(true).set_fill_forms(true);
391
392        assert!(perm.can_print());
393        assert!(perm.can_copy());
394        assert!(perm.can_fill_forms());
395        assert!(!perm.can_modify_contents());
396    }
397
398    #[test]
399    fn test_permission_flags_debug() {
400        let flags = PermissionFlags {
401            print: true,
402            modify_contents: false,
403            copy: true,
404            modify_annotations: false,
405            fill_forms: true,
406            accessibility: true,
407            assemble: false,
408            print_high_quality: true,
409        };
410
411        // Test that debug formatting works
412        let debug_str = format!("{flags:?}");
413        assert!(debug_str.contains("PermissionFlags"));
414    }
415
416    #[test]
417    fn test_permission_flags_clone() {
418        let flags = PermissionFlags {
419            print: true,
420            modify_contents: false,
421            copy: true,
422            modify_annotations: false,
423            fill_forms: true,
424            accessibility: true,
425            assemble: false,
426            print_high_quality: true,
427        };
428
429        let cloned_flags = flags;
430        assert_eq!(flags.print, cloned_flags.print);
431        assert_eq!(flags.copy, cloned_flags.copy);
432        assert_eq!(flags.fill_forms, cloned_flags.fill_forms);
433    }
434
435    #[test]
436    fn test_permissions_specific_bit_patterns() {
437        // Test that specific bit combinations work correctly
438        let mut perm = Permissions::from_bits(0xFFFFF0C0);
439
440        // Set bit 2 (print permission)
441        perm.set_print(true);
442        assert_eq!(perm.bits() & (1 << 2), 1 << 2);
443
444        // Set bit 3 (modify contents)
445        perm.set_modify_contents(true);
446        assert_eq!(perm.bits() & (1 << 3), 1 << 3);
447
448        // Set bit 4 (copy)
449        perm.set_copy(true);
450        assert_eq!(perm.bits() & (1 << 4), 1 << 4);
451
452        // Set bit 5 (modify annotations)
453        perm.set_modify_annotations(true);
454        assert_eq!(perm.bits() & (1 << 5), 1 << 5);
455    }
456
457    #[test]
458    fn test_permissions_roundtrip_conversion() {
459        let original_flags = PermissionFlags {
460            print: true,
461            modify_contents: false,
462            copy: true,
463            modify_annotations: true,
464            fill_forms: false,
465            accessibility: true,
466            assemble: false,
467            print_high_quality: true,
468        };
469
470        let perm = Permissions::from_flags(original_flags);
471        let converted_flags = perm.flags();
472
473        assert_eq!(original_flags.print, converted_flags.print);
474        assert_eq!(
475            original_flags.modify_contents,
476            converted_flags.modify_contents
477        );
478        assert_eq!(original_flags.copy, converted_flags.copy);
479        assert_eq!(
480            original_flags.modify_annotations,
481            converted_flags.modify_annotations
482        );
483        assert_eq!(original_flags.fill_forms, converted_flags.fill_forms);
484        assert_eq!(original_flags.accessibility, converted_flags.accessibility);
485        assert_eq!(original_flags.assemble, converted_flags.assemble);
486        assert_eq!(
487            original_flags.print_high_quality,
488            converted_flags.print_high_quality
489        );
490    }
491
492    #[test]
493    fn test_permissions_edge_cases() {
494        // Test with bits that shouldn't affect permissions
495        let perm = Permissions::from_bits(0x00000000);
496        assert!(!perm.can_print());
497        assert!(!perm.can_copy());
498
499        // Test with all bits set
500        let perm = Permissions::from_bits(0xFFFFFFFF);
501        assert!(perm.can_print());
502        assert!(perm.can_modify_contents());
503        assert!(perm.can_copy());
504        assert!(perm.can_modify_annotations());
505        assert!(perm.can_fill_forms());
506        assert!(perm.can_access_for_accessibility());
507        assert!(perm.can_assemble());
508        assert!(perm.can_print_high_quality());
509    }
510}