pdfium_render/pdf/document/
permissions.rs1use crate::bindgen::FPDF_DOCUMENT;
5use crate::error::PdfiumError;
6use crate::pdfium::PdfiumLibraryBindingsAccessor;
7use bitflags::bitflags;
8use std::marker::PhantomData;
9use std::os::raw::c_int;
10
11#[cfg(doc)]
12use crate::pdf::document::PdfDocument;
13
14bitflags! {
15 struct FpdfPermissions: u32 {
16 const RESERVED_BIT_1 = 0b00000000000000000000000000000001;
17 const RESERVED_BIT_2 = 0b00000000000000000000000000000010;
18 const CAN_PRINT_BIT_3 = 0b00000000000000000000000000000100;
19 const CAN_MODIFY_BIT_4 = 0b00000000000000000000000000001000;
20 const CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_5 = 0b00000000000000000000000000010000;
21 const CAN_ANNOTATE_AND_FORM_FILL_BIT_6 = 0b00000000000000000000000000100000;
22 const RESERVED_BIT_7 = 0b00000000000000000000000001000000;
23 const RESERVED_BIT_8 = 0b00000000000000000000000010000000;
24 const V3_CAN_FORM_FILL_BIT_9 = 0b00000000000000000000000100000000;
25 const V3_CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_10 = 0b00000000000000000000001000000000;
26 const V3_CAN_ASSEMBLE_DOCUMENT_BIT_11 = 0b00000000000000000000010000000000;
27 const V3_CAN_PRINT_HIGH_QUALITY_BIT_12 = 0b00000000000000000000100000000000;
28 }
29}
30
31#[derive(Copy, Clone, Debug, PartialEq)]
33pub enum PdfSecurityHandlerRevision {
34 Unprotected,
35 Revision2,
36 Revision3,
37 Revision4,
38}
39
40impl PdfSecurityHandlerRevision {
41 pub(crate) fn from_pdfium(value: c_int) -> Option<Self> {
42 match value {
43 -1 => Some(PdfSecurityHandlerRevision::Unprotected),
44 2 => Some(PdfSecurityHandlerRevision::Revision2),
45 3 => Some(PdfSecurityHandlerRevision::Revision3),
46 4 => Some(PdfSecurityHandlerRevision::Revision4),
47 _ => None,
48 }
49 }
50}
51
52pub struct PdfPermissions<'a> {
58 document_handle: FPDF_DOCUMENT,
59 lifetime: PhantomData<&'a FPDF_DOCUMENT>,
60}
61
62impl<'a> PdfPermissions<'a> {
63 #[inline]
64 pub(crate) fn from_pdfium(document_handle: FPDF_DOCUMENT) -> Self {
65 Self {
66 document_handle,
67 lifetime: PhantomData,
68 }
69 }
70
71 #[inline]
73 fn get_permissions_bits(&self) -> FpdfPermissions {
74 FpdfPermissions::from_bits_truncate(unsafe {
75 self.bindings().FPDF_GetDocPermissions(self.document_handle)
76 } as u32)
77 }
78
79 pub fn security_handler_revision(&self) -> Result<PdfSecurityHandlerRevision, PdfiumError> {
82 PdfSecurityHandlerRevision::from_pdfium(unsafe {
83 self.bindings()
84 .FPDF_GetSecurityHandlerRevision(self.document_handle)
85 })
86 .ok_or(PdfiumError::UnknownPdfSecurityHandlerRevision)
87 }
88
89 pub fn can_print_high_quality(&self) -> Result<bool, PdfiumError> {
92 let permissions = self.get_permissions_bits();
93
94 let result = match self.security_handler_revision()? {
95 PdfSecurityHandlerRevision::Unprotected => true,
96 PdfSecurityHandlerRevision::Revision2 => {
97 permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3)
98 }
99 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
100 permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3)
101 && permissions.contains(FpdfPermissions::V3_CAN_PRINT_HIGH_QUALITY_BIT_12)
102 }
103 };
104
105 Ok(result)
106 }
107
108 pub fn can_print_only_low_quality(&self) -> Result<bool, PdfiumError> {
112 let permissions = self.get_permissions_bits();
113
114 let result = match self.security_handler_revision()? {
115 PdfSecurityHandlerRevision::Unprotected | PdfSecurityHandlerRevision::Revision2 => {
116 false
117 }
118 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
119 permissions.contains(FpdfPermissions::CAN_PRINT_BIT_3)
120 && !permissions.contains(FpdfPermissions::V3_CAN_PRINT_HIGH_QUALITY_BIT_12)
121 }
122 };
123
124 Ok(result)
125 }
126
127 pub fn can_assemble_document(&self) -> Result<bool, PdfiumError> {
131 let permissions = self.get_permissions_bits();
132
133 let result = match self.security_handler_revision()? {
134 PdfSecurityHandlerRevision::Unprotected => true,
135 PdfSecurityHandlerRevision::Revision2 => {
136 permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4)
137 }
138 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
139 permissions.contains(FpdfPermissions::V3_CAN_ASSEMBLE_DOCUMENT_BIT_11)
140 }
141 };
142
143 Ok(result)
144 }
145
146 pub fn can_modify_document_content(&self) -> Result<bool, PdfiumError> {
152 let permissions = self.get_permissions_bits();
153
154 let result = match self.security_handler_revision()? {
155 PdfSecurityHandlerRevision::Unprotected => true,
156 _ => permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4),
157 };
158
159 Ok(result)
160 }
161
162 pub fn can_extract_text_and_graphics(&self) -> Result<bool, PdfiumError> {
164 let permissions = self.get_permissions_bits();
165
166 let result = match self.security_handler_revision()? {
167 PdfSecurityHandlerRevision::Unprotected => true,
168 PdfSecurityHandlerRevision::Revision2 => {
169 permissions.contains(FpdfPermissions::CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_5)
170 }
171 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
173 permissions.contains(FpdfPermissions::V3_CAN_EXTRACT_TEXT_AND_GRAPHICS_BIT_10)
174 }
175 };
176
177 Ok(result)
178 }
179
180 pub fn can_fill_existing_interactive_form_fields(&self) -> Result<bool, PdfiumError> {
183 let permissions = self.get_permissions_bits();
184
185 let result = match self.security_handler_revision()? {
186 PdfSecurityHandlerRevision::Unprotected => true,
187 PdfSecurityHandlerRevision::Revision2 => {
188 permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6)
189 }
190 PdfSecurityHandlerRevision::Revision3 | PdfSecurityHandlerRevision::Revision4 => {
191 permissions.contains(FpdfPermissions::V3_CAN_FORM_FILL_BIT_9)
192 }
193 };
194
195 Ok(result)
196 }
197
198 pub fn can_create_new_interactive_form_fields(&self) -> Result<bool, PdfiumError> {
201 let permissions = self.get_permissions_bits();
202
203 let result = match self.security_handler_revision()? {
204 PdfSecurityHandlerRevision::Unprotected => true,
205 _ => {
206 permissions.contains(FpdfPermissions::CAN_MODIFY_BIT_4)
207 && permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6)
208 }
209 };
210
211 Ok(result)
212 }
213
214 pub fn can_add_or_modify_text_annotations(&self) -> Result<bool, PdfiumError> {
217 let permissions = self.get_permissions_bits();
218
219 let result = match self.security_handler_revision()? {
220 PdfSecurityHandlerRevision::Unprotected => true,
221 _ => permissions.contains(FpdfPermissions::CAN_ANNOTATE_AND_FORM_FILL_BIT_6),
222 };
223
224 Ok(result)
225 }
226}
227
228impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPermissions<'a> {}
229
230#[cfg(feature = "thread_safe")]
231unsafe impl<'a> Send for PdfPermissions<'a> {}
232
233#[cfg(feature = "thread_safe")]
234unsafe impl<'a> Sync for PdfPermissions<'a> {}