use std::{
error::Error,
fmt::{Display, Formatter},
path::PathBuf,
};
use qpdf::{EncryptionParams, EncryptionParamsR6, writer};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PermissionParams {
pub user_password: Option<String>,
pub owner_password: Option<String>,
pub allow_accessibility: bool,
pub allow_extract: bool,
pub allow_assemble: bool,
pub allow_annotate_and_form: bool,
pub allow_form_filling: bool,
pub allow_modify_other: bool,
pub allow_print: PrintPermission,
pub encrypt_metadata: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PrintPermission {
Full,
Low,
None,
}
impl Display for PrintPermission {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PrintPermission::Full => write!(f, "full"),
PrintPermission::Low => write!(f, "low"),
PrintPermission::None => write!(f, "none"),
}
}
}
impl From<&PrintPermission> for writer::PrintPermission {
fn from(permission: &PrintPermission) -> writer::PrintPermission {
match permission {
PrintPermission::Full => qpdf::PrintPermission::Full,
PrintPermission::Low => qpdf::PrintPermission::Low,
PrintPermission::None => qpdf::PrintPermission::None,
}
}
}
impl From<String> for PrintPermission {
fn from(permission: String) -> PrintPermission {
match permission.to_lowercase().as_str() {
"full" => PrintPermission::Full,
"low" => PrintPermission::Low,
_ => PrintPermission::None,
}
}
}
impl From<&PermissionParams> for EncryptionParams {
fn from(params: &PermissionParams) -> EncryptionParams {
EncryptionParams::R6(EncryptionParamsR6 {
user_password: params.user_password.clone().unwrap_or_default(),
owner_password: params.owner_password.clone().unwrap_or_default(),
allow_accessibility: params.allow_accessibility,
allow_extract: params.allow_extract,
allow_assemble: params.allow_assemble,
allow_annotate_and_form: params.allow_annotate_and_form,
allow_form_filling: params.allow_form_filling,
allow_modify_other: params.allow_modify_other,
allow_print: (¶ms.allow_print).into(),
encrypt_metadata: params.encrypt_metadata,
})
}
}
impl Default for PermissionParams {
fn default() -> Self {
Self {
user_password: None,
owner_password: None,
allow_accessibility: true,
allow_extract: true,
allow_assemble: false,
allow_annotate_and_form: true,
allow_form_filling: false,
allow_modify_other: false,
allow_print: PrintPermission::Full,
encrypt_metadata: true,
}
}
}
pub fn set_permission(
input: PathBuf,
output: PathBuf,
params: &PermissionParams,
) -> Result<(), Box<dyn Error>> {
if input == output {
return Err("in-place update is not possible".into());
}
qpdf::QPdf::read(input)
.unwrap()
.writer()
.encryption_params(params.into())
.write(output)
.map_err(|e| e.into())
}