Skip to content

FreePDF 7.4.0

Choose a tag to compare

@christianz christianz released this 04 Nov 07:27
8985eab

FreePDF 7.4.0

FreePDF 7.4.0 saves documents as incremental updates, so a signed PDF can be
filled in or signed again without breaking the signatures already in it.

Packages

dotnet add package io7.FreePDF --version 7.4.0
dotnet add package io7.FreePDF.Layout --version 7.4.0

New

  • Incremental save with PdfDocumentOpenMode.Append. PDFsharp 6.2.4 always
    writes a new file: saving a signed document after any change breaks its
    signatures, and a signed document cannot be signed a second time. A document
    opened in Append mode is saved as the original file, byte for byte, followed
    by one update that holds only the new and changed objects:

    using var document = PdfReader.Open("signed.pdf", PdfDocumentOpenMode.Append);
    ((PdfFormTextField)document.Catalog.GetAcroForm()!.Fields["name"]!).Text = "Ada Lovelace";
    DigitalSignatureHandler.ForDocument(document, signer, options);   // optional: sign it again
    document.Save("signed-filled.pdf");
    • The signatures in the file stay valid. A new signature covers the whole
      file, earlier signatures included.
    • The update ends with a cross-reference table, or a cross-reference stream
      when the file uses one, and a trailer that points back to the previous one.
      Object numbers, the first file identifier and the page tree stay as they are.
    • A document with no changes is saved exactly as it was. Otherwise the
      document information gets a new modification date (unless you set one) and
      FreePDF as its producer.
    • Pages can be added and removed when all pages hang directly under the page
      tree's root, which is the common case. When the page tree is nested,
      inserting, removing or moving pages throws before anything changes.

Fixed

  • Opening a form set a new modification date (/M) on every field that is also
    a widget. The date was written on the next save although the field had not
    changed, and signature validators count it as an unexplained change. Fields
    now keep their own date; only new widgets get one.

Upgrading from 7.3.x

Update all FreePDF packages to 7.4.0 together and rebuild; the assembly version
is now 7.4.0.0. PdfDocumentOpenMode.Append is new; documents opened in
Modify mode are saved as before, as a new file. Behaviour change to check:

  • A form field that is also a widget keeps its modification date when a
    document is opened and saved in Modify mode. Up to 7.3.0 it got the time the
    document was opened.

Limits of Append mode in 7.4.0:

  • Encrypted documents cannot be opened in Append mode, nor can files whose
    cross-reference table names the wrong objects; open those with Modify to
    save a new file. A document opened in Append mode cannot be given a password.
  • FreePDF does not check a certification signature's permissions (DocMDP); a
    document certified with "no changes allowed" should not be changed at all.
  • Whether a validator accepts a change after a signature depends on the
    signature's permissions and on the validator. Filling in fields and adding
    signatures are permitted for an ordinary (approval) signature. Acrobat permits
    added comments, but pyHanko reports any added comment.
  • Reading page.Annotations, document.Outlines or document.ViewerPreferences
    creates them when the file has none, and saving writes that as a change.

Validation

All 7.3.0 release gates apply, plus:

  • regression tests for incremental saving: the original bytes are kept, only
    changed objects are written, an unchanged document is saved byte for byte,
    object numbers and the first identifier are kept, table and stream updates,
    saving to the file it was opened from, page insertion in flat and nested page
    trees, refusals, and a signature made before filling in a field or before a
    second signature that still verifies (CMS over the byte range); 458
    regression tests in all;
  • poppler's pdfsig reported every signature valid in signed, filled,
    annotated and countersigned files, and pyHanko 0.29.1's difference analysis
    rated filling in and countersigning as "signing and form filling";
  • a file signed by pyHanko, with cross-reference streams, was countersigned by
    FreePDF, and both validators accept both signatures;
  • every readable file of a 2,950-file veraPDF and producer corpus (2,930) was
    saved unchanged with identical bytes, and with one change writing only the
    changed objects; the 13 encrypted files were refused; mutool parsed a sample
    of 290 updated files, with one warning that comes from the original file;
  • an independent review of the incremental save code, whose findings were fixed
    or documented before release.

See the migration guide's "Signed documents" section (https://github.com/io7/FreePDF/blob/8985eab0d57aa774b3771050b5222f09a7b898cd/docs/migrating-to-7.md#signed-documents)
and the support policy (https://github.com/io7/FreePDF/blob/8985eab0d57aa774b3771050b5222f09a7b898cd/docs/support-policy.md).

The attached packages are the verified CI artifacts from source revision 8985eab0d57aa774b3771050b5222f09a7b898cd, and the same files that were
uploaded to NuGet.org. SHA256SUMS and validation.json record their hashes and package-install evidence.
NuGet.org adds its repository signature, so a package downloaded from NuGet.org has a different hash from the attached file.

CI: https://github.com/io7/FreePDF/actions/runs/41789366099 (core),
https://github.com/io7/FreePDF/actions/runs/41789366102 (packages/API/independent checks),
https://github.com/io7/FreePDF/actions/runs/41789366178 (comparisons),
https://github.com/io7/FreePDF/actions/runs/41790809228 (NuGet publication).