M8: Redaction drops /PCAdded from rewritten content streams so redacted added text does not stay in the file (#1)
Text added with Edit ▸ Add content keeps its source string in the stream dictionary's /PCAdded. Applying a redaction rewrote the stream's glyphs but copied the dictionary unchanged, so the redacted text survived in the saved PDF. The redacted item now stays as plain drawn content and is no longer editable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9d99f4b278
commit
0523ccdfdc
|
|
@ -296,6 +296,10 @@ pub fn apply(doc: &mut Document, pages: Option<&[usize]>) -> Result<Report, Reda
|
|||
_ => Dict::new(),
|
||||
};
|
||||
dict.remove(b"Length");
|
||||
// Edit ▸ Add content keeps an added item's source text in `/PCAdded`; once its glyphs
|
||||
// are redacted, keeping it would leave the redacted text in the file. The item stays
|
||||
// as plain drawn content but is no longer editable.
|
||||
dict.remove(b"PCAdded");
|
||||
// A new object: the original may be shared with other pages.
|
||||
new_list[i] = Object::Ref(doc.add(Object::Stream(Stream::flate(dict, &bytes))));
|
||||
changed = true;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use printcraft_annot::{Meta, NewAnnotation, Shape, Style, add_annotation, rect_quad};
|
||||
use printcraft_cos::{Document, SaveOptions, write_incremental};
|
||||
use printcraft_cos::{Document, SaveOptions, write_full, write_incremental};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
@ -99,6 +99,24 @@ fn glyphs_under_a_mark_go_and_the_rest_stays_put() {
|
|||
assert!(!content(&doc, 0).contains("1234"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn added_text_parameters_do_not_keep_redacted_text() {
|
||||
// An Edit ▸ Add content item: its stream dictionary keeps the source text under /PCAdded.
|
||||
let mut doc = pdf(vec![
|
||||
b"<< /Type /Catalog /Pages 2 0 R >>".to_vec(),
|
||||
b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>".to_vec(),
|
||||
b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 300 300] /Contents [4 0 R] /Resources << /Font << /F1 5 0 R >> >> >>".to_vec(),
|
||||
stream("/PCMark /Added /PCAdded << /Kind /Text /Text (AB1234CD) >>", b"BT /F1 10 Tf 10 100 Td (AB1234CD) Tj ET"),
|
||||
FONT.replace("95 0 R", "6 0 R").into_bytes(),
|
||||
widths(),
|
||||
]);
|
||||
mark(&mut doc, 0, &[[20.0, 95.0, 40.0, 110.0]], "");
|
||||
apply(&mut doc, None).unwrap();
|
||||
assert!(!content(&doc, 0).contains("1234"));
|
||||
let bytes = write_full(&doc, &SaveOptions::default()).unwrap();
|
||||
assert!(!bytes.windows(4).any(|w| w == b"1234"), "redacted text left in the saved file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kerning_spacing_scaling_and_line_operators_are_honoured() {
|
||||
// TJ kerning, character and word spacing, 50% horizontal scaling, ' and ".
|
||||
|
|
|
|||
Loading…
Reference in New Issue