Skip to content

v0.9.0

Choose a tag to compare

@dkulyk dkulyk released this 05 Sep 10:46
· 25 commits to main since this release
337f0eb

Added

  • ContentCompression::store() registers content types whose payload is already
    a compressed stream, so a codec this library does not yet know about is
    declared once at start-up instead of being special-cased at every call site.
  • addPart(), addPartFromStream(), addPartFromPath(), writePart(),
    writePartFromStream(), writePartFromPath() and the setContents*() methods
    of a part take a $compress argument that overrides what the content type
    implies for that one part. null, the default, keeps the existing behaviour.
    PackageInterface and PartInterface declare the argument, so an outside
    implementation of either has to accept it.

Changed

  • [Content_Types].xml and relationship parts are serialized as strings rather
    than through DOM. The output is byte for byte what it was, escaping included.
  • Reads go straight to their source: an unchanged entry is read from the archive
    rather than through a stream and its wrapper objects, and a staged part is read
    where it already is instead of being copied first.
  • Relationship collections are held for the package's lifetime instead of only
    while something else keeps them alive. Every whole-package operation walks all
    relationships, and each walk re-parsed every .rels part. The package keeps
    referring to itself weakly from the collections, so nothing holds a cycle and
    the source archive is still released with the package.
  • Parts whose content type is already a compressed stream — JPEG, PNG, GIF,
    WebP, HEIC, HEIF, AVIF, JP2, MP3, MP4, Ogg and WebM audio, any video/*, ZIP,
    gzip, and embedded OPC or OpenDocument documents — are stored in the package
    instead of being deflated a second time. The types are matched exactly, not by
    family: an embedded deck is …presentationml.presentation and a slide inside
    the package is …presentationml.slide+xml, and only the first is a ZIP.
    Everything else, including SVG, BMP, EMF, WMF, VML, OLE objects and any
    unrecognised type, is still deflated.

Fixed

  • ContentTypes::toXml() no longer sorts the collection's own arrays as a side
    effect of serializing it.
  • A package containing an entry that the content types do not cover no longer
    becomes unusable. getParts() skipped nothing and threw, which also stopped
    getInboundRelationships(), removePart(), removePartAndRelationships()
    and movePart(), so the package could be opened and validated but never
    repaired. getParts() now skips such an entry, validate() still reports it,
    and setDefaultContentType() makes it a part.
  • PartName::normalize() no longer clears its whole validation cache when it
    fills up. A package with more part names than the cache bound made every pass
    over it miss on every name; the bound is now above the name count of a large
    package and eviction drops the older half.
  • ZIP entries are read through a bound set by the size their directory declares.
    Package limits were checked once against that directory and never again, so an
    entry declaring a small size and inflating to a large one delivered every byte
    through getContents(), openStream(), and getLocalPath(). Such an entry is
    now rejected with a PackageLimitException while it is read.
  • PartInterface::getContentType() reports the content type registered now
    rather than the one registered when the handle was made, so a part obtained
    before setDefaultContentType() no longer reports a stale type. The package
    exposes the same lookup as getPartContentType().