use spectre_pdf::Document;
fn fixture(name: &str) -> Vec<u8> {
let path = format!("tests/fixtures/encrypted/{name}");
std::fs::read(&path).unwrap_or_else(|e| panic!("read {path}: {e}"))
}
fn baseline_text() -> String {
let bytes = fixture("source.pdf");
let doc = Document::open(&bytes).expect("open unencrypted source");
doc.text().expect("extract source text").trim().to_owned()
}
fn roundtrip(name: &str, password: &[u8]) {
let bytes = fixture(name);
let doc = Document::open_with_password(&bytes, password)
.unwrap_or_else(|e| panic!("open {name} with password: {e}"));
let got = doc.text().expect("extract text").trim().to_owned();
let want = baseline_text();
assert_eq!(got, want, "{name}: decrypted text differs from baseline");
}
#[test]
fn v1_r2_rc4_40_roundtrip() {
roundtrip("v1_rc4_40.pdf", b"secret");
}
#[test]
fn v2_r3_rc4_128_roundtrip() {
roundtrip("v2_rc4_128.pdf", b"secret");
}
#[test]
fn v4_r4_aes128_roundtrip() {
roundtrip("v4_aes_128.pdf", b"secret");
}
#[test]
fn v4_r4_aes128_empty_user_roundtrip() {
roundtrip("v4_aes_128_empty_user.pdf", b"");
}
#[test]
fn v5_r5_aes256_roundtrip() {
roundtrip("v5_aes_256_r5.pdf", b"secret");
}
#[test]
fn v5_r6_aes256_roundtrip() {
roundtrip("v5_aes_256.pdf", b"secret");
}
#[test]
fn v5_r6_aes256_empty_user_roundtrip() {
roundtrip("v5_aes_256_empty_user.pdf", b"");
}
fn assert_rejects(name: &str) {
let bytes = fixture(name);
match Document::open_with_password(&bytes, b"wrong-password") {
Ok(_) => panic!("{name}: wrong password incorrectly accepted"),
Err(e) => {
let msg = format!("{e:?}");
assert!(
msg.contains("Encrypted"),
"{name}: expected ExtractError::Encrypted, got {msg}"
);
}
}
}
#[test]
fn wrong_password_rejected_aes128() {
assert_rejects("v4_aes_128.pdf");
}
#[test]
fn wrong_password_rejected_aes256() {
assert_rejects("v5_aes_256.pdf");
}
#[test]
fn user_password_pdf_surfaces_encrypted_via_free_function() {
let bytes = fixture("v4_aes_128.pdf");
let err = spectre_pdf::extract_text(&bytes).expect_err("user-password PDF must error");
let msg = format!("{err:?}");
assert!(
msg.contains("Encrypted"),
"free extract_text on user-password PDF should give Encrypted, got {msg}"
);
let err = spectre_pdf::extract_words(&bytes, None).expect_err("user-password PDF must error");
let msg = format!("{err:?}");
assert!(
msg.contains("Encrypted"),
"free extract_words on user-password PDF should give Encrypted, got {msg}"
);
let err = spectre_pdf::extract_blocks(&bytes, None).expect_err("user-password PDF must error");
let msg = format!("{err:?}");
assert!(
msg.contains("Encrypted"),
"free extract_blocks on user-password PDF should give Encrypted, got {msg}"
);
}