Skip to content

FreePDF 7.7.0

Choose a tag to compare

@christianz christianz released this 05 Nov 10:20
d889ee8

FreePDF 7.7.0

FreePDF 7.7.0 adds, removes and moves pages in Append mode when the page tree
is nested, keeps the page attributes of new and moved pages right, accepts every
XMP packet header the XMP specification allows, and fixes how metadata is
handled in encrypted documents.

Packages

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

New

  • Page changes in nested page trees. In a document opened with
    PdfDocumentOpenMode.Append, Insert, Remove, RemoveAt, MovePage,
    InsertRange and PdfDocument.AppendPages now work when the page tree has
    intermediate nodes; they threw NotSupportedException. The update writes only
    the nodes between the root and the pages that come or go:

    • a page goes next to its neighbours in their node, preferring the node it was
      in;
    • a node left without pages is taken out of the tree unchanged;
    • a page moved under another node keeps its media box, crop box and rotation.

    A certification signature (DocMDP) refuses page changes as before.

Fixed

  • New pages and inherited attributes. A new page took the crop box, rotation
    or resources of the page tree node it went into: in Append mode from its
    node, in Modify mode from the opened file's root.
  • Re-inserting a page. A page taken out with Remove or RemoveAt can be
    inserted again; Insert threw "Object already in table".
  • Rotation and boxes in the page tree.
    • An inherited /Rotate given as an indirect object or a real number was
      ignored.
    • A page with its own indirect media box or crop box could not be opened under
      a node that has one.
  • AppendPages and the catalog. AppendPages no longer adds an empty
    outline to the catalog when there are no bookmarks to merge.
  • XMP packet headers. PdfMetadata.SetMetadata(string) accepts a header in
    single quotes and a begin attribute that holds U+FEFF; both threw "Unknown
    metadata encoding tag".
  • Compressed metadata. SetMetadata on compressed metadata wrote plain XML
    under /FlateDecode. Now the old filters are dropped and only the crypt filter
    stays.
  • Unmarked document metadata. With EncryptMetadata false, a Modify save
    with DoNotResetEncryption marks the document's metadata with the Identity
    crypt filter. Metadata that another writer left unmarked could not be read by
    pyHanko and MuPDF. Metadata that names another crypt filter stays encrypted
    with it.
  • Re-encrypted files that could not be opened. Encrypting a document again
    with EncryptMetadata true, when the opened file had it false, kept
    /EncryptMetadata false, and for V4 no one could open the file with its
    password.
  • Crypt filters in older and unusual layouts.
    • An Append save of an RC4 file with encryption version 1 to 3 threw "Crypt
      filters are not supported" when its encryption dictionary carried
      /EncryptMetadata false and the metadata changed.
    • Crypt filter parameters held by reference inside a /DecodeParms array are
      read.

Upgrading from 7.6.1

Update all FreePDF packages to 7.7.0 together and rebuild; the assembly version
is now 7.7.0.0. The public API is unchanged. Behaviour changes to check:

  • In Modify mode, the root of the page tree no longer holds the inheritable
    values it had in the opened file, because every page holds them.
  • In Append mode, a new page under a node or root with a rotation or crop box
    gets an explicit /Rotate 0 or crop box.
  • SetMetadata(byte[]) takes plain XML and drops the old filters except the
    crypt filter.
  • SetMetadata(string) accepts only encoding names in the begin attribute.
  • Metadata that names an encrypting crypt filter while EncryptMetadata is false
    stays encrypted. pyHanko 0.29.1 cannot read such V4 metadata, because it uses
    the file key instead of the per-object key; MuPDF and FreePDF read it.

Validation

All 7.6.1 release gates apply, plus:

  • 58 new regression tests, 723 in all:
    • nested page trees: inserting, removing, moving and merging; the objects each
      update writes; consistent counts and parents; inherited values; moving a page
      back saves the original bytes; refusals under a certification;
    • XMP headers;
    • document metadata in V4-RC4, AES-128 and AES-256 files;
    • re-encryption.
  • Nested-tree files signed with pyHanko 0.29.1, edited in Append mode (insert
    with drawing, move, remove, merge, FreePDF countersignature): poppler and MuPDF
    show the expected page sizes and rotations, and pdfsig reports every signature
    valid. A pyHanko certification with "form filling" (P=2) refuses the insert.
  • pyHanko and mutool read the document metadata of unmarked V4-RC4, AES-128 and
    AES-256 files after a Modify save with DoNotResetEncryption.
  • Independent reviews (two rounds for the page tree change, three for the
    metadata fixes) found issues, which were fixed before release.
  • A clean install from nuget.org, with an empty package cache, edited the pyHanko-signed nested-tree file (insert, move, remove, merge): the original stayed a byte-for-byte prefix, page sizes and rotation are right in poppler, and pdfsig reports the signature valid. The certified nested file refused the insert. pyHanko reads the document metadata after a save that keeps the encryption, and a file encrypted again with EncryptMetadata true opens with its new password. The earlier install checks still pass: pyHanko judges the certified form after filling, the countersigned encrypted form and the signed existing field VALID.

The attached packages are the verified CI artifacts from source revision d889ee8a03f2139f129b9684ae15feb787387596, 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/42005793074 (core),
https://github.com/io7/FreePDF/actions/runs/42005793204 (packages/API/independent checks),
https://github.com/io7/FreePDF/actions/runs/42005793114 (comparisons),
https://github.com/io7/FreePDF/actions/runs/42007801101 (NuGet publication).