QPDF Changelog

What's new in QPDF 8.4.0

Feb 2, 2019
  • Command-line Enhancements:
  • Non-compatible CLI change: The qpdf command-line tool interprets passwords given at the command-line
  • Differently from previous releases when the passwords contain non-ASCII characters. In some cases, the
  • Behavior differs from previous releases. For a discussion of the current behavior, please see Section 3.10,
  • “Unicode Passwords”, page 20. The incompatibilities are as follows:
  • On Windows, qpdf now receives all command-line options as Unicode strings if it can figure out the
  • Appropriate compile/link options. This is enabled at least for MSVC and mingw builds. That means that
  • If non-ASCII strings are passed to the qpdf CLI in Windows, qpdf will now correctly receive them. In the
  • Past, they would have either been encoded as Windows code page 1252 (also known as “Windows ANSI”
  • Or as something unintelligible. In almost all cases, qpdf is able to properly interpret Unicode arguments
  • Now, whereas in the past, it would almost never interpret them properly. The result is that non-ASCII
  • Passwords given to the qpdf CLI on Windows now have a much greater chance of creating PDF files that
  • Can be opened by a variety of readers. In the past, usually files encrypted from the Windows CLI using
  • Non-ASCII passwords would not be readable by most viewers. Note that the current version of qpdf is able
  • To decrypt files that it previously created using the previously supplied password.
  • The PDF specification requires passwords to be encoded as UTF-8 for 256-bit encryption and with PDF
  • Doc encoding for 40-bit or 128-bit encryption. Older versions of qpdf left it up to the user to provide
  • Passwords with the correct encoding. The qpdf CLI now detects when a password is given with UTF-8
  • Encoding and automatically transcodes it to what the PDF spec requires. While this is almost always the
  • Correct behavior, it is possible to override the behavior if there is some reason to do so. This is discussed
  • In more depth in Section 3.10, “Unicode Passwords”, page 20.
  • New options --externalize-inline-images, --ii-min-bytes, and --keep-inline-images control qpdf's handling
  • Of inline images and possible conversion of them to regular images. By default, --optimize-images now
  • Also applies to inline images. These options are discussed in Section 3.8, “Advanced Transformation Options”,
  • Page 13.
  • Add options --overlay and --underlay for overlaying or underlaying pages of other files onto output pages.
  • See Section 3.6, “Overlay and Underlay Options”, page 12 for details.
  • When opening an encrypted file with a password, if the specified password doesn't work and the password
  • Contains any non-ASCII characters, qpdf will try a number of alternative passwords to try to compensate for
  • Possible character encoding errors. This behavior can be suppressed with the --suppress-password-recovery
  • Option. See Section 3.10, “Unicode Passwords”, page 20 for a full discussion.
  • Add the --password-mode option to fine-tune how qpdf interprets password arguments, especially when
  • They contain non-ASCII characters. See Section 3.10, “Unicode Passwords”, page 20 for more information.
  • In the --pages option, it is now possible to copy the same page more than once from the same file without
  • Using the previous workaround of specifying two different paths to the same file.
  • In the --pages option, allow use of “.” as a shortcut for the primary input file. That way, you can do qpdf
  • In.pdf --pages . 1-2 -- out.pdf instead of having to repeat in.pdf in the command.
  • Release Notes
  • When encrypting with 128-bit and 256-bit encryption, new encryption options --assemble, --annotate, --
  • Form, and --modify-other allow more fine-grained granularity in configuring options. Before, the --modify
  • Option only configured certain predefined groups of permissions.
  • Bug Fixes and Enhancements
  • Potential data-loss bug: Versions of qpdf between 8.1.0 and 8.3.0 had a bug that could cause page splitting
  • And merging operations to drop some font or image resources if the PDF file's internal structure shared these
  • Resource lists across pages and if some but not all of the pages in the output did not reference all the fonts and
  • Images. Using the --preserve-unreferenced-resources option would work around the incorrect behavior.
  • This bug was the result of a typo in the code and a deficiency in the test suite. The case that triggered the error
  • Was known, just not handled properly. This case is now exercised in qpdf's test suite and properly handled.
  • When optimizing images, detect and refuse to optimize images that can't be converted to JPEG because of
  • Bit depth or color space.
  • Linearization and page manipulation APIs now detect and recover from files that have duplicate Page objects
  • In the pages tree.
  • Using older option --stream-data=compress with object streams, object streams and xref streams were not
  • Compressed.
  • When the tokenizer returns inline image tokens, delimiters following ID and EI operators are no longer
  • Excluded. This makes it possible to reliably extract the actual image data.
  • Library Enhancements
  • Add method QPDFPageObjectHelper::externalizeInlineImages to convert inline images to regular images.
  • Add method QUtil::possible_repaired_encodings() to generate a list of strings that represent other ways the
  • Given string could have been encoded. This is the method the QPDF CLI uses to generate the strings it tries
  • When recovering incorrectly encoded Unicode passwords.
  • Add new versions of QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow more granular setting of
  • Permissions bits. See QPDFWriter.hh for details.
  • Add new versions of the transcoders from UTF-8 to single-byte coding systems in QUtil that report success
  • Or failure rather than just substituting a specified unknown character.
  • Add method QUtil::analyze_encoding() to determine whether a string has high-bit characters and is appears
  • To be UTF-16 or valid UTF-8 encoding.
  • Add new method QPDFPageObjectHelper::shallowCopyPage() to copy a new page that is a “shallow copy”
  • Of a page. The resulting object is an indirect object ready to be passed to QPDFPageDocumentHelper::addPage()
  • For either the original QPDF object or a different one. This is what the qpdf command-line tool uses
  • To copy the same page multiple times from the same file during splitting and merging operations.
  • Add method QPDF::getUniqueId(), which returns a unique identifier for the given QPDF object. The identifier
  • Will be unique across the life of the application. The returned value can be safely used as a map key.
  • Add method QPDF::setImmediateCopyFrom. This further enhances qpdf's ability to allow a QPDF object
  • From which objects are being copied to go out of scope before the destination object is written. If you call
  • This method on a QPDF instances, objects copied from this instance will be copied immediately instead of
  • Lazily. This option uses more memory but allows the source object to go out of scope before the destination
  • Object is written in all cases. See comments in QPDF.hh for details.
  • Release Notes
  • Add method QPDFPageObjectHelper::getAttribute for retrieving an attribute from the page dictionary taking
  • Inheritance into consideration, and optionally making a copy if your intention is to modify the attribute.
  • Fix long-standing limitation of QPDFPageObjectHelper::getPageImages so that it now properly reports images
  • From inherited resources dictionaries, eliminating the need to call QPDFPageDocumentHelper::pushInheritedAttributesToPage
  • In this case.
  • Add method QPDFObjectHandle::getUniqueResourceName for finding an unused name in a resource dictionary.
  • Add method QPDFPageObjectHelper::getFormXObjectForPage for generating a form XObject equivalent
  • To a page. The resulting object can be used in the same file or copied to another file with copyForeignObject.
  • This can be useful for implementing underlay, overlay, n-up, thumbnails, or any other functionality requiring
  • Replication of pages in other contexts.
  • Add method QPDFPageObjectHelper::placeFormXObject for generating content stream text that places
  • A given form XObject on a page, centered and fit within a specified rectangle. This method takes care of
  • Computing the proper transformation matrix and may optionally compensate for rotation or scaling of the
  • Destination page.
  • Build Improvements
  • Add new configure option --enable-avoid-windows-handle, which causes the preprocessor symbol
  • AVOID_WINDOWS_HANDLE to be defined. When defined, qpdf will avoid referencing the Windows HANDLE
  • Type, which is disallowed with certain versions of the Windows SDK.
  • For Windows builds, attempt to determine what options, if any, have to be passed to the compiler and linker
  • To enable use of wmain. This causes the preprocessor symbol WINDOWS_WMAIN to be defined. If you do
  • Your own builds with other compilers, you can define this symbol to cause wmain to be used. This is needed
  • To allow the Windows qpdf command to receive Unicode command-line options.

New in QPDF 8.3.0 (Jan 8, 2019)

  • Command-line Enhancements:
  • Shell completion: you can now use eval $(qpdf --completion-bash) and eval $(qpdf --completion-zsh) to enable shell completion for bash and zsh.
  • Page numbers (also known as page labels) are now preserved when merging and splitting files with the -pages and --split-pages options.
  • Bookmarks are partially preserved when splitting pages with the --split-pages option. Specifically, the outlines dictionary and some supporting metadata are copied into the split files. The result is that all bookmarks from the original file appear, those that point to pages that are preserved work, and those that point to pages that are not preserved don't do anything. This is an interim step toward proper support for bookmarks in splitting and merging operations.
  • Page collation: add new option --collate. When specified, the semantics of --pages change from concatenation to collation. See Section 3.5, “Page Selection Options”, page 9 for examples and discussion.
  • Generation of information in JSON format, primarily to facilitate use of qpdf from languages other than C ++. Add new options --json, --json-key, and --json-object to generate a JSON representation of the PDF file. Run qpdf --json-help to get a description of the JSON format. For more information, see Chapter 6, QPDF JSON, page 22.
  • The --generate-appearances flag will cause qpdf to generate appearances for form fields if the PDF file indicates that form field appearances are out of date. This can happen when PDF forms are filled in by a program that doesn't know how to regenerate the appearances of the filled-in fields.
  • The --flatten-annotations flag can be used to flatten annotations, including form fields. Ordinarily, annotations are drawn separately from the page. Flattening annotations is the process of combining their appearances into the page's contents. You might want to do this if you are going to rotate or combine pages using a tool that doesn't understand about annotations. You may also want to use --generate-appearances when using this flag since annotations for outdated form fields are not flattened as that would cause loss of information.
  • The --optimize-images flag tells qpdf to recompresses every image using DCT (JPEG) compression as long as the image is not already compressed with lossy compression and recompressing the image reduces its size. The additional options --oi-min-width, --oi-min-height, and --oi-min-area prevent recompression of images whose width, height, or pixel area (width × height) are below a specified threshold.
  • The --show-object option can now be given as --show-object=trailer to show the trailer dictionary.
  • Bug Fixes and Enhancements:
  • QPDF now automatically detects and recovers from dangling references. If a PDF file contained an indirect reference to a non-existent object, which is valid, when adding a new object to the file, it was possible for the new object to take the object ID of the dangling reference, thereby causing the dangling reference to point to the new object. This case is now prevented.
  • Fixes to form field setting code: strings are always written in UTF-16 format, and checkboxes and radio buttons are handled properly with respect to synchronization of
  • The QPDF::checkLinearization() no longer causes the program to crash when it detects problems with linearization data. Instead, it issues a normal warning or error.
  • Ordinarily qpdf treats an argument of the form @file to mean that command-line options should be read from file. Now, if file does not exist but @file does, qpdf will treat @file as a regular option. This makes it possible to work more easily with PDF files whose names happen to start with the @ character.
  • Library Enhancements:
  • Remove the restriction in most cases that the source QPDF object used in a QPDF::copyForeignObject call has to stick around until the destination QPDF is written. The exceptional case is when the source stream gets is data using a QPDFObjectHandle::StreamDataProvider. For a more in-depth discussion, see comments around copyForeignObject in QPDF.hh.
  • Add new method QPDFWriter::getFinalVersion(), which returns the PDF version that will ultimately be written to the final file. See comments in QPDFWriter.hh for some restrictions on its use.
  • Add several methods for transcoding strings to some of the character sets used in PDF files: QUtil::utf8_to_ascii, QUtil::utf8_to_win_ansi, QUtil::utf8_to_mac_roman, and QUtil::utf8_to_utf16. For the single-byte encodings that support only a limited character sets, these methods replace unsupported characters with a specified substitute.
  • Add new methods to QPDFAnnotationObjectHelper and QPDFFormFieldObjectHelper for querying flags and interpretation of different field types. Define constants in qpdf/Constants.h to help with interpretation of flag values.
  • Add new methods QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded and QPDFFormFieldObjectHelper::generateAppearance for generating appearance streams. See discussion in QPDFFormFieldObjectHelper.hh for limitations.
  • Add two new helper functions for dealing with resource dictionaries: QPDFObjectHandle::getResourceNames() returns a list of all second-level keys, which correspond to the names of resources, and QPDFObjectHandle::mergeResources() merges two resources dictionaries as long as they have non-conflicting keys. These methods are useful for certain types of objects that resolve resources from multiple places, such as form fields.
  • Add methods QPDFPageDocumentHelper::flattenAnnotations() and QPDFAnnotationObjectHelper::getPageContentForAppearance() for handling low-level details of annotation flattening.
  • Add new helper classes: QPDFOutlineDocumentHelper, QPDFOutlineObjectHelper, QPDFPageLabelDocumentHelper, QPDFNameTreeObjectHelper, and QPDFNumberTreeObjectHelper.
  • Add method QPDFObjectHandle::getJSON() that returns a JSON representation of the object. Call serialize() on the result to convert it to a string.
  • Add a simple JSON serializer. This is not a complete or general-purpose JSON library. It allows assembly and serialization of JSON structures with some restrictions, which are described in the header file. This is the serializer used by qpdf's new JSON representation.
  • Add new QPDFObjectHandle::Matrix class along with a few convenience methods for dealing with sixelement numerical arrays as matrices.
  • Add new method QPDFObjectHandle::wrapInArray, which returns the object itself if it is an array, or an array containing the object otherwise. This is a common construct in PDF. This method prevents you from having to explicitly test whether something is a single element or an array.
  • Build Improvements:
  • It is no longer necessary to run autogen.sh to build from a pristine checkout. Automatically generated files are now committed so that it is possible to build on platforms without autoconf directly from a clean checkout of the repository. The configure script detects if the files are out of date when it also determines that the tools are present to regenerate them.
  • Pull requests and the master branch are now built automatically in Azure Pipelines [https://dev.azure.com/qpdf/qpdf/_build], which is free for open source projects. The build includes Linux, mac, Windows 32-bit and 64-bit with mingw and MSVC, and an AppImage build. Official qpdf releases are now built with Azure Pipelines.
  • Notes for Packagers:
  • A new section has been added to the documentation with notes for packagers. Please see Section 2.3, “Notes for Packagers”, page 3.
  • The qpdf detects out-of-date automatically generated files. If your packaging system automatically refreshes libtool or autoconf files, it could cause this check to fail. To avoid this problem, pass --disable-checkautofiles to configure.
  • If you would like to have qpdf completion enabled automatically, you can install completion files in the distribution's default location. You can find sample completion files to install in the completions directory.

New in QPDF 8.1.0 (Jun 23, 2018)

  • Usability Improvements:
  • When splitting files, qpdf detects fonts and images that the document metadata claims are referenced from a page but are not actually referenced and omits them from the output file. This change can cause a significant reduction in the size of split PDF files for files created by some software packages. Prior versions of qpdf would believe the document metadata and sometimes include all the images from all the other pages even though the pages were no longer present. In the unlikely event that the old behavior should be desired, it can be enabled by specifying --preserve-unreferenced-resources. For additional details, please see Section 3.6, “Advanced Transformation Options”.
  • When merging multiple PDF files, qpdf no longer leaves all the files open. This makes it possible to merge numbers of files that may exceed the operating system's limit for the maximum number of open files.
  • The --rotate option's syntax has been extended to make the page range optional. If you specify --rotate=angle without specifying a page range, the rotation will be applied to all pages. This can be especially useful for adjusting a PDF created from a multi-page document that was scanned upside down.
  • When merging multiple files, the --verbose option now prints information about each file as it operates on that file.
  • When the --progress option is specified, qpdf will print a running indicator of its best guess at how far through the writing process it is. Note that, as with all progress meters, it's an approximation. This option is implemented in a way that makes it useful for software that uses the qpdf library; see API Enhancements below.
  • Bug Fixes:
  • Properly decrypt files that use revision 3 of the standard security handler but use 40 bit keys (even though revision 3 supports 128-bit keys).
  • Limit depth of nested data structures to prevent crashes from certain types of malformed (malicious) PDFs.
  • In “newline before endstream” mode, insert the required extra newline before the endstream at the end of object streams. This one case was previously omitted.
  • API Enhancements:
  • The first round of higher level “helper” interfaces has been introduced. These are designed to provide a more convenient way of interacting with certain document features than using QPDFObjectHandle directly. For details on helpers, see Section 6.3, “Helper Classes”. Specific additional interfaces are described below.
  • Add two new document helper classes: QPDFPageDocumentHelper for working with pages, and QPDFAcroFormDocumentHelper for working with interactive forms. No old methods have been removed, but QPDFPageDocumentHelper is now the preferred way to perform operations on pages rather than calling the old methods in QPDFObjectHandle and QPDF directly. Comments in the header files direct you to the new interfaces. Please see the header files and ChangeLog for additional details.
  • Add three new object helper class: QPDFPageObjectHelper for pages, QPDFFormFieldObjectHelper for interactive form fields, and QPDFAnnotationObjectHelper for annotations. All three classes are fairly sparse at the moment, but they have some useful, basic functionality.
  • A new example program examples/pdf-set-form-values.cc has been added that illustrates use of the new document and object helpers.
  • The method QPDFWriter::registerProgressReporter has been added. This method allows you to register a function that is called by QPDFWriter to update your idea of the percentage it thinks it is through writing its output. Client programs can use this to implement reasonably accurate progress meters. The qpdf command line tool uses this to implement its --progress option.
  • New methods QPDFObjectHandle::newUnicodeString and QPDFObject::unparseBinary have been added to allow for more convenient creation of strings that are explicitly encoded using big-endian UTF-16. This is useful for creating strings that appear outside of content streams, such as labels, form fields, outlines, document metadata, etc.
  • A new class QPDFObjectHandle::Rectangle has been added to ease working with PDF rectangles, which are just arrays of four numeric values.

New in QPDF 7.1.1 (Feb 5, 2018)

  • Bug fix: files whose /ID fields were other than 16 bytes long can now be properly linearlized
  • A few compile and link issues have been corrected for some platforms.

New in QPDF 7.1.0 (Jan 15, 2018)

  • PDF files contain streams that may be compressed with various compression algorithms which, in some cases, may be enhanced by various predictor functions. Previously only the PNG up predictor was supported. In this version, all the PNG predictors as well as the TIFF predictor are supported. This increases the range of files that qpdf is able to handle.
  • QPDF now allows a raw encryption key to be specified in place of a password when opening encrypted files, and will optionally display the encryption key used by a file. This is a non-standard operation, but it can be useful in certain situations. Please see the discussion of --password-is-hex-key in Section 3.2, “Basic Options” or the comments around QPDF::setPasswordIsHexKey in QPDF.hh for additional details.
  • Bug fix: numbers ending with a trailing decimal point are now properly recognized as numbers.
  • Bug fix: when building qpdf from source on some platforms (especially MacOS), the build could get confused by older versions of qpdf installed on the system. This has been corrected.

New in QPDF 7.0.0 (Sep 17, 2017)

  • Packaging and Distribution Changes:
  • QPDF's primary license is now version 2.0 of the Apache License [http://www.apache.org/licenses/LICENSE-2.0] rather than version 2.0 of the Artistic License. You may still, at your option, consider qpdf to be licensed with version 2.0 of the Artistic license.
  • QPDF no longer has a dependency on the PCRE (Perl-Compatible Regular Expression) library. QPDF now has an added dependency on the JPEG library.
  • Bug Fixes:
  • This release contains many bug fixes for various infinite loops, memory leaks, and other memory errors that could be encountered with specially crafted or otherwise erroneous PDF files.
  • New Features:
  • QPDF now supports reading and writing streams encoded with JPEG or RunLength encoding. Library API enhancements and command-line options have been added to control this behavior. See command-line options --compress-streams and --decode-level and methods QPDFWriter::setCompressStreams and QPDFWriter::setDecodeLevel.
  • QPDF is much better at recovering from broken files. In most cases, qpdf will skip invalid objects and will preserve broken stream data by not attempting to filter broken streams. QPDF is now able to recover or at least not crash on dozens of broken test files I have received over the past few years.
  • Page rotation is now supported and accessible from both the library and the command line.
  • QPDFWriter supports writing files in a way that preserves PCLm compliance in support of driverless printing. This is very specialized and is only useful to applications that already know how to create PCLm files.
  • Enhancements to the qpdf Command-line Tool. All new options listed here are documented in more detail in Chapter 3, Running QPDF, page 4.
  • Command-line arguments can now be read from files or standard input using @file or @- syntax. Please see Section 3.1, “Basic Invocation”, page 4.
  • rotate: request page rotation
  • newline-before-endstream: ensure that a newline appears before every endstream keyword in the file; used to prevent qpdf from breaking PDF/A compliance on already compliant files.
  • preserve-unreferenced: preserve unreferenced objects in the input PDF
  • split-pages: break output into chunks with fixed numbers of pages
  • verbose: print the name of each output file that is created
  • compress-streams and --decode-level replace --stream-data for improving granularity of controlling compression and decompression of stream data. The --stream-data option will remain available. 30
  • Release Notes:
  • When running qpdf --check with other options, checks are always run first. This enables qpdf to perform its full recovery logic before outputting other information. This can be especially useful when manually recovering broken files, looking at qpdf's regenerated cross reference table, or other similar operations.
  • Process --pages earlier so that other options like --show-pages or --split-pages can operate on the file after page splitting/merging has occurred.
  • API Changes. All new API calls are documented in their respective classes' header files.
  • QPDFObjectHandle::rotatePage: apply rotation to a page object
  • QPDFWriter::setNewlineBeforeEndstream: force newline to appear before endstream
  • QPDFWriter::setPreserveUnreferencedObjects: preserve unreferenced objects that appear in the input PDF. The default behavior is to discard them.
  • New Pipeline types Pl_RunLength and Pl_DCT are available for developers who wish to produce or consume RunLength or DCT stream data directly. The examples/pdf-create.cc example illustrates their use.
  • QPDFWriter::setCompressStreams and QPDFWriter::setDecodeLevel methods control handling of different types of stream compression.
  • Add new C API functions qpdf_set_compress_streams, qpdf_set_decode_level, qpdf_set_preserve_unreferenced_objects, and qpdf_set_newline_before_endstream corresponding to the new QPDFWriter methods.

New in QPDF 6.0.0 (Nov 21, 2015)

  • Implement --deterministic-id command-line option and QPDFWriter::setDeterministicID as well as C API function qpdf_set_deterministic_ID for generating a deterministic ID for non-encrypted files. When this option is selected, the ID of the file depends on the contents of the output file, and not on transient items such as the timestamp or output file name.
  • Make qpdf more tolerant of files whose xref table entries are not the correct length.

New in QPDF 5.1.3 (May 26, 2015)

  • Bug fix: fix-qdf was not properly handling files that contained object streams with more than 255 objects in them.
  • Bug fix: qpdf was not properly initializing Microsoft's secure crypto provider on fresh Windows installations that had not had any keys created yet.
  • Fix a few errors
  • Properly handle pages that have no contents at all. There were many cases in which qpdf handled this fine, but a few methods blindly obtained page contents with handling the possibility that there were no contents.
  • Make qpdf more robust for a few more kinds of problems that may occur in invalid PDF files

New in QPDF 5.1.2 (Jun 9, 2014)

  • Bug fix: linearizing files could create a corrupted output file under extremely unlikely file size circumstances. The odds of getting hit by this are very low, though one person did.
  • Bug fix: qpdf would fail to write files that had streams with decode parameters referencing other streams.
  • New example program: pdf-split-pages: efficiently split PDF files into individual pages. The example program does this more efficiently than using qpdf--pages to do it.
  • Packaging fix: Visual C++ binaries did not support Windows XP. This has been rectified by updating the
  • compilers used to generate the release binaries.

New in QPDF 5.1.1 (Jan 16, 2014)

  • Performance fix: copying foreign objects could be very slow with certain types of files. This was most likely to be visible during page splitting and was due to traversing the same objects multiple times in some cases.

New in QPDF 5.0.1 (Oct 23, 2013)

  • When available, operating system-specific secure random number generation is used for generating initialization vectors and other random values used during encryption or file creation. For the Windows build, this results
  • in an added dependency on Microsoft's cryptography API. To disable the OS-specific cryptography and use the old version, pass the --enable-insecure-random option to ./configure.
  • The qpdf command-line tool now issues a warning when -accessibility=n is specified for newer encryption versions stating that the option is ignored. qpdf, per the spec, has always ignored this flag, but it previously did so silently. This warning

New in QPDF 5.0.0 (Jul 11, 2013)

  • Bug fix: previous versions of QPDF would lose objects with generation != 0 when generating object streams. Fixing this required changes to the public API.
  • Removed methods from public API that were only supposed to be called by QPDFWriter and couldn't realistically be called anywhere else.
  • New QPDFObjGen class added to represent an object ID/generation pair. QPDFObjectHandle::getObjGen() is now preferred over QPDFObjectHandle::getObjectID() and QPDFObjectHandle::getGeneration() as it makes it less likely for people to accidentally write code that ignores the generation number. See QPDF.hh and QPDFObjectHandle.hh for additional notes.
  • Add --show-npages command-line option to the QPDF command to show the number of pages in a file.
  • Allow omission of the page range within --pages for the QPDF command. When omitted, the page range is implicitly taken to be all the pages in the file.
  • Various enhancements were made to support different types of broken files or broken readers.

New in QPDF 4.2.0 (Jul 8, 2013)

  • Bug fix: previous versions of qpdf would lose objects with generation != 0 when generating object streams. This also required deprecation of QPDF::getCompressibleObjects(), which has now been replaced with QPDF::getCompressibleObjGens().
  • New QPDFObjGen class added to represent an object ID/generation pair. The new method QPDF::getCompressibleObjGens() uses this type, and a handful of other API additions were made that use this type. In particular, QPDFObjectHandle::getObjGen() is now preferred over QPDFObjectHandle::getObjectID() and QPDFObjectHandle::getGeneration() as it makes it less likely for people to accidentally write code that ignores the generation number. See QPDF.hh and QPDFObjectHandle.hh for additional notes.
  • Add --show-npages command-line option to the qpdf command to show the number of pages in a file.
  • Allow omission of the page range within --pages for the qpdf command. When omitted, the page range is implicitly taken to be all the pages in the file.
  • Various enhancements were made to support different types of broken files or broken readers.

New in QPDF 4.1.0 (Apr 15, 2013)

  • Note to people including qpdf in distributions: the .la files generated by libtool are now installed by qpdf's make install target. Before, they were not installed. This means that if your distribution does not want to include .la files, you must remove them as part of your packaging process.
  • Major enhancement: API enhancements have been made to support parsing of content streams. This enhance- ment includes the following changes:
  • QPDFObjectHandle::parseContentStream method parses objects in a content stream and calls handlers in a callback class. The example examples/pdf-parse-content.cc illustrates how this may be used.
  • QPDFObjectHandle can now represent operators and inline images, object types that may only appear in content streams.
  • Method QPDFObjectHandle::getTypeCode() returns an enumerated type value representing the underlying object type. Method QPDFObjectHandle::getTypeName() returns a text string describing the name of the type of a QPDFObjectHandle object. These methods can be used for more efficient parsing and debug- ging/diagnostic messages.
  • qpdf --check now parses all pages' content streams in addition to doing other checks. While there are still many types of errors that cannot be detected, syntactic errors in content streams will now be reported.
  • Minor compilation enhancements have been made to facilitate easier for support for a broader range of compilers and compiler versions.
  • Warning flags have been moved into a separate variable in autoconf.mk
  • The configure flag --enable-werror work for Microsoft compilers
  • All MSVC CRT security warnings have been resolved.
  • All C-style casts in C++ Code have been replaced by C++ casts, and many casts that had been included to suppress higher warning levels for some compilers have been removed, primarily for clarity. Places where integer type coercion occurs have been scrutinized. A new casting policy has been documented in the manual. This is of concern mainly to people porting qpdf to new platforms or compilers. It is not visible to program- mers writing code that uses the library
  • Some internal limits have been removed in code that converts numbers to strings. This is largely invisible to users, but it does trigger a bug in some older versions of mingw-w64's C++ library. See README-windows.txt in the source distribution if you think this may affect you. The copy of the DLL distributed with qpdf's binary distribution is not affected by this problem.
  • The RPM spec file previously included with qpdf has been removed. This is because virtually all Linux distri- butions include qpdf now that it is a dependency of CUPS filters.
  • A few bug fixes are included:
  • Overridden compressed objects are properly handled. Before, there were certain constructs that could cause qpdf to see old versions of some objects. The most usual manifestation of this was loss of filled in form values for certain files.

New in QPDF 4.0.1 (Jan 18, 2013)

  • Fix detection of binary attachments in test suite to avoid false test failures on some platforms.
  • Add clarifying comment in QPDF.hh to methods that return the user password explaining that it is no longer
  • possible with newer encryption formats to recover the user password knowing the owner password. In earlier
  • encryption formats, the user password was encrypted in the file using the owner password. In newer encryption
  • formats, a separate encryption key is used on the file, and that key is independently encrypted using both the
  • user password and the owner password.

New in QPDF 4.0.0 (Jan 18, 2013)

  • Major enhancement: support has been added for newer encryption schemes supported by version X of Adobe
  • Acrobat. This includes use of 127-character passwords, 256-bit encryption keys, and the encryption scheme
  • specified in ISO 32000-2, the PDF 2.0 specification. This scheme can be chosen from the command line by
  • specifying use of 256-bit keys. qpdf also supports the deprecated encryption method used by Acrobat IX. This
  • encryption style has known security weaknesses and should not be used in practice. However, such files exist “in
  • the wild,” so support for this scheme is still useful. New methods QPDFWriter::setR6EncryptionParameters
  • (for the PDF 2.0 scheme) and QPDFWriter::setR5EncryptionParameters (for the deprecated scheme) have
  • been added to enable these new encryption schemes. Corresponding functions have been added to the C API
  • as well.
  • Full support for Adobe extension levels in PDF version information. Starting with PDF version 1.7, corresponding
  • to ISO 32000, Adobe adds new functionality by increasing the extension level rather than increasing
  • the version. This support includes addition of the QPDF::getExtensionLevel method for retrieving
  • the document's extension level, addition of versions of QPDFWriter::setMinimumPDFVersion and
  • QPDFWriter::forcePDFVersion that accept an extension level, and extended syntax for specifying forced and
  • minimum versions on the command line as described in Section 3.5, “Advanced Transformation Options”, page
  • 8. Corresponding functions have been added to the C API as well.
  • Minor fixes to prevent qpdf from referencing objects in the file that are not referenced in the file's overall
  • structure. Most files don't have any such objects, but some files have contain unreferenced objects with errors,
  • so these fixes prevent qpdf from needlessly rejecting or complaining about such objects.
  • Add new generalized methods for reading and writing files from/to programmer-defined sources. The
  • method QPDF::processInputSource allows the programmer to use any input source for the input file, and
  • QPDFWriter::setOutputPipeline allows the programmer to write the output file through any pipeline. These
  • methods would make it possible to perform any number of specialized operations, such as accessing external
  • storage systems, creating bindings for qpdf in other programming languages that have their own I/O systems,
  • etc.
  • Add new method QPDF::getEncryptionKey for retrieving the underlying encryption key used in the file.
  • This release includes a small handful of non-compatible API changes. While effort is made to avoid such
  • changes, all the non-compatible API changes in this version were to parts of the API that would likely never
  • be used outside the library itself. In all cases, the altered methods or structures were parts of the QPDF that
  • were public to enable them to be called from either QPDFWriter or were part of validation code that was overzealous
  • in reporting problems in parts of the file that would not ordinarily be referenced. In no case did any of
  • the removed methods do anything worse that falsely report error conditions in files that were broken in ways
  • that didn't matter. The following public parts of the QPDF class were changed in a non-compatible way
  • Updated nested QPDF::EncryptionData class to add fields needed by the newer encryption formats, member
  • variables changed to private so that future changes will not require breaking backward compatibility.
  • Added additional parameters to compute_data_key, which is used by QPDFWriter to compute the encryption
  • key used to encrypt a specific object.
  • Removed the method flattenScalarReferences. This method was previously used prior to writing a new PDF
  • file, but it has the undesired side effect of causing qpdf to read objects in the file that were not referenced.
  • Some otherwise files have unreferenced objects with errors in them, so this could cause qpdf to reject files
  • that would be accepted by virtually all other PDF readers. In fact, qpdf relied on only a very small part of
  • what flattenScalarReferences did, so only this part has been preserved, and it is now done directly inside
  • QPDFWriter.
  • Removed the method decodeStreams. This method was used by the --check option of the qpdf command-line
  • tool to force all streams in the file to be decoded, but it also suffered from the problem of opening otherwise
  • unreferenced streams and thus could report false positive. The --check option now causes qpdf to go through
  • all the motions of writing a new file based on the original one, so it will always reference and check exactly
  • those parts of a file that any ordinary viewer would check.
  • Removed the method trimTrailerForWrite. This method was used by QPDFWriter to modify the original
  • QPDF object by removing fields from the trailer dictionary that wouldn't apply to the newly written file.
  • This functionality, though generally harmless, was a poor implementation and has been replaced by having
  • QPDFWriter filter these out when copying the trailer rather than modifying the original QPDF object. (Note
  • that qpdf never modifies the original file itself.)
  • Allow the PDF header to appear anywhere in the first 1024 bytes of the file. This is consistent with what other
  • readers do.
  • Fix the pkg-config files to list zlib and pcre in Requires.private to better support static linking using pkg-config.

New in QPDF 3.0.2 (Jan 18, 2013)

  • Bug fix: QPDFWriter::setOutputMemory did not work when not used with QPDFWriter::setStaticID, which
  • made it pretty much useless. This has been fixed.
  • New API call QPDFWriter::setExtraHeaderText inserts additional text near the header of the PDF file. The
  • intended use case is to insert comments that may be consumed by a downstream application, though other use
  • cases may exist.

New in QPDF 3.0.1 (Jan 18, 2013)

  • Version 3.0.0 included addition of files for pkg-config, but this was not mentioned in the release notes. The
  • release notes for 3.0.0 were updated to mention this.
  • Bug fix: if an object stream ended with a scalar object not followed by space, qpdf would incorrectly report that
  • it encountered a premature EOF. This bug has been in qpdf since version 2.0.