M6: a secured form's notice bar still says it is a form (#3404)

This commit is contained in:
Eric Kaden
2026-10-19 12:58:03 -04:00
committed by GitHub
parent 32abf71049
commit caaf058815
4 changed files with 65 additions and 10 deletions
+17 -5
View File
@@ -4502,11 +4502,8 @@ fn notices(
// A form whose scripts were turned off no longer calculates or answers its buttons: that
// comes before what else there is to say about the document.
let scripts_off = doc.xfa_scripts_off();
let msg = if scripts_off {
Some(("triangle-alert", crate::js_ui::scripts_off_notice(), true))
} else if secured {
Some(("lock", tl!("This document is secured. Some changes are restricted by its security settings.").to_string(), false))
} else if let Some(x) = xfa {
// What the document is as a form, if it is one: what the bar says first, secured or not.
let form = if let Some(x) = xfa {
let lang = crate::i18n::current();
let pages = crate::i18n::trn(lang, x.pages as u64, "{n} page", "{n} pages");
let fields = crate::i18n::trn(lang, x.fields as u64, "{n} field", "{n} fields");
@@ -4537,6 +4534,21 @@ fn notices(
crate::i18n::fmt(tl!("This document contains {n} interactive form fields."), &[("n", &info.fields.len().to_string())]),
true,
))
} else {
None
};
let msg = if scripts_off {
Some(("triangle-alert", crate::js_ui::scripts_off_notice(), true))
} else if secured {
// A secured form still says what it is, and keeps Highlight fields: the security
// sentence follows the form's.
let security = tl!("This document is secured. Some changes are restricted by its security settings.");
Some(match form {
Some((icon, text, fields)) => (icon, format!("{text} {security}"), fields),
None => ("lock", security.to_string(), false),
})
} else if form.is_some() {
form
} else if repaired {
Some(("bandage", tl!("This file was damaged and has been repaired. Saving keeps the repaired version.").to_string(), false))
} else if !info.warnings.is_empty() {
+25 -1
View File
@@ -2024,7 +2024,12 @@ fn protected(user: &str, owner: &str, permissions: i32) -> Vec<u8> {
}
fn protected_with(algorithm: pdfcraft_cos::Algorithm, user: &str, owner: &str, permissions: i32) -> Vec<u8> {
let mut doc = pdfcraft_cos::Document::open(std::sync::Arc::new(fixture(2))).unwrap();
encrypted(fixture(2), algorithm, user, owner, permissions)
}
/// `bytes` rewritten encrypted.
fn encrypted(bytes: Vec<u8>, algorithm: pdfcraft_cos::Algorithm, user: &str, owner: &str, permissions: i32) -> Vec<u8> {
let mut doc = pdfcraft_cos::Document::open(std::sync::Arc::new(bytes)).unwrap();
doc.set_encryption(&pdfcraft_cos::NewEncryption {
algorithm,
user_password: user,
@@ -2146,6 +2151,25 @@ fn remove_security_asks_for_the_permissions_password_first() {
assert!(doc.dirty && doc.security_summary().is_none(), "security is removed (written by the next save)");
}
/// A secured form still says it is one and offers Highlight fields: the security notice joins
/// the form's instead of replacing it.
#[test]
fn a_secured_form_shows_its_form_notice_and_its_security() {
// Changing and assembling withheld, filling allowed (as government forms are often set).
let bytes = encrypted(include_bytes!("data/form.pdf").to_vec(), pdfcraft_cos::Algorithm::Aes256, "", "owner", -1036);
let mut h = Harness::builder().with_size(egui::vec2(1600.0, 900.0)).build_eframe(move |_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.open_bytes("form.pdf", None, bytes).unwrap();
app
});
h.run_steps(4);
h.get_by_label_contains("interactive form fields. This document is secured. Some changes are restricted by its security settings.");
h.get_by_label("Highlight fields");
h.get_by_label("Security settings");
h.get_by_label("Unlock…");
}
#[test]
fn restricted_documents_show_a_notice_and_block_page_changes() {
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_cc| {
+19
View File
@@ -212,3 +212,22 @@ fn scripts_turned_off_by_a_click_bring_a_closed_notice_bar_back() {
assert!(h.state().views[0].notice_dismissed);
assert!(!says_scripts_are_off(&h.state().toast), "{:?}", h.state().toast);
}
#[test]
fn a_secured_dynamic_xfa_form_shows_its_layout_and_its_security() {
// Changing and assembling withheld, filling allowed.
let mut doc = pdfcraft_cos::Document::open(std::sync::Arc::new(pdfcraft_xfa::fixtures::shell(&pdfcraft_xfa::fixtures::template(2)))).unwrap();
doc.set_encryption(&pdfcraft_cos::NewEncryption {
algorithm: pdfcraft_cos::Algorithm::Aes256,
user_password: "",
owner_password: "owner",
permissions: -1036,
encrypt_metadata: true,
seed: [4; 32],
})
.unwrap();
let h = open(pdfcraft_cos::write_full(&doc, &Default::default()).unwrap());
h.get_by_label_contains("laid out from its template: 2 pages, 11 fields. This document is secured.");
h.get_by_label("Highlight fields");
h.get_by_label("Security settings");
}
+4 -4
View File
@@ -1802,8 +1802,8 @@ milestone = "M3"
status = "shipped"
commands = []
tools = []
evidence = ["crates/ui-egui/tests/editing.rs::restricted_documents_show_a_notice_and_block_page_changes"]
notes = ""
evidence = ["crates/ui-egui/tests/editing.rs::restricted_documents_show_a_notice_and_block_page_changes", "crates/ui-egui/tests/editing.rs::a_secured_form_shows_its_form_notice_and_its_security", "crates/ui-egui/tests/ui_group/xfa.rs::a_secured_dynamic_xfa_form_shows_its_layout_and_its_security"]
notes = "On a secured form (fields or XFA), the security sentence follows the form's notice, which keeps Highlight fields and the XFA layout notes."
[[feature]]
id = "view.pdfa-view-mode"
@@ -4392,8 +4392,8 @@ milestone = "M3"
status = "shipped"
commands = []
tools = []
evidence = ["crates/ui-egui/tests/view.rs::highlight_fields_tints_the_field_area", "crates/ui-egui/tests/view.rs::required_radio_buttons_get_a_round_red_border", "crates/ui-egui/tests/view.rs::field_highlighting_is_remembered"]
notes = "remembered for the next document and session; required fields get a red border (round for radio buttons); the tint is drawn over the field, where Acrobat paints the highlight colour behind it"
evidence = ["crates/ui-egui/tests/view.rs::highlight_fields_tints_the_field_area", "crates/ui-egui/tests/view.rs::required_radio_buttons_get_a_round_red_border", "crates/ui-egui/tests/view.rs::field_highlighting_is_remembered", "crates/ui-egui/tests/editing.rs::a_secured_form_shows_its_form_notice_and_its_security"]
notes = "offered on secured forms too; remembered for the next document and session; required fields get a red border (round for radio buttons); the tint is drawn over the field, where Acrobat paints the highlight colour behind it"
[[feature]]
id = "form.field-appearance-display"