pdfium_render/pdf/document/
permissions.rs1use crate::bindgen::FPDF_DOCUMENT;
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::PdfiumError;
7use bitflags::bitflags;
8use std::os::raw::c_int;
9
10#[cfg(doc)]
11use crate::pdf::document::PdfDocument;
12
13bitflags! {
14 struct FpdfPermissions: u32 {
15 const RESERVED_BIT_1 = 0b00000000000000000000000000000001;
16 const RESERVED_BIT_2 = 0b00000000000000000000000000000010;
17 const CAN_PRINT_BIT_3 = 0b00000000000000000000000000000100;
18 const CAN_MODIFY_BIT_4 = 0b00000000000000000000000000001000;
19 const CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_5 = 0b00000000000000000000000000010000;
20 const CAN_ANNOTATE_AND_FORM_FILL_BIT_6 = 0b00000000000000000000000000100000;
21 const RESERVED_BIT_7 = 0b00000000000000000000000001000000;
22 const RESERVED_BIT_8 = 0b00000000000000000000000010000000;
23 const V3_CAN_FORM_FILL_BIT_9 = 0b00000000000000000000000100000000;
24 const V3_CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_10 = 0b00000000000000000000001000000000;
25 const V3_CAN_ASSEMBLE_DOCUMENT_BIT_11 = 0b00000000000000000000010000000000;
26 const V3_CAN_PRINT_HIGH_QUALITY_BIT_12 = 0b00000000000000000000100000000000;
27 }
28}
29
30#[derive(Copy, Clone, Debug, PartialEq)]
32pub enum PdfSecurityHandlerRevision {
33 Unprotected,
34 Revision2,
35 Revision3,
36 Revision4,
37}
38
39impl PdfSecurityHandlerRevision {
40 pub(crate) fn from_pdfium(value: c_int) -> Option<Self> {
41 match value {
42 -1 => Some(PdfSecurityHandlerRevision::Unprotected),
43 2 => Some(PdfSecurityHandlerRevision::Revision2),
44 3 => Some(PdfSecurityHandlerRevision::Revision3),
45 4 => Some(PdfSecurityHandlerRevision::Revision4),
46 _ => None,
47 }
48 }
49}
50
51pub struct PdfPermissions<'a> {
57 document_handle: FPDF_DOCUMENT,
58 bindings: &'a dyn PdfiumLibraryBindings,
59}
60
61impl<'a> PdfPermissions<'a> {
62 #[inline]
63 pub(crate) fn from_pdfium(document_handle: FPDF_DOCUMENT, bindings: &'a dyn PdfiumLibraryBindings) -> Self {
64 Self {
65 document_handle,
66 bindings,
67 }
68 }
69
70 #[inline]
72 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
73 self.bindings
74 }
75
76 #[inline]
78 fn get_permissions_bits(&self) -> FpdfPermissions {
79 #[allow(clippy::unnecessary_cast)]
80 FpdfPermissions::from_bits_truncate(self.bindings().FPDF_GetDocPermissions(self.document_handle) as u32)
81 }
82
83 pub fn security_handler_revision(&self) -> Result<PdfSecurityHandlerRevision, PdfiumError> {
86 PdfSecurityHandlerRevision::from_pdfium(self.bindings().FPDF_GetSecurityHandlerRevision(self.document_handle))
87 .ok_or(PdfiumError::UnknownPdfSecurityHandlerRevision)
88 }
89
90 pub fn can_print_high_quality(&self) -> Result<bool, PdfiumError> {
93 let permissions = self.get_permissions_bits();
94
95 let result = match self.security_handler_revision()? {
96 PdfSecurityHandlerRevision::Unprotected => true,
97 PdfSecurityHandlerRevision::Revision2 => permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3),
98 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
99 permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3)
100 && permissions.contains(FpdfPermissions::V3_CAN_PRINT_HIGH_QUALITY_BIT_12)
101 }
102 };
103
104 Ok(result)
105 }
106
107 pub fn can_print_only_low_quality(&self) -> Result<bool, PdfiumError> {
111 let permissions = self.get_permissions_bits();
112
113 let result = match self.security_handler_revision()? {
114 PdfSecurityHandlerRevision::Unprotected | PdfSecurityHandlerRevision::Revision2 => false,
115 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
116 permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3)
117 && !permissions.contains(FpdfPermissions::V3_CAN_PRINT_HIGH_QUALITY_BIT_12)
118 }
119 };
120
121 Ok(result)
122 }
123
124 pub fn can_assemble_document(&self) -> Result<bool, PdfiumError> {
128 let permissions = self.get_permissions_bits();
129
130 let result = match self.security_handler_revision()? {
131 PdfSecurityHandlerRevision::Unprotected => true,
132 PdfSecurityHandlerRevision::Revision2 => permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4),
133 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
134 permissions.contains(FpdfPermissions::V3_CAN_ASSEMBLE_DOCUMENT_BIT_11)
135 }
136 };
137
138 Ok(result)
139 }
140
141 pub fn can_modify_document_content(&self) -> Result<bool, PdfiumError> {
147 let permissions = self.get_permissions_bits();
148
149 let result = match self.security_handler_revision()? {
150 PdfSecurityHandlerRevision::Unprotected => true,
151 _ => permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4),
152 };
153
154 Ok(result)
155 }
156
157 pub fn can_extract_text_and_graphics(&self) -> Result<bool, PdfiumError> {
159 let permissions = self.get_permissions_bits();
160
161 let result = match self.security_handler_revision()? {
162 PdfSecurityHandlerRevision::Unprotected => true,
163 PdfSecurityHandlerRevision::Revision2 => {
164 permissions.contains(FpdfPermissions::CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_5)
165 }
166 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
168 permissions.contains(FpdfPermissions::V3_CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_10)
169 }
170 };
171
172 Ok(result)
173 }
174
175 pub fn can_fill_existing_interactive_form_fields(&self) -> Result<bool, PdfiumError> {
178 let permissions = self.get_permissions_bits();
179
180 let result = match self.security_handler_revision()? {
181 PdfSecurityHandlerRevision::Unprotected => true,
182 PdfSecurityHandlerRevision::Revision2 => {
183 permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6)
184 }
185 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
186 permissions.contains(FpdfPermissions::V3_CAN_FORM_FILL_BIT_9)
187 }
188 };
189
190 Ok(result)
191 }
192
193 pub fn can_create_new_interactive_form_fields(&self) -> Result<bool, PdfiumError> {
196 let permissions = self.get_permissions_bits();
197
198 let result = match self.security_handler_revision()? {
199 PdfSecurityHandlerRevision::Unprotected => true,
200 _ => {
201 permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4)
202 && permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6)
203 }
204 };
205
206 Ok(result)
207 }
208
209 pub fn can_add_or_modify_text_annotations(&self) -> Result<bool, PdfiumError> {
212 let permissions = self.get_permissions_bits();
213
214 let result = match self.security_handler_revision()? {
215 PdfSecurityHandlerRevision::Unprotected => true,
216 _ => permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6),
217 };
218
219 Ok(result)
220 }
221}