forked from openkylin/qpdf
Compare commits
No commits in common. "openkylin/yangtze" and "pristine-tar" have entirely different histories.
openkylin/
...
pristine-t
|
@ -1,28 +0,0 @@
|
|||
*.pdb
|
||||
.lineno
|
||||
appimage/build
|
||||
autoconf.mk
|
||||
autom4te.cache/
|
||||
config.log
|
||||
config.status
|
||||
distfiles.zip
|
||||
doc/fix-qdf.1
|
||||
doc/qpdf-manual.html
|
||||
doc/qpdf-manual.pdf
|
||||
doc/qpdf.1
|
||||
doc/zlib-flate.1
|
||||
examples/build/
|
||||
external-libs
|
||||
fuzz/build/
|
||||
libqpdf.map
|
||||
libqpdf.pc
|
||||
libqpdf/build/
|
||||
libqpdf/qpdf/qpdf-config.h
|
||||
libtests/build/
|
||||
libtool
|
||||
manual/build/
|
||||
manual/html.xsl
|
||||
manual/print.xsl
|
||||
qpdf/build/
|
||||
zlib-flate/build/
|
||||
distribution/
|
21
.travis.yml
21
.travis.yml
|
@ -1,21 +0,0 @@
|
|||
language: cpp
|
||||
compiler: gcc
|
||||
sudo: require
|
||||
dist: xenial
|
||||
|
||||
install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libgnutls28-dev docbook-xsl fop xsltproc less inkscape
|
||||
|
||||
script:
|
||||
- appimage/build-appimage
|
||||
|
||||
after_success:
|
||||
- cd appimage/build
|
||||
- find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
|
||||
- ls -l # for more debugging in Travis' log
|
||||
- curl --upload-file ./qpdf*.AppImage https://transfer.sh/qpdf-git.$(git rev-parse --short HEAD)-x86_64.AppImage
|
||||
- sha512sum ./qpdf*.AppImage*
|
||||
# Not ready to have travis automatically create github releases
|
||||
# - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
# - bash upload.sh qpdf-*x86_64.AppImage* # This should upload the .zsync file as well
|
191
Artistic-2.0
191
Artistic-2.0
|
@ -1,191 +0,0 @@
|
|||
Artistic License 2.0
|
||||
|
||||
Copyright (c) 2000-2006, The Perl Foundation.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
This license establishes the terms under which a given free software
|
||||
Package may be copied, modified, distributed, and/or
|
||||
redistributed. The intent is that the Copyright Holder maintains some
|
||||
artistic control over the development of that Package while still
|
||||
keeping the Package available as open source and free software.
|
||||
|
||||
You are always permitted to make arrangements wholly outside of this
|
||||
license directly with the Copyright Holder of a given Package. If the
|
||||
terms of this license do not permit the full use that you propose to
|
||||
make of the Package, you should contact the Copyright Holder and seek
|
||||
a different licensing arrangement.
|
||||
|
||||
Definitions
|
||||
|
||||
"Copyright Holder" means the individual(s) or organization(s) named
|
||||
in the copyright notice for the entire Package.
|
||||
|
||||
"Contributor" means any party that has contributed code or other
|
||||
material to the Package, in accordance with the Copyright Holder's
|
||||
procedures.
|
||||
|
||||
"You" and "your" means any person who would like to copy,
|
||||
distribute, or modify the Package.
|
||||
|
||||
"Package" means the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection and/or of
|
||||
those files. A given Package may consist of either the Standard
|
||||
Version, or a Modified Version.
|
||||
|
||||
"Distribute" means providing a copy of the Package or making it
|
||||
accessible to anyone else, or in the case of a company or
|
||||
organization, to others outside of your company or organization.
|
||||
|
||||
"Distributor Fee" means any fee that you charge for Distributing
|
||||
this Package or providing support for this Package to another
|
||||
party. It does not mean licensing fees.
|
||||
|
||||
"Standard Version" refers to the Package if it has not been
|
||||
modified, or has been modified only in ways explicitly requested by
|
||||
the Copyright Holder.
|
||||
|
||||
"Modified Version" means the Package, if it has been changed, and
|
||||
such changes were not explicitly requested by the Copyright Holder.
|
||||
|
||||
"Original License" means this Artistic License as Distributed with
|
||||
the Standard Version of the Package, in its current version or as
|
||||
it may be modified by The Perl Foundation in the future.
|
||||
|
||||
"Source" form means the source code, documentation source, and
|
||||
configuration files for the Package.
|
||||
|
||||
"Compiled" form means the compiled bytecode, object code, binary,
|
||||
or any other form resulting from mechanical transformation or
|
||||
translation of the Source form.
|
||||
|
||||
Permission for Use and Modification Without Distribution
|
||||
|
||||
(1) You are permitted to use the Standard Version and create and use
|
||||
Modified Versions for any purpose without restriction, provided that
|
||||
you do not Distribute the Modified Version.
|
||||
|
||||
Permissions for Redistribution of the Standard Version
|
||||
|
||||
(2) You may Distribute verbatim copies of the Source form of the
|
||||
Standard Version of this Package in any medium without restriction,
|
||||
either gratis or for a Distributor Fee, provided that you duplicate
|
||||
all of the original copyright notices and associated disclaimers. At
|
||||
your discretion, such verbatim copies may or may not include a
|
||||
Compiled form of the Package.
|
||||
|
||||
(3) You may apply any bug fixes, portability changes, and other
|
||||
modifications made available from the Copyright Holder. The resulting
|
||||
Package will still be considered the Standard Version, and as such
|
||||
will be subject to the Original License.
|
||||
|
||||
Distribution of Modified Versions of the Package as Source
|
||||
|
||||
(4) You may Distribute your Modified Version as Source (either gratis
|
||||
or for a Distributor Fee, and with or without a Compiled form of the
|
||||
Modified Version) provided that you clearly document how it differs
|
||||
from the Standard Version, including, but not limited to, documenting
|
||||
any non-standard features, executables, or modules, and provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
(a) make the Modified Version available to the Copyright Holder of
|
||||
the Standard Version, under the Original License, so that the
|
||||
Copyright Holder may include your modifications in the Standard
|
||||
Version.
|
||||
|
||||
(b) ensure that installation of your Modified Version does not
|
||||
prevent the user installing or running the Standard Version. In
|
||||
addition, the Modified Version must bear a name that is different
|
||||
from the name of the Standard Version.
|
||||
|
||||
(c) allow anyone who receives a copy of the Modified Version to
|
||||
make the Source form of the Modified Version available to others
|
||||
under
|
||||
|
||||
(i) the Original License or
|
||||
|
||||
(ii) a license that permits the licensee to freely copy, modify
|
||||
and redistribute the Modified Version using the same licensing
|
||||
terms that apply to the copy that the licensee received, and
|
||||
requires that the Source form of the Modified Version, and of
|
||||
any works derived from it, be made freely available in that
|
||||
license fees are prohibited but Distributor Fees are allowed.
|
||||
Distribution of Compiled Forms of the Standard Version or
|
||||
Modified Versions without the Source
|
||||
|
||||
(5) You may Distribute Compiled forms of the Standard Version without
|
||||
the Source, provided that you include complete instructions on how to
|
||||
get the Source of the Standard Version. Such instructions must be
|
||||
valid at the time of your distribution. If these instructions, at any
|
||||
time while you are carrying out such distribution, become invalid, you
|
||||
must provide new instructions on demand or cease further
|
||||
distribution. If you provide valid instructions or cease distribution
|
||||
within thirty days after you become aware that the instructions are
|
||||
invalid, then you do not forfeit any of your rights under this
|
||||
license.
|
||||
|
||||
(6) You may Distribute a Modified Version in Compiled form without the
|
||||
Source, provided that you comply with Section 4 with respect to the
|
||||
Source of the Modified Version.
|
||||
|
||||
Aggregating or Linking the Package
|
||||
|
||||
(7) You may aggregate the Package (either the Standard Version or
|
||||
Modified Version) with other packages and Distribute the resulting
|
||||
aggregation provided that you do not charge a licensing fee for the
|
||||
Package. Distributor Fees are permitted, and licensing fees for other
|
||||
components in the aggregation are permitted. The terms of this license
|
||||
apply to the use and Distribution of the Standard or Modified Versions
|
||||
as included in the aggregation.
|
||||
|
||||
(8) You are permitted to link Modified and Standard Versions with
|
||||
other works, to embed the Package in a larger work of your own, or to
|
||||
build stand-alone binary or bytecode versions of applications that
|
||||
include the Package, and Distribute the result without restriction,
|
||||
provided the result does not expose a direct interface to the Package.
|
||||
|
||||
Items That are Not Considered Part of a Modified Version
|
||||
|
||||
(9) Works (including, but not limited to, modules and scripts) that
|
||||
merely extend or make use of the Package, do not, by themselves, cause
|
||||
the Package to be a Modified Version. In addition, such works are not
|
||||
considered parts of the Package itself, and are not subject to the
|
||||
terms of this license.
|
||||
|
||||
General Provisions
|
||||
|
||||
(10) Any use, modification, and distribution of the Standard or
|
||||
Modified Versions is governed by this Artistic License. By using,
|
||||
modifying or distributing the Package, you accept this license. Do not
|
||||
use, modify, or distribute the Package, if you do not accept this
|
||||
license.
|
||||
|
||||
(11) If your Modified Version has been derived from a Modified Version
|
||||
made by someone other than you, you are nevertheless required to
|
||||
ensure that your Modified Version complies with the requirements of
|
||||
this license.
|
||||
|
||||
(12) This license does not grant you the right to use any trademark,
|
||||
service mark, tradename, or logo of the Copyright Holder.
|
||||
|
||||
(13) This license includes the non-exclusive, worldwide,
|
||||
free-of-charge patent license to make, have made, use, offer to sell,
|
||||
sell, import and otherwise transfer the Package with respect to any
|
||||
patent claims licensable by the Copyright Holder that are necessarily
|
||||
infringed by the Package. If you institute patent litigation
|
||||
(including a cross-claim or counterclaim) against any party alleging
|
||||
that the Package constitutes direct or contributory patent
|
||||
infringement, then this Artistic License to you shall terminate on the
|
||||
date that such litigation is filed.
|
||||
|
||||
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
|
||||
HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
|
||||
PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
|
||||
HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
216
INSTALL
216
INSTALL
|
@ -1,216 +0,0 @@
|
|||
These instructions based on the generic INSTALL file from automake
|
||||
1.10. However, qpdf does not use automake, so not all of that file
|
||||
applies.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
You can also define the variable DESTDIR when you run make install
|
||||
to install the package in a separate subdirectory. This is useful for
|
||||
packaging.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
202
LICENSE.txt
202
LICENSE.txt
|
@ -1,202 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
140
Makefile
140
Makefile
|
@ -1,140 +0,0 @@
|
|||
# This makefile is inspired by abuild (http://www.abuild.org), which
|
||||
# was used during the development of qpdf. The goal here is to have a
|
||||
# non-recursive build with all the proper dependencies so we can start
|
||||
# the build from anywhere and get the right stuff. Each directory has
|
||||
# a build.mk that is included from here and is written from this
|
||||
# directory's perspective. Each directory also has a proxy Makefile
|
||||
# that allows you to start the build from any directory and get
|
||||
# reasonable semantics for the all, check, and clean targets.
|
||||
|
||||
# Our "build items" are directories. They are listed here such that
|
||||
# no item precedes any item it depends on. Therefore, each item can
|
||||
# safely reference variables set in its predecessors.
|
||||
|
||||
# For each build item B, you can run make build_B, make check_B, or
|
||||
# make clean_B to build, test, or clean B. Full dependencies are
|
||||
# represented across all the items, so it is possible to start
|
||||
# anywhere. From the top level, the "all", "check", and "clean"
|
||||
# targets build, test, or clean everything.
|
||||
|
||||
# To run test suites without rebuilding, pass NO_REBUILD=1 to the
|
||||
# build. This can be useful for testing binary interface compatibility
|
||||
# as it enables you to rebuild libraries and rerun tests without
|
||||
# relinking.
|
||||
|
||||
# Although this is not a GNU package and does not use automake, you
|
||||
# can still run make clean to remove everything that is compiled, make
|
||||
# distclean to remove everything that is generated by the end user,
|
||||
# and make maintainer-clean to remove everything that is generated
|
||||
# including things distributed with the source distribution. You can
|
||||
# pass CLEAN=1 to prevent this Makefile from complaining if
|
||||
# ./configure has not been run.
|
||||
|
||||
# The install target works as usual and obeys --prefix and so forth
|
||||
# passed to ./configure. You can also pass DESTDIR=/dir to make
|
||||
# install to install in a separate location. This is useful for
|
||||
# packagers.
|
||||
|
||||
BUILD_ITEMS := manual libqpdf zlib-flate libtests qpdf fuzz examples
|
||||
OUTPUT_DIR = build
|
||||
ALL_TARGETS =
|
||||
|
||||
.PHONY: default
|
||||
default: all
|
||||
|
||||
CLEAN ?=
|
||||
ifneq ($(CLEAN),1)
|
||||
ifeq ($(words $(wildcard autoconf.mk)),0)
|
||||
DUMMY := $(shell echo 1>&2)
|
||||
DUMMY := $(shell echo 1>&2 Please run ./configure before running $(MAKE))
|
||||
DUMMY := $(shell echo 1>&2)
|
||||
$(error unable to continue with build)
|
||||
endif
|
||||
|
||||
autoconf.mk:
|
||||
|
||||
include autoconf.mk
|
||||
|
||||
endif
|
||||
|
||||
# Prevent gnu make from trying to rebuild .dep files
|
||||
$(foreach B,$(BUILD_ITEMS),$(eval \
|
||||
$(B)/$(OUTPUT_DIR)/%.dep: ;))
|
||||
|
||||
# Prevent gnu make from trying to rebuild .mk files
|
||||
$(foreach B,$(BUILD_ITEMS),$(eval \
|
||||
$(B)/%.mk: ;))
|
||||
%.mk: ;
|
||||
make/%.mk: ;
|
||||
|
||||
BUILDRULES ?= libtool
|
||||
include make/rules.mk
|
||||
|
||||
DUMMY := $(shell mkdir $(foreach B,$(BUILD_ITEMS),$(B)/$(OUTPUT_DIR)) 2>/dev/null)
|
||||
|
||||
include $(foreach B,$(BUILD_ITEMS),$(B)/build.mk)
|
||||
|
||||
ALL_TARGETS = $(foreach B,$(BUILD_ITEMS),$(TARGETS_$(B)))
|
||||
|
||||
TEST_ITEMS = $(foreach D,\
|
||||
$(wildcard $(foreach B,$(BUILD_ITEMS),$(B)/qtest)),\
|
||||
$(subst /,,$(dir $(D))))
|
||||
|
||||
TEST_TARGETS = $(foreach B,$(TEST_ITEMS),check_$(B))
|
||||
|
||||
CLEAN_TARGETS = $(foreach B,$(BUILD_ITEMS),clean_$(B))
|
||||
|
||||
# For test suites
|
||||
export QPDF_BIN = $(abspath qpdf/$(OUTPUT_DIR)/qpdf)
|
||||
export QPDF_SKIP_TEST_COMPARE_IMAGES
|
||||
export QPDF_LARGE_FILE_TEST_PATH
|
||||
|
||||
clean:: $(CLEAN_TARGETS)
|
||||
$(RM) -r appimage/build
|
||||
|
||||
.PHONY: $(CLEAN_TARGETS)
|
||||
$(foreach B,$(BUILD_ITEMS),$(eval \
|
||||
clean_$(B): ; \
|
||||
$(RM) -r $(B)/$(OUTPUT_DIR)))
|
||||
|
||||
DISTFILES = doc/qpdf-manual.html doc/qpdf-manual.pdf
|
||||
distfiles.zip: $(DISTFILES)
|
||||
$(RM) distfiles.zip
|
||||
zip distfiles.zip $(DISTFILES)
|
||||
|
||||
distclean: clean
|
||||
$(RM) -r autoconf.mk autom4te.cache config.log config.status libtool
|
||||
$(RM) libqpdf/qpdf/qpdf-config.h
|
||||
$(RM) manual/html.xsl
|
||||
$(RM) manual/print.xsl
|
||||
$(RM) doc/*.1
|
||||
$(RM) libqpdf.pc libqpdf.map
|
||||
|
||||
maintainer-clean: distclean
|
||||
$(RM) doc/qpdf-manual.*
|
||||
$(RM) -r install-mingw* install-msvc* external-libs
|
||||
$(RM) distfiles.zip
|
||||
|
||||
.PHONY: $(TEST_TARGETS)
|
||||
|
||||
NO_REBUILD ?=
|
||||
ifneq ($(NO_REBUILD),1)
|
||||
$(foreach B,$(TEST_ITEMS),$(eval \
|
||||
check_$(B): $(TARGETS_$(B))))
|
||||
endif
|
||||
|
||||
.PHONY: $(foreach B,$(BUILD_ITEMS),build_$(B))
|
||||
$(foreach B,$(BUILD_ITEMS),$(eval \
|
||||
build_$(B): $(TARGETS_$(B))))
|
||||
|
||||
.PHONY: all
|
||||
all: $(ALL_TARGETS) ;
|
||||
|
||||
check: $(TEST_TARGETS)
|
||||
|
||||
# Install targets are in the make directory in the rules-specific make
|
||||
# fragments.
|
||||
|
||||
QTEST=$(abspath qtest/bin/qtest-driver)
|
||||
$(TEST_TARGETS):
|
||||
$(call run_qtest,$(subst check_,,$@))
|
42
NOTICE.md
42
NOTICE.md
|
@ -1,42 +0,0 @@
|
|||
QPDF is copyright (c) 2005-2020 Jay Berkenbilt
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic License. At your option, you may continue to consider qpdf to be licensed under those terms. Please see the manual for additional information.
|
||||
|
||||
The qpdf distribution includes a copy of [qtest](http://qtest.qbilt.org), which is released under the terms of the [version 2.0 of the Artistic license](https://opensource.org/licenses/Artistic-2.0), which can be found at https://opensource.org/licenses/Artistic-2.0.
|
||||
|
||||
The Rijndael encryption implementation used as the basis for AES encryption and decryption support comes from Philip J. Erdelsky's public domain implementation. The files `libqpdf/rijndael.cc` and `libqpdf/qpdf/rijndael.h` remain in the public domain. They were obtained from
|
||||
* http://www.efgh.com/software/rijndael.htm
|
||||
* http://www.efgh.com/software/rijndael.txt
|
||||
|
||||
The embedded sha2 code comes from sphlib 3.0
|
||||
* http://www.saphir2.com/sphlib/
|
||||
|
||||
That code has the following license:
|
||||
```
|
||||
Copyright (c) 2007-2011 Projet RNRT SAPHIR
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
|
@ -1,9 +0,0 @@
|
|||
# Using the QPDF AppImage bundle (for Linux x86_64 systems only)
|
||||
|
||||
Tips:
|
||||
|
||||
* After downloading, you have to set the executable bit for any AppImage (for security reasons this is disabled by default): `chmod +x <name-of-application>.AppImage`
|
||||
|
||||
* Run the QPDF AppImage with the `--ai-usage` parameter to start learning some useful details about built-in features of this specific AppImage.
|
||||
|
||||
* You can rename the AppImage to any name allowed for file names on Linux. The `.AppImage` suffix is not required for it to function. It will also work as expected if you invoke it from a symlink. Using `qpdf` as its filename or symlink name is OK. However, you may want to continue using the QPDF package provided by your system's package manager side by side with the AppImage bundle: in this case it is recommended to use `qpdf.ai` as a short name for (or as the symlink name to) the qpdf-<version>.AppImage.
|
|
@ -1,89 +0,0 @@
|
|||
# Avoiding `operator[]`
|
||||
|
||||
During a security review by Red Hat security team (specifically Florian Weimer), it was discovered that qpdf used `std::string` and `std::vector`'s `operator[]`, which has no bounds checking by design. Instead, using those objects' `at()` method is preferable since it does bounds checking. Florian has a tool that can detect all uses of these methods and report them. I have a short perl script that automatically corrects any such uses. The perl script is not intended to be general, but it could be reasonably general. The only known shortcut is that it might not work very well with some cases of nested `[]`'s like `a[b[c]]` or with cases where there are line breaks inside the brackets. For qpdf's coding style, it worked on all cases reported.
|
||||
|
||||
To use this, obtain htcondor-analyzer, run it, and respond to the report. Here's what I did.
|
||||
|
||||
```
|
||||
sudo aptitude install libclang-dev llvm llvm-dev clang
|
||||
cd /tmp
|
||||
git clone https://github.com/fweimer/htcondor-analyzer
|
||||
# HEAD = 5fa06fc68a9b0677e9de162279185d58ba1e8477 at this writing
|
||||
cd htcondor-analyzer
|
||||
make
|
||||
```
|
||||
|
||||
In qpdf:
|
||||
|
||||
```
|
||||
/tmp/htcondor-analyzer/create-db
|
||||
CC=/tmp/htcondor-analyzer/cc CXX=/tmp/htcondor-analyzer/cxx ./configure --disable-shared --disable-werror
|
||||
# to remove conftest.c
|
||||
\rm htcondor-analyzer.sqlite
|
||||
/tmp/htcondor-analyzer/create-db
|
||||
```
|
||||
|
||||
Repeat until no more errors:
|
||||
|
||||
```
|
||||
/tmp/fix-at.pl is shown below.
|
||||
```
|
||||
|
||||
```
|
||||
make
|
||||
/tmp/htcondor-analyzer/report | grep std:: | grep qpdf >| /tmp/r
|
||||
perl /tmp/fix-at.pl /tmp/r
|
||||
# move all *.new over the original file. patmv is my script. Can
|
||||
# also use a for loop.
|
||||
patmv -f s/.new// **/*.new
|
||||
```
|
||||
|
||||
/tmp/fix-at.pl:
|
||||
```perl
|
||||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
use warnings;
|
||||
use strict;
|
||||
use File::Basename;
|
||||
|
||||
my $whoami = basename($0);
|
||||
|
||||
my %to_fix = ();
|
||||
while (<>)
|
||||
{
|
||||
chomp;
|
||||
die unless m/^([^:]+):(\d+):(\d+):\s*(.*)$/;
|
||||
my ($file, $line, $col, $message) = ($1, $2, $3, $4);
|
||||
if ($message !~ m/operator\[\]/)
|
||||
{
|
||||
warn "skipping $_\n";
|
||||
next;
|
||||
}
|
||||
push(@{$to_fix{$file}}, [$line, $col, $message]);
|
||||
}
|
||||
foreach my $file (sort keys %to_fix)
|
||||
{
|
||||
open(F, "<$file") or die;
|
||||
my @lines = (<F>);
|
||||
close(F);
|
||||
my $last = "";
|
||||
my @data = reverse sort { ($a->[0] <=> $b->[0]) || ($a->[1] <=> $b->[1]) } @{$to_fix{$file}};
|
||||
foreach my $d (@data)
|
||||
{
|
||||
my ($line, $col) = @$d;
|
||||
next if $last eq "$line:$col";
|
||||
$last = "$line:$col";
|
||||
die if $line-- < 1;
|
||||
die if $col-- < 1;
|
||||
print $lines[$line];
|
||||
$lines[$line] =~ s/^(.{$col})([^\[]+)\[([^\]]+)\]/$1$2.at($3)/ or die "$file:$last\n";
|
||||
print $lines[$line];
|
||||
}
|
||||
open(F, ">$file.new") or die;
|
||||
foreach my $line (@lines)
|
||||
{
|
||||
print F $line;
|
||||
}
|
||||
close(F) or die;
|
||||
}
|
||||
```
|
|
@ -1,338 +0,0 @@
|
|||
ROUTINE DEVELOPMENT
|
||||
|
||||
**Remember to check pull requests as well as issues in github.**
|
||||
|
||||
Default:
|
||||
|
||||
./configure CXX="g++ --std=c++11" --enable-werror
|
||||
|
||||
Debugging:
|
||||
|
||||
./configure CXX="g++ --std=c++11" CFLAGS="-g" CXXFLAGS="-g" \
|
||||
--enable-werror --disable-shared
|
||||
|
||||
Profiling:
|
||||
|
||||
./configure CXX="g++ --std=c++11" CFLAGS="-g -pg" CXXFLAGS="-g -pg" \
|
||||
LDFLAGS="-pg" --enable-werror --disable-shared
|
||||
|
||||
Then run `gprof gmon.out`. Note that gmon.out is not cumulative.
|
||||
|
||||
Memory checks:
|
||||
|
||||
./configure CFLAGS="-fsanitize=address -fsanitize=undefined -g" \
|
||||
CXXFLAGS="-fsanitize=address -fsanitize=undefined -g" \
|
||||
LDFLAGS="-fsanitize=address -fsanitize=undefined" \
|
||||
CC=clang CXX="clang++ --std=c++11" \
|
||||
--enable-werror --disable-shared
|
||||
|
||||
|
||||
GOOGLE OSS-FUZZ
|
||||
|
||||
* See ../misc/fuzz (not in repo) for unfixed, downloaded fuzz test cases
|
||||
|
||||
* qpdf project: https://github.com/google/oss-fuzz/tree/master/projects/qpdf
|
||||
|
||||
* To test locally, see https://github.com/google/oss-fuzz/tree/master/docs/,
|
||||
especially new_project_guide.md. Summary:
|
||||
|
||||
Clone the oss-fuzz project. From the root directory of the repository:
|
||||
|
||||
Add `-e GITHUB_FORK=fork -e GITHUB_BRANCH=branch` to build_fuzzers
|
||||
from a qpdf fork/branch rather than qpdf/master.
|
||||
|
||||
python infra/helper.py build_image --pull qpdf
|
||||
python infra/helper.py build_fuzzers [ --sanitizer memory|undefined|address ] qpdf
|
||||
python infra/helper.py check_build qpdf
|
||||
python infra/helper.py build_fuzzers --sanitizer coverage qpdf
|
||||
python infra/helper.py coverage qpdf
|
||||
|
||||
To reproduce a test case, build with the correct sanitizer, then run
|
||||
|
||||
python infra/helper.py reproduce qpdf fuzzer testcase
|
||||
|
||||
where fuzzer is the fuzzer used in the crash.
|
||||
|
||||
The fuzzer is in build/out/qpdf. It can be run with a directory as
|
||||
an argument to run against files in a directory. You can use
|
||||
|
||||
qpdf_fuzzer -merge=1 cur new >& /dev/null&
|
||||
|
||||
to add any files from new into cur if they increase coverage. You
|
||||
need to do this with the coverage build (the one with
|
||||
--sanitizer coverage)
|
||||
|
||||
* General documentation: http://libfuzzer.info
|
||||
|
||||
* Build status: https://oss-fuzz-build-logs.storage.googleapis.com/index.html
|
||||
|
||||
* Project status: https://oss-fuzz.com/ (private -- log in with Google account)
|
||||
|
||||
* Latest corpus:
|
||||
gs://qpdf-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/qpdf_fuzzer/latest.zip
|
||||
|
||||
|
||||
CODING RULES
|
||||
|
||||
* Avoid atoi. Use QUtil::string_to_int instead. It does
|
||||
overflow/underflow checking.
|
||||
|
||||
* Remember to avoid using `operator[]` with `std::string` or
|
||||
`std::vector`. Instead, use `at()`. See README-hardening.md for
|
||||
details.
|
||||
|
||||
* Use QIntC for type conversions -- see casting policy in docs.
|
||||
|
||||
* Use QPDF_DLL on all methods that are to be exported in the shared
|
||||
library/DLL. Use QPDF_DLL_CLASS for all classes whose type
|
||||
information is needed. This is important for exception classes and
|
||||
it seems also for classes that are intended to be subclassed across
|
||||
the shared library boundary.
|
||||
|
||||
* Put private member variables in PointerHolder<Members> for all
|
||||
public classes. Remember to use QPDF_DLL on ~Members().
|
||||
|
||||
|
||||
RELEASE PREPARATION
|
||||
|
||||
* Each year, update copyright notices. Just do a case-insensitive
|
||||
search for copyright. Don't forget copyright in manual. Also update
|
||||
debian copyright in debian package. Last updated: 2020.
|
||||
|
||||
* Check for open fuzz crashes at https://oss-fuzz.com
|
||||
|
||||
* Check all open issues and pull requests in github and the
|
||||
sourceforge trackers. See ~/scripts/github-issues.
|
||||
|
||||
* Check `TODO` file to make sure all planned items for the release are
|
||||
done or retargeted.
|
||||
|
||||
* Run a spelling checker over the source code to catch errors in
|
||||
variable names, strings, and comments.
|
||||
|
||||
ispell -p ispell-words **/*.hh **/*.cc manual/* ChangeLog README* TODO
|
||||
|
||||
* If needed, run large file and image comparison tests. Configure
|
||||
options:
|
||||
|
||||
--enable-test-compare-images --with-large-file-test-path=/path
|
||||
|
||||
For Windows, use a Windows style path, not an MSYS path for large files.
|
||||
|
||||
* Test with clang. Pass `CC=clang CXX=clang++` to `./configure`. Test
|
||||
with newer version of gcc if available.
|
||||
|
||||
* Test 32-bit. Pass `CC=i686-linux-gnu-gcc CXX=i686-linux-gnu-g++` to
|
||||
`./configure`. (Done in CI.)
|
||||
|
||||
* Test build on a mac. (Done in CI.)
|
||||
|
||||
* Test with address sanitizer as described above. (Done in CI with
|
||||
gcc; test locally with clang.)
|
||||
|
||||
* A small handful of additional files have been taken from autotools
|
||||
programs. These should probably be updated from time to time.
|
||||
|
||||
* `config.guess`, `config.sub`, `ltmain.sh`, and the `m4` directory:
|
||||
these were created by running `libtoolize -c`. To update, run
|
||||
`libtoolize -f -c` or remove the files and rerun `libtoolize`. For
|
||||
`config.guess` and `config.sub`, search for "latest" in the files,
|
||||
and follow directions for updating them.
|
||||
|
||||
* Other files copied as indicated:
|
||||
```
|
||||
cp /usr/share/automake-1.11/install-sh .
|
||||
cp /usr/share/automake-1.11/mkinstalldirs .
|
||||
cp /usr/share/aclocal/pkg.m4 m4
|
||||
```
|
||||
|
||||
The entire contents of the `m4` directory came from `libtool.m4`. If
|
||||
we had some additional local parts, we could also add those to the
|
||||
`m4` directory. In order for this to work, it is necessary to run
|
||||
`aclocal -I m4` before running `autoheader` and `autoconf`. The
|
||||
`autogen.sh` script handles this.
|
||||
|
||||
* If any interfaces were added or changed, check C API to see whether
|
||||
changes are appropriate there as well. If necessary, review the
|
||||
casting policy in the manual, and ensure that integer types are
|
||||
properly handled with QIntC or the appropriate cast.
|
||||
|
||||
* Increment shared library version information as needed (`LT_*` in
|
||||
`configure.ac`). Remember to rerun ./autogen.sh.
|
||||
|
||||
* Test for binary compatibility:
|
||||
* Check out the last release
|
||||
* ./configure --enable-werror && make -j$(nproc)
|
||||
* Check out the current version
|
||||
* ./configure --enable-werror && make -j$(nproc) build_libqpdf
|
||||
* Checkout the last release
|
||||
* make -k check NO_REBUILD=1
|
||||
|
||||
* Update release notes in manual. Look at diffs and ChangeLog. Update
|
||||
release date in `manual/qpdf-manual.xml`. Remember to ensure that
|
||||
the entities at the top of the document are consistent with the
|
||||
release notes for both version and release date.
|
||||
|
||||
* Make sure version numbers are consistent in the following locations:
|
||||
* configure.ac
|
||||
* libqpdf/QPDF.cc
|
||||
* manual/qpdf-manual.xml
|
||||
* qpdf/qpdf.cc
|
||||
`make_dist` verifies this consistency.
|
||||
|
||||
* Add a release entry to ChangeLog.
|
||||
|
||||
|
||||
CREATING A RELEASE
|
||||
|
||||
* Push to master. The azure pipeline will create an artifact called
|
||||
distribution which will contain all the distribution files. Download
|
||||
these, verify the checksums from the job output, rename to remove
|
||||
-ci from the names, and copy to the release archive area.
|
||||
|
||||
* Sign the source distribution:
|
||||
|
||||
version=x.y.z
|
||||
gpg --detach-sign --armor qpdf-$version.tar.gz
|
||||
|
||||
* Build and test the debian package
|
||||
|
||||
* Sign the releases. The release archive area should contain the
|
||||
Windows binaries, the AppImage, the source tarball, and the source
|
||||
tarball signature.
|
||||
|
||||
\rm -f *.{md5,sha1,sha512}
|
||||
files=(*)
|
||||
for i in md5 sha1 sha512; do
|
||||
${i}sum ${files[*]} >| qpdf-$version.$i
|
||||
gpg --clearsign --armor qpdf-$version.$i
|
||||
mv qpdf-$version.$i.asc qpdf-$version.$i
|
||||
done
|
||||
chmod 444 *
|
||||
chmod 555 *.AppImage
|
||||
|
||||
* When creating releases on github and sourceforge, remember to copy
|
||||
`README-what-to-download.md` separately onto the download area if
|
||||
needed.
|
||||
|
||||
* Ensure that the master branch has been pushed to github. The
|
||||
rev-parse command below should show the same commit hash for all its
|
||||
arguments. Create and push a signed tag. This should be run with
|
||||
HEAD pointing to the tip of master.
|
||||
|
||||
git rev-parse master upstream/master @
|
||||
git tag -s release-qpdf-$version @ -m"qpdf $version"
|
||||
git push upstream release-qpdf-$version
|
||||
|
||||
* In Azure Pipelines, retain the build that was used to generate the
|
||||
release.
|
||||
|
||||
* Create a github release after pushing the tag. `gcurl` is an alias
|
||||
that includes the auth token.
|
||||
|
||||
# Create release
|
||||
TOKEN=$(cat ~/.github-token)
|
||||
function gcurl() { curl -H "Authorization: token $TOKEN" ${1+"$@"}; }
|
||||
url=$(gcurl -s -XPOST https://api.github.com/repos/qpdf/qpdf/releases -d'{"tag_name": "release-qpdf-'$version'", "name": "qpdf '$version'", "draft": true}' | jq -r '.url')
|
||||
|
||||
# Get upload url
|
||||
upload_url=$(gcurl -s $url | jq -r '.upload_url' | sed -E -e 's/\{.*\}//')
|
||||
echo $upload_url
|
||||
|
||||
# Upload all the files. You can add a label attribute too, which
|
||||
# overrides the name.
|
||||
for i in *; do
|
||||
mime=$(file -b --mime-type $i)
|
||||
gcurl -H "Content-Type: $mime" --data-binary @$i "$upload_url?name=$i"
|
||||
done
|
||||
|
||||
If needed, go onto github and make any manual updates such as
|
||||
indicating a pre-release, adding release notes, etc.
|
||||
|
||||
# Publish release
|
||||
gcurl -XPOST $url -d'{"draft": false}'
|
||||
|
||||
* Upload files to sourceforge.
|
||||
|
||||
rsync -vrlcO ./ jay_berkenbilt,qpdf@frs.sourceforge.net:/home/frs/project/q/qp/qpdf/qpdf/$version/
|
||||
|
||||
* On sourceforge, make the source package the default for all but
|
||||
Windows, and make the 32-bit mingw build the default for Windows.
|
||||
|
||||
* Publish a news item manually on sourceforge.
|
||||
|
||||
* Update the web page to indicate the new version and to put the new
|
||||
documentation in the `files` subdirectory of the website on
|
||||
sourceforge.net.
|
||||
|
||||
(cd /tmp; mkdir -p z; cd z; \
|
||||
tar xf ~/Q/storage/releases/qpdf/qpdf/$version/qpdf-$version.tar.gz qpdf-$version/doc; \
|
||||
scp -p qpdf-$version/doc/qpdf-* jay_berkenbilt,qpdf@frs.sourceforge.net:htdocs/files/)
|
||||
|
||||
* Email the qpdf-announce list.
|
||||
|
||||
|
||||
OTHER NOTES
|
||||
|
||||
To construct a source distribution from a pristine checkout,
|
||||
`make_dist` does the following:
|
||||
|
||||
./configure --enable-doc-maintenance --enable-werror
|
||||
make build_manual
|
||||
make distclean
|
||||
|
||||
To create a source release of external libs, do an export from the
|
||||
version control system into a directory called `qpdf-external-libs`
|
||||
and just make a zip file of the result called
|
||||
`qpdf-external-libs-src.zip`. See the README.txt file there for
|
||||
information on creating binary external libs releases. Run this from
|
||||
the external-libs repository:
|
||||
|
||||
git archive --prefix=external-libs/ HEAD . | (cd /tmp; tar xf -)
|
||||
cd /tmp
|
||||
zip -r qpdf-external-libs-src.zip external-libs
|
||||
|
||||
When releasing on sourceforge, `external-libs` distributions go in
|
||||
`external-libs/yyyymmdd`, and qpdf distributions go in `qpdf/vvv`.
|
||||
|
||||
For local iteration on the AppImage generation, it works to just
|
||||
./azure-pipelines/build-appimage and get the resulting AppImage from
|
||||
the distribution directory. You can also pass -e SKIP_TESTS=1
|
||||
build-appimage, which passes it along to to docker, to skip the test
|
||||
suite, which useful for rapid iteration.
|
||||
|
||||
|
||||
GENERAL BUILD STUFF
|
||||
|
||||
QPDF uses autoconf and libtool but does not use automake. The only
|
||||
files distributed with the qpdf source distribution that are not
|
||||
controlled are `configure`, `libqpdf/qpdf/qpdf-config.h.in`,
|
||||
`aclocal.m4`, and some documentation. See above for the steps required
|
||||
to prepare a source distribution.
|
||||
|
||||
If building or editing documentation, configure with
|
||||
`--enable-doc-maintenance`. This will ensure that all tools or files
|
||||
required to validate and build documentation are available.
|
||||
|
||||
If you want to run `make maintainer-clean` or `make distclean` and you
|
||||
haven't run `./configure`, you can pass `CLEAN=1` to make on the
|
||||
command line to prevent it from complaining about configure not having
|
||||
been run.
|
||||
|
||||
If you want to run checks without rerunning the build, pass
|
||||
`NO_REBUILD=1` to make. This can be useful for special testing
|
||||
scenarios such as validation of memory fixes or binary compatibility.
|
||||
|
||||
|
||||
LOCAL WINDOWS TESTING PROCEDURE
|
||||
|
||||
This is what I do for routine testing on Windows.
|
||||
|
||||
From Windows, git clone from my Linux clone, and unzip
|
||||
`external-libs`.
|
||||
|
||||
Look at `make_windows_releases`. Set up path the same way and run
|
||||
whichever `./config-*` is appropriate for whichever compiler I need to
|
||||
test with. Start one of the Visual Studio native compiler shells, and
|
||||
from there, run one of the msys shells. The Visual Studio step is not
|
||||
necessary if just building with mingw.
|
|
@ -1,32 +0,0 @@
|
|||
To build from source for Linux or other UNIX/UNIX-like systems, it is generally sufficient to download just the source `qpdf-<version>.tar.gz` file.
|
||||
|
||||
Virtually all Linux distributions include packages for qpdf. If you'd like to run the latest version of qpdf as an [AppImage](https://appimage.org/), you can download `qpdf-<version>-x86_64.AppImage`. This is a self-contained executable that you make symlink `qpdf` to and run on most reasonably recent Linux distributions. See README-appimage.md in the qpdf source distribution for additional details, or run the AppImage with the `--ai-usage` argument to get help specific to the AppImage.
|
||||
|
||||
For Windows, there are several additional files that you might want to download.
|
||||
|
||||
* `qpdf-<version>-bin-mingw32.zip`
|
||||
|
||||
If you just want to use the qpdf command line program or use the qpdf DLL's C-language interface, you can download this file. You can also download this version if you are using MINGW's gcc and want to program using the C++ interface.
|
||||
|
||||
* `qpdf-<version>-bin-mingw64.zip`
|
||||
|
||||
A 64-bit version built with mingw. Use this for 64-bit Windows systems. The 32-bit version will also work on Windows 64-bit. Both the 32-bit and the 64-bit version support files over 2 GB in size, but you may find it easier to integrate this with your own software if you use the 64-bit version.
|
||||
|
||||
* `qpdf-<version>-bin-msvc32.zip`
|
||||
|
||||
If you want to program using qpdf's C++ interface and you are using Microsoft Visual C++ 2015 in 32-bit mode, you can download this file.
|
||||
|
||||
* `qpdf-<version>-bin-msvc64.zip`
|
||||
|
||||
If you want to program using qpdf's C++ interface and you are using Microsoft Visual C++ 2015 in 64-bit mode, you can download this file.
|
||||
|
||||
* `qpdf-external-libs-bin.zip`
|
||||
|
||||
If you want to build qpdf for Windows yourself with either MINGW or MSVC 2015, you can download this file and extract it inside the qpdf source distribution. Please refer to README-windows.md in the qpdf source distribution for additional details. Note that you need the 2017-08-21 version or later to be able to build qpdf 7.0 or newer. Generally grab the `external-libs` distribution that was the latest version at the time of the release of whichever version of qpdf you are building.
|
||||
|
||||
* `qpdf-external-libs-src.zip`
|
||||
|
||||
If you want to build the external libraries on your own (for Windows or anything else), you can download this archive. In addition to including an unmodified distribution `zlib` and the `jpeg` library, it includes a `README` file and some scripts to help you build it for Windows. You will also have to provide those.
|
||||
|
||||
If you want to build on Windows, please see also README-windows.md in the qpdf source distribution.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
This file is README-windows-install.txt in the source distribution and
|
||||
README.txt in the Windows binary distribution.
|
||||
|
||||
QPDF is completely relocatable. To use qpdf.exe or the qpdf DLL, just
|
||||
have the bin directory in your path. To compile with qpdf, just add
|
||||
the lib directory to your library path and the include directory to
|
||||
your include path. If you are going to use Pl_DCT in your code, you
|
||||
will also need to have jpeg library development files in your build
|
||||
environment. Detailed documentation may be found in the doc directory.
|
||||
|
||||
Enjoy!
|
|
@ -1,107 +0,0 @@
|
|||
Common Setup
|
||||
============
|
||||
|
||||
You may need to disable antivirus software to run qpdf's test suite. Running Windows Defender on Windows 10 does not interfere with building or running qpdf or its test suite.
|
||||
|
||||
To be able to build qpdf and run its test suite, you must have MSYS2 installed. This replaces the old process of having a mixture of msys, mingw-w64, and ActiveState perl. It is now possible to do everything with just MSYS2.
|
||||
|
||||
Here's what I did on my system:
|
||||
|
||||
* Download msys2 (64-bit) from msys2.org
|
||||
* Run the installer.
|
||||
* Run msys2_shell.cmd by allowing the installer to start it.
|
||||
* From the prompt:
|
||||
* Run `pacman -Syuu` and follow the instructions, which may tell you
|
||||
to close the window and rerun the command multiple times.
|
||||
* `pacman -S make base-devel git zip unzip`
|
||||
* `pacman -S mingw-w64-x86_64-toolchain mingw-w64-i686-toolchain`
|
||||
|
||||
If you would like to build with Microsoft Visual C++, install a suitable Microsoft Visual Studio edition. In early 2016, 2015 community edition with C++ support is fine. It may crash a few times during installation, but repeating the installation will allow it to finish, and the resulting software is stable.
|
||||
|
||||
To build qpdf with Visual Studio, start the msys2 mingw32 or mingw64 shell from a command window started from one of the Visual Studio shell windows. You must use the mingw shell for the same word size (32 or 64 bit) as the Windows compiler since the MSVC build uses objdump from the msys distribution. You must also have it inherit the path. For example:
|
||||
|
||||
* Start x64 native tools command prompt from msvc
|
||||
* `set MSYS2_PATH_TYPE=inherit`
|
||||
* `C:\msys64\mingw64`
|
||||
|
||||
Image comparison tests are disabled by default, but it is possible to run them on Windows. To do so, add `--enable-test-compare-images` from the configure statements given below and install some additional third-party dependencies. These may be provided in an environment such as MSYS or Cygwin or can be downloaded separately for other environments. You may extract or install the following software into separate folders each and add the `bin` folder to your `PATH` environment variable to make executables and DLLs available. If installers are provided, they might do that already by default.
|
||||
|
||||
* [LibJpeg](http://gnuwin32.sourceforge.net/packages/jpeg.htm): This archive provides some needed DLLs needed by LibTiff.
|
||||
* [LibTiff](http://gnuwin32.sourceforge.net/packages/tiff.htm): This archive provides some needed binaries and DLLs if you want to use the image comparison tests. It depends on some DLLs from LibJpeg.
|
||||
* [GhostScript](http://www.ghostscript.com/download/gsdnld.html): GhostScript is needed for image comparison tests. It's important that the binary is available as `gs`, while its default name is `gswin32[c].exe`. You can either copy one of the original files, use `mklink` to create a hard/softlink, or provide a custom `gs.cmd` wrapper that forwards all arguments to one of the original binaries. Using `mklink` with `gswin32c.exe` is probably the best choice.
|
||||
|
||||
# External Libraries
|
||||
|
||||
In order to build qpdf, you must have a copy of `zlib` and the `jpeg` library. The easy way to get it is to download the external libs from the qpdf download area. There are packages called `external-libs-bin.zip` and `external-libs-src.zip`. If you are building with MSVC 2015 or MINGW with MSYS2, you can just extract the `qpdf-external-libs-bin.zip` zip file into the top-level qpdf source tree. Note that you need the 2017-08-21 version (at least) to build qpdf 7.0 or greater since this includes jpeg. Passing `--enable-external-libs` to `./configure` (which is done automatically if you follow the instructions below) is sufficient to find them.
|
||||
|
||||
You can also obtain `zlib` and `jpeg` directly on your own and install them. If you are using mingw, you can just set `CPPFLAGS`, `LDFLAGS`, and `LIBS` when you run ./configure so that it can find the header files and libraries. If you are building with MSVC and you want to do this, it probably won't work because `./configure` doesn't know how to interpret `LDFLAGS` and `LIBS` properly for MSVC (though qpdf's own build system does). In this case, you can probably get away with cheating by passing `--enable-external-libs` to `./configure` and then just editing `CPPFLAGS`, `LDFLAGS`, `LIBS` in the generated autoconf.mk file. Note that you should use UNIX-like syntax (`-I`, `-L`, `-l`) even though this is not what cl takes on the command line. qpdf's build rules will fix it.
|
||||
|
||||
You can also download `qpdf-external-libs-src.zip` and follow the instructions in the README.txt there for how to build external libs.
|
||||
|
||||
# Building from version control
|
||||
|
||||
If you check out qpdf from version control, documentation files will not be generated or installed. Documentation files are included in the source distribution, but they can only be built from Linux.
|
||||
|
||||
# Building with MinGW
|
||||
|
||||
QPDF is known to build and pass its test suite with MSYS2 using the 32-bit and 64-bit compilers. MSYS2 is required to build as well in order to get make and other related tools. See common setup at the top of this file for installation and configuration of MSYS2. Then, from the suitable 32-bit or 64-bit environment, run
|
||||
|
||||
```
|
||||
./config-mingw
|
||||
make
|
||||
```
|
||||
|
||||
Note that `./config-mingw` just runs `./configure` with specific arguments, so you can look at it, make adjustments, and manually run configure instead.
|
||||
|
||||
Add the absolute path to the `libqpdf/build` directory to your `PATH`. Make sure you can run the qpdf command by typing qpdf/build/qpdf and making sure you get a help message rather than an error loading the DLL or no output at all. Run the test suite by typing
|
||||
|
||||
```
|
||||
make check
|
||||
```
|
||||
|
||||
If all goes well, you should get a passing test suite.
|
||||
|
||||
To create an installation directory, run `make install`. This will create `install-mingw/qpdf-VERSION` and populate it. The binary download of qpdf for Windows with mingw is created from this directory.
|
||||
|
||||
You can also take a look at `make_windows_releases` for reference. This is how the distributed Windows executables are created.
|
||||
|
||||
# Building with MSVC 2015
|
||||
|
||||
These instructions would likely work with newer versions of MSVC and are known to have worked with versions as old as 2008 Express.
|
||||
|
||||
You should first set up your environment to be able to run MSVC from the command line. There is usually a batch file included with MSVC that does this. Make sure that you start a command line environment configured for whichever of 32-bit or 64-bit output that you intend to build for.
|
||||
|
||||
From that cmd prompt, you can start your MSYS2 shell with path inheritance as described above.
|
||||
|
||||
Configure and build as follows:
|
||||
|
||||
```
|
||||
./config-msvc
|
||||
make
|
||||
```
|
||||
|
||||
Note that `./config-msvc` just runs `./configure` with specific arguments, so you can look at it, make adjustments, and manually run configure instead.
|
||||
|
||||
NOTE: automated dependencies are not generated with the msvc build. If you're planning on making modifications, you should probably work with mingw. If there is a need, I can add dependency information to the msvc build, but since I only use it for generating release versions, I haven't bothered.
|
||||
|
||||
Once built, add the full path to the `libqpdf/build` directory to your path and run
|
||||
|
||||
```
|
||||
make check
|
||||
```
|
||||
|
||||
to run the test suite.
|
||||
|
||||
If you are building with MSVC and want to debug a crash in MSVC's debugger, first start an instance of Visual C++. Then run qpdf. When the abort/retry/ignore dialog pops up, first attach the process from within visual C++, and then click Retry in qpdf.
|
||||
|
||||
A release version of qpdf is built by default. If you want to link against debugging libraries, you will have to change `/MD` to `/MDd` in `make/msvc.mk`. Note that you must redistribute the Microsoft runtime DLLs. Linking with static runtime (`/MT`) won't work; see "Static Runtime" below for details.
|
||||
|
||||
# Runtime DLLs
|
||||
|
||||
Both build methods create executables and DLLs that are dependent on the compiler's runtime DLLs. When you run make install, the installation process will automatically detect the DLLs and copy them into the installation bin directory. Look at the `copy_dlls` script for details on how this is accomplished.
|
||||
|
||||
Redistribution of the runtime DLL is unavoidable as of this writing; see "Static Runtime" below for details.
|
||||
|
||||
# Static Runtime
|
||||
|
||||
Building the DLL and executables with static runtime does not work with either Visual C++ .NET 2008 (a.k.a. vc9) using `/MT` or with mingw (at least as of 4.4.0) using `-static-libgcc`. The reason is that, in both cases, there is static data involved with exception handling, and when the runtime is linked in statically, exceptions cannot be thrown across the DLL to EXE boundary. Since qpdf uses exception handling extensively for error handling, we have no choice but to redistribute the C++ runtime DLLs. Maybe this will be addressed in a future version of the compilers. This has not been retested with the toolchain versions used to create qpdf >= 3.0 distributions. This has not been revisited since MSVC 2008, but redistributing runtime DLLs is extremely common and should not be a problem.
|
106
README.md
106
README.md
|
@ -1,106 +0,0 @@
|
|||
# QPDF
|
||||
|
||||
[![QPDF](logo/qpdf.svg)](http://qpdf.sourceforge.net)
|
||||
|
||||
[![Azure Pipeline Build Status](https://dev.azure.com/qpdf/qpdf/_apis/build/status/qpdf.qpdf)](https://dev.azure.com/qpdf/qpdf/_build/latest?definitionId=5) [![Travis Build Status](https://travis-ci.org/qpdf/qpdf.svg?branch=master)](https://travis-ci.org/qpdf/qpdf)
|
||||
|
||||
This is the QPDF package. Information about it can be found at http://qpdf.sourceforge.net. The source code repository is hosted at GitHub: https://github.com/qpdf/qpdf.
|
||||
|
||||
# Verifying Distributions
|
||||
|
||||
The public key used to sign qpdf source distributions has fingerprint `C2C9 6B10 011F E009 E6D1 DF82 8A75 D109 9801 2C7E` and can be found at https://q.ql.org/pubkey.asc or downloaded from a public key server.
|
||||
|
||||
# Copyright, License
|
||||
|
||||
QPDF is copyright (c) 2005-2020 Jay Berkenbilt
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
You may also see the license in the file [LICENSE.txt](LICENSE.txt) in the source distribution.
|
||||
|
||||
Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic License. At your option, you may continue to consider qpdf to be licensed under those terms. Please see the manual for additional information. The Artistic License appears in the file [Artistic-2.0](Artistic-2.0) in the source distribution.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
QPDF requires a C++ compiler that supports C++-11.
|
||||
|
||||
QPDF depends on the external libraries [zlib](https://www.zlib.net/) and [jpeg](https://www.ijg.org/files/). The [libjpeg-turbo](https://libjpeg-turbo.org/) library is also known to work since it is compatible with the regular jpeg library, and QPDF doesn't use any interfaces that aren't present in the straight jpeg8 API. These are part of every Linux distribution and are readily available. Download information appears in the documentation. For Windows, you can download pre-built binary versions of these libraries for some compilers; see [README-windows.md](README-windows.md) for additional details.
|
||||
|
||||
If the optional GnuTLS crypto provider is enabled,
|
||||
then [GnuTLS](https://www.gnutls.org/) is also required. This is
|
||||
discussed more in `Crypto providers` below.
|
||||
|
||||
# Licensing terms of embedded software
|
||||
|
||||
QPDF makes use of zlib and jpeg libraries for its functionality. These packages can be downloaded separately from their own download locations, or they can be downloaded in the external-libs area of the qpdf download site. If the optional GnuTLS crypto provider is enabled, then GnuTLS is also required.
|
||||
|
||||
Please see the [NOTICE](NOTICE.md) file for information on licenses of embedded software.
|
||||
|
||||
# Crypto providers
|
||||
|
||||
As of version 9.1.0, qpdf can use different crypto implementations. These can be selected at compile time or at runtime. The native crypto implementations that were used in all versions prior to 9.1.0 are still present and enabled by default.
|
||||
|
||||
Initially, the following providers are available:
|
||||
* `native`: a native implementation where all the source is embedded in qpdf and no external dependencies are required
|
||||
* `gnutls`: an implementation that uses the GnuTLS library to provide crypto; causes libqpdf to link with the GnuTLS library
|
||||
|
||||
The default behavior is for ./configure to discover which other crypto providers can be supported based on available external libraries, to build all available crypto providers, and to use an external provider as the default over the native one. This behavior can be changed with the following flags to ./configure:
|
||||
|
||||
* `--enable-crypto-x` -- (where `x` is a supported crypto provider): enable the `x` crypto provider, requiring any external dependencies it needs
|
||||
* `--disable-crypto-x` -- disable the `x` provider, and do not link against its dependencies even if they are available
|
||||
* `--with-default-crypto=x` -- make `x` the default provider even if a higher priority one is available
|
||||
* `--disable-implicit-crypto` -- only build crypto providers that are explicitly requested with an `--enable-crypto-x` option
|
||||
|
||||
For example, if you want to guarantee that the GnuTLS crypto provider is used, you could run ./configure with `--enable-crypto-gnutls --disable-implicit-crypto`.
|
||||
|
||||
Please see the section on crypto providers in the manual for more details.
|
||||
|
||||
# Building from a pristine checkout
|
||||
|
||||
When building qpdf from a pristine checkout from version control, generated documentation files are not present. You may either generate them (by passing `--enable-doc-maintenance` to `./configure` and satisfying the extra build-time dependencies) or obtain them from a released source package, which includes them. If you want to grab just the files that are in the source distribution but not in the repository, extract a source distribution in a temporary directory, and run `make CLEAN=1 distfiles.zip`. This will create a file called `distfiles.zip`, which can you can extract in a checkout of the source repository. This step is optional unless you are running make install and want the html and PDF versions of the documentation to be installed.
|
||||
|
||||
# Building from source distribution on UNIX/Linux
|
||||
|
||||
For UNIX and UNIX-like systems, you can usually get by with just
|
||||
|
||||
```
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
Packagers may set DESTDIR, in which case make install will install inside of DESTDIR, as is customary with many packages. For more detailed general information, see the "INSTALL" file in this directory. If you are already accustomed to building and installing software that uses autoconf, there's nothing new for you in the INSTALL file. Note that qpdf uses `autoconf` but not `automake`. We have our own system of Makefiles that allows cross-directory dependencies, doesn't use recursive make, and works better on non-UNIX platforms.
|
||||
|
||||
# Building on Windows
|
||||
|
||||
QPDF is known to build and pass its test suite with mingw (latest version tested: gcc 7.2.0), mingw64 (latest version tested: 7.2.0) and Microsoft Visual C++ 2015, both 32-bit and 64-bit versions. MSYS2 is required to build as well in order to get make and other related tools. See [README-windows.md](README-windows.md) for details on how to build under Windows.
|
||||
|
||||
# Additional Notes on Build
|
||||
|
||||
QPDF's build system, inspired by [abuild](https://www.qbilt.org/abuild), can optionally use its own built-in rules rather than using libtool and obeying the compiler specified with configure. This can be enabled by passing `--with-buildrules=buildrules` where buildrules corresponds to one of the `.mk` files (other than `rules.mk`) in the make directory. This should never be necessary on a UNIX system, but may be necessary on a Windows system. See [README-windows.md](README-windows.md) for details.
|
||||
|
||||
The QPDF package provides some executables and a software library. A user manual can be found in the "doc" directory. The docbook sources to the user manual can be found in the `manual` directory.
|
||||
|
||||
The software library is just `libqpdf`, and all the header files are in the `qpdf` subdirectories of `include` and `libqpdf`. If you link statically with `-lqpdf`, then you will also need to link with `-lz` and `-ljpeg`. The shared qpdf library is linked with `-lz` and `-ljpeg`, none of qpdf's public header files directly include files from `libz`, and only `Pl_DCT.hh` includes files from `libjpeg`, so for most cases, qpdf's development files are self contained. If you need to use `Pl_DCT` in your application code, you will need to have the header files for some libjpeg distribution in your include path.
|
||||
|
||||
To learn about using the library, please read comments in the header files in `include/qpdf`, especially `QPDF.hh`, `QPDFObjectHandle.hh`, and
|
||||
`QPDFWriter.hh`. These are the best sources of documentation on the API. You can also study the code of `qpdf/qpdf.cc`, which exercises most of the public interface. There are additional example programs in the examples directory. Reading all the source files in the `qpdf` directory (including the qpdf command-line tool and some test drivers) along with the code in the examples directory will give you a complete picture of every aspect of the public interface.
|
||||
|
||||
# Additional Notes on Test Suite
|
||||
|
||||
By default, slow tests and tests that require dependencies beyond those needed to build qpdf are disabled. Slow tests include image comparison tests and large file tests. Image comparison tests can be enabled by passing `--enable-test-compare-images` to ./configure. This was on by default in qpdf versions prior to 3.0, but is now off by default. Large file tests can be enabled by passing `--with-large-file-test-path=path` to `./configure` or by setting the `QPDF_LARGE_FILE_TEST_PATH` environment variable. On Windows, this should be a Windows path. Run `./configure --help` for additional options. The test suite provides nearly full coverage even without these tests. Unless you are making deep changes to the library that would impact the contents of the generated PDF files or testing this on a new platform for the first time, there is no real reason to run these tests. If you're just running the test suite to make sure that qpdf works for your build, the default tests are adequate. The configure rules for these tests do nothing other than setting variables in `autoconf.mk`, so you can feel free to turn these on and off directly in `autoconf.mk` rather than rerunning configure.
|
||||
|
||||
If you are packaging qpdf for a distribution and preparing a build that is run by an autobuilder, you may want to add the `--enable-show-failed-test-output` to configure options. This way, if the test suite fails, test failure detail will be included in the build output. Otherwise, you will have to have access to the `qtest.log` file from the build to view test failures. The Debian packages for qpdf enable this option.
|
||||
|
||||
# Random Number Generation
|
||||
|
||||
By default, when `qpdf` detects either the Windows cryptography API or the existence of `/dev/urandom`, `/dev/arandom`, or `/dev/random`, it uses them to generate cryptography secure random numbers. If none of these conditions are true, the build will fail with an error. This behavior can be modified in several ways:
|
||||
* If you configure with `--disable-os-secure-random` or define `SKIP_OS_SECURE_RANDOM`, qpdf will not attempt to use Windows cryptography or the random device. You must either supply your own random data provider or allow use of insecure random numbers.
|
||||
* If you configure qpdf with the `--enable-insecure-random` option or define `USE_INSECURE_RANDOM`, qpdf will try insecure random numbers if OS-provided secure random numbers are disabled. This is not a fallback. In order for insecure random numbers to be used, you must also disable OS secure random numbers since, otherwise, failure to find OS secure random numbers is a compile error. The insecure random number source is stdlib's `random()` or `rand()` calls. These random numbers are not cryptography secure, but the qpdf library is fully functional using them. Using non-secure random numbers means that it's easier in some cases to guess encryption keys. If you're not generating encrypted files, there's no advantage to using secure random numbers.
|
||||
* In all cases, you may supply your own random data provider. To do this, derive a class from `qpdf/RandomDataProvider` (since version 5.1.0) and call `QUtil::setRandomDataProvider` before you create any `QPDF` objects. If you supply your own random data provider, it will always be used even if support for one of the other random data providers is compiled in. If you wish to avoid any possibility of your build of qpdf from using anything but a user-supplied random data provider, you can define `SKIP_OS_SECURE_RANDOM` and not `USE_INSECURE_RANDOM`. In this case, qpdf will throw a runtime error if any attempt is made to generate random numbers and no random data provider has been supplied.
|
||||
|
||||
If you are building qpdf on a platform that qpdf doesn't know how to generate secure random numbers on, a patch would be welcome.
|
410
TODO
410
TODO
|
@ -1,410 +0,0 @@
|
|||
Fuzz Errors
|
||||
===========
|
||||
|
||||
* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=<N>
|
||||
|
||||
* To fix:
|
||||
* 19253 - indirect leaks. Not sure of the cause, but it might have
|
||||
something to do with multiple instances of the same object being
|
||||
read and discarded during file recovery. Maybe there's a missing
|
||||
call to releaseResolved.
|
||||
|
||||
* Ignoring these:
|
||||
* Problems inside the jpeg library: 15470, 15751, 18633, 18732, 18745
|
||||
* Timeout: 15471, 17630
|
||||
|
||||
ABI Changes
|
||||
===========
|
||||
|
||||
This is a list of changes to make next time there is an ABI change.
|
||||
Comments appear in the code prefixed by "ABI"
|
||||
|
||||
* QPDFPageObjectHelper::placeFormXObject: name should be std::string
|
||||
const& (issue #374)
|
||||
|
||||
* (Source compatibility) As somewhat discussed in issue 219, the
|
||||
original pipeStreamData in QPDF_Stream has various logic for
|
||||
reporting warnings and letting the caller retry. This logic is not
|
||||
implemented for stream data providers. When copying foreign streams,
|
||||
qpdf uses a stream data provider (QPDF::CopiedStreamDataProvider) to
|
||||
read the stream data from the original file. While a warning is
|
||||
issued for that case, there is no way to actually propagate failure
|
||||
information back through because
|
||||
StreamDataProvider::provideStreamData doesn't take the
|
||||
suppress_warnings or will_retry options, and adding them would break
|
||||
source compatibility.
|
||||
|
||||
C++-11
|
||||
======
|
||||
|
||||
* My c++11 branch adds re-implements PointerHolder so that it is
|
||||
interchangeable with std::shared_ptr. It is not actually possible to
|
||||
just replace PointerHolder with std::shared_ptr for two reasons:
|
||||
there is no automatic creation of std::shared_ptr<T> from T* like
|
||||
there is for PointerHolder, which breaks some code, and also there
|
||||
is no automatic conversion from something like
|
||||
std::vector<PointerHolder<T>> to std::vector<std::shared_ptr<T>>. It
|
||||
may be a good idea to replace PointerHolder with std::shared_ptr in
|
||||
the API even if it requires some work for the developer, but even if
|
||||
that isn't worth it, we should find all occurrences of PointerHolder
|
||||
within the code and replace with std::shared_ptr or std::unique_ptr
|
||||
as needed. This will definitely break binary compatibility as the
|
||||
PointerHolder<Members> pattern is part of the ABI for almost every
|
||||
class.
|
||||
|
||||
* QIntC.hh could be simplified with type_traits.
|
||||
|
||||
* Search for ::iterator and ::const_iterator and replace with either
|
||||
auto or foreach-style iteration.
|
||||
|
||||
* There may be some places where std::function and lambdas can
|
||||
simplify handlers rather than using classes with apply methods.
|
||||
|
||||
* Find places where we declare but don't define copy and assignment
|
||||
and replace with deleted methods to move errors from link to compile
|
||||
time.
|
||||
|
||||
|
||||
Page splitting/merging
|
||||
======================
|
||||
|
||||
* Update page splitting and merging to handle document-level
|
||||
constructs with page impact such as interactive forms and article
|
||||
threading. Check keys in the document catalog for others, such as
|
||||
outlines, page labels, thumbnails, and zones. For threads,
|
||||
Subramanyam provided a test file; see ../misc/article-threads.pdf.
|
||||
Email Q-Count: 431864 from 2009-11-03.
|
||||
|
||||
* bookmarks (outlines) 12.3.3
|
||||
* support bookmarks when merging
|
||||
* prune bookmarks that don't point to a surviving page when merging
|
||||
or splitting
|
||||
* make sure conflicting named destinations work possibly test by
|
||||
including the same file by two paths in a merge
|
||||
* see also comments in issue 343
|
||||
|
||||
Note: original implementation of bookmark preservation for split
|
||||
pages caused a very high performance hit. The problem was
|
||||
introduced in 313ba081265f69ac9a0324f9fe87087c72918191 and reverted
|
||||
in the commit that adds this paragraph. The revert includes marking
|
||||
a few tests cases as $td->EXPECT_FAILURE. When properly coded, the
|
||||
test cases will need to be adjusted to only include the parts of
|
||||
the outlines that are actually copied. The tests in question are
|
||||
"split page with outlines". When implementing properly, ensure that
|
||||
the performance is not adversely affected by timing split-pages on
|
||||
a large file with complex outlines such as the PDF specification.
|
||||
|
||||
When pruning outlines, keep all outlines in the hierarchy that are
|
||||
above an outline for a page we care about. If one of the ancestor
|
||||
outlines points to a non-existent page, clear its dest. If an
|
||||
outline does not have any children that point to pages in the
|
||||
document, just omit it.
|
||||
|
||||
Possible strategy:
|
||||
* resolve all named destinations to explicit destinations
|
||||
* concatenate top-level outlines
|
||||
* prune outlines whose dests don't point to a valid page
|
||||
* recompute all /Count fields
|
||||
|
||||
Test files
|
||||
* page-labels-and-outlines.pdf: old file with both page labels and
|
||||
outlines. All destinations are explicit destinations. Each page
|
||||
has Potato and a number. All titles are feline names.
|
||||
* outlines-with-actions.pdf: mixture of explicit destinations,
|
||||
named destinations, goto actions with explicit destinations, and
|
||||
goto actions with named destinations; uses /Dests key in names
|
||||
dictionary. Each page has Salad and a number. All titles are
|
||||
silly words. One destination is an indirect object.
|
||||
* outlines-with-old-root-dests.pdf: like outlines-with-actions
|
||||
except it uses the PDF-1.1 /Dests dictionary for named
|
||||
destinations, and each page has Soup and a number. Also pages are
|
||||
numbered with upper-case Roman numerals starting with 0. All
|
||||
titles are silly words preceded by a bullet.
|
||||
|
||||
If outline handling is significantly improved, see
|
||||
../misc/bad-outlines/bad-outlines.pdf and email:
|
||||
https://mail.google.com/mail/u/0/#search/rfc822msgid%3A02aa01d3d013%249f766990%24de633cb0%24%40mono.hr)
|
||||
|
||||
* Form fields: should be similar to outlines.
|
||||
|
||||
MSVC Wildcard Expansion
|
||||
=======================
|
||||
|
||||
(This section is referenced in azure_pipelines.yml.)
|
||||
|
||||
The qpdf executable built with msvc is linked with setargv.obj or
|
||||
wsetargv.obj so that wildcard expansion works. It doesn't work exactly
|
||||
the way a UNIX system would work in that the program itself does the
|
||||
expansion (rather than the shell), which means that invoking qpdf.exe
|
||||
as built by msvc will expand "*.pdf" just as it will expand *.pdf. In
|
||||
some earlier versions, wildcard expansion didn't work with the msvc
|
||||
executable. The way to make this work appears to be different in some
|
||||
versions of MSVC than in others. As such, if upgrading MSVC or
|
||||
changing the build environment, the wildcard expansion behavior of the
|
||||
qpdf executable in Windows should be retested manually.
|
||||
|
||||
Unfortunately, there is no automated test for wildcard expansion with
|
||||
MSVC because I can't figure out how to prevent qtest from expanding
|
||||
the wildcards before passing them in, and explicitly running "cmd /c
|
||||
..." from qtest doesn't seem to work in Azure Pipelines, though I can
|
||||
make it work locally.
|
||||
|
||||
Ideally, we should figure out a way to test this in CI by having a
|
||||
test that fails if wildcard expansion is broken. In the absence of
|
||||
this, it will be necessary to test the behavior manually in both mingw
|
||||
and msvc when run from cmd and from msys bash.
|
||||
|
||||
General
|
||||
=======
|
||||
|
||||
NOTE: Some items in this list refer to files in my personal home
|
||||
directory or that are otherwise not publicly accessible. This includes
|
||||
things sent to me by email that are specifically not public. Even so,
|
||||
I find it useful to make reference to them in this list
|
||||
|
||||
* Add support for writing name and number trees
|
||||
|
||||
* Figure out how to render Gajić correctly in the PDF version of the
|
||||
qpdf manual.
|
||||
|
||||
* Consider creating a PPA for Ubuntu
|
||||
|
||||
* Investigate whether there is a way to automate the memory checker
|
||||
tests for Windows.
|
||||
|
||||
* Support user-pluggable stream filters. This would enable external
|
||||
code to provide interpretation for filters that are missing from
|
||||
qpdf. Make it possible for user-provided filters to override
|
||||
built-in filters. Make sure that the pluggable filters can be
|
||||
prioritized so that we can poll all registered filters to see
|
||||
whether they are capable of filtering a particular stream.
|
||||
|
||||
* If possible, consider adding CCITT3, CCITT4, or any other easy
|
||||
filters. For some reference code that we probably can't use but may
|
||||
be handy anyway, see
|
||||
http://partners.adobe.com/public/developer/ps/sdk/index_archive.html
|
||||
|
||||
* If possible, support the following types of broken files:
|
||||
|
||||
- Files that have no whitespace token after "endobj" such that
|
||||
endobj collides with the start of the next object
|
||||
|
||||
- See ../misc/broken-files
|
||||
|
||||
* Additional form features
|
||||
* set value from CLI? Specify title, and provide way to
|
||||
disambiguate, probably by giving objgen of field
|
||||
|
||||
* replace mode: --replace-object, --replace-stream-raw,
|
||||
--replace-stream-filtered
|
||||
* update first paragraph of QPDF JSON in the manual to mention this
|
||||
* object numbers are not preserved by write, so object ID lookup
|
||||
has to be done separately for each invocation
|
||||
* you don't have to specify length for streams
|
||||
* you only have to specify filtering for streams if providing raw data
|
||||
|
||||
* Pl_TIFFPredictor is pretty slow.
|
||||
|
||||
* Support for handling file names with Unicode characters in Windows
|
||||
is incomplete. qpdf seems to support them okay from a functionality
|
||||
standpoint, and the right thing happens if you pass in UTF-8
|
||||
encoded filenames to QPDF library routines in Windows (they are
|
||||
converted internally to wchar_t*), but file names are encoded in
|
||||
UTF-8 on output, which doesn't produce nice error messages or
|
||||
output on Windows in some cases.
|
||||
|
||||
* If we ever wanted to do anything more with character encoding, see
|
||||
../misc/character-encoding/, which includes machine-readable dump
|
||||
of table D.2 in the ISO-32000 PDF spec. This shows the mapping
|
||||
between Unicode, StandardEncoding, WinAnsiEncoding,
|
||||
MacRomanEncoding, and PDFDocEncoding.
|
||||
|
||||
* Some test cases on bad files fail because qpdf is unable to find
|
||||
the root dictionary when it fails to read the trailer. Recovery
|
||||
could find the root dictionary and even the info dictionary in
|
||||
other ways. In particular, issue-202.pdf can be opened by evince,
|
||||
and there's no real reason that qpdf couldn't be made to be able to
|
||||
recover that file as well.
|
||||
|
||||
* Audit every place where qpdf allocates memory to see whether there
|
||||
are cases where malicious inputs could cause qpdf to attempt to
|
||||
grab very large amounts of memory. Certainly there are cases like
|
||||
this, such as if a very highly compressed, very large image stream
|
||||
is requested in a buffer. Hopefully normal input to output
|
||||
filtering doesn't ever try to do this. QPDFWriter should be checked
|
||||
carefully too. See also bugs/private/from-email-663916/
|
||||
|
||||
* Interactive form modification:
|
||||
https://github.com/qpdf/qpdf/issues/213 contains a good discussion
|
||||
of some ideas for adding methods to modify annotations and form
|
||||
fields if we want to make it easier to support modifications to
|
||||
interactive forms. Some of the ideas have been implemented, and
|
||||
some of the probably never will be implemented, but it's worth a
|
||||
read if there is an intention to work on this. In the issue, search
|
||||
for "Regarding write functionality", and read that comment and the
|
||||
responses to it.
|
||||
|
||||
* Look at ~/Q/pdf-collection/forms-from-appian/
|
||||
|
||||
* Consider adding "uninstall" target to makefile. It should only
|
||||
uninstall what it installed, which means that you must run
|
||||
uninstall from the version you ran install with. It would only be
|
||||
supported for the toolchains that support the install target
|
||||
(libtool).
|
||||
|
||||
* Provide support in QPDFWriter for writing incremental updates.
|
||||
Provide support in qpdf for preserving incremental updates. The
|
||||
goal should be that QDF mode should be fully functional for files
|
||||
with incremental updates including fix_qdf.
|
||||
|
||||
Note that there's nothing that says an indirect object in one
|
||||
update can't refer to an object that doesn't appear until a later
|
||||
update. This means that QPDF has to treat indirect null objects
|
||||
differently from how it does now. QPDF drops indirect null objects
|
||||
that appear as members of arrays or dictionaries. For arrays, it's
|
||||
handled in QPDFWriter where we make indirect nulls direct. This is
|
||||
in a single if block, and nothing else in the code cares about it.
|
||||
We could just remove that if block and not break anything except a
|
||||
few test cases that exercise the current behavior. For
|
||||
dictionaries, it's more complicated. In this case,
|
||||
QPDF_Dictionary::getKeys() ignores all keys with null values, and
|
||||
hasKey() returns false for keys that have null values. We would
|
||||
probably want to make QPDF_Dictionary able to handle the special
|
||||
case of keys that are indirect nulls and basically never have it
|
||||
drop any keys that are indirect objects.
|
||||
|
||||
If we make a change to have qpdf preserve indirect references to
|
||||
null objects, we have to note this in ChangeLog and in the release
|
||||
notes since this will change output files. We did this before when
|
||||
we stopped flattening scalar references, so this is probably not a
|
||||
big deal. We also have to make sure that the testing for this
|
||||
handles non-trivial cases of the targets of indirect nulls being
|
||||
replaced by real objects in an update. I'm not sure how this plays
|
||||
with linearization, if at all. For cases where incremental updates
|
||||
are not being preserved as incremental updates and where the data
|
||||
is being folded in (as is always the case with qpdf now), none of
|
||||
this should make any difference in the actual semantics of the
|
||||
files.
|
||||
|
||||
* When decrypting files with /R=6, hash_V5 is called more than once
|
||||
with the same inputs. Caching the results or refactoring to reduce
|
||||
the number of identical calls could improve performance for
|
||||
workloads that involve processing large numbers of small files.
|
||||
|
||||
* Consider adding a method to balance the pages tree. It would call
|
||||
pushInheritedAttributesToPage, construct a pages tree from scratch,
|
||||
and replace the /Pages key of the root dictionary with the new
|
||||
tree.
|
||||
|
||||
* Secure random number generation could be made more efficient by
|
||||
using a local static to ensure a single random device or crypt
|
||||
provider as long as this can be done in a thread-safe fashion. In
|
||||
the initial implementation, this is being skipped to avoid having
|
||||
to add any dependencies on threading libraries.
|
||||
|
||||
* Study what's required to support savable forms that can be saved by
|
||||
Adobe Reader. Does this require actually signing the document with
|
||||
an Adobe private key? Search for "Digital signatures" in the PDF
|
||||
spec, and look at ~/Q/pdf-collection/form-with-full-save.pdf, which
|
||||
came from Adobe's example site. See also
|
||||
../misc/digital-sign-from-trueroad/. If digital signatures are
|
||||
implemented, update the docs on crypto providers, which mention
|
||||
that this may happen in the future.
|
||||
|
||||
* See if we can avoid preserving unreferenced objects in object
|
||||
streams even when preserving the object streams.
|
||||
|
||||
* Provide APIs for embedded files. See *attachments*.pdf in test
|
||||
suite. The private method findAttachmentStreams finds at least
|
||||
cases for modern versions of Adobe Reader (>= 1.7, maybe earlier).
|
||||
PDF Reference 1.7 section 3.10, "File Specifications", discusses
|
||||
this.
|
||||
|
||||
A sourceforge user asks if qpdf can handle extracting and embedded
|
||||
resources and references these tools, which may be useful as a
|
||||
reference.
|
||||
|
||||
http://multivalent.sourceforge.net/Tools/pdf/Extract.html
|
||||
http://multivalent.sourceforge.net/Tools/pdf/Embed.html
|
||||
|
||||
* The description of Crypt filters is unclear with respect to how to
|
||||
use them to override /StmF for specific streams. I'm not sure
|
||||
whether qpdf will do the right thing for any specific individual
|
||||
streams that might have crypt filters, but I believe it does based
|
||||
on my testing of a limited subset. The specification seems to imply
|
||||
that only embedded file streams and metadata streams can have crypt
|
||||
filters, and there are already special cases in the code to handle
|
||||
those. Most likely, it won't be a problem, but someday someone may
|
||||
find a file that qpdf doesn't work on because of crypt filters.
|
||||
There is an example in the spec of using a crypt filter on a
|
||||
metadata stream.
|
||||
|
||||
For now, we notice /Crypt filters and decode parameters consistent
|
||||
with the example in the PDF specification, and the right thing
|
||||
happens for metadata filters that happen to be uncompressed or
|
||||
otherwise compressed in a way we can filter. This should handle
|
||||
all normal cases, but it's more or less just a guess since I don't
|
||||
have any test files that actually use stream-specific crypt filters
|
||||
in them.
|
||||
|
||||
* The second xref stream for linearized files has to be padded only
|
||||
because we need file_size as computed in pass 1 to be accurate. If
|
||||
we were not allowing writing to a pipe, we could seek back to the
|
||||
beginning and fill in the value of /L in the linearization
|
||||
dictionary as an optimization to alleviate the need for this
|
||||
padding. Doing so would require us to pad the /L value
|
||||
individually and also to save the file descriptor and determine
|
||||
whether it's seekable. This is probably not worth bothering with.
|
||||
|
||||
* The whole xref handling code in the QPDF object allows the same
|
||||
object with more than one generation to coexist, but a lot of logic
|
||||
assumes this isn't the case. Anything that creates mappings only
|
||||
with the object number and not the generation is this way,
|
||||
including most of the interaction between QPDFWriter and QPDF. If
|
||||
we wanted to allow the same object with more than one generation to
|
||||
coexist, which I'm not sure is allowed, we could fix this by
|
||||
changing xref_table. Alternatively, we could detect and disallow
|
||||
that case. In fact, it appears that Adobe reader and other PDF
|
||||
viewing software silently ignores objects of this type, so this is
|
||||
probably not a big deal.
|
||||
|
||||
* Based on an idea suggested by user "Atom Smasher", consider
|
||||
providing some mechanism to recover earlier versions of a file
|
||||
embedded prior to appended sections.
|
||||
|
||||
* From a suggestion in bug 3152169, consider having an option to
|
||||
re-encode inline images with an ASCII encoding.
|
||||
|
||||
* From github issue 2, provide more in-depth output for examining
|
||||
hint stream contents. Consider adding on option to provide a
|
||||
human-readable dump of linearization hint tables. This should
|
||||
include improving the 'overflow reading bit stream' message as
|
||||
reported in issue #2. There are multiple calls to stopOnError in
|
||||
the linearization checking code. Ideally, these should not
|
||||
terminate checking. It would require re-acquiring an understanding
|
||||
of all that code to make the checks more robust. In particular,
|
||||
it's hard to look at the code and quickly determine what is a true
|
||||
logic error and what could happen because of malformed user input.
|
||||
See also ../misc/linearization-errors.
|
||||
|
||||
* If I ever decide to make appearance stream-generation aware of
|
||||
fonts or font metrics, see email from Tobias with Message-ID
|
||||
<5C3C9C6C.8000102@thax.hardliners.org> dated 2019-01-14.
|
||||
|
||||
* Consider creating a sanitizer to make it easier for people to send
|
||||
broken files. Now that we have json mode, this is probably no
|
||||
longer worth doing. Here is the previous idea, possibly implemented
|
||||
by making it possible to run the lexer (tokenizer) over a whole
|
||||
file. Make it possible to replace all strings in a file lexically
|
||||
even on badly broken files. Ideally this should work files that are
|
||||
lacking xref, have broken links, etc., and ideally it should work
|
||||
with encrypted files if possible. This should go through the
|
||||
streams and strings and replace them with fixed or random
|
||||
characters, preferably, but not necessarily, in a manner that works
|
||||
with fonts. One possibility would be to detect whether a string
|
||||
contains characters with normal encoding, and if so, use 0x41. If
|
||||
the string uses character maps, use 0x01. The output should
|
||||
otherwise be unrelated to the input. This could be built after the
|
||||
filtering and tokenizer rewrite and should be done in a manner that
|
||||
takes advantage of the other lexical features. This sanitizer
|
||||
should also clear metadata and replace images.
|
|
@ -1,22 +0,0 @@
|
|||
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||
m4_include([m4/ax_cxx_compile_stdcxx.m4])
|
||||
m4_include([m4/ax_random_device.m4])
|
||||
m4_include([m4/libtool.m4])
|
||||
m4_include([m4/ltoptions.m4])
|
||||
m4_include([m4/ltsugar.m4])
|
||||
m4_include([m4/ltversion.m4])
|
||||
m4_include([m4/lt~obsolete.m4])
|
||||
m4_include([m4/pkg.m4])
|
550
appimage/AppRun
550
appimage/AppRun
|
@ -1,550 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2017 Simon Peter (@probonopd)
|
||||
# Copyright (c) 2018 Kurt Pfeifle (@pdfkungfoo)
|
||||
#
|
||||
# License: MIT
|
||||
#
|
||||
# The purpose of this custom AppRun script is to enable symlinking the
|
||||
# AppImage and invoking the corresponding binary depending on which
|
||||
# symlink name was used to invoke the AppImage.
|
||||
#
|
||||
# At the same time it also allows to invoke the embedded binaries as
|
||||
# 'sub-commands'. This is in the interest of saving users from
|
||||
# creating extra symlinks (without preventing others from STILL using
|
||||
# such, should they want or need these).
|
||||
#
|
||||
# It also provides some additional help parameters in order to allow
|
||||
# faster familiarization with functionality embedded in this AppImage.
|
||||
# For example it support the listing and viewing of embedded manpages,
|
||||
# HTML files, PDF files, licenses and READMEs.
|
||||
#
|
||||
# Note, the AppImage can be renamed to anything what's 'legal' for an
|
||||
# executable name under Linux or used via a symlink under any name and
|
||||
# it should behave like 'qpdf' is expected to behave. If the symlink
|
||||
# name is 'fix-qdf' or 'zlib-flate' it should behave like these...
|
||||
|
||||
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||
|
||||
# Set APPDIR and ARGV0 when running directly from the AppDir.
|
||||
# Running from the AppDir can be beneficial when debugging the
|
||||
# AppImage (or give performance improvements):
|
||||
if [ -z $APPDIR ]; then
|
||||
APPDIR="$HERE"
|
||||
ARGV0="$0"
|
||||
fi
|
||||
|
||||
# This is a semi-secret environment variable which can be set for
|
||||
# debugging the AppImage. For now it is only meant for temporary use
|
||||
# and may be removed again in the near future once things have
|
||||
# settled:
|
||||
if [ "x$SET_BASH_X_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
set -x
|
||||
else
|
||||
set +x
|
||||
fi
|
||||
|
||||
# Another semi-secret environment var:
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
env | less
|
||||
fi
|
||||
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPIMAGE" == "xYeSS" ] ; then
|
||||
env | grep --color -E '(APPIMAGE|APPDIR|APP|ARGV0|HERE)'
|
||||
fi
|
||||
|
||||
|
||||
function usage() {
|
||||
echo "
|
||||
--------------------------------------------------------------------------
|
||||
All QPDF command line functionality inside an AppImage package.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
(This package uses the AppImage software packaging technology for
|
||||
Linux ['One App == One File'] for easy availability of the newest
|
||||
QPDF releases across all major Linux distributions.)
|
||||
|
||||
Usage:
|
||||
------
|
||||
|
||||
$ARGV0 --help
|
||||
# Show help screen of QPDF itself
|
||||
|
||||
$ARGV0 --ai-usage
|
||||
# This message (it's only present in the AppImage
|
||||
# incarnation of QPDF)
|
||||
|
||||
$ARGV0 qpdf|fix-qdf|zlib-flate
|
||||
# Run the named sub-command; not available if the AppImage
|
||||
# is invoked as one of the embedded executables
|
||||
|
||||
$ARGV0 --list-exe
|
||||
# List all executables embedded in AppImage
|
||||
|
||||
$ARGV0 --list-man
|
||||
# List available, embedded manual pages
|
||||
|
||||
$ARGV0 --man qpdf|zlib-flate|fix-qdf
|
||||
# Display embedded manual page(s)
|
||||
|
||||
$ARGV0 --list-html
|
||||
# List all HTML documents embedded in AppImage
|
||||
|
||||
$ARGV0 --html <path/to/file>
|
||||
# Use browser to show HTML file embedded in AppImage
|
||||
# (for list of available HTML files see \"$ARGV0 --list-html\")
|
||||
|
||||
$ARGV0 --list-pdf
|
||||
# List all PDF documents embedded in AppImage
|
||||
|
||||
$ARGV0 --pdf <path/to/file>
|
||||
# Use system default PDF viewer to display embedded PDF
|
||||
# document(s)
|
||||
# (for list of available PDF files see \"$ARGV0 --list-pdf\")
|
||||
|
||||
$ARGV0 --list-readme
|
||||
# List all READMEs embedded in AppImage
|
||||
|
||||
$ARGV0 --readme <path/to/readme>
|
||||
# Show content of README embedded in AppImage
|
||||
# (for list of available READMEs see \"$ARGV0 --list-readme\")
|
||||
|
||||
$ARGV0 --list-license
|
||||
# List all LICENSE files embedded in AppImage
|
||||
|
||||
$ARGV0 --license <name-of-license>
|
||||
# Show content of LICENSE file embedded in AppImage
|
||||
# (piped thru 'less -N')
|
||||
|
||||
$ARGV0 --show-apprun|--self-show|--selfshow
|
||||
# Show 'AppRun' invoked by 'less -N'; type '-N' to toggle
|
||||
# line number display
|
||||
|
||||
$ARGV0 --appimage-help
|
||||
# Show AppImage options available for all 'type 2' AppImages
|
||||
|
||||
$ARGV0 --help
|
||||
# Show help screen of QPDF itself
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
NOTE: The execution of this AppImage is controlled by a custom AppRun
|
||||
script. The state of this script is experimental and preliminary.
|
||||
Hence it may not work as expected, or miss some functionality. You
|
||||
can hack on this script by unpacking this AppImage into a local
|
||||
subdirectory [currently named 'squashfs-root'] with this command:
|
||||
|
||||
$ARGV0 --appimage-extract
|
||||
|
||||
After you're done with your hacks, repackage the AppImage again with
|
||||
this command:
|
||||
|
||||
appimagetool [/path/to/]squashfs-root [/path/to/]QPDF-*.AppImage
|
||||
|
||||
Latest versions of tools provided by AppImageKit are always available from
|
||||
* https://github.com/AppImage/AppImageKit/releases/ and
|
||||
* https://github.com/AppImage/AppImageUpdate/releases/ and
|
||||
* https://github.com/AppImage/zsync2/releases and
|
||||
* https://github.com/probonopd/linuxdeployqt/releases/
|
||||
------------------------------------------------------------------------------
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
function mimetype() {
|
||||
case "$#" in
|
||||
1)
|
||||
# 'file --mime-type some-foo-file.ext' usually returns: 'some-foo-file.ext: major/minor', on stderr...
|
||||
# However, we want to get back only 'major/minor', on stdout!
|
||||
file --mime-type "$1" 2>&1 | sed 's#'"$1"':##;s# ##'
|
||||
;;
|
||||
0)
|
||||
echo "" 1>&2
|
||||
echo " # This is a Bash function, named \"$FUNCNAME\"." 1>&2
|
||||
echo " # You cannot run it without an argument. If you run it with a" 1>&2
|
||||
echo " # [path to a] file as a single argument, it simply returns the" 1>&2
|
||||
echo " # 'major/minor' MIME type. If you add multiple [paths to] files" 1>&2
|
||||
echo " # as arguments, it returns a list of 'major/minor' MIME types with" 1>&2
|
||||
echo " # the respective file names prepended. Example usage:" 1>&2
|
||||
echo " #" 1>&2
|
||||
echo " # $> $FUNCNAME /path/to/a.pdf" 1>&2
|
||||
echo " #" 1>&2
|
||||
echo " # $> $FUNCNAME /path/to/a.txt ./myscript.sh ../some.txt" 1>&2
|
||||
echo " #" 1>&2
|
||||
echo " # This Bash function's source code is this:" 1>&2
|
||||
echo "" 1>&2
|
||||
typeset -f "${FUNCNAME}" 1>&2
|
||||
echo "" 1>&2
|
||||
;;
|
||||
*)
|
||||
file --mime-type "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
if [ x"$1" == "xshow-apprun" -o \
|
||||
x"$1" == "x--show-apprun" -o \
|
||||
x"$1" == "x--apprunshow" -o \
|
||||
x"$1" == "x--apprun-show" -o \
|
||||
x"$1" == "xselfshow" -o \
|
||||
x"$1" == "x--selfshow" -o \
|
||||
x"$1" == "xself-show" -o \
|
||||
x"$1" == "x--self-show" -o \
|
||||
x"$1" == "x--show-self" -o \
|
||||
x"$1" == "x--showself" -o \
|
||||
x"$1" == "xshow-self" -o \
|
||||
x"$1" == "xshowself" ] ; then
|
||||
cd "$HERE"
|
||||
less -N AppRun
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlistlicense" -o \
|
||||
x"$1" == "x--listlicense" -o \
|
||||
x"$1" == "xlist-license" -o \
|
||||
x"$1" == "x--list-license" -o \
|
||||
x"$1" == "x--licenselist" -o \
|
||||
x"$1" == "x--license-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This will then display the respective license file:"
|
||||
echo ""
|
||||
find . -type f -name "*LICENSE*" -o -name "*license*" | sed 's#^./# --license #'
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xai-usage" -o \
|
||||
x"$1" == "x--aiusage" -o \
|
||||
x"$1" == "x--ai-usage" ]; then
|
||||
usage | less
|
||||
#usage
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlistman" -o \
|
||||
x"$1" == "x--listman" -o \
|
||||
x"$1" == "xlist-man" -o \
|
||||
x"$1" == "x--list-man" -o \
|
||||
x"$1" == "x--manlist" -o \
|
||||
x"$1" == "x--man-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This will then open the respective manual page:"
|
||||
echo ""
|
||||
find usr/share/man* -type f | sed 's#^# --man #'
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlistexe" -o \
|
||||
x"$1" == "x--listexe" -o \
|
||||
x"$1" == "xlist-exe" -o \
|
||||
x"$1" == "x--list-exe" -o \
|
||||
x"$1" == "x--exelist" -o \
|
||||
x"$1" == "x--exe-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This would run the respective exe as a 'sub-command':"
|
||||
echo ""
|
||||
find . \( \( -type f -o -type l -o -type s -o -type p \) -a -executable \) | grep '/bin/' | grep -v qpdf | sed 's#./usr/bin/# #' | sort -V | grep -v ".sh$"
|
||||
echo ""
|
||||
find . \( \( -type f -o -type l -o -type s -o -type p \) -a -executable \) | grep '/bin/' | grep -v qpdf | sed 's#./usr/bin/# #' | sort -V | grep ".sh$"
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlistreadme" -o \
|
||||
x"$1" == "x--listreadme" -o \
|
||||
x"$1" == "xlist-readme" -o \
|
||||
x"$1" == "x--list-readme" -o \
|
||||
x"$1" == "x--readmelist" -o \
|
||||
x"$1" == "x--readme-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This will then display the respective README file:"
|
||||
echo ""
|
||||
find . -type f -iname "*README*" -o -iname "*.txt" -o -iname "*.md" -o -iname "*copyright*" -o -iname "*changelog*" -o -iname "*todo*" | sed 's#^./# --readme #'
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlisthtml" -o \
|
||||
x"$1" == "x--listhtml" -o \
|
||||
x"$1" == "xlist-html" -o \
|
||||
x"$1" == "x--list-html" -o \
|
||||
x"$1" == "x--htmllist" -o \
|
||||
x"$1" == "x--html-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This will then open the respective HTML file in your preferred browser:"
|
||||
echo ""
|
||||
find . -type f -name "*.html" | sed 's#^./# --html #'
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlistpdf" -o \
|
||||
x"$1" == "x--listpdf" -o \
|
||||
x"$1" == "xlist-pdf" -o \
|
||||
x"$1" == "x--list-pdf" -o \
|
||||
x"$1" == "x--pdflist" -o \
|
||||
x"$1" == "x--pdf-list" ] ; then
|
||||
cd "$HERE"
|
||||
echo ""
|
||||
echo "You may invoke \"$ARGV0\" with one of the following additional arguments."
|
||||
echo "This will then open the respective PDF file in your preferred viewer program:"
|
||||
echo ""
|
||||
find . -type f -name "*.pdf" | sed 's#^./# --pdf #'
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xreadme" -o \
|
||||
x"$1" == "x--readme" ] ; then
|
||||
cd "$HERE"
|
||||
shift
|
||||
echo ""
|
||||
if [ x"$1" == "x" ] ; then
|
||||
echo " You must give a path to the README you want to open."
|
||||
echo " For available READMEs run \"$ARGV0 --listreadme\"."
|
||||
else
|
||||
readmefile=$( find . -type f -iname "*README*" -o -iname "*.txt" -o -iname "*.md" -o -iname "*copyright*" -o -iname "*changelog*" | grep "${1}" | sort -rV | head -n 1 )
|
||||
MIME=$(mimetype $readmefile)
|
||||
case $MIME in
|
||||
text/html|application/pdf|application/epub*)
|
||||
xdg-open "$readmefile"
|
||||
sleep 3 # sleep to allow slow xdg-open do its job
|
||||
;;
|
||||
inode/x-empty)
|
||||
echo ""
|
||||
echo " Sorry, this file, \"$readmefile\", is empty and has no content."
|
||||
echo ""
|
||||
;;
|
||||
text/*)
|
||||
less -N "$readmefile"
|
||||
;;
|
||||
esac
|
||||
sleep 0
|
||||
fi
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xlicense" -o \
|
||||
x"$1" == "x--license" ] ; then
|
||||
cd "$HERE"
|
||||
shift
|
||||
echo ""
|
||||
if [ x"$1" == "x" ] ; then
|
||||
echo " You must give a path to the LICENSE you want to open."
|
||||
echo " For available LICENSE run \"$ARGV0 --list-license\"."
|
||||
else
|
||||
licensefile=$( find . -type f -iname "*LICENSE*" | grep "${1}" | sort -rV | head -n 1 )
|
||||
#if PDF or EPUB or HTML ; then xdg-open $licensefile ; else
|
||||
MIME=$(mimetype $licensefile)
|
||||
case $MIME in
|
||||
text/html|application/pdf|application/epub*)
|
||||
xdg-open "$licensefile"
|
||||
sleep 3 # sleep to allow slow xdg-open do its job
|
||||
;;
|
||||
inode/x-empty)
|
||||
echo ""
|
||||
echo " Sorry, this file, \"$licensefile\", is empty and has no content."
|
||||
echo ""
|
||||
;;
|
||||
text/*)
|
||||
less -N "$licensefile"
|
||||
;;
|
||||
esac
|
||||
sleep 0
|
||||
fi
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xman" -o x"$1" == "x--man" ] ; then
|
||||
export MANPATH="$HERE/usr/share/man:$MANPATH"
|
||||
shift
|
||||
exec man "$@" || man $(basename $1)
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xpdf" -o x"$1" == "x--pdf" ] ; then
|
||||
cd "$HERE"
|
||||
shift
|
||||
echo ""
|
||||
if [ x"$1" == "x" ] ; then
|
||||
echo ""
|
||||
echo " You must give a path to the PDF file you want to open."
|
||||
echo " For available PDFs run \"$ARGV0 --list-pdf\""
|
||||
echo ""
|
||||
else
|
||||
pdffile=$( find . -type f -name "*.pdf" | grep "${1/.pdf/}.pdf" | sort -rV | head -n 1 )
|
||||
xdg-open "$pdffile"
|
||||
sleep 5
|
||||
fi
|
||||
echo ""
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "xhtml" -o x"$1" == "x--html" ] ; then
|
||||
cd "$HERE"
|
||||
shift
|
||||
if [ x"$1" == "x" ] ; then
|
||||
echo ""
|
||||
echo " You must give a path to the HTML file you want to open."
|
||||
echo " For available HTMLs run \"$ARGV0 --list-html\""
|
||||
echo ""
|
||||
else
|
||||
htmlfile=$( find . -type f -name "*.html" | grep "${1}" | sort -rV | head -n 1 )
|
||||
xdg-open "$htmlfile"
|
||||
sleep 5
|
||||
fi
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$1" == "x--appimage-help" ] ; then
|
||||
cd "$HERE"
|
||||
shift
|
||||
if [ x"$APPIMAGE" == "x" ] ; then
|
||||
echo ""
|
||||
echo " The parameter '--appimage-help' does not work if you run this application from an AppDir (as you do)."
|
||||
echo " To create an AppImage from your AppDir run this command:"
|
||||
echo ""
|
||||
echo " appimagetool -n $APPDIR qpdf.AppImage"
|
||||
echo ""
|
||||
echo " You can download the latest version of 'appimagetool' (as an AppImage) from here:"
|
||||
echo ""
|
||||
echo " https://github.com/AppImage/AppImageKit/releases"
|
||||
echo ""
|
||||
fi
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into output of qpdf|fix-qdf|zlib-flate which goes to stdout!
|
||||
echo ARGV0=$ARGV0 1>&2 # Don't leak strings into output of qpdf|fix-qdf|zlib-flate which goes to stdout!
|
||||
echo dollar0=$0 1>&2 # Don't leak strings into output of qpdf|fix-qdf|zlib-flate which goes to stdout!
|
||||
echo dollar1=$1 1>&2 # Don't leak strings into output of qpdf|fix-qdf|zlib-flate which goes to stdout!
|
||||
echo dollar_at="$@" 1>&2 # Don't leak strings into output of qpdf|fix-qdf|zlib-flate which goes to stdout!
|
||||
fi
|
||||
|
||||
|
||||
### Main stuff happens from here:
|
||||
if [ ! -z $APPIMAGE ] ; then
|
||||
# We run as an AppImage
|
||||
BINARY_NAME=$(basename "$ARGV0")
|
||||
APPIMAGE=$APPIMAGE
|
||||
CALLED_SUBCMD=$( basename $1 2>/dev/null )
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into output of qpdf|fix-pdf|zlib-flate going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into output of qpdf|fix-pdf|zlib-flate going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into output of qpdf|fix-pdf|zlib-flate going to stdout!
|
||||
fi
|
||||
|
||||
if [ -x "$HERE/usr/bin/$BINARY_NAME" ] && [ x"$BINARY_NAME" != "x" ] ; then
|
||||
# We are invoked from a symlink (like 'fix-qdf' or 'zlib-flate')
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
shift
|
||||
exec "$HERE/usr/bin/$BINARY_NAME" "$@"
|
||||
|
||||
else
|
||||
if [ -x "$HERE/usr/bin/$CALLED_SUBCMD" ] && [ x"$CALLED_SUBCMD" != "x" ] ; then
|
||||
# We are invoked by a (currently not yet known future) binary name which may be located in ./usr/bin/ ...
|
||||
BINARY_NAME=$1
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
shift
|
||||
exec "$HERE/usr/bin/$BINARY_NAME" "$@"
|
||||
elif [ -x "$HERE/$CALLED_SUBCMD" ] && [ x"$CALLED_SUBCMD" != "x" ] ; then
|
||||
# We are invoked by a (currently not yet known future) binary name which may be located in our root AppDir ...
|
||||
BINARY_NAME=$CALLED_SUBCMD
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
shift
|
||||
exec "$HERE/$BINARY_NAME" "$@"
|
||||
else
|
||||
# this clause may not be necessary...
|
||||
exec "$HERE/usr/bin/qpdf" "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
# Most likely we run from an AppDir, not as an AppImage:
|
||||
BINARY_NAME=$(basename "$ARGV0")
|
||||
APPIMAGE=$APPIMAGE
|
||||
CALLED_SUBCMD=$( basename $1 2>/dev/null )
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
|
||||
if [ -x "$HERE/usr/bin/$CALLED_SUBCMD" ] && [ "x$CALLED_SUBCMD" != "x" ]; then
|
||||
#echo before shift dollar_at=$@
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
shift
|
||||
#echo after shift dollar_at=$@
|
||||
#echo CALLED_SUBCMD=$CALLED_SUBCMD
|
||||
exec "$HERE/usr/bin/$CALLED_SUBCMD" "$@"
|
||||
|
||||
elif [ -x "$HERE/usr/bin/$BINARY_NAME" ] && [ "x$BINARY_NAME" != "x" ] ; then
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
shift
|
||||
exec "$HERE/usr/bin/$BINARY_NAME" "$@"
|
||||
|
||||
else
|
||||
if [ "x$SET_SHOW_ENV_FOR_APPRUN" == "xYeSS" ] ; then
|
||||
# We have the (hidden) env var for debugging stuff set
|
||||
echo BINARY_NAME=$BINARY_NAME 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo APPIMAGE=$APPIMAGE 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
echo CALLED_SUBCMD=$CALLED_SUBCMD 1>&2 # Don't leak strings into qpdf|fix-pdf|zlib-flate output going to stdout!
|
||||
fi
|
||||
exec "$HERE/usr/bin/qpdf" "$@"
|
||||
fi
|
||||
|
||||
fi
|
|
@ -1,11 +0,0 @@
|
|||
FROM ubuntu:16.04
|
||||
RUN apt-get update && \
|
||||
apt-get -y install screen autoconf git sudo \
|
||||
build-essential zlib1g-dev libjpeg-dev libgnutls28-dev \
|
||||
docbook-xsl fop xsltproc \
|
||||
inkscape imagemagick busybox-static wget fuse && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
COPY entrypoint /entrypoint
|
||||
RUN chmod +x /entrypoint
|
||||
ENTRYPOINT [ "/entrypoint" ]
|
|
@ -1,206 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2019-2020 Jay Berkenbilt and Kurt Pfeifle
|
||||
#
|
||||
# This script is mainly meant to build an 'AppImage' from GitHub
|
||||
# sources of QPDF via Travis CI on an Ubuntu Trusty (14.04) LTS system
|
||||
# (see https://appimage.org/).
|
||||
#
|
||||
# But it also allows Linux users to build such an AppImage on their
|
||||
# own systems. Please read 'README.md' from the top level Git sources
|
||||
# to see what preconditions you must meet to build QPDF in general.
|
||||
# The same apply to build an AppImage. Then follow these three steps:
|
||||
#
|
||||
# 1. Clone Git sources: `git clone https://github.com/qpdf/qpdf.git git.qpdf`
|
||||
# 2. Change into git dir: `cd git.qpdf`
|
||||
# 3. Run this script: `bash appimage/build-appimage`
|
||||
#
|
||||
# The resulting AppImage will be placed in
|
||||
# './appimage/build/QPDF-x86_64.AppImage'. Read the output of the
|
||||
# script for hints in case something goes wrong.
|
||||
#
|
||||
# You may pass custom options for the configure step by setting them
|
||||
# into the 'CUSTOM_CONFIGURE' environment variable and exporting it
|
||||
# before running this script. For example:
|
||||
#
|
||||
# export CUSTOM_CONFIGURE=" --enable-test-compare-images [--more-other-options]"
|
||||
#
|
||||
# ATTENTION:
|
||||
#
|
||||
# 1. To build the AppImage you should have a working internet
|
||||
# connection. Reason: the script downloads the most recent
|
||||
# 'linuxdeployqt' utility for building the AppImage.
|
||||
# 2. If you build the AppImage on a too recent Linux distribution,
|
||||
# it may only work on the exact distribution you build it on. For
|
||||
# an AppImage to work on a wide range of different distributions
|
||||
# from the last 3-4 years if should be built on Ubuntu Trusty
|
||||
# (14.04).
|
||||
|
||||
set -ex
|
||||
|
||||
# Support for signing the AppImage (only by original maintainer):
|
||||
sign=
|
||||
if [ "x$1" == "x--sign" ]; then
|
||||
sign=--sign
|
||||
fi
|
||||
|
||||
|
||||
# Check if we are on Ubuntu Trusty
|
||||
_osversion=$(cat /etc/os-release | grep PRETTY_NAME | awk -F'=' '{print $2}' | sed 's#"##g')
|
||||
|
||||
# Warn users building the AppImage locally:
|
||||
if [[ ! $_osversion =~ Ubuntu\ 16.04.*\ LTS ]]; then
|
||||
set +x
|
||||
echo ""
|
||||
# 0 1 2 3 4 5 6 7
|
||||
# 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
echo "+===========================================================================+"
|
||||
echo "|| WARNING: You are about to build a QPDF AppImage on a system which is ||"
|
||||
echo "|| NOT Ubuntu 16.04 LTS ('Xenial'). ||"
|
||||
echo "|| ||"
|
||||
echo "|| It is recommended that you use a distribution that is at least a ||"
|
||||
echo "|| few years old to maximize the number of Linux distributions the ||"
|
||||
echo "|| resulting AppImage will work on. AppImages often don't work on ||"
|
||||
echo "|| distributions older than the one they were built on because of ||"
|
||||
echo "|| standard library differences. ||"
|
||||
echo "+===========================================================================+"
|
||||
echo ""
|
||||
set -x
|
||||
fi
|
||||
|
||||
|
||||
# From where do we run this script?
|
||||
here="$(dirname $(readlink -f "$0"))"
|
||||
top=$(dirname $here)
|
||||
|
||||
# Move to root of GitHub sources:
|
||||
cd $top
|
||||
|
||||
# Set 'appdir' environment variable name:
|
||||
appdir=$here/build/appdir
|
||||
|
||||
# Clean up stuff from previous build attempts:
|
||||
rm -rf $here/build
|
||||
|
||||
# Prepare build of QPDF from sources:
|
||||
./configure --prefix=/usr --enable-werror \
|
||||
--enable-crypto-gnutls --disable-implicit-crypto \
|
||||
--enable-show-failed-test-output \
|
||||
--enable-html-doc --enable-pdf-doc "$CUSTOM_CONFIGURE"
|
||||
|
||||
# Build!
|
||||
make -j$(nproc)
|
||||
|
||||
if [ "$SKIP_TESTS" = "" ]; then
|
||||
# Run built-in QPDF checks:
|
||||
make -k check
|
||||
fi
|
||||
|
||||
# Prepare AppDir which is the basis for the AppImage:
|
||||
mkdir -p $appdir
|
||||
|
||||
# Install build result into AppDir:
|
||||
make install DESTDIR=$appdir; find $appdir
|
||||
|
||||
# Change into build directory:
|
||||
cd $here/build
|
||||
|
||||
# Don't bundle developer stuff
|
||||
rm -rf appdir/usr/include appdir/usr/lib/pkgconfig appdir/usr/lib/*.{a,la,so}
|
||||
|
||||
# Copy icon which is needed for desktop integration into place:
|
||||
for width in 64 128 256 512; do
|
||||
dir=appdir/usr/share/icons/hicolor/${width}x${width}/apps
|
||||
mkdir -p $dir
|
||||
inkscape -z -e qpdf-tmp.png -w $width -b white $top/logo/qpdf.svg
|
||||
convert qpdf-tmp.png -gravity center -background white -extent ${width}x${width} $dir/qpdf.png
|
||||
rm qpdf-tmp.png
|
||||
done
|
||||
|
||||
# Copy .desktop and .appdata.xml metadata for desktop integration into place:
|
||||
for i in appdir/usr/share/applications; do
|
||||
mkdir -p $i
|
||||
cp $top/appimage/qpdf.desktop $i
|
||||
done
|
||||
for i in appdir/usr/share/metainfo; do
|
||||
mkdir -p $i
|
||||
cp $top/appimage/qpdf.appdata.xml $i
|
||||
done
|
||||
for i in appdir/usr/share/doc/qpdf; do
|
||||
mkdir -p $i
|
||||
cp $top/README* $i
|
||||
cp $top/NOTICE.md $i/README-notice.md
|
||||
cp $top/LICENSE.txt $i
|
||||
cp $top/Artistic-2.0 $i/Artistic-LICENSE.txt
|
||||
cp $top/ChangeLog $i/README-ChangeLog
|
||||
cp $top/TODO $i/README-todo
|
||||
done
|
||||
|
||||
# The following lines are experimental (for debugging; and to test
|
||||
# support for unexpected future binaries added to QPDF):
|
||||
for i in /usr/bin/env /bin/less /bin/busybox; do
|
||||
cp $i appdir/usr/bin/
|
||||
done
|
||||
ls -l /usr/bin/env /bin/less /bin/busybox
|
||||
|
||||
# Fetch 'linuxdeployqt' which will transform the AppDir into an AppImage:
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt*.AppImage
|
||||
|
||||
# Set up a clean environment:
|
||||
unset QTDIR; unset QT_PLUGIN_PATH; unset LD_LIBRARY_PATH
|
||||
|
||||
# Let 'linuxdeployqt' do its first stage of work:
|
||||
./linuxdeployqt*.AppImage appdir/usr/share/applications/*.desktop -bundle-non-qt-libs
|
||||
|
||||
# In addition to the main executable, we have additional ones to process
|
||||
./linuxdeployqt*.AppImage appdir/usr/bin/zlib-flate -bundle-non-qt-libs
|
||||
|
||||
# To eventually generate the AppImage we extract the linuxdeployqt
|
||||
# AppImage to get access to the embedded 'appimagetool':
|
||||
./linuxdeployqt*.AppImage --appimage-extract
|
||||
|
||||
# We want to run our custom AppRun script.
|
||||
# Replace symlink with custom script
|
||||
rm appdir/AppRun; cp $top/appimage/AppRun appdir; chmod a+x appdir/AppRun
|
||||
|
||||
# If we are not on Ubuntu Trusty, we need to disable 'appstreamcli' validation:
|
||||
if [[ $_osversion =~ Ubuntu\ 14.04.*\ LTS ]]; then
|
||||
appimagetool_param=""
|
||||
else
|
||||
appimagetool_param="-n"
|
||||
set +x
|
||||
echo ""
|
||||
echo " Running 'appimagetool' with '-n' parameter..."
|
||||
echo " Reason: this does not seem to be a Travis CI build running on"
|
||||
echo " Ubuntu Trusty 14.04."
|
||||
echo " '-n' disables checking of AppStream data by the 'appstreamcli'"
|
||||
echo " utility since post-Trusty versions have incompatible changes."
|
||||
echo ""
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Set up a version string to include in the AppImage name
|
||||
MAJOR_QPDF_VERSION=$( ./appdir/usr/bin/qpdf --version | grep "qpdf version" | awk '{print $3}' )
|
||||
declare -a UPDATE_INFO
|
||||
if [ "$TRAVIS_JOB_NUMBER" != "" ]; then
|
||||
VERSION=${MAJOR_QPDF_VERSION}-continuous-${TRAVIS_JOB_NUMBER}-$(date "+%Y-%m-%d")-git.$(git rev-parse --short HEAD)
|
||||
# No update info supported for travis builds for now.
|
||||
else
|
||||
VERSION=${MAJOR_QPDF_VERSION}
|
||||
UPDATE_INFO=(-u "gh-releases-zsync|qpdf|qpdf|latest|qpdf-*x86_64.AppImage.zsync")
|
||||
fi
|
||||
|
||||
# Remove the default AppRun/symlink and use our own custom AppRun script
|
||||
rm appdir/AppRun; cp $top/appimage/AppRun appdir; chmod a+x appdir/AppRun
|
||||
|
||||
# Finally, generate the AppImage:
|
||||
PATH=./squashfs-root/usr/bin:$PATH ./squashfs-root/usr/bin/appimagetool $sign $UPDATE_FLAG ${UPDATE_INFO[*]} $appimagetool_param appdir qpdf-$VERSION-x86_64.AppImage
|
||||
|
||||
set +x
|
||||
# Tell everyone where our result is stored:
|
||||
echo ""
|
||||
echo "============================================================================="
|
||||
echo " === AppImage is ready in $top/appimage/build ==="
|
||||
echo "============================================================================="
|
||||
echo ""
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
if [ "$SKIP_TESTS" = "1" ]; then
|
||||
touch /tmp/skip-tests
|
||||
fi
|
||||
if [ $(id -u) = 0 ]; then
|
||||
if [ ! -d /tmp/build ]; then
|
||||
echo "/tmp/build must exist"
|
||||
exit 2
|
||||
fi
|
||||
id=$(stat -c %u /tmp/build)
|
||||
adduser --home /tmp/build --no-create-home --uid $id --disabled-password --gecos build build
|
||||
exec sudo -iu build $0 "$@"
|
||||
fi
|
||||
|
||||
cd /tmp/build
|
||||
if [ ! -d qpdf ]; then
|
||||
if [ "$1" == "" ]; then
|
||||
echo "A repository and optional git clone arguments must be given"
|
||||
exit 2
|
||||
fi
|
||||
git clone "$@" qpdf
|
||||
fi
|
||||
cd qpdf
|
||||
if [ -f /tmp/skip-tests ]; then
|
||||
export SKIP_TESTS=1
|
||||
fi
|
||||
./appimage/build-appimage
|
Binary file not shown.
Before Width: | Height: | Size: 596 KiB |
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2005-2020 Jay Berkenbilt -->
|
||||
<component>
|
||||
<id>org.QPDF.qpdf.desktop</id>
|
||||
<metadata_license>MIT</metadata_license>
|
||||
<project_license>Apache-2.0</project_license>
|
||||
<name>QPDF</name>
|
||||
<summary>Structural, content-preserving transformations on PDF files</summary>
|
||||
<description>
|
||||
<p> QPDF is a command-line program that does structural, content-preserving transformations on PDF files.
|
||||
It could have been called something like pdf-to-pdf.
|
||||
It also provides many useful capabilities to developers of PDF-producing software or for people
|
||||
who just want to look at the innards of a PDF file to learn more about how they work.</p>
|
||||
<p> QPDF is capable of creating linearized (also known as web-optimized) files and encrypted files.
|
||||
It is also capable of converting PDF files with object streams (also known as compressed objects)
|
||||
to files with no compressed objects or to generate object streams from files that don't have them
|
||||
(or even those that already do). QPDF also supports a special mode designed to allow you to edit
|
||||
the content of PDF files in a text editor. For more details, please see the documentation links
|
||||
below.</p>
|
||||
<p> QPDF includes support for merging and splitting PDFs through the ability to copy objects from one PDF
|
||||
file into another and to manipulate the list of pages in a PDF file. The QPDF library also makes
|
||||
it possible for you to create PDF files from scratch. In this mode, you are responsible for
|
||||
supplying all the contents of the file, while the QPDF library takes care off all the syntactical
|
||||
representation of the objects, creation of cross references tables and, if you use them, object
|
||||
streams, encryption, linearization, and other syntactic details.</p>
|
||||
<p>QPDF is not a PDF content creation library, a PDF viewer, or a program capable of converting PDF into
|
||||
other formats. In particular, QPDF knows nothing about the semantics of PDF content streams.
|
||||
If you are looking for something that can do that, you should look elsewhere.
|
||||
However, once you have a valid PDF file, QPDF can be used to transform that file in ways perhaps
|
||||
your original PDF creation can't handle. For example, programs generate simple PDF files but
|
||||
can't password-protect them, web-optimize them, or perform other transformations of that type.</p>
|
||||
</description>
|
||||
<x-launchable type="desktop-id">qpdf.desktop</x-launchable>
|
||||
<url type="homepage">http://qpdf.sourceforge.net/</url>
|
||||
<url type="bugtracker">https://github.com/qpdf/qpdf/issues</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image width="798" height="1550">https://raw.githubusercontent.com/qpdf/qpdf/master/appimage/qpdf-screenshot.jpeg</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<provides>
|
||||
<id>org.QPDF.qpdf.desktop</id>
|
||||
</provides>
|
||||
<!-- <update_contact></update_contact> -->
|
||||
</component>
|
|
@ -1,8 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Terminal=true
|
||||
Exec=qpdf
|
||||
Name=qpdf
|
||||
Comment=Structural, content-preserving transformations on PDF files
|
||||
Icon=qpdf
|
||||
Categories=Utility;
|
|
@ -1,54 +0,0 @@
|
|||
PACKAGE_TARNAME=@PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION=@PACKAGE_VERSION@
|
||||
LT_CURRENT=@LT_CURRENT@
|
||||
LT_REVISION=@LT_REVISION@
|
||||
LT_AGE=@LT_AGE@
|
||||
top_builddir=@top_builddir@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
datarootdir=@datarootdir@
|
||||
mandir=@mandir@
|
||||
docdir=@docdir@
|
||||
htmldir=@htmldir@
|
||||
pdfdir=@pdfdir
|
||||
CC=@CC@
|
||||
WFLAGS=@WFLAGS@
|
||||
CXXWFLAGS=@CXXWFLAGS@
|
||||
CFLAGS=@CFLAGS@ $(WFLAGS)
|
||||
LDFLAGS=@LDFLAGS@
|
||||
LIBS=@LIBS@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
CXX=@CXX@
|
||||
CXXFLAGS=@CXXFLAGS@ $(CXXWFLAGS) $(WFLAGS)
|
||||
AR=@AR@
|
||||
RANLIB=@RANLIB@
|
||||
DLLTOOL=@DLLTOOL@
|
||||
STRIP=@STRIP@
|
||||
OBJDUMP=@OBJDUMP@
|
||||
GENDEPS=@GENDEPS@
|
||||
LIBTOOL=@LIBTOOL@
|
||||
USE_CRYPTO_NATIVE=@USE_CRYPTO_NATIVE@
|
||||
USE_CRYPTO_GNUTLS=@USE_CRYPTO_GNUTLS@
|
||||
DOCBOOKX_DTD=@DOCBOOKX_DTD@
|
||||
FOP=@FOP@
|
||||
XSLTPROC=@XSLTPROC@
|
||||
XMLLINT=@XMLLINT@
|
||||
BUILD_HTML=@BUILD_HTML@
|
||||
BUILD_PDF=@BUILD_PDF@
|
||||
VALIDATE_DOC=@VALIDATE_DOC@
|
||||
OSS_FUZZ=@OSS_FUZZ@
|
||||
QPDF_SKIP_TEST_COMPARE_IMAGES=@QPDF_SKIP_TEST_COMPARE_IMAGES@
|
||||
BUILDRULES=@BUILDRULES@
|
||||
HAVE_LD_VERSION_SCRIPT=@HAVE_LD_VERSION_SCRIPT@
|
||||
IS_32BIT=@IS_32BIT@
|
||||
WINDOWS_WORDSIZE=@WINDOWS_WORDSIZE@
|
||||
WINDOWS_WMAIN_COMPILE=@WINDOWS_WMAIN_COMPILE@
|
||||
WINDOWS_WMAIN_LINK=@WINDOWS_WMAIN_LINK@
|
||||
WINDOWS_WMAIN_XLINK_FLAGS=@WINDOWS_WMAIN_XLINK_FLAGS@
|
||||
WINDOWS_MAIN_XLINK_FLAGS=@WINDOWS_MAIN_XLINK_FLAGS@
|
||||
SHOW_FAILED_TEST_OUTPUT=@SHOW_FAILED_TEST_OUTPUT@
|
||||
# Allow environment variable to override
|
||||
QPDF_LARGE_FILE_TEST_PATH?=@QPDF_LARGE_FILE_TEST_PATH@
|
|
@ -1,11 +0,0 @@
|
|||
4db55494bcfbd5053f956d435416f30591a59bc24b1c4f4431d0b3da27a54ef7 configure.ac
|
||||
d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4
|
||||
2e4cd495837be1b8454a4d8aef541b000988634be89d9c05a9cf5de67dffef5e libqpdf/qpdf/qpdf-config.h.in
|
||||
5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4
|
||||
35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4
|
||||
6a1e4f8aa2902d7993300660c43e6ee479b4b6781ed7d5ef9c9f9f1cc46623b7 m4/libtool.m4
|
||||
e77ebba8361b36f14b4d0927173a034b98c5d05049697a9ded84d85eb99a7990 m4/ltoptions.m4
|
||||
5a6735cda60e0ba0d1b706c0ef648f5d096298da46daefd9cdecdb6a0f4584d3 m4/ltsugar.m4
|
||||
a27b754709de61575197bf5a980696c98ae49da3f92f0de8ee7f42dd543b7465 m4/ltversion.m4
|
||||
26fa3285c35dd6ab00ed1e466ba92a17e4655e01897731ec18a587a4cf5e4f8d m4/lt~obsolete.m4
|
||||
9fab676fae13feb97d5183a8ed86ae9398c76d21927c28bc59460d230f3e0884 m4/pkg.m4
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
aclocal -I m4
|
||||
autoheader
|
||||
autoconf
|
||||
rm -f m4/*~ 2>/dev/null || true
|
||||
sha256sum configure.ac aclocal.m4 libqpdf/qpdf/qpdf-config.h.in m4/* >| autofiles.sums
|
|
@ -1,135 +0,0 @@
|
|||
jobs:
|
||||
- job: Linux
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- script: azure-pipelines/build-linux
|
||||
displayName: 'Generate, build, and test'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: '$(System.DefaultWorkingDirectory)/distfiles.zip'
|
||||
artifactName: distfiles
|
||||
displayName: 'Upload extra distribution files'
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: '$(System.DefaultWorkingDirectory)/distribution'
|
||||
artifactName: distribution
|
||||
displayName: 'Upload source distribution'
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: Linux
|
||||
buildPlatform: Linux
|
||||
- job: Windows
|
||||
pool:
|
||||
# If updating this, see note in TODO about MSVC wildcard expansion.
|
||||
vmImage: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
msvc32:
|
||||
wordsize: 32
|
||||
tool: msvc
|
||||
msvc64:
|
||||
wordsize: 64
|
||||
tool: msvc
|
||||
mingw32:
|
||||
wordsize: 32
|
||||
tool: mingw
|
||||
mingw64:
|
||||
wordsize: 64
|
||||
tool: mingw
|
||||
maxParallel: 4
|
||||
steps:
|
||||
- bash: git config --global core.autocrlf input
|
||||
displayName: 'Disable git autocrlf'
|
||||
- checkout: self
|
||||
displayName: 'Get sources'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download distribution files'
|
||||
inputs:
|
||||
artifactName: distfiles
|
||||
downloadPath: $(System.DefaultWorkingDirectory)
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- script: azure-pipelines/build-windows.bat $(wordsize) $(tool)
|
||||
displayName: 'Build, test, generate binary distributions'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: '$(System.DefaultWorkingDirectory)/distribution'
|
||||
artifactName: distribution
|
||||
displayName: 'Upload binary distributions'
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: Windows-$(wordsize)$(tool)
|
||||
buildPlatform: Windows-$(wordsize)$(tool)
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
||||
- job: macOS
|
||||
pool:
|
||||
vmImage: macOS-10.14
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download distribution files'
|
||||
inputs:
|
||||
artifactName: distfiles
|
||||
downloadPath: $(System.DefaultWorkingDirectory)
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- script: azure-pipelines/build-mac
|
||||
displayName: 'Mac build and test'
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: MacOS
|
||||
buildPlatform: MacOS
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
||||
- job: AppImage
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- script: azure-pipelines/build-appimage
|
||||
displayName: 'Build AppImage'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: '$(System.DefaultWorkingDirectory)/distribution'
|
||||
artifactName: distribution
|
||||
displayName: 'Upload AppImage'
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: AppImage
|
||||
buildPlatform: AppImage
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
||||
- job: Linux32
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- script: azure-pipelines/build-linux32
|
||||
displayName: 'Linux 32-bit'
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: Linux32
|
||||
buildPlatform: Linux32
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
||||
- job: Fuzzers
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- script: azure-pipelines/build-fuzzer
|
||||
displayName: 'Build Fuzzer'
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
||||
- job: Sanitizers
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
steps:
|
||||
- script: azure-pipelines/test-sanitizers
|
||||
displayName: 'Sanitizer Tests'
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testRunTitle: Sanitizers
|
||||
buildPlatform: Sanitizers
|
||||
dependsOn: Linux
|
||||
condition: succeeded()
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Any extra args are passed to the docker run command before the
|
||||
# invocation of qpdfbuild. This is useful for iterating locally as
|
||||
# described in README-maintainer.
|
||||
#
|
||||
set -ex
|
||||
cd appimage
|
||||
docker build -t qpdfbuild .
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd ..
|
||||
git clone .git appimage/build/qpdf
|
||||
docker run --privileged --rm \
|
||||
-v $PWD/appimage/build:/tmp/build ${1+"$@"} qpdfbuild
|
||||
rm -rf distribution
|
||||
mkdir distribution
|
||||
cp -p appimage/build/qpdf/appimage/build/qpdf*AppImage* distribution
|
||||
for i in distribution/*; do
|
||||
mv $i $(echo $i | sed -e 's/\.AppImage/-ci.AppImage/')
|
||||
done
|
||||
sha256sum distribution/*
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
export WORK=$PWD/work
|
||||
export OUT=$PWD/out
|
||||
mkdir -p $WORK $OUT
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install \
|
||||
autoconf build-essential zlib1g-dev libjpeg-dev
|
||||
./fuzz/oss-fuzz-build
|
||||
ls -l out/qpdf*fuzzer
|
||||
ls -l out/
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install \
|
||||
autoconf build-essential zlib1g-dev libjpeg-dev libgnutls28-dev \
|
||||
docbook-xsl fop xsltproc libxml2-utils inkscape imagemagick
|
||||
./configure --enable-werror --enable-doc-maintenance \
|
||||
--enable-crypto-native --enable-crypto-gnutls \
|
||||
--enable-show-failed-test-output
|
||||
make -j$(nproc) -k
|
||||
for i in $(./qpdf/build/qpdf --show-crypto); do
|
||||
echo "*** Running tests with crypto provider $i"
|
||||
env QPDF_CRYPTO_PROVIDER=$i make -k check
|
||||
done
|
||||
make distfiles.zip
|
||||
./make_dist --ci --no-tests
|
||||
mkdir distribution
|
||||
cp /tmp/qpdf*-ci.tar.gz distribution
|
||||
sha256sum distribution/*
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# dpkg --add-architecture not needed for Ubuntu 18.04
|
||||
sudo dpkg --add-architecture i386
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
# For Ubuntu 18.04:
|
||||
#
|
||||
# sudo apt-get -y install \
|
||||
# autoconf build-essential zlib1g-dev:i386 libjpeg-dev:i386 \
|
||||
# g++-multilib-i686-linux-gnu
|
||||
# ./configure --enable-werror --enable-show-failed-test-output \
|
||||
# CC=i686-linux-gnu-gcc CXX=i686-linux-gnu-g++
|
||||
|
||||
sudo apt-get -y install \
|
||||
autoconf build-essential zlib1g-dev:i386 libjpeg-dev:i386 \
|
||||
g++-multilib
|
||||
./configure --enable-werror --enable-show-failed-test-output \
|
||||
CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32
|
||||
|
||||
make -j$(nproc) -k
|
||||
make -k check
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
curl -L https://github.com/qpdf/qpdf/raw/external-libs/jpegsrc.v9c.tar.gz -o jpegsrc.v9c.tar.gz
|
||||
tar xzf jpegsrc.v9c.tar.gz
|
||||
cd jpeg-9c
|
||||
./configure
|
||||
make -k
|
||||
sudo make install
|
||||
cd ..
|
||||
if [ -f distfiles/distfiles.zip ]; then
|
||||
unzip distfiles/distfiles.zip
|
||||
fi
|
||||
./configure --enable-werror --enable-show-failed-test-output
|
||||
make -j$(nproc) -k
|
||||
make -k check
|
|
@ -1,39 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
cd $(dirname $0)/..
|
||||
wordsize=$1
|
||||
tool=$2
|
||||
|
||||
if [[ $tool == mingw ]]; then
|
||||
pacman -Sy --noconfirm make base-devel tar zip unzip
|
||||
if [[ $wordsize == 64 ]]; then
|
||||
pacman -Sy --noconfirm mingw-w64-x86_64-toolchain
|
||||
PATH="/c/tools/msys64/mingw64/bin:$PATH"
|
||||
else
|
||||
pacman -Sy --noconfirm mingw-w64-i686-toolchain
|
||||
PATH="/c/tools/msys64/mingw32/bin:$PATH"
|
||||
fi
|
||||
g++ -v
|
||||
elif [[ $tool == msvc ]]; then
|
||||
cl
|
||||
fi
|
||||
if [ -f distfiles/distfiles.zip ]; then
|
||||
unzip distfiles/distfiles.zip
|
||||
fi
|
||||
curl -L https://github.com/qpdf/qpdf/raw/external-libs/qpdf-external-libs-bin.zip -o qpdf-external-libs-bin.zip
|
||||
unzip qpdf-external-libs-bin.zip
|
||||
cwd=`pwd`
|
||||
PATH=$cwd/libqpdf/build:$PATH
|
||||
|
||||
installdir=install-$tool$wordsize
|
||||
rm -rf $installdir
|
||||
./config-$tool --enable-show-failed-test-output --disable-crypto-gnutls
|
||||
make -j$(nproc) -k
|
||||
make -k check
|
||||
make install
|
||||
|
||||
v=`(cd $installdir; ls -d qpdf-*)`
|
||||
cp -p README-windows-install.txt $installdir/$v/README.txt
|
||||
mkdir distribution
|
||||
(cd $installdir; zip -r ../distribution/$v-bin-$tool$wordsize-ci.zip $v)
|
||||
sha256sum distribution/*
|
|
@ -1,16 +0,0 @@
|
|||
@echo on
|
||||
@rem Usage: build-windows {32|64} {msvc|mingw}
|
||||
if %2 == msvc (
|
||||
if %1 == 64 (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
) else (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
|
||||
)
|
||||
choco install zip
|
||||
bash ./azure-pipelines/build-windows %1 %2
|
||||
) else (
|
||||
@rem The vs2017-win2016 pool has an ancient 64-bit-only mingw.
|
||||
@rem Install msys2 so we can get current gcc toolchains.
|
||||
choco install msys2
|
||||
C:\tools\msys64\usr\bin\env.exe MSYSTEM=MINGW64 /bin/bash -l %CD%/azure-pipelines/build-windows %1 %2
|
||||
)
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install \
|
||||
autoconf build-essential zlib1g-dev libjpeg-dev libgnutls28-dev
|
||||
./configure \
|
||||
CFLAGS="-fsanitize=address -fsanitize=undefined -g" \
|
||||
CXXFLAGS="-fsanitize=address -fsanitize=undefined -g" \
|
||||
LDFLAGS="-fsanitize=address -fsanitize=undefined" \
|
||||
--enable-crypto-native --enable-crypto-gnutls \
|
||||
--enable-werror --disable-shared --enable-show-failed-test-output
|
||||
make -j$(nproc) -k
|
||||
for i in $(./qpdf/build/qpdf --show-crypto); do
|
||||
echo "*** Running tests with crypto provider $i"
|
||||
env QPDF_CRYPTO_PROVIDER=$i make -k check
|
||||
done
|
|
@ -1,10 +0,0 @@
|
|||
These completion files may be installed in your system's vendor completion area for bash and zsh.
|
||||
|
||||
For example, on a debian-based system, you could install these as
|
||||
|
||||
```
|
||||
cp bash/qpdf /usr/share/bash-completion/completions/
|
||||
cp zsh/_qpdf /usr/share/zsh/vendor-completions/
|
||||
```
|
||||
|
||||
Packagers are encouraged to install these in whatever locations appropriate for their systems.
|
|
@ -1 +0,0 @@
|
|||
eval $(/usr/bin/qpdf --completion-bash)
|
|
@ -1,2 +0,0 @@
|
|||
#compdef qpdf
|
||||
eval $(/usr/bin/qpdf --completion-zsh)
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
set -x
|
||||
if echo $PATH | grep -q /mingw64; then
|
||||
wordsize=64
|
||||
else
|
||||
wordsize=32
|
||||
fi
|
||||
./configure --disable-test-compare-images --enable-external-libs --enable-werror --with-buildrules=mingw ${1+"$@"}
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
set -x
|
||||
if echo $PATH | grep -q /mingw64; then
|
||||
wordsize=64
|
||||
else
|
||||
wordsize=32
|
||||
fi
|
||||
CC=cl CXX="cl -TP -GR" ./configure --disable-test-compare-images --enable-external-libs --enable-werror --with-buildrules=msvc ${1+"$@"}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
818
configure.ac
818
configure.ac
|
@ -1,818 +0,0 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl This config.in requires autoconf 2.5 or greater.
|
||||
|
||||
AC_PREREQ([2.68])
|
||||
AC_INIT([qpdf],[9.1.1])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_FILES([autoconf.mk])
|
||||
AC_CONFIG_FILES([manual/html.xsl manual/print.xsl])
|
||||
AC_CONFIG_FILES([libqpdf.pc])
|
||||
AC_CONFIG_FILES([libqpdf.map])
|
||||
AC_CONFIG_HEADERS([libqpdf/qpdf/qpdf-config.h])
|
||||
|
||||
AC_ARG_ENABLE(check-autofiles,
|
||||
AS_HELP_STRING([--enable-check-autofiles],
|
||||
[if specified, verify checksums on automatically generated files (default=yes); package maintainers may want to disable this]),
|
||||
[if test "$enableval" = "no"; then
|
||||
CHECK_AUTOFILES=0
|
||||
else
|
||||
CHECK_AUTOFILES=1
|
||||
fi],
|
||||
[CHECK_AUTOFILES=1])
|
||||
|
||||
# Check to see if automatically generated files are outdated and if we
|
||||
# can update them.
|
||||
AC_CHECK_PROG(AUTOCONF,autoconf,1,0)
|
||||
AC_CHECK_PROG(AUTOHEADER,autoheader,1,0)
|
||||
AC_CHECK_PROG(ACLOCAL,aclocal,1,0)
|
||||
AC_CHECK_PROG(SHA256SUM,sha256sum,1,0)
|
||||
if test "$CHECK_AUTOFILES$AUTOCONF$AUTOHEADER$ACLOCAL$SHA256SUM" = "11111"; then
|
||||
if ! sha256sum -c autofiles.sums; then
|
||||
AC_MSG_ERROR(autofiles are outdated; rerun autogen.sh)
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
|
||||
AC_HEADER_STDC
|
||||
LT_INIT([win32-dll])
|
||||
|
||||
# * If any interfaces have been removed or changed, or if any private
|
||||
# member variables or virtual functions have been added to any
|
||||
# class, we are not binary compatible. Increment LT_CURRENT, and set
|
||||
# LT_AGE and LT_REVISION to 0.
|
||||
#
|
||||
# * Otherwise, if any interfaces have been added since the last public
|
||||
# release, then increment LT_CURRENT and LT_AGE, and set LT_REVISION
|
||||
# to 0.
|
||||
#
|
||||
# * Otherwise, increment LT_REVISION
|
||||
|
||||
# LT = libtool
|
||||
LT_CURRENT=27
|
||||
LT_AGE=1
|
||||
LT_REVISION=1
|
||||
AC_SUBST(LT_CURRENT)
|
||||
AC_SUBST(LT_REVISION)
|
||||
AC_SUBST(LT_AGE)
|
||||
LT_SONAME=$(expr $LT_CURRENT - $LT_AGE)
|
||||
AC_SUBST(LT_SONAME)
|
||||
|
||||
AC_MSG_CHECKING(for -fvisibility=hidden)
|
||||
try_flags=-fvisibility=hidden
|
||||
oCXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS $try_flags"
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[class X
|
||||
{
|
||||
public:
|
||||
__attribute__ ((visibility ("default")))
|
||||
X() {}
|
||||
__attribute__ ((visibility ("default")))
|
||||
void f() {}
|
||||
};
|
||||
]],[[X x; x.f();]])],
|
||||
[qpdf_VISIBILITY_HIDDEN=1],
|
||||
[qpdf_VISIBILITY_HIDDEN=0])
|
||||
AC_LANG_POP
|
||||
if test "$qpdf_VISIBILITY_HIDDEN" = "0"; then
|
||||
AC_MSG_RESULT(no)
|
||||
CXXFLAGS=$oCXXFLAGS
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
CFLAGS="$CFLAGS $try_flags"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(whether to use insecure random numbers)
|
||||
AC_ARG_ENABLE(insecure-random,
|
||||
AS_HELP_STRING([--enable-insecure-random],
|
||||
[whether to use stdlib's random number generator (default is no)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
qpdf_INSECURE_RANDOM=1;
|
||||
else
|
||||
qpdf_INSECURE_RANDOM=0;
|
||||
fi], [qpdf_INSECURE_RANDOM=0])
|
||||
if test "$qpdf_INSECURE_RANDOM" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([USE_INSECURE_RANDOM], [1], [Whether to use insecure random numbers])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(whether to use OS-provided secure random numbers)
|
||||
AC_ARG_ENABLE(os-secure-random,
|
||||
AS_HELP_STRING([--enable-os-secure-random],
|
||||
[whether to try to use OS-provided secure random numbers (default is yes)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
qpdf_OS_SECURE_RANDOM=1;
|
||||
else
|
||||
qpdf_OS_SECURE_RANDOM=0;
|
||||
fi], [qpdf_OS_SECURE_RANDOM=1])
|
||||
if test "$qpdf_OS_SECURE_RANDOM" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE([SKIP_OS_SECURE_RANDOM], [1], [Whether to suppress use of OS-provided secure random numbers])
|
||||
fi
|
||||
|
||||
AX_RANDOM_DEVICE
|
||||
|
||||
AC_MSG_CHECKING(whether to avoid Windows HANDLE type)
|
||||
AC_ARG_ENABLE(avoid-windows-handle,
|
||||
AS_HELP_STRING([--enable-avoid-windows-handle],
|
||||
[whether to avoid use of HANDLE, useful for some embedded Windows builds (default is no)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
qpdf_AVOID_HANDLE=1;
|
||||
else
|
||||
qpdf_AVOID_HANDLE=0;
|
||||
fi], [qpdf_AVOID_HANDLE=0])
|
||||
if test "$qpdf_AVOID_HANDLE" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([AVOID_WINDOWS_HANDLE], [1], [Whether to avoid use of HANDLE in Windows])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
USE_EXTERNAL_LIBS=0
|
||||
AC_MSG_CHECKING(for whether to use external libraries distribution)
|
||||
AC_ARG_ENABLE(external-libs,
|
||||
AS_HELP_STRING([--enable-external-libs],
|
||||
[whether to use external libraries distribution]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
USE_EXTERNAL_LIBS=1;
|
||||
else
|
||||
USE_EXTERNAL_LIBS=0;
|
||||
fi], [BUILD_INTERNAL_LIBS=0])
|
||||
if test "$BUILD_INTERNAL_LIBS" = "0"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
if test "$ac_cv_sizeof_size_t" = "4"; then
|
||||
IS_32BIT=1
|
||||
WINDOWS_WORDSIZE=32
|
||||
else
|
||||
IS_32BIT=0
|
||||
WINDOWS_WORDSIZE=64
|
||||
fi
|
||||
AC_SUBST(IS_32BIT)
|
||||
AC_SUBST(WINDOWS_WORDSIZE)
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
if test "$BUILD_INTERNAL_LIBS" = "0"; then
|
||||
if test "$PKG_CONFIG" != ""; then
|
||||
PKG_CHECK_MODULES([pc_zlib], [zlib],
|
||||
[CFLAGS="$CFLAGS $pc_zlib_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $pc_zlib_CXXFLAGS"
|
||||
LIBS="$LIBS $pc_zlib_LIBS"
|
||||
], [:])
|
||||
PKG_CHECK_MODULES([pc_libjpeg], [libjpeg],
|
||||
[CFLAGS="$CFLAGS $pc_libjpeg_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $pc_libjpeg_CXXFLAGS"
|
||||
LIBS="$LIBS $pc_libjpeg_LIBS"
|
||||
],[:])
|
||||
fi
|
||||
if test "$pc_zlib_LIBS" = ""; then
|
||||
AC_CHECK_HEADER(zlib.h,,[MISSING_ZLIB_H=1; MISSING_ANY=1])
|
||||
AC_SEARCH_LIBS(deflate,z zlib,,[MISSING_ZLIB=1; MISSING_ANY=1])
|
||||
fi
|
||||
if test "$pc_libjpeg_LIBS" = ""; then
|
||||
AC_CHECK_HEADER(jpeglib.h,,[MISSING_JPEG_H=1; MISSING_ANY=1])
|
||||
AC_SEARCH_LIBS(jpeg_destroy,jpeg,,[MISSING_JPEG=1; MISSING_ANY=1])
|
||||
fi
|
||||
if test "$LIBS" != ""; then
|
||||
nLIBS=""
|
||||
for x in $LIBS; do
|
||||
if echo $x | grep -q '^-L'; then
|
||||
LDFLAGS="$LDFLAGS $x"
|
||||
else
|
||||
nLIBS="$nLIBS $x"
|
||||
fi
|
||||
LIBS=$nLIBS
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
qpdf_USE_WMAIN=0
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_SUBST(WINDOWS_WMAIN_COMPILE)
|
||||
AC_SUBST(WINDOWS_WMAIN_LINK)
|
||||
for i in 0 1; do
|
||||
if test "$qpdf_USE_WMAIN" = "0"; then
|
||||
oLDFLAGS="$LDFLAGS"
|
||||
if test "$i" = "1"; then
|
||||
nLDFLAGS="-municode"
|
||||
LDFLAGS="$LDFLAGS $nLDFLAGS"
|
||||
msg="checking for wmain with $nLDFLAGS"
|
||||
else
|
||||
nLDFLAGS=
|
||||
msg="checking for wmain"
|
||||
fi
|
||||
AC_MSG_CHECKING($msg)
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE(
|
||||
[[#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
extern "C"
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
size_t x = wcslen(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
]])],
|
||||
[qpdf_USE_WMAIN=1],
|
||||
[qpdf_USE_WMAIN=0])
|
||||
LDFLAGS="$oLDFLAGS"
|
||||
if test "$qpdf_USE_WMAIN" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
WINDOWS_WMAIN_COMPILE="-DWINDOWS_WMAIN $nLDFLAGS"
|
||||
WINDOWS_WMAIN_LINK="$nLDFLAGS"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
done
|
||||
AC_LANG_POP
|
||||
|
||||
if test "x$qpdf_OS_SECURE_RANDOM" = "x1"; then
|
||||
OLIBS=$LIBS
|
||||
LIBS="$LIBS Advapi32.lib"
|
||||
AC_MSG_CHECKING(for Advapi32 library)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#pragma comment(lib, "crypt32.lib")
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
HCRYPTPROV cp;]],
|
||||
[CryptAcquireContext(&cp, NULL, NULL, PROV_RSA_FULL, 0);]
|
||||
)],
|
||||
[AC_MSG_RESULT(yes)
|
||||
LIBS="$OLIBS -lAdvapi32"],
|
||||
[AC_MSG_RESULT(no)
|
||||
LIBS=$OLIBS])
|
||||
fi
|
||||
|
||||
QPDF_LARGE_FILE_TEST_PATH=
|
||||
AC_SUBST(QPDF_LARGE_FILE_TEST_PATH)
|
||||
AC_ARG_WITH(large-file-test-path,
|
||||
AS_HELP_STRING([--with-large-file-test-path=path],
|
||||
[To enable testing of files > 4GB, give the path to a directory with at least 11 GB free. The test suite will write temporary files to this directory. Alternatively, just set the QPDF_LARGE_FILE_TEST_PATH environment variable to the path before running the test suite.]),
|
||||
[QPDF_LARGE_FILE_TEST_PATH=$withval],
|
||||
[QPDF_LARGE_FILE_TEST_PATH=])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
AC_FUNC_FSEEKO
|
||||
AC_CHECK_FUNCS([fseeko64])
|
||||
|
||||
AC_CHECK_FUNCS(random)
|
||||
|
||||
# Check if LD supports linker scripts, and define conditional
|
||||
# HAVE_LD_VERSION_SCRIPT if so. This functionality is currently
|
||||
# constrained to compilers using GNU ld on ELF systems or systems
|
||||
# which provide an adequate emulation thereof.
|
||||
AC_ARG_ENABLE([ld-version-script],
|
||||
AS_HELP_STRING([--enable-ld-version-script],
|
||||
[enable linker version script (default is enabled)]),
|
||||
[have_ld_version_script=$enableval], [have_ld_version_script=yes])
|
||||
if test "$have_ld_version_script" != no; then
|
||||
AC_MSG_CHECKING([if LD -Wl,--version-script works])
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
|
||||
cat > conftest.map <<EOF
|
||||
VERS_1 {
|
||||
global: sym;
|
||||
};
|
||||
|
||||
VERS_2 {
|
||||
global: sym;
|
||||
} VERS_1;
|
||||
EOF
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||
[have_ld_version_script=yes], [have_ld_version_script=no])
|
||||
rm -f conftest.map
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
AC_MSG_RESULT($have_ld_version_script)
|
||||
fi
|
||||
if test "$have_ld_version_script" = "yes"; then
|
||||
HAVE_LD_VERSION_SCRIPT=1
|
||||
else
|
||||
HAVE_LD_VERSION_SCRIPT=0
|
||||
fi
|
||||
AC_SUBST(HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
make_okay=0
|
||||
for make_prog in make gmake; do
|
||||
this_make_okay=0
|
||||
AC_MSG_CHECKING(for gnu make >= 3.81 ($make_prog))
|
||||
if $make_prog --version >/dev/null 2>&1; then
|
||||
v=`$make_prog --version | grep 'GNU Make' | sed -e 's/.*Make //'`
|
||||
maj=`echo $v | cut -d. -f 1`
|
||||
min=`echo $v | cut -d. -f 2`
|
||||
if test $maj -gt 3 -o '(' $maj -eq 3 -a $min -ge 81 ')'; then
|
||||
this_make_okay=1
|
||||
make_okay=1
|
||||
fi
|
||||
fi
|
||||
if test "$this_make_okay" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
done
|
||||
|
||||
if test "$make_okay" = "0"; then
|
||||
dnl Don't set MISSING_ANY=1 -- maybe user calls make something else
|
||||
MISSING_MAKE_381=1
|
||||
ISSUE_WARNINGS=1
|
||||
fi
|
||||
|
||||
AC_SUBST(GENDEPS)
|
||||
GENDEPS=0
|
||||
AC_MSG_CHECKING(for whether $CC supports -MD -MF x.dep -MP)
|
||||
oCFLAGS=$CFLAGS
|
||||
rm -f x.dep
|
||||
CFLAGS="$CFLAGS -MD -MF x.dep -MP"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <stdio.h>]], [[FILE* a = stdout]]
|
||||
)],
|
||||
[qpdf_DEPFLAGS=yes],
|
||||
[qpdf_DEPFLAGS=no])
|
||||
CFLAGS=$oCFLAGS
|
||||
if test "$qpdf_DEPFLAGS" = "yes"; then
|
||||
if ! grep stdio.h x.dep >/dev/null 2>&1; then
|
||||
qpdf_DEPFLAGS=no
|
||||
fi
|
||||
fi
|
||||
rm -f x.dep
|
||||
if test "$qpdf_DEPFLAGS" = "yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
GENDEPS=1
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(which build rules to use)
|
||||
AC_SUBST(BUILDRULES)
|
||||
AC_ARG_WITH(buildrules,
|
||||
AS_HELP_STRING([--with-buildrules=rules],
|
||||
[which build rules to use; see README.md]),
|
||||
[BUILDRULES=$withval],
|
||||
[BUILDRULES=libtool])
|
||||
AC_MSG_RESULT($BUILDRULES)
|
||||
|
||||
AC_SUBST(WFLAGS)
|
||||
AC_SUBST(CXXWFLAGS)
|
||||
qpdf_USE_EXTRA_WARNINGS=0
|
||||
if test "$BUILDRULES" = "msvc"; then
|
||||
dnl /w14996 makes warning 4996 a level 1 warning. This warning
|
||||
dnl reports on functions that Microsoft considers unsafe or
|
||||
dnl deprecated. Removing these warnings helps people who want to
|
||||
dnl write applications based on qpdf that can be Windows 8
|
||||
dnl certified.
|
||||
try_flags="-w14996"
|
||||
else
|
||||
try_flags="-Wall"
|
||||
fi
|
||||
AC_MSG_CHECKING(for whether $CC supports $try_flags)
|
||||
oCFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $try_flags"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[int a = 1; int b = a; a = b;]])],
|
||||
[qpdf_USE_EXTRA_WARNINGS=1],[qpdf_USE_EXTRA_WARNINGS=0])
|
||||
CFLAGS=$oCFLAGS
|
||||
if test "$qpdf_USE_EXTRA_WARNINGS" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
WFLAGS="$try_flags"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
if test "$BUILDRULES" != "msvc"; then
|
||||
qpdf_USE_EXTRA_WARNINGS=0
|
||||
try_flags="-Wold-style-cast"
|
||||
AC_MSG_CHECKING(for whether $CXX supports $try_flags)
|
||||
oCXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS $try_flags"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[int a = 1; int b = a; a = b;]])],
|
||||
[qpdf_USE_EXTRA_WARNINGS=1],[qpdf_USE_EXTRA_WARNINGS=0])
|
||||
CXXFLAGS=$oCXXFLAGS
|
||||
if test "$qpdf_USE_EXTRA_WARNINGS" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CXXWFLAGS="$try_flags"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$BUILDRULES" = "msvc"; then
|
||||
try_flags=-FS
|
||||
AC_MSG_CHECKING(for whether $CC supports $try_flags)
|
||||
oCFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $try_flags"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[int a = 1; int b = a; a = b;]])],
|
||||
[qpdf_USE_FS=1],[qpdf_USE_FS=0])
|
||||
if test "$qpdf_USE_FS" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CXXFLAGS="$CXXFLAGS $try_flags"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
CFLAGS=$oCFLAGS
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$BUILDRULES" = "msvc"; then
|
||||
try_flags="-WX"
|
||||
else
|
||||
try_flags="-Werror"
|
||||
fi
|
||||
AC_MSG_CHECKING(for whether to use $try_flags)
|
||||
AC_ARG_ENABLE(werror,
|
||||
AS_HELP_STRING([--enable-werror],
|
||||
[whether to treat warnings as errors (default is no)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
qpdf_USE_WERROR=1;
|
||||
else
|
||||
qpdf_USE_WERROR=0;
|
||||
fi], [qpdf_USE_WERROR=0])
|
||||
if test "$qpdf_USE_WERROR" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
WFLAGS="$WFLAGS $try_flags"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
if test "$BUILDRULES" = "msvc"; then
|
||||
try_flags="-W3"
|
||||
else
|
||||
try_flags="-Wconversion -Wsign-conversion"
|
||||
fi
|
||||
AC_MSG_CHECKING(for whether to use $try_flags)
|
||||
AC_ARG_ENABLE(int-warnings,
|
||||
AS_HELP_STRING([--enable-int-warnings],
|
||||
[whether to turn on integer type warnings (default is yes)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
qpdf_INT_WARNINGS=1;
|
||||
else
|
||||
qpdf_INT_WARNINGS=0;
|
||||
fi], [qpdf_INT_WARNINGS=1])
|
||||
if test "$qpdf_INT_WARNINGS" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
WFLAGS="$WFLAGS $try_flags"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(WINDOWS_WMAIN_XLINK_FLAGS)
|
||||
AC_SUBST(WINDOWS_MAIN_XLINK_FLAGS)
|
||||
if test "$BUILDRULES" = "msvc"; then
|
||||
WINDOWS_WMAIN_XLINK_FLAGS="-link wsetargv.obj"
|
||||
WINDOWS_MAIN_XLINK_FLAGS="-link setargv.obj"
|
||||
fi
|
||||
|
||||
dnl BEGIN CRYPTO
|
||||
|
||||
dnl By default, we build in support for every crypto provider that we
|
||||
dnl can. If implicit crypto is disabled, we don't build support for
|
||||
dnl any crypto that is not explicitly enabled. Test for various crypto
|
||||
dnl providers in increasing order of priority. The last one found
|
||||
dnl becomes the default unless a default is explicitly specified.
|
||||
|
||||
AC_MSG_CHECKING(for whether to use implicit crypto)
|
||||
AC_ARG_ENABLE(implicit-crypto,
|
||||
AS_HELP_STRING([--enable-implicit-crypto],
|
||||
[whether to enable available crypto providers that are not explicitly requested; true by default]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
IMPLICIT_CRYPTO=1
|
||||
else
|
||||
IMPLICIT_CRYPTO=0
|
||||
fi],
|
||||
[IMPLICIT_CRYPTO=1])
|
||||
if test "$IMPLICIT_CRYPTO" = "1"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl Native crypto is always available unless explicitly disabled.
|
||||
|
||||
AC_SUBST(USE_CRYPTO_NATIVE)
|
||||
AC_ARG_ENABLE(crypto-native,
|
||||
AS_HELP_STRING([--enable-crypto-native],
|
||||
[whether to include support for native crypto provider]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
USE_CRYPTO_NATIVE=1
|
||||
else
|
||||
USE_CRYPTO_NATIVE=0
|
||||
fi],
|
||||
[USE_CRYPTO_NATIVE=$IMPLICIT_CRYPTO])
|
||||
if test "$USE_CRYPTO_NATIVE" = "1"; then
|
||||
AC_DEFINE([USE_CRYPTO_NATIVE], 1, [Whether to use the native crypto provider])
|
||||
DEFAULT_CRYPTO=native
|
||||
fi
|
||||
|
||||
dnl If the gnutls provider is explicitly requested, require gnutls. If
|
||||
dnl the gnutls provider is not explicitly disabled, enable it if
|
||||
dnl gnutls is available. If the gnutls provider is explicitly
|
||||
dnl disabled, do not link with gnutls even if present.
|
||||
|
||||
PKG_CHECK_MODULES([pc_gnutls], [gnutls], [GNUTLS_FOUND=1], [GNUTLS_FOUND=0])
|
||||
if test "$GNUTLS_FOUND" = "0"; then
|
||||
AC_CHECK_HEADER(gnutls/gnutls.h,[GNUTLS_FOUND=1],[GNUTLS_FOUND=0])
|
||||
AC_SEARCH_LIBS(gnutls_hash_init,gnutls,[GNUTLS_FOUND=1],[GNUTLS_FOUND=0])
|
||||
fi
|
||||
|
||||
IMPLICIT_GNUTLS=0
|
||||
USE_CRYPTO_GNUTLS=0
|
||||
AC_SUBST(USE_CRYPTO_GNUTLS)
|
||||
AC_ARG_ENABLE(crypto-gnutls,
|
||||
AS_HELP_STRING([--enable-crypto-gnutls],
|
||||
[whether to include support for gnutls crypto provider]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
USE_CRYPTO_GNUTLS=1
|
||||
else
|
||||
USE_CRYPTO_GNUTLS=0
|
||||
fi],
|
||||
[IMPLICIT_GNUTLS=$IMPLICIT_CRYPTO])
|
||||
|
||||
if test "$IMPLICIT_GNUTLS" = "1"; then
|
||||
USE_CRYPTO_GNUTLS=$GNUTLS_FOUND
|
||||
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||
AC_MSG_NOTICE(enabling gnutls crypto provider since gnutls is available)
|
||||
else
|
||||
AC_MSG_NOTICE(not enabling gnutls crypto provider since gnutls was not found)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$USE_CRYPTO_GNUTLS" = "1" -a "$GNUTLS_FOUND" = "0"; then
|
||||
AC_MSG_ERROR(unable to use requested gnutls crypto provider without gnutls)
|
||||
fi
|
||||
|
||||
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||
CFLAGS="$CFLAGS $pc_gnutls_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $pc_gnutls_CXXFLAGS"
|
||||
LIBS="$LIBS $pc_gnutls_LIBS"
|
||||
AC_DEFINE([USE_CRYPTO_GNUTLS], 1, [Whether to use the gnutls crypto provider])
|
||||
DEFAULT_CRYPTO=gnutls
|
||||
elif test "$GNUTLS_FOUND" = "1"; then
|
||||
AC_MSG_NOTICE(not linking with gnutls even though it is available)
|
||||
fi
|
||||
|
||||
dnl Allow the default crypto provider to be specified explicitly.
|
||||
|
||||
AC_MSG_CHECKING(which crypto to use by default)
|
||||
AC_SUBST(DEFAULT_CRYPTO)
|
||||
AC_ARG_WITH(default-crypto,
|
||||
AS_HELP_STRING([--with-default-crypto=provider],
|
||||
[which crypto provider to use by default; see README.md]),
|
||||
[DEFAULT_CRYPTO=$withval],
|
||||
[])
|
||||
AC_MSG_RESULT($DEFAULT_CRYPTO)
|
||||
AC_DEFINE_UNQUOTED([DEFAULT_CRYPTO], "$DEFAULT_CRYPTO", [Default crypto provider])
|
||||
|
||||
dnl Make sure the default crypto provider is actually being built.
|
||||
|
||||
bad_crypto=0
|
||||
case "$DEFAULT_CRYPTO" in
|
||||
"native")
|
||||
if test "$USE_CRYPTO_NATIVE" != "1"; then
|
||||
bad_crypto=1
|
||||
fi
|
||||
;;
|
||||
"gnutls")
|
||||
if test "$USE_CRYPTO_GNUTLS" != "1"; then
|
||||
bad_crypto=1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
bad_crypto=1
|
||||
;;
|
||||
esac
|
||||
if test "$bad_crypto" = "1"; then
|
||||
AC_MSG_ERROR(Unsupported default crypto: $DEFAULT_CRYPTO)
|
||||
fi
|
||||
|
||||
dnl END CRYPTO
|
||||
|
||||
AC_SUBST(QPDF_SKIP_TEST_COMPARE_IMAGES)
|
||||
AC_ARG_ENABLE(test-compare-images,
|
||||
AS_HELP_STRING([--enable-test-compare-images],
|
||||
[whether to compare images in test suite; disabled by default, enabling requires ghostscript and tiffcmp to be available]),
|
||||
[if test "$enableval" = "no"; then
|
||||
QPDF_SKIP_TEST_COMPARE_IMAGES=1
|
||||
else
|
||||
QPDF_SKIP_TEST_COMPARE_IMAGES=0
|
||||
fi],
|
||||
[QPDF_SKIP_TEST_COMPARE_IMAGES=1])
|
||||
|
||||
AC_SUBST(SHOW_FAILED_TEST_OUTPUT)
|
||||
AC_ARG_ENABLE(show-failed-test-output,
|
||||
AS_HELP_STRING([--enable-show-failed-test-output],
|
||||
[if specified, write failed test output to the console; useful for building on build servers where you can't easily open the test output files]),
|
||||
[if test "$enableval" = "no"; then
|
||||
SHOW_FAILED_TEST_OUTPUT=0
|
||||
else
|
||||
SHOW_FAILED_TEST_OUTPUT=1
|
||||
fi],
|
||||
[SHOW_FAILED_TEST_OUTPUT=0])
|
||||
|
||||
AC_ARG_WITH(docbook-xsl,
|
||||
AS_HELP_STRING([--with-docbook-xsl=DIR],
|
||||
[location of docbook 4.x xml stylesheets]),
|
||||
[DOCBOOK_XSL=$withval],
|
||||
[DOCBOOK_XSL=/usr/share/xml/docbook/stylesheet/nwalsh])
|
||||
|
||||
DOCBOOK_XHTML=
|
||||
AC_SUBST(DOCBOOK_XHTML)
|
||||
AC_MSG_CHECKING(for xml to xhtml docbook stylesheets)
|
||||
if test -f "$DOCBOOK_XSL/xhtml/docbook.xsl"; then
|
||||
DOCBOOK_XHTML="$DOCBOOK_XSL/xhtml/docbook.xsl"
|
||||
AC_MSG_RESULT($DOCBOOK_XHTML)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
DOCBOOK_FO=
|
||||
AC_SUBST(DOCBOOK_FO)
|
||||
AC_MSG_CHECKING(for xml to fo docbook stylesheets)
|
||||
if test -f "$DOCBOOK_XSL/fo/docbook.xsl"; then
|
||||
DOCBOOK_FO="$DOCBOOK_XSL/fo/docbook.xsl"
|
||||
AC_MSG_RESULT($DOCBOOK_FO)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
DOCBOOKX_DTD=
|
||||
AC_SUBST(DOCBOOKX_DTD)
|
||||
AC_ARG_WITH(docbookx-dtd,
|
||||
AS_HELP_STRING([--with-docbookx-dtd=FILE],
|
||||
[location of docbook 4.x xml DTD]),
|
||||
[DOCBOOKX_DTD=$withval],
|
||||
[DOCBOOKX_DTD=/usr/share/xml/docbook/schema/dtd/4/docbookx.dtd])
|
||||
AC_MSG_CHECKING(for docbook 4.x xml DTD)
|
||||
if test -f "$DOCBOOKX_DTD"; then
|
||||
AC_MSG_RESULT($DOCBOOKX_DTD)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_CHECK_PROG(FOP,fop,fop,[])
|
||||
AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,[])
|
||||
AC_CHECK_PROG(XMLLINT,xmllint,xmllint,[])
|
||||
|
||||
AC_ARG_ENABLE(doc-maintenance,
|
||||
AS_HELP_STRING([--enable-doc-maintenance],
|
||||
[if set, enables all documentation options]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
doc_default=1;
|
||||
else
|
||||
doc_default=0;
|
||||
fi],
|
||||
[doc_default=0])
|
||||
|
||||
BUILD_HTML=0
|
||||
AC_SUBST(BUILD_HTML)
|
||||
AC_ARG_ENABLE(html-doc,
|
||||
AS_HELP_STRING([--enable-html-doc],
|
||||
[whether to build HTML documents]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
BUILD_HTML=1;
|
||||
else
|
||||
BUILD_HTML=0;
|
||||
fi],
|
||||
[BUILD_HTML=$doc_default])
|
||||
BUILD_PDF=0
|
||||
AC_SUBST(BUILD_PDF)
|
||||
AC_ARG_ENABLE(pdf-doc,
|
||||
AS_HELP_STRING([--enable-pdf-doc],
|
||||
[whether to build PDF documents]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
BUILD_PDF=1;
|
||||
else
|
||||
BUILD_PDF=0;
|
||||
fi],
|
||||
[BUILD_PDF=$doc_default])
|
||||
VALIDATE_DOC=0
|
||||
AC_SUBST(VALIDATE_DOC)
|
||||
AC_ARG_ENABLE(validate-doc,
|
||||
AS_HELP_STRING([--enable-validate-doc],
|
||||
[whether to validate xml document source]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
VALIDATE_DOC=1;
|
||||
else
|
||||
VALIDATE_DOC=0;
|
||||
fi],
|
||||
[VALIDATE_DOC=$doc_default])
|
||||
|
||||
AC_SUBST(OSS_FUZZ)
|
||||
AC_ARG_ENABLE(oss-fuzz,
|
||||
AS_HELP_STRING([--enable-oss-fuzz],
|
||||
[if set, build static fuzzers for oss-fuzz]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
OSS_FUZZ=1;
|
||||
else
|
||||
OSS_FUZZ=0;
|
||||
fi],
|
||||
[OSS_FUZZ=0])
|
||||
|
||||
if test "$VALIDATE_DOC" = "1"; then
|
||||
if test "$XMLLINT" = ""; then
|
||||
MISSING_XMLLINT=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
fi
|
||||
if test "$BUILD_HTML" = "1"; then
|
||||
if test "$XSLTPROC" = ""; then
|
||||
MISSING_XSLTPROC=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
if test "$DOCBOOK_XHTML" = ""; then
|
||||
MISSING_DOCBOOK_XHTML=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
fi
|
||||
if test "$BUILD_PDF" = "1"; then
|
||||
if test "$XSLTPROC" = ""; then
|
||||
MISSING_XSLTPROC=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
if test "$DOCBOOK_FO" = ""; then
|
||||
MISSING_DOCBOOK_FO=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
if test "$FOP" = ""; then
|
||||
MISSING_FOP=1
|
||||
MISSING_ANY=1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if test "$MISSING_ANY" = "1"; then
|
||||
ISSUE_WARNINGS=1
|
||||
fi
|
||||
if test "$ISSUE_WARNINGS" = "1"; then
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if test "$MISSING_MAKE_381" = "1"; then
|
||||
AC_MSG_WARN(gnu make >= 3.81 is required)
|
||||
fi
|
||||
|
||||
if test "$MISSING_ZLIB_H" = "1"; then
|
||||
AC_MSG_WARN(unable to find required header zlib.h)
|
||||
fi
|
||||
|
||||
if test "$MISSING_ZLIB" = "1"; then
|
||||
AC_MSG_WARN(unable to find required library z (or zlib))
|
||||
fi
|
||||
|
||||
if test "$MISSING_JPEG_H" = "1"; then
|
||||
AC_MSG_WARN(unable to find required header jpeglib.h)
|
||||
fi
|
||||
|
||||
if test "$MISSING_JPEG" = "1"; then
|
||||
AC_MSG_WARN(unable to find required library jpeg)
|
||||
fi
|
||||
|
||||
if test "$MISSING_DOCBOOK_FO" = "1"; then
|
||||
AC_MSG_WARN(docbook fo stylesheets are required to build PDF documentation)
|
||||
fi
|
||||
|
||||
if test "$MISSING_DOCBOOK_XHTML" = "1"; then
|
||||
AC_MSG_WARN(docbook xhmtl stylesheets are required to build HTML documentation)
|
||||
fi
|
||||
|
||||
if test "$MISSING_FOP" = "1"; then
|
||||
AC_MSG_WARN(apache fop is required to build PDF documentation)
|
||||
fi
|
||||
|
||||
if test "$MISSING_XMLLINT" = "1"; then
|
||||
AC_MSG_WARN(xmllint is required to validate documentation)
|
||||
fi
|
||||
|
||||
if test "$MISSING_XSLTPROC" = "1"; then
|
||||
AC_MSG_WARN(xsltproc is required to build documentation)
|
||||
fi
|
||||
|
||||
if test "$ISSUE_WARNINGS" = "1"; then
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if test "$MISSING_ANY" = "1"; then
|
||||
AC_MSG_ERROR(some required prerequisites were not found)
|
||||
fi
|
||||
|
||||
# Do this last so it doesn't interfere with other tests.
|
||||
if test "$USE_EXTERNAL_LIBS" = "1"; then
|
||||
# Don't actually check for the presence of this -- we document that
|
||||
# the user can run this and then edit autoconf.mk if they have too
|
||||
# much trouble getting it to work with a different compiler.
|
||||
CPPFLAGS="$CPPFLAGS -Iexternal-libs/include"
|
||||
LDFLAGS="$LDFLAGS -Lexternal-libs/lib-$BUILDRULES$WINDOWS_WORDSIZE"
|
||||
LIBS="$LIBS -lz -ljpeg"
|
||||
fi
|
||||
|
||||
AC_OUTPUT
|
144
copy_dlls
144
copy_dlls
|
@ -1,144 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
require 5.008;
|
||||
BEGIN { $^W = 1; }
|
||||
use strict;
|
||||
use File::Basename;
|
||||
|
||||
my $whoami = basename($0);
|
||||
|
||||
usage() unless @ARGV == 4;
|
||||
my ($file, $destdir, $objdump, $windows_wordsize) = @ARGV;
|
||||
my $filedir = dirname($file);
|
||||
|
||||
my $sep = ($^O eq 'MSWin32' ? ';' : ':');
|
||||
my @path = ($filedir, '.', split($sep, $ENV{'PATH'}));
|
||||
foreach my $var (qw(LIB))
|
||||
{
|
||||
if (exists $ENV{$var})
|
||||
{
|
||||
push(@path, split($sep, $ENV{$var}));
|
||||
}
|
||||
}
|
||||
my $redist_suffix = (($windows_wordsize eq '64') ? "x64" : "x86");
|
||||
if (exists $ENV{'VCINSTALLDIR'})
|
||||
{
|
||||
my $redist = $ENV{'VCINSTALLDIR'} . "/Redist/$redist_suffix";
|
||||
if (opendir(D, $redist))
|
||||
{
|
||||
my @entries = readdir(D);
|
||||
closedir(D);
|
||||
foreach my $e (@entries)
|
||||
{
|
||||
if ($e =~ m/\.CRT$/i)
|
||||
{
|
||||
unshift(@path, "$redist/$e");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exists $ENV{'UniversalCRTSdkDir'})
|
||||
{
|
||||
my $redist = $ENV{'UniversalCRTSdkDir'} . "/Redist/ucrt/DLLs/$redist_suffix";
|
||||
unshift(@path, $redist);
|
||||
}
|
||||
|
||||
my $format = undef;
|
||||
my @to_find = get_dlls($file);
|
||||
|
||||
my %final = ();
|
||||
my @notfound = ();
|
||||
|
||||
while (@to_find)
|
||||
{
|
||||
my $dll = shift(@to_find);
|
||||
my $found = 0;
|
||||
foreach my $dir (@path)
|
||||
{
|
||||
if ((-f "$dir/$dll") && is_format("$dir/$dll", $format))
|
||||
{
|
||||
if (! exists $final{$dll})
|
||||
{
|
||||
$final{$dll} = "$dir/$dll";
|
||||
push(@to_find, get_dlls("$dir/$dll"));
|
||||
}
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (! $found)
|
||||
{
|
||||
push(@notfound, $dll);
|
||||
}
|
||||
}
|
||||
if (@notfound)
|
||||
{
|
||||
die "$whoami: can't find the following dlls: " .
|
||||
join(', ', @notfound), "\n";
|
||||
}
|
||||
|
||||
foreach my $dll (sort keys (%final))
|
||||
{
|
||||
my $f = $final{$dll};
|
||||
$f =~ s,\\,/,g;
|
||||
print "Copying $f to $destdir\n";
|
||||
system("cp -p '$f' '$destdir'") == 0 or
|
||||
die "$whoami: copy $f to $destdir failed\n";
|
||||
}
|
||||
|
||||
sub get_dlls
|
||||
{
|
||||
my @result = ();
|
||||
my $exe = shift;
|
||||
open(O, "$objdump -p \"$exe\"|") or die "$whoami: can't run objdump\n";
|
||||
while (<O>)
|
||||
{
|
||||
if (m/^\s+DLL Name:\s+(.+\.dll)/i)
|
||||
{
|
||||
my $dll = $1;
|
||||
$dll =~ tr/A-Z/a-z/;
|
||||
next if $dll =~ m/^(kernel32|user32|msvcrt|advapi32)\.dll$/;
|
||||
push(@result, $dll);
|
||||
}
|
||||
elsif (m/^Magic.*\((PE.+?)\)/)
|
||||
{
|
||||
$format = $1;
|
||||
}
|
||||
}
|
||||
close(O);
|
||||
if (! defined $format)
|
||||
{
|
||||
die "$whoami: can't determine format of $exe\n";
|
||||
}
|
||||
@result;
|
||||
}
|
||||
|
||||
sub is_format
|
||||
{
|
||||
my ($file, $format) = @_;
|
||||
$file =~ s,\\,/,g;
|
||||
# Special case: msvc*.dll seem to be able to behave both as 32-bit
|
||||
# and 64-bit DLLs. Either that, or this logic is wrong for those
|
||||
# DLLs and it doesn't matter because they're already installed on
|
||||
# my test system (which doesn't have msvc installed on it).
|
||||
if ($file =~ m,/msvc,i)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
my $result = 0;
|
||||
my $file_format = `file "$file"`;
|
||||
print "$file $format $file_format\n";
|
||||
if ($? == 0)
|
||||
{
|
||||
if ($file_format =~ m/\Q${format}\E executable/)
|
||||
{
|
||||
$result = 1;
|
||||
}
|
||||
}
|
||||
$result;
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die "Usage: $whoami {exe|dll} destdir\n";
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
eval $(/usr/bin/qpdf --completion-bash)
|
|
@ -1,17 +0,0 @@
|
|||
qpdf (9.1.1-ok3) yangtze; urgency=medium
|
||||
|
||||
* omelette-guo CVE-2021-36978 安全更新:当某个下游写操作失败时,QPDF中存在基于堆的缓冲区溢出漏洞
|
||||
|
||||
-- lichaoheng <o_o@bupt.edu.cn> Tue, 14 Mar 2023 11:06:54 +0800
|
||||
|
||||
qpdf (9.1.1-ok2) yangtze; urgency=medium
|
||||
|
||||
* Update version.
|
||||
|
||||
-- zhouganqing <zhouganqing@kylinos.cn> Mon, 15 Aug 2022 17:00:51 +0800
|
||||
|
||||
qpdf (9.1.1-ok1) yangtze; urgency=medium
|
||||
|
||||
* Build for openKylin.
|
||||
|
||||
-- openKylinBot <openKylinBot@openkylin.com> Mon, 25 Apr 2022 22:03:04 +0800
|
|
@ -1 +0,0 @@
|
|||
10
|
|
@ -1,86 +0,0 @@
|
|||
Source: qpdf
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>> 10.3~), libjpeg-dev, zlib1g-dev, libgnutls28-dev
|
||||
Maintainer: Openkylin Developers <packaging@lists.openkylin.top>
|
||||
Standards-Version: 4.5.0
|
||||
Homepage: http://qpdf.sourceforge.net
|
||||
|
||||
Package: libqpdf26
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Pre-Depends: ${misc:Pre-Depends}
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: runtime library for PDF transformation/inspection software
|
||||
QPDF is a program that can be used to linearize (web-optimize),
|
||||
encrypt (password-protect), decrypt, and inspect PDF files from the
|
||||
command-line. It does these and other structural, content-preserving
|
||||
transformations on PDF files, reading a PDF file as input and
|
||||
creating a new one as output. It also provides many useful
|
||||
capabilities to developers of PDF-producing software or for people
|
||||
who just want to look at the innards of a PDF file to learn more
|
||||
about how they work.
|
||||
.
|
||||
QPDF understands PDF files that use compressed object streams
|
||||
(supported by newer PDF applications) and can convert such files into
|
||||
those that can be read with older viewers. It can also be used for
|
||||
checking PDF files for structural errors, inspecting stream contents,
|
||||
or extracting objects from PDF files. QPDF is not PDF content
|
||||
creation or viewing software -- it does not have the capability to
|
||||
create PDF files from scratch or to display PDF files.
|
||||
.
|
||||
This package contains the qpdf runtime libraries required to run
|
||||
programs that link with the qpdf library.
|
||||
|
||||
Package: libqpdf-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Pre-Depends: ${misc:Pre-Depends}
|
||||
Depends: ${misc:Depends}, libqpdf26 (= ${binary:Version}), libjpeg-dev, zlib1g-dev
|
||||
Description: development files for PDF transformation/inspection library
|
||||
QPDF is a program that can be used to linearize (web-optimize),
|
||||
encrypt (password-protect), decrypt, and inspect PDF files from the
|
||||
command-line. It does these and other structural, content-preserving
|
||||
transformations on PDF files, reading a PDF file as input and
|
||||
creating a new one as output. It also provides many useful
|
||||
capabilities to developers of PDF-producing software or for people
|
||||
who just want to look at the innards of a PDF file to learn more
|
||||
about how they work.
|
||||
.
|
||||
QPDF understands PDF files that use compressed object streams
|
||||
(supported by newer PDF applications) and can convert such files into
|
||||
those that can be read with older viewers. It can also be used for
|
||||
checking PDF files for structural errors, inspecting stream contents,
|
||||
or extracting objects from PDF files. QPDF is not PDF content
|
||||
creation or viewing software -- it does not have the capability to
|
||||
create PDF files from scratch or to display PDF files.
|
||||
.
|
||||
This package includes all development files needed to compile
|
||||
applications that use the qpdf library.
|
||||
|
||||
Package: qpdf
|
||||
Section: text
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: tools for transforming and inspecting PDF files
|
||||
QPDF is a program that can be used to linearize (web-optimize),
|
||||
encrypt (password-protect), decrypt, and inspect PDF files from the
|
||||
command-line. It does these and other structural, content-preserving
|
||||
transformations on PDF files, reading a PDF file as input and
|
||||
creating a new one as output. It also provides many useful
|
||||
capabilities to developers of PDF-producing software or for people
|
||||
who just want to look at the innards of a PDF file to learn more
|
||||
about how they work.
|
||||
.
|
||||
QPDF understands PDF files that use compressed object streams
|
||||
(supported by newer PDF applications) and can convert such files into
|
||||
those that can be read with older viewers. It can also be used for
|
||||
checking PDF files for structural errors, inspecting stream contents,
|
||||
or extracting objects from PDF files. QPDF is not PDF content
|
||||
creation or viewing software -- it does not have the capability to
|
||||
create PDF files from scratch or to display PDF files.
|
||||
.
|
||||
This package includes the command-line qpdf tools. It also contains
|
||||
the documentation.
|
|
@ -1,296 +0,0 @@
|
|||
This package was debianized by Jay Berkenbilt <qjb@debian.org> on
|
||||
April 26, 2008.
|
||||
|
||||
It can be downloaded from https://github.com/qpdf/qpdf/releases
|
||||
|
||||
Upstream Maintainers:
|
||||
Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
For these files, which are no longer built in the debian package:
|
||||
|
||||
libqpdf/sph/sph_sha2.h
|
||||
libqpdf/sph/sph_types.h
|
||||
libqpdf/sph/md_helper.c
|
||||
libqpdf/sha2big.c
|
||||
libqpdf/sha2.c
|
||||
|
||||
the following copyright applies:
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Copyright (c) 2007-2010 Projet RNRT SAPHIR
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------
|
||||
|
||||
For the file libqpdf/MD5_native.cc, which is no longer built in the
|
||||
debian package, the following copyright applies:
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
----------------------------------------------------------------------
|
||||
|
||||
QPDF embeds a copy of qtest (http://qtest.qbilt.org), which has the
|
||||
same author as qpdf. qtest has the following copyright:
|
||||
|
||||
Copyright 1993-2007, Jay Berkenbilt
|
||||
|
||||
QTest is distributed under the terms of version 2.0 of the Artistic
|
||||
license, which may be found at
|
||||
https://opensource.org/licenses/Artistic-2.0 and which also appears
|
||||
below.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
For everything else, the following copyright applies:
|
||||
|
||||
Copyright (C) 2005-2017 Jay Berkenbilt
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Versions of qpdf prior to version 7 were released under the terms of
|
||||
version 2.0 of the Artistic License. At your option, you may continue
|
||||
to consider qpdf to be licensed under those terms. The text of the
|
||||
Artistic License version 2.0 is included below.
|
||||
|
||||
For the text of the Apache license version 2.0, see
|
||||
/usr/share/common-licenses/Apache-2.0
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Artistic License 2.0
|
||||
|
||||
Copyright (c) 2000-2006, The Perl Foundation.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
This license establishes the terms under which a given free software
|
||||
Package may be copied, modified, distributed, and/or
|
||||
redistributed. The intent is that the Copyright Holder maintains some
|
||||
artistic control over the development of that Package while still
|
||||
keeping the Package available as open source and free software.
|
||||
|
||||
You are always permitted to make arrangements wholly outside of this
|
||||
license directly with the Copyright Holder of a given Package. If the
|
||||
terms of this license do not permit the full use that you propose to
|
||||
make of the Package, you should contact the Copyright Holder and seek
|
||||
a different licensing arrangement.
|
||||
|
||||
Definitions
|
||||
|
||||
"Copyright Holder" means the individual(s) or organization(s) named
|
||||
in the copyright notice for the entire Package.
|
||||
|
||||
"Contributor" means any party that has contributed code or other
|
||||
material to the Package, in accordance with the Copyright Holder's
|
||||
procedures.
|
||||
|
||||
"You" and "your" means any person who would like to copy,
|
||||
distribute, or modify the Package.
|
||||
|
||||
"Package" means the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection and/or of
|
||||
those files. A given Package may consist of either the Standard
|
||||
Version, or a Modified Version.
|
||||
|
||||
"Distribute" means providing a copy of the Package or making it
|
||||
accessible to anyone else, or in the case of a company or
|
||||
organization, to others outside of your company or organization.
|
||||
|
||||
"Distributor Fee" means any fee that you charge for Distributing
|
||||
this Package or providing support for this Package to another
|
||||
party. It does not mean licensing fees.
|
||||
|
||||
"Standard Version" refers to the Package if it has not been
|
||||
modified, or has been modified only in ways explicitly requested by
|
||||
the Copyright Holder.
|
||||
|
||||
"Modified Version" means the Package, if it has been changed, and
|
||||
such changes were not explicitly requested by the Copyright Holder.
|
||||
|
||||
"Original License" means this Artistic License as Distributed with
|
||||
the Standard Version of the Package, in its current version or as
|
||||
it may be modified by The Perl Foundation in the future.
|
||||
|
||||
"Source" form means the source code, documentation source, and
|
||||
configuration files for the Package.
|
||||
|
||||
"Compiled" form means the compiled bytecode, object code, binary,
|
||||
or any other form resulting from mechanical transformation or
|
||||
translation of the Source form.
|
||||
|
||||
Permission for Use and Modification Without Distribution
|
||||
|
||||
(1) You are permitted to use the Standard Version and create and use
|
||||
Modified Versions for any purpose without restriction, provided that
|
||||
you do not Distribute the Modified Version.
|
||||
|
||||
Permissions for Redistribution of the Standard Version
|
||||
|
||||
(2) You may Distribute verbatim copies of the Source form of the
|
||||
Standard Version of this Package in any medium without restriction,
|
||||
either gratis or for a Distributor Fee, provided that you duplicate
|
||||
all of the original copyright notices and associated disclaimers. At
|
||||
your discretion, such verbatim copies may or may not include a
|
||||
Compiled form of the Package.
|
||||
|
||||
(3) You may apply any bug fixes, portability changes, and other
|
||||
modifications made available from the Copyright Holder. The resulting
|
||||
Package will still be considered the Standard Version, and as such
|
||||
will be subject to the Original License.
|
||||
|
||||
Distribution of Modified Versions of the Package as Source
|
||||
|
||||
(4) You may Distribute your Modified Version as Source (either gratis
|
||||
or for a Distributor Fee, and with or without a Compiled form of the
|
||||
Modified Version) provided that you clearly document how it differs
|
||||
from the Standard Version, including, but not limited to, documenting
|
||||
any non-standard features, executables, or modules, and provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
(a) make the Modified Version available to the Copyright Holder of
|
||||
the Standard Version, under the Original License, so that the
|
||||
Copyright Holder may include your modifications in the Standard
|
||||
Version.
|
||||
|
||||
(b) ensure that installation of your Modified Version does not
|
||||
prevent the user installing or running the Standard Version. In
|
||||
addition, the Modified Version must bear a name that is different
|
||||
from the name of the Standard Version.
|
||||
|
||||
(c) allow anyone who receives a copy of the Modified Version to
|
||||
make the Source form of the Modified Version available to others
|
||||
under
|
||||
|
||||
(i) the Original License or
|
||||
|
||||
(ii) a license that permits the licensee to freely copy, modify
|
||||
and redistribute the Modified Version using the same licensing
|
||||
terms that apply to the copy that the licensee received, and
|
||||
requires that the Source form of the Modified Version, and of
|
||||
any works derived from it, be made freely available in that
|
||||
license fees are prohibited but Distributor Fees are allowed.
|
||||
Distribution of Compiled Forms of the Standard Version or
|
||||
Modified Versions without the Source
|
||||
|
||||
(5) You may Distribute Compiled forms of the Standard Version without
|
||||
the Source, provided that you include complete instructions on how to
|
||||
get the Source of the Standard Version. Such instructions must be
|
||||
valid at the time of your distribution. If these instructions, at any
|
||||
time while you are carrying out such distribution, become invalid, you
|
||||
must provide new instructions on demand or cease further
|
||||
distribution. If you provide valid instructions or cease distribution
|
||||
within thirty days after you become aware that the instructions are
|
||||
invalid, then you do not forfeit any of your rights under this
|
||||
license.
|
||||
|
||||
(6) You may Distribute a Modified Version in Compiled form without the
|
||||
Source, provided that you comply with Section 4 with respect to the
|
||||
Source of the Modified Version.
|
||||
|
||||
Aggregating or Linking the Package
|
||||
|
||||
(7) You may aggregate the Package (either the Standard Version or
|
||||
Modified Version) with other packages and Distribute the resulting
|
||||
aggregation provided that you do not charge a licensing fee for the
|
||||
Package. Distributor Fees are permitted, and licensing fees for other
|
||||
components in the aggregation are permitted. The terms of this license
|
||||
apply to the use and Distribution of the Standard or Modified Versions
|
||||
as included in the aggregation.
|
||||
|
||||
(8) You are permitted to link Modified and Standard Versions with
|
||||
other works, to embed the Package in a larger work of your own, or to
|
||||
build stand-alone binary or bytecode versions of applications that
|
||||
include the Package, and Distribute the result without restriction,
|
||||
provided the result does not expose a direct interface to the Package.
|
||||
|
||||
Items That are Not Considered Part of a Modified Version
|
||||
|
||||
(9) Works (including, but not limited to, modules and scripts) that
|
||||
merely extend or make use of the Package, do not, by themselves, cause
|
||||
the Package to be a Modified Version. In addition, such works are not
|
||||
considered parts of the Package itself, and are not subject to the
|
||||
terms of this license.
|
||||
|
||||
General Provisions
|
||||
|
||||
(10) Any use, modification, and distribution of the Standard or
|
||||
Modified Versions is governed by this Artistic License. By using,
|
||||
modifying or distributing the Package, you accept this license. Do not
|
||||
use, modify, or distribute the Package, if you do not accept this
|
||||
license.
|
||||
|
||||
(11) If your Modified Version has been derived from a Modified Version
|
||||
made by someone other than you, you are nevertheless required to
|
||||
ensure that your Modified Version complies with the requirements of
|
||||
this license.
|
||||
|
||||
(12) This license does not grant you the right to use any trademark,
|
||||
service mark, tradename, or logo of the Copyright Holder.
|
||||
|
||||
(13) This license includes the non-exclusive, worldwide,
|
||||
free-of-charge patent license to make, have made, use, offer to sell,
|
||||
sell, import and otherwise transfer the Package with respect to any
|
||||
patent claims licensable by the Copyright Holder that are necessarily
|
||||
infringed by the Package. If you institute patent litigation
|
||||
(including a cross-claim or counterclaim) against any party alleging
|
||||
that the Package constitutes direct or contributory patent
|
||||
infringement, then this Artistic License to you shall terminate on the
|
||||
date that such litigation is filed.
|
||||
|
||||
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
|
||||
HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
|
||||
PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
|
||||
HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,4 +0,0 @@
|
|||
debian/tmp/usr/lib/*/lib*.so
|
||||
debian/tmp/usr/lib/*/lib*.a
|
||||
debian/tmp/usr/lib/*/pkgconfig/*.pc
|
||||
debian/tmp/usr/include
|
|
@ -1 +0,0 @@
|
|||
debian/tmp/usr/lib/*/libqpdf.so.*
|
|
@ -1 +0,0 @@
|
|||
libqpdf 26 libqpdf26 (>> 9.1~)
|
|
@ -1,12 +0,0 @@
|
|||
Document: qpdf-manual
|
||||
Title: Manual for QPDF
|
||||
Author: Jay Berkenbilt
|
||||
Abstract: This manual describes how to use the QPDF tools and library.
|
||||
Section: Text
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/qpdf/qpdf-manual.html
|
||||
Files: /usr/share/doc/qpdf/qpdf-manual.html /usr/share/doc/qpdf/stylesheet.css
|
||||
|
||||
Format: PDF
|
||||
Files: /usr/share/doc/qpdf/qpdf-manual.pdf
|
|
@ -1,3 +0,0 @@
|
|||
debian/tmp/usr/bin
|
||||
debian/tmp/usr/share/man/man1
|
||||
debian/tmp/usr/share/doc/qpdf/*
|
|
@ -1,4 +0,0 @@
|
|||
# hardening-check says this is from memmove
|
||||
qpdf: hardening-no-fortify-functions usr/bin/qpdf
|
||||
# hardening-check says this is from fread
|
||||
qpdf: hardening-no-fortify-functions usr/bin/zlib-flate
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_MAKE_CHECK_TARGET = check
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_compress:
|
||||
dh_compress --exclude=qpdf-manual --exclude=.css --exclude examples/
|
||||
|
||||
override_dh_auto_clean:
|
||||
make distclean CLEAN=1
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- \
|
||||
--libdir="\$${prefix}/lib/$(DEB_HOST_MULTIARCH)" \
|
||||
--enable-crypto-gnutls --disable-implicit-crypto \
|
||||
--enable-show-failed-test-output --disable-check-autofiles
|
||||
|
||||
override_dh_install:
|
||||
dh_install
|
||||
mkdir -p debian/libqpdf-dev/usr/share/doc/libqpdf-dev/examples
|
||||
cp -p examples/*.cc examples/*.c \
|
||||
debian/libqpdf-dev/usr/share/doc/libqpdf-dev/examples
|
||||
cp -p README.md debian/libqpdf-dev/usr/share/doc/libqpdf-dev/README.md
|
||||
mkdir -p debian/qpdf/usr/share/bash-completion/completions
|
||||
cp completions/bash/qpdf \
|
||||
debian/qpdf/usr/share/bash-completion/completions/qpdf
|
||||
mkdir -p debian/qpdf/usr/share/zsh/vendor-completions
|
||||
cp completions/zsh/_qpdf \
|
||||
debian/qpdf/usr/share/zsh/vendor-completions/_qpdf
|
||||
dh_missing --list-missing -X.la
|
|
@ -1 +0,0 @@
|
|||
3.0 (native)
|
|
@ -1,63 +0,0 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBExjXa4BEAC45kKqS7zebKaGZXbgZXQYzXbNk0eRSohclwdfgfoNbkthMyp9
|
||||
IDHlnuCam5fr8mrK5l+xKoB+kHqZRc7bE1CTtlopVY0WzNU1ntnTUnBi6eDKePg+
|
||||
vg9dk84Hi3dJF5j5EHibmvKM/jwTaegnp8qrN63mELWFfEfkAztGk9A7T6Fkd9m7
|
||||
RZLCJfzlRQaJNpmh7mFMC/LTTLsGBU4d8rKJGIF8AV9kKQKWnU1nPt3bTNhnmOds
|
||||
04TDVPwErV58hBELpyK9Ww6sJ7j//cOXS8RxXMXHanl6gYK58uGRXY4rXH/fp9eF
|
||||
g4z5inARTc16OEcIQ2iz7G6qeI4+Q4ZOczVxwHPfB+5CcydcnDerNfLK2ITAHsRL
|
||||
HW63uz+uUA3iwXVR0rH92KN1oe7Jffn00iruMg+tu209l2pzq/oQRKeUlYs72Z7m
|
||||
LJWX/LWEYdgP3dS2II62j6/CblegnHSWrNAyhqPUgy8IjbsoDqb65NkWQxt2NKJP
|
||||
ot3avbu5+kDBdn0RmQLD6x7+VnvjHaykKs4A9dBT4Ie1KJ5BBJnljfc9+DdF8QG1
|
||||
mr4RJGrQqmzydpCaMpcEKj8Wqa5V4h/mtHKkwzNhvXSRDQxOTrsHTsx0750F5KJ+
|
||||
souOwI7eX0ymgioQQLe95jdk0/uUe6MsFdZ2vlwGQTnv7wYtIzzY3ijXWQARAQAB
|
||||
tBtKYXkgQmVya2VuYmlsdCA8ZWpiQHFsLm9yZz6JAjsEEwECACUCGwMGCwkIBwMC
|
||||
BhUIAgkKCwQWAgMBAh4BAheABQJMY2G4AhkBAAoJEIp10QmYASx+gmIQAIhPkc4Y
|
||||
c2UfA9rkVdCiPH0GTgrf3mra+HEt0Tc4Osb8VSEJKtL2zJ94W6M0+e1+qRtQ2odN
|
||||
F7mJUOnHJGSEbtBRlvatWSbdwkV7Ws/rXAreXnrqWdvvE/xFe5cXtj2SReaDWfoZ
|
||||
LgwMVBeQDHnngfkVWV8LYL3PWdF5tNyYdjgSvyxYgEaqYtDyQdElVMIomAOCUkew
|
||||
3zcHaCNWq4RmQEqM3WmF8/DgB7xpd0Nyupy6IyxVfUkSHs2nsnvmGFPDAIW3cZtW
|
||||
wPcts2T9i1MOrL6gpiFIDqJW+2c2w2SXhAE74brWjbY9xd+6zpko4PEFujXs8ZXW
|
||||
8lkeXax9Vg1Z7QdV4imnXiPGt5etiPQij0fJYTEOpM4VKUDEpFYh1eQ4+HUI6MJu
|
||||
PZBs10RUxjSbr1Q9XnMEBbGCsPk3H3IiCNxXk23xEUtujshVVLtD3H3S6zpm6vol
|
||||
Jy0MkMDZicwtYS7ftuvXiOQcRdoBUvvLyd8RqHANSp5A6M42v2jLgaq93ZZojWA4
|
||||
9M52ytoJlKfFMO3/XUwP6ZyBwByUJfWH0+MglokuqedVypIRx65CmqXoU1FhlJJn
|
||||
3EL3y1OlB+ZqdyaHF4sGLlb4ZYBoIWw3p/vMjo/pMUV01FsG1ZNUzYg6rY+DbbRd
|
||||
o9i140u+aH3yru7vStdlGUyRd9UXLL9l6/PWtB9KYXkgQmVya2VuYmlsdCA8cWpi
|
||||
QGRlYmlhbi5vcmc+iQI4BBMBAgAiBQJMY16oAhsDBgsJCAcDAgYVCAIJCgsEFgID
|
||||
AQIeAQIXgAAKCRCKddEJmAEsfoNMD/9JMDvAamWF7/CKtnXK8sURGeuTBAxQ6zLQ
|
||||
BUWPBIowPyR0yuIGUDwhc+vbO9Gk6FZCBpCXGnFCc6uRnLpPanq70pXHexncnOde
|
||||
KYNnCk0S0ju0ALPmlc4OhNjC3oLasWJHMzsvDr3IVucmC1IO8JXL83t4J66nLiL/
|
||||
mpmenqWxyX1LJkf2WmQ+9k6N+pGgQkr+hO8u3e+7KG1HzhnjIXXioYaYYSB2ve1Z
|
||||
CK7Er/QTxzsdk+DmSjUsILQvwAupkN3osS00/Rv+HB1hebMv1BOSoLzSlwbIXwRe
|
||||
wAKJrAJSq7Ec58l9LZsUJrg9tuJavxgMkD2yjMd50jt4o5oJKLvcRSUNdqsZ01Ej
|
||||
NfD5GIXqmH4XntlWUMN0nm3M64gVc2oVpw73s0M+UW7/Bft/Dc+pT1Vy/uQXky0m
|
||||
zR8SGrWLSGj5r6m5MWkH4EKp3hqFxQSq9R5Ed5fRIBvGKngkuwFN8dbllWN/PFFv
|
||||
Smacfw7Jv0yn58alrk71Caag0KOSbHH0jh9pyFAv0xRo4LDeoi8WlY5ycgscXD5h
|
||||
HETEw7AlmDSounu3haDDoy9L3cts2A4Nbld6SOQ/QmdArgdQ0a5nNXY5DlIDdiZo
|
||||
2GaPgiTOI8mqM9TV5RCUKG9uHepQzYUBs4enUh83HE+zYFiykXIatg/3DR42MEGf
|
||||
Hx4F+Qb+HrkCDQRMY12uARAA2uFSD5WZGDXzZ010+jXI1F5uLjZYV8FozRABoxoG
|
||||
Q2LbsSc1gVRtaiDPeUb763y0l1iVze/agUZbVgtc5WHa+GsciTyag8orirEl9rnA
|
||||
Ihh/p7/5HB1/2vqMHYvfh0xkdV68ZBF4fMjxIIFONvQ3rfGHwqUpSLDqgGTTHynP
|
||||
DydSPGgKhCwVsqW4qEPNtZDmlIbsWXQIN+8+Y6Q7lpLhHo9igDKa7jaadTyShvjq
|
||||
FqznnmeLYqGOfkpTzkVOBkdF+mlXHI50Q6zUeBBeoQ8ARLsRcEydswY9ynykDOWv
|
||||
I3/zGx2u8KF5IzosYO1VHgkC6vZTpaxPDvb5Ys7UlUX7gb5GvE1L7Mu4CwwentGW
|
||||
VmM4T6i0gjweHCr9nL1yZK8k6pbro5uvGtiE+sl++lB2LEAtSyQwOVaQTLPFT3bb
|
||||
fhUAHkkiwHGSBhrY6JnjK5reuvkGMlshTScI0mEH8M3sst1TjS4CysKZ+2aUSa1Y
|
||||
GFRBr+y0FbhBwTlvxVEs1YlmPpdZDz5yOe+VknMOPNdYldtnBRPhZDHs5NBiVRfP
|
||||
ABSES8esKqgPsG77snBzSsTgqX3LXO2FDxvFuNvQVTGcBapxzE98PJnUPSKxTqhA
|
||||
ziXZsN79x6rXkOflPK5mEngF50PxVU7DC6U51DCoqMYqlzLYri4r/4qFW8xg8dYF
|
||||
TYUAEQEAAYkCHwQYAQIACQUCTGNdrgIbDAAKCRCKddEJmAEsfm3zD/9Q3aeYDhi7
|
||||
87jUg3nazUnTr5Iny7ovLsqVRh9IKu/BwJKCG+UV+EjO3n3+fMoFzZjg9SLs7EfI
|
||||
KT5BI8NysPWTuaxNAx4SrDc98G50wCDKeVKwRW3ZERK0bHvIRA+qx91ztFFX42fC
|
||||
gb8RtoOHaUkoYOY4q0KOw4U7b6OlwAa/qzxZ3pZFQ0f5gPXEQHjwAmx6HdNEvN2v
|
||||
fXnbFBjOC1tAhvijra6BANEr12LLwq97RK6s4sh0IzCig85SI0arc4r2wAjXiO1f
|
||||
my+kOhp+K3kMmYo7O+pG4Zy9VD+93e5mymXbUFs+MB0eDnuDR8fGpb1jKwhj9xP2
|
||||
70pEX0qynvvwvSvMRsTeQhotckjeQuMMz61XSFg4tsF5guArWG/LUt2eSM8r/Sjf
|
||||
N+LxGnWi8b0eFhrD2S9RWSzlZyBTzKoS7O7MPaaM9k8HOhs0f86vhX/aDpwZzqUU
|
||||
yzUcbGesi6o2+plQXzYwQJqkv402WLrEQY/2hq3ndi2H1aFwsK69+TPiRCDuKs39
|
||||
C57YZmvGCZaUKbm6ALJKblP94thc8J4Hxhicns+JUyj3Afu6HfWLWrffhOzPXMzj
|
||||
HZHZTPo1z5hmDKT9EoGiXKk7vSabwqijsjgwDJVesIHUx6PsH3oK9D6W+pwFmmWy
|
||||
EhBGyHr3h10ly+Ja090RrIGpygQcoKSu8Q==
|
||||
=bPTF
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -1,6 +0,0 @@
|
|||
version=4
|
||||
# qpdf releases are based on artifacts that are explicitly uploaded
|
||||
# rather than the automatically created source releases.
|
||||
opts=pgpsigurlmangle=s/$/.asc/,\
|
||||
uversionmangle=s/(\d)\.([a-z].+)$/$1~$2/ \
|
||||
https://github.com/qpdf/qpdf/releases .*/qpdf-(\d\S+)\.tar\.gz
|
|
@ -1,2 +0,0 @@
|
|||
#compdef qpdf
|
||||
eval $(/usr/bin/qpdf --completion-zsh)
|
5233
doc/qpdf-manual.html
5233
doc/qpdf-manual.html
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,284 +0,0 @@
|
|||
/**************************************************************/
|
||||
/* Custom style-sheet for the QPDF manual in HTML form. */
|
||||
/**************************************************************/
|
||||
|
||||
/*
|
||||
* This file is the CSS for the QPDF manual. It is based heavily on
|
||||
* the CSS for the Subversion book. That file contains the following
|
||||
* copyright and attribution:
|
||||
*
|
||||
* Copyright (c) 2003-2007
|
||||
* Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato.
|
||||
*
|
||||
* This work is licensed under the Creative Commons Attribution License.
|
||||
* To view a copy of this license, visit
|
||||
* http://creativecommons.org/licenses/by/2.0/ or send a letter to
|
||||
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
body
|
||||
{
|
||||
background: white;
|
||||
margin: 0.5in;
|
||||
}
|
||||
|
||||
p, li, ul, ol, dd, dt
|
||||
{
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
}
|
||||
|
||||
tt, pre
|
||||
{
|
||||
font-family: courier new,courier,fixed;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
background: rgb(75%,75%,100%);
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: purple;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
h1.title
|
||||
{
|
||||
font-size: 250%;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
h2.subtitle
|
||||
{
|
||||
font-size: 150%;
|
||||
font-style: italic;
|
||||
color: black;
|
||||
}
|
||||
|
||||
h2.title
|
||||
{
|
||||
font-size: 150%;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
h3.title
|
||||
{
|
||||
font-size: 125%;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
h4.title
|
||||
{
|
||||
font-size: 100%;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.toc b
|
||||
{
|
||||
font-size: 125%;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.screen, .programlisting, .literal
|
||||
{
|
||||
font-family: courier new,courier,fixed;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.command, .option, .type
|
||||
{
|
||||
font-family: courier new,courier,fixed;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.filename
|
||||
{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.property
|
||||
{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.classname
|
||||
{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.varname, .function, .envar
|
||||
{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.replaceable
|
||||
{
|
||||
font-style: italic;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.figure, .example, .table
|
||||
{
|
||||
margin: 0.125in 0.25in;
|
||||
}
|
||||
|
||||
.table table
|
||||
{
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
border-spacing: 0;
|
||||
background: rgb(240,240,240);
|
||||
}
|
||||
|
||||
.table td
|
||||
{
|
||||
border: none;
|
||||
border-right: 1px black solid;
|
||||
border-bottom: 1px black solid;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.table th
|
||||
{
|
||||
background: rgb(180,180,180);
|
||||
border: none;
|
||||
border-right: 1px black solid;
|
||||
border-bottom: 1px black solid;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.table p.title, .figure p.title, .example p.title
|
||||
{
|
||||
text-align: left !important;
|
||||
font-size: 100% !important;
|
||||
}
|
||||
|
||||
.author, .pubdate
|
||||
{
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.preface div.author, .preface .pubdate
|
||||
{
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.sidebar
|
||||
{
|
||||
border-top: dotted 1px black;
|
||||
border-left: dotted 1px black;
|
||||
border-right: solid 2px black;
|
||||
border-bottom: solid 2px black;
|
||||
background: rgb(240,220,170);
|
||||
padding: 0 0.12in;
|
||||
margin: 0.25in;
|
||||
}
|
||||
|
||||
.note .programlisting, .note .screen,
|
||||
.tip .programlisting, .tip .screen,
|
||||
.warning .programlisting, .warning .screen,
|
||||
.sidebar .programlisting, .sidebar .screen
|
||||
{
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.sidebar p.title
|
||||
{
|
||||
text-align: center;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.note
|
||||
{
|
||||
border: black solid 1px;
|
||||
background: url(./images/note.png) no-repeat rgb(252,246,220);
|
||||
margin: 0.125in 0;
|
||||
padding: 0 55px;
|
||||
}
|
||||
|
||||
.tip
|
||||
{
|
||||
border: black solid 1px;
|
||||
background: url(./images/tip.png) no-repeat rgb(224,244,255);
|
||||
margin: 0.125in 0;
|
||||
padding: 0 55px;
|
||||
}
|
||||
|
||||
.warning
|
||||
{
|
||||
border: black solid 1px;
|
||||
background: url(./images/warning.png) no-repeat rgb(255,210,210);
|
||||
margin: 0.125in 0;
|
||||
padding: 0 55px;
|
||||
}
|
||||
|
||||
/*
|
||||
.note .title, .tip .title, .warning .title
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.programlisting, .screen
|
||||
{
|
||||
font-size: 90%;
|
||||
color: black;
|
||||
margin: 1em 0.25in;
|
||||
padding: 0.5em;
|
||||
background: rgb(240,240,240);
|
||||
border-top: black dotted 1px;
|
||||
border-left: black dotted 1px;
|
||||
border-right: black solid 2px;
|
||||
border-bottom: black solid 2px;
|
||||
}
|
||||
|
||||
.navheader, .navfooter
|
||||
{
|
||||
border: black solid 1px;
|
||||
background: rgb(180,180,200);
|
||||
}
|
||||
|
||||
.navheader hr, .navfooter hr
|
||||
{
|
||||
display: none;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
include ../make/proxy.mk
|
|
@ -1,46 +0,0 @@
|
|||
BINS_examples = \
|
||||
pdf-bookmarks \
|
||||
pdf-mod-info \
|
||||
pdf-npages \
|
||||
pdf-double-page-size \
|
||||
pdf-invert-images \
|
||||
pdf-create \
|
||||
pdf-parse-content \
|
||||
pdf-split-pages \
|
||||
pdf-filter-tokens \
|
||||
pdf-count-strings \
|
||||
pdf-set-form-values \
|
||||
pdf-overlay-page
|
||||
CBINS_examples = pdf-linearize
|
||||
|
||||
TARGETS_examples = $(foreach B,$(BINS_examples) $(CBINS_examples),examples/$(OUTPUT_DIR)/$(call binname,$(B)))
|
||||
|
||||
$(TARGETS_examples): $(TARGETS_qpdf)
|
||||
|
||||
INCLUDES_examples = include
|
||||
|
||||
TC_SRCS_examples = $(wildcard examples/*.cc)
|
||||
|
||||
# -----
|
||||
|
||||
$(foreach B,$(BINS_examples),$(eval \
|
||||
OBJS_$(B) = $(call src_to_obj,examples/$(B).cc)))
|
||||
|
||||
$(foreach B,$(CBINS_examples),$(eval \
|
||||
OBJS_$(B) = $(call c_src_to_obj,examples/$(B).c)))
|
||||
|
||||
ifeq ($(GENDEPS),1)
|
||||
-include $(foreach B,$(BINS_examples) $(CBINS_examples),$(call obj_to_dep,$(OBJS_$(B))))
|
||||
endif
|
||||
|
||||
$(foreach B,$(BINS_examples),$(eval \
|
||||
$(OBJS_$(B)): examples/$(OUTPUT_DIR)/%.$(OBJ): examples/$(B).cc ; \
|
||||
$(call compile,examples/$(B).cc,$(INCLUDES_examples))))
|
||||
|
||||
$(foreach B,$(CBINS_examples),$(eval \
|
||||
$(OBJS_$(B)): examples/$(OUTPUT_DIR)/%.$(OBJ): examples/$(B).c ; \
|
||||
$(call c_compile,examples/$(B).c,$(INCLUDES_examples))))
|
||||
|
||||
$(foreach B,$(BINS_examples) $(CBINS_examples),$(eval \
|
||||
examples/$(OUTPUT_DIR)/$(call binname,$(B)): $(OBJS_$(B)) ; \
|
||||
$(call makebin,$(OBJS_$(B)),$$@,$(LDFLAGS_libqpdf) $(LDFLAGS),$(LIBS_libqpdf) $(LIBS))))
|
|
@ -1,19 +0,0 @@
|
|||
pdf-bookmarks lines 0
|
||||
pdf-bookmarks numbers 0
|
||||
pdf-bookmarks none 0
|
||||
pdf-bookmarks has count 0
|
||||
pdf-bookmarks no count 0
|
||||
pdf-bookmarks open 0
|
||||
pdf-bookmarks closed 0
|
||||
pdf-bookmarks dest 0
|
||||
pdf-bookmarks targets 0
|
||||
pdf-mod-info --dump 0
|
||||
pdf-mod-info no in file 0
|
||||
pdf-mod-info in-place 0
|
||||
pdf-mod-info -key 0
|
||||
pdf-mod-info usage wrong val 0
|
||||
pdf-mod-info -val 0
|
||||
pdf-mod-info usage junk 0
|
||||
pdf-mod-info no keys 0
|
||||
pdf-mod-info has info 0
|
||||
pdf-mod-info file no info 0
|
|
@ -1,252 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
|
||||
// This program demonstrates extraction of bookmarks using the qpdf
|
||||
// outlines API. Note that all the information shown by this program
|
||||
// can also be obtained from a PDF file using qpdf's --json option.
|
||||
|
||||
static char const* whoami = 0;
|
||||
static enum { st_none, st_numbers, st_lines } style = st_none;
|
||||
static bool show_open = false;
|
||||
static bool show_targets = false;
|
||||
static std::map<QPDFObjGen, int> page_map;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " [options] file.pdf [password]"
|
||||
<< std::endl
|
||||
<< "Options:" << std::endl
|
||||
<< " -numbers give bookmarks outline-style numbers"
|
||||
<< std::endl
|
||||
<< " -lines draw lines to show bookmark hierarchy"
|
||||
<< std::endl
|
||||
<< " -show-open indicate whether a bookmark is initially open"
|
||||
<< std::endl
|
||||
<< " -show-targets show target if possible"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void print_lines(std::vector<int>& numbers)
|
||||
{
|
||||
for (unsigned int i = 0; i < numbers.size() - 1; ++i)
|
||||
{
|
||||
if (numbers.at(i))
|
||||
{
|
||||
std::cout << "| ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generate_page_map(QPDF& qpdf)
|
||||
{
|
||||
QPDFPageDocumentHelper dh(qpdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
int n = 0;
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFObjectHandle oh = (*iter).getObjectHandle();
|
||||
page_map[oh.getObjGen()] = ++n;
|
||||
}
|
||||
}
|
||||
|
||||
void show_bookmark_details(QPDFOutlineObjectHelper outline,
|
||||
std::vector<int> numbers)
|
||||
{
|
||||
// No default so gcc will warn on missing tag
|
||||
switch (style)
|
||||
{
|
||||
case st_none:
|
||||
QTC::TC("examples", "pdf-bookmarks none");
|
||||
break;
|
||||
|
||||
case st_numbers:
|
||||
QTC::TC("examples", "pdf-bookmarks numbers");
|
||||
for (std::vector<int>::iterator iter = numbers.begin();
|
||||
iter != numbers.end(); ++iter)
|
||||
{
|
||||
std::cout << *iter << ".";
|
||||
}
|
||||
std::cout << " ";
|
||||
break;
|
||||
|
||||
case st_lines:
|
||||
QTC::TC("examples", "pdf-bookmarks lines");
|
||||
print_lines(numbers);
|
||||
std::cout << "|" << std::endl;
|
||||
print_lines(numbers);
|
||||
std::cout << "+-+ ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (show_open)
|
||||
{
|
||||
int count = outline.getCount();
|
||||
if (count)
|
||||
{
|
||||
QTC::TC("examples", "pdf-bookmarks has count");
|
||||
if (count > 0)
|
||||
{
|
||||
// hierarchy is open at this point
|
||||
QTC::TC("examples", "pdf-bookmarks open");
|
||||
std::cout << "(v) ";
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-bookmarks closed");
|
||||
std::cout << "(>) ";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-bookmarks no count");
|
||||
std::cout << "( ) ";
|
||||
}
|
||||
}
|
||||
|
||||
if (show_targets)
|
||||
{
|
||||
QTC::TC("examples", "pdf-bookmarks targets");
|
||||
std::string target = "unknown";
|
||||
QPDFObjectHandle dest_page = outline.getDestPage();
|
||||
if (! dest_page.isNull())
|
||||
{
|
||||
QTC::TC("examples", "pdf-bookmarks dest");
|
||||
QPDFObjGen og = dest_page.getObjGen();
|
||||
if (page_map.count(og))
|
||||
{
|
||||
target = QUtil::int_to_string(page_map[og]);
|
||||
}
|
||||
}
|
||||
std::cout << "[ -> " << target << " ] ";
|
||||
}
|
||||
|
||||
std::cout << outline.getTitle() << std::endl;
|
||||
}
|
||||
|
||||
void extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines,
|
||||
std::vector<int>& numbers)
|
||||
{
|
||||
numbers.push_back(0);
|
||||
for (std::vector<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
|
||||
iter != outlines.end(); ++iter)
|
||||
{
|
||||
++(numbers.back());
|
||||
show_bookmark_details(*iter, numbers);
|
||||
std::vector<QPDFOutlineObjectHelper>::iterator next = iter;
|
||||
++next;
|
||||
bool has_next = (next != outlines.end());
|
||||
if ((style == st_lines) && (! has_next))
|
||||
{
|
||||
numbers.back() = 0;
|
||||
}
|
||||
extract_bookmarks((*iter).getKids(), numbers);
|
||||
}
|
||||
numbers.pop_back();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
||||
{
|
||||
std::cout << whoami << " version 1.5" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int arg;
|
||||
for (arg = 1; arg < argc; ++arg)
|
||||
{
|
||||
if (argv[arg][0] == '-')
|
||||
{
|
||||
if (strcmp(argv[arg], "-numbers") == 0)
|
||||
{
|
||||
style = st_numbers;
|
||||
}
|
||||
else if (strcmp(argv[arg], "-lines") == 0)
|
||||
{
|
||||
style = st_lines;
|
||||
}
|
||||
else if (strcmp(argv[arg], "-show-open") == 0)
|
||||
{
|
||||
show_open = true;
|
||||
}
|
||||
else if (strcmp(argv[arg], "-show-targets") == 0)
|
||||
{
|
||||
show_targets = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg >= argc)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* filename = argv[arg++];
|
||||
char const* password = "";
|
||||
|
||||
if (arg < argc)
|
||||
{
|
||||
password = argv[arg++];
|
||||
}
|
||||
if (arg != argc)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(filename, password);
|
||||
|
||||
QPDFOutlineDocumentHelper odh(qpdf);
|
||||
if (odh.hasOutlines())
|
||||
{
|
||||
std::vector<int> numbers;
|
||||
if (show_targets)
|
||||
{
|
||||
generate_page_map(qpdf);
|
||||
}
|
||||
extract_bookmarks(odh.getTopLevelOutlines(), numbers);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << filename << " has no bookmarks" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << filename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
//
|
||||
// This example illustrates the use of QPDFObjectHandle::TokenFilter
|
||||
// with filterPageContents. See also pdf-filter-tokens.cc for an
|
||||
// example that uses QPDFObjectHandle::TokenFilter with
|
||||
// addContentTokenFilter.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/Pl_StdioFile.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile" << std::endl
|
||||
<< "Applies token filters to infile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
class StringCounter: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
public:
|
||||
StringCounter() :
|
||||
count(0)
|
||||
{
|
||||
}
|
||||
virtual ~StringCounter()
|
||||
{
|
||||
}
|
||||
virtual void handleToken(QPDFTokenizer::Token const&);
|
||||
virtual void handleEOF();
|
||||
int getCount() const;
|
||||
|
||||
private:
|
||||
int count;
|
||||
};
|
||||
|
||||
void
|
||||
StringCounter::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
// Count string tokens
|
||||
if (token.getType() == QPDFTokenizer::tt_string)
|
||||
{
|
||||
++this->count;
|
||||
}
|
||||
// Preserve input verbatim by passing each token to any specified
|
||||
// downstream filter.
|
||||
writeToken(token);
|
||||
}
|
||||
|
||||
void
|
||||
StringCounter::handleEOF()
|
||||
{
|
||||
// Write a comment at the end of the stream just to show how we
|
||||
// can enhance the output if we want.
|
||||
write("\n% strings found: ");
|
||||
write(QUtil::int_to_string(this->count));
|
||||
}
|
||||
|
||||
int
|
||||
StringCounter::getCount() const
|
||||
{
|
||||
return this->count;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* infilename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
int pageno = 0;
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& ph(*iter);
|
||||
++pageno;
|
||||
// Pass the contents of a page through our string counter.
|
||||
// If it's an even page, capture the output. This
|
||||
// illustrates that you may capture any output generated
|
||||
// by the filter, or you may ignore it.
|
||||
StringCounter counter;
|
||||
if (pageno % 2)
|
||||
{
|
||||
// Ignore output for odd pages.
|
||||
ph.filterPageContents(&counter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write output to stdout for even pages.
|
||||
Pl_StdioFile out("stdout", stdout);
|
||||
std::cout << "% Contents of page " << pageno << std::endl;
|
||||
ph.filterPageContents(&counter, &out);
|
||||
std::cout << "\n% end " << pageno << std::endl;
|
||||
}
|
||||
std::cout << "Page " << pageno
|
||||
<< ": strings = " << counter.getCount() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,446 +0,0 @@
|
|||
//
|
||||
// This is an example of creating a PDF file from scratch. It
|
||||
// illustrates use of several QPDF operations for creating objects and
|
||||
// streams. It also serves as an illustration of how to use
|
||||
// StreamDataProvider with different types of filters.
|
||||
//
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
#include <qpdf/Pl_RunLength.hh>
|
||||
#include <qpdf/Pl_DCT.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
// This is a simple StreamDataProvider that writes image data for an
|
||||
// orange square of the given width and height.
|
||||
class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
||||
{
|
||||
public:
|
||||
ImageProvider(std::string const& color_space,
|
||||
std::string const& filter);
|
||||
virtual ~ImageProvider();
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline);
|
||||
size_t getWidth() const;
|
||||
size_t getHeight() const;
|
||||
|
||||
private:
|
||||
size_t width;
|
||||
size_t stripe_height;
|
||||
std::string color_space;
|
||||
std::string filter;
|
||||
size_t n_stripes;
|
||||
std::vector<std::string> stripes;
|
||||
J_COLOR_SPACE j_color_space;
|
||||
};
|
||||
|
||||
ImageProvider::ImageProvider(std::string const& color_space,
|
||||
std::string const& filter) :
|
||||
width(400),
|
||||
stripe_height(80),
|
||||
color_space(color_space),
|
||||
filter(filter),
|
||||
n_stripes(6),
|
||||
j_color_space(JCS_UNKNOWN)
|
||||
{
|
||||
if (color_space == "/DeviceCMYK")
|
||||
{
|
||||
j_color_space = JCS_CMYK;
|
||||
stripes.push_back(std::string("\xff\x00\x00\x00", 4));
|
||||
stripes.push_back(std::string("\x00\xff\x00\x00", 4));
|
||||
stripes.push_back(std::string("\x00\x00\xff\x00", 4));
|
||||
stripes.push_back(std::string("\xff\x00\xff\x00", 4));
|
||||
stripes.push_back(std::string("\xff\xff\x00\x00", 4));
|
||||
stripes.push_back(std::string("\x00\x00\x00\xff", 4));
|
||||
}
|
||||
else if (color_space == "/DeviceRGB")
|
||||
{
|
||||
j_color_space = JCS_RGB;
|
||||
stripes.push_back(std::string("\xff\x00\x00", 3));
|
||||
stripes.push_back(std::string("\x00\xff\x00", 3));
|
||||
stripes.push_back(std::string("\x00\x00\xff", 3));
|
||||
stripes.push_back(std::string("\xff\x00\xff", 3));
|
||||
stripes.push_back(std::string("\xff\xff\x00", 3));
|
||||
stripes.push_back(std::string("\x00\x00\x00", 3));
|
||||
}
|
||||
else if (color_space == "/DeviceGray")
|
||||
{
|
||||
j_color_space = JCS_GRAYSCALE;
|
||||
stripes.push_back(std::string("\xee", 1));
|
||||
stripes.push_back(std::string("\xcc", 1));
|
||||
stripes.push_back(std::string("\x99", 1));
|
||||
stripes.push_back(std::string("\x66", 1));
|
||||
stripes.push_back(std::string("\x33", 1));
|
||||
stripes.push_back(std::string("\x00", 1));
|
||||
}
|
||||
}
|
||||
|
||||
ImageProvider::~ImageProvider()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
ImageProvider::getWidth() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
size_t
|
||||
ImageProvider::getHeight() const
|
||||
{
|
||||
return stripe_height * n_stripes;
|
||||
}
|
||||
|
||||
void
|
||||
ImageProvider::provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline)
|
||||
{
|
||||
std::vector<PointerHolder<Pipeline> > to_delete;
|
||||
Pipeline* p = pipeline;
|
||||
|
||||
if (filter == "/DCTDecode")
|
||||
{
|
||||
p = new Pl_DCT(
|
||||
"image encoder", pipeline,
|
||||
QIntC::to_uint(width), QIntC::to_uint(getHeight()),
|
||||
QIntC::to_int(stripes[0].length()), j_color_space);
|
||||
to_delete.push_back(p);
|
||||
}
|
||||
else if (filter == "/RunLengthDecode")
|
||||
{
|
||||
p = new Pl_RunLength(
|
||||
"image encoder", pipeline, Pl_RunLength::a_encode);
|
||||
to_delete.push_back(p);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n_stripes; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < width * stripe_height; ++j)
|
||||
{
|
||||
p->write(
|
||||
QUtil::unsigned_char_pointer(stripes[i].c_str()),
|
||||
stripes[i].length());
|
||||
}
|
||||
}
|
||||
p->finish();
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
||||
<< "Creates a simple PDF and writes it to filename" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static QPDFObjectHandle createPageContents(QPDF& pdf, std::string const& text)
|
||||
{
|
||||
// Create a stream that displays our image and the given text in
|
||||
// our font.
|
||||
std::string contents =
|
||||
"BT /F1 24 Tf 72 320 Td (" + text + ") Tj ET\n"
|
||||
"q 244 0 0 144 184 100 cm /Im1 Do Q\n";
|
||||
return QPDFObjectHandle::newStream(&pdf, contents);
|
||||
}
|
||||
|
||||
QPDFObjectHandle newName(std::string const& name)
|
||||
{
|
||||
return QPDFObjectHandle::newName(name);
|
||||
}
|
||||
|
||||
QPDFObjectHandle newInteger(size_t val)
|
||||
{
|
||||
return QPDFObjectHandle::newInteger(QIntC::to_int(val));
|
||||
}
|
||||
|
||||
void add_page(QPDFPageDocumentHelper& dh, QPDFObjectHandle font,
|
||||
std::string const& color_space,
|
||||
std::string const& filter)
|
||||
{
|
||||
QPDF& pdf(dh.getQPDF());
|
||||
|
||||
// Create a stream to encode our image. QPDFWriter will fill in
|
||||
// the length and will respect our filters based on stream data
|
||||
// mode. Since we are not specifying, QPDFWriter will compress
|
||||
// with /FlateDecode if we don't provide any other form of
|
||||
// compression.
|
||||
ImageProvider* p = new ImageProvider(color_space, filter);
|
||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> provider(p);
|
||||
size_t width = p->getWidth();
|
||||
size_t height = p->getHeight();
|
||||
QPDFObjectHandle image = QPDFObjectHandle::newStream(&pdf);
|
||||
image.replaceDict(QPDFObjectHandle::parse(
|
||||
"<<"
|
||||
" /Type /XObject"
|
||||
" /Subtype /Image"
|
||||
" /BitsPerComponent 8"
|
||||
">>"));
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
image_dict.replaceKey("/ColorSpace", newName(color_space));
|
||||
image_dict.replaceKey("/Width", newInteger(width));
|
||||
image_dict.replaceKey("/Height", newInteger(height));
|
||||
|
||||
// Provide the stream data.
|
||||
image.replaceStreamData(provider,
|
||||
QPDFObjectHandle::parse(filter),
|
||||
QPDFObjectHandle::newNull());
|
||||
|
||||
// Create direct objects as needed by the page dictionary.
|
||||
QPDFObjectHandle procset = QPDFObjectHandle::parse(
|
||||
"[/PDF /Text /ImageC]");
|
||||
|
||||
QPDFObjectHandle rfont = QPDFObjectHandle::newDictionary();
|
||||
rfont.replaceKey("/F1", font);
|
||||
|
||||
QPDFObjectHandle xobject = QPDFObjectHandle::newDictionary();
|
||||
xobject.replaceKey("/Im1", image);
|
||||
|
||||
QPDFObjectHandle resources = QPDFObjectHandle::newDictionary();
|
||||
resources.replaceKey("/ProcSet", procset);
|
||||
resources.replaceKey("/Font", rfont);
|
||||
resources.replaceKey("/XObject", xobject);
|
||||
|
||||
QPDFObjectHandle mediabox = QPDFObjectHandle::newArray();
|
||||
mediabox.appendItem(newInteger(0));
|
||||
mediabox.appendItem(newInteger(0));
|
||||
mediabox.appendItem(newInteger(612));
|
||||
mediabox.appendItem(newInteger(392));
|
||||
|
||||
// Create the page content stream
|
||||
QPDFObjectHandle contents = createPageContents(
|
||||
pdf, color_space + " with filter " + filter);
|
||||
|
||||
// Create the page dictionary
|
||||
QPDFObjectHandle page = pdf.makeIndirectObject(
|
||||
QPDFObjectHandle::newDictionary());
|
||||
page.replaceKey("/Type", newName("/Page"));
|
||||
page.replaceKey("/MediaBox", mediabox);
|
||||
page.replaceKey("/Contents", contents);
|
||||
page.replaceKey("/Resources", resources);
|
||||
|
||||
// Add the page to the PDF file
|
||||
dh.addPage(page, false);
|
||||
}
|
||||
|
||||
static void check(char const* filename,
|
||||
std::vector<std::string> const& color_spaces,
|
||||
std::vector<std::string> const& filters)
|
||||
{
|
||||
// Each stream is compressed the way it is supposed to be. We will
|
||||
// add additional tests in qpdf.test to exercise QPDFWriter more
|
||||
// fully. In this case, we want to make sure that we actually have
|
||||
// RunLengthDecode and DCTDecode where we are supposed to and
|
||||
// FlateDecode where we provided no filters.
|
||||
|
||||
// Each image is correct. For non-lossy image compression, the
|
||||
// uncompressed image data should exactly match what ImageProvider
|
||||
// provided. For the DCTDecode data, allow for some fuzz to handle
|
||||
// jpeg compression as well as its variance on different systems.
|
||||
|
||||
// These tests should use QPDFObjectHandle's stream data retrieval
|
||||
// methods, but don't try to fully exercise them here. That is
|
||||
// done elsewhere.
|
||||
|
||||
size_t n_color_spaces = color_spaces.size();
|
||||
size_t n_filters = filters.size();
|
||||
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
if (n_color_spaces * n_filters != pages.size())
|
||||
{
|
||||
throw std::logic_error("incorrect number of pages");
|
||||
}
|
||||
size_t pageno = 1;
|
||||
bool errors = false;
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
|
||||
pages.begin();
|
||||
page_iter != pages.end(); ++page_iter)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*page_iter);
|
||||
std::map<std::string, QPDFObjectHandle> images = page.getPageImages();
|
||||
if (images.size() != 1)
|
||||
{
|
||||
throw std::logic_error("incorrect number of images on page");
|
||||
}
|
||||
|
||||
// Check filter and color space.
|
||||
std::string desired_color_space =
|
||||
color_spaces[(pageno - 1) / n_color_spaces];
|
||||
std::string desired_filter =
|
||||
filters[(pageno - 1) % n_filters];
|
||||
// In the default mode, QPDFWriter will compress with
|
||||
// /FlateDecode if no filters are provided.
|
||||
if (desired_filter == "null")
|
||||
{
|
||||
desired_filter = "/FlateDecode";
|
||||
}
|
||||
QPDFObjectHandle image = images.begin()->second;
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
|
||||
QPDFObjectHandle filter = image_dict.getKey("/Filter");
|
||||
bool this_errors = false;
|
||||
if (! (filter.isName() && (filter.getName() == desired_filter)))
|
||||
{
|
||||
this_errors = errors = true;
|
||||
std::cout << "page " << pageno << ": expected filter "
|
||||
<< desired_filter << "; actual filter = "
|
||||
<< filter.unparse() << std::endl;
|
||||
}
|
||||
if (! (color_space.isName() &&
|
||||
(color_space.getName() == desired_color_space)))
|
||||
{
|
||||
this_errors = errors = true;
|
||||
std::cout << "page " << pageno << ": expected color space "
|
||||
<< desired_color_space << "; actual color space = "
|
||||
<< color_space.unparse() << std::endl;
|
||||
}
|
||||
|
||||
if (! this_errors)
|
||||
{
|
||||
// Check image data
|
||||
PointerHolder<Buffer> actual_data =
|
||||
image.getStreamData(qpdf_dl_all);
|
||||
ImageProvider* p = new ImageProvider(desired_color_space, "null");
|
||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> provider(p);
|
||||
Pl_Buffer b_p("get image data");
|
||||
provider->provideStreamData(0, 0, &b_p);
|
||||
PointerHolder<Buffer> desired_data(b_p.getBuffer());
|
||||
|
||||
if (desired_data->getSize() != actual_data->getSize())
|
||||
{
|
||||
std::cout << "page " << pageno
|
||||
<< ": image data length mismatch" << std::endl;
|
||||
this_errors = errors = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compare bytes. For JPEG, allow a certain number of
|
||||
// the bytes to be off desired by more than a given
|
||||
// tolerance. Any of the samples may be a little off
|
||||
// because of lossy compression, and around sharp
|
||||
// edges, things can be quite off. For non-lossy
|
||||
// compression, do not allow any tolerance.
|
||||
unsigned char const* actual_bytes = actual_data->getBuffer();
|
||||
unsigned char const* desired_bytes = desired_data->getBuffer();
|
||||
size_t len = actual_data->getSize();
|
||||
unsigned int mismatches = 0;
|
||||
int tolerance = (
|
||||
desired_filter == "/DCTDecode" ? 10 : 0);
|
||||
size_t threshold = (
|
||||
desired_filter == "/DCTDecode" ? len / 40U : 0);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
int delta = actual_bytes[i] - desired_bytes[i];
|
||||
if ((delta > tolerance) || (delta < -tolerance))
|
||||
{
|
||||
++mismatches;
|
||||
}
|
||||
}
|
||||
if (mismatches > threshold)
|
||||
{
|
||||
std::cout << "page " << pageno
|
||||
<< ": " << desired_color_space << ", "
|
||||
<< desired_filter
|
||||
<< ": mismatches: " << mismatches
|
||||
<< " of " << len << std::endl;
|
||||
this_errors = errors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++pageno;
|
||||
}
|
||||
if (errors)
|
||||
{
|
||||
throw std::logic_error("errors found");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "all checks passed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void create_pdf(char const* filename)
|
||||
{
|
||||
QPDF pdf;
|
||||
|
||||
// Start with an empty PDF that has no pages or non-required objects.
|
||||
pdf.emptyPDF();
|
||||
|
||||
// Add an indirect object to contain a font descriptor for the
|
||||
// built-in Helvetica font.
|
||||
QPDFObjectHandle font = pdf.makeIndirectObject(
|
||||
QPDFObjectHandle::parse(
|
||||
"<<"
|
||||
" /Type /Font"
|
||||
" /Subtype /Type1"
|
||||
" /Name /F1"
|
||||
" /BaseFont /Helvetica"
|
||||
" /Encoding /WinAnsiEncoding"
|
||||
">>"));
|
||||
|
||||
std::vector<std::string> color_spaces;
|
||||
color_spaces.push_back("/DeviceCMYK");
|
||||
color_spaces.push_back("/DeviceRGB");
|
||||
color_spaces.push_back("/DeviceGray");
|
||||
std::vector<std::string> filters;
|
||||
filters.push_back("null");
|
||||
filters.push_back("/DCTDecode");
|
||||
filters.push_back("/RunLengthDecode");
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
for (std::vector<std::string>::iterator c_iter = color_spaces.begin();
|
||||
c_iter != color_spaces.end(); ++c_iter)
|
||||
{
|
||||
for (std::vector<std::string>::iterator f_iter = filters.begin();
|
||||
f_iter != filters.end(); ++f_iter)
|
||||
{
|
||||
add_page(dh, font, *c_iter, *f_iter);
|
||||
}
|
||||
}
|
||||
|
||||
QPDFWriter w(pdf, filename);
|
||||
w.write();
|
||||
|
||||
// For test suite, verify that everything is the way it is
|
||||
// supposed to be.
|
||||
check(filename, color_spaces, filters);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
create_pdf(filename);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||
<< std::endl
|
||||
<< "Double size of all pages in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void doubleBoxSize(QPDFObjectHandle& page, char const* box_name)
|
||||
{
|
||||
// If there is a box of this name, replace it with a new box whose
|
||||
// elements are double the values of the original box.
|
||||
QPDFObjectHandle box = page.getKey(box_name);
|
||||
if (box.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (! (box.isArray() && (box.getArrayNItems() == 4)))
|
||||
{
|
||||
throw std::runtime_error(std::string("box ") + box_name +
|
||||
" is not an array of four elements");
|
||||
}
|
||||
std::vector<QPDFObjectHandle> doubled;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
doubled.push_back(
|
||||
QPDFObjectHandle::newReal(
|
||||
box.getArrayItem(i).getNumericValue() * 2.0, 2));
|
||||
}
|
||||
page.replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
// For test suite
|
||||
bool static_id = false;
|
||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
||||
{
|
||||
static_id = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (! ((argc == 3) || (argc == 4)))
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* infilename = argv[1];
|
||||
char const* outfilename = argv[2];
|
||||
char const* password = (argc == 4) ? argv[3] : "";
|
||||
|
||||
// Text to prepend to each page's contents
|
||||
std::string content = "2 0 0 2 0 0 cm\n";
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(qpdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
||||
pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& ph(*iter);
|
||||
QPDFObjectHandle page = ph.getObjectHandle();
|
||||
|
||||
// Prepend the buffer to the page's contents
|
||||
ph.addPageContents(
|
||||
QPDFObjectHandle::newStream(&qpdf, content), true);
|
||||
|
||||
// Double the size of each of the content boxes
|
||||
doubleBoxSize(page, "/MediaBox");
|
||||
doubleBoxSize(page, "/CropBox");
|
||||
doubleBoxSize(page, "/BleedBox");
|
||||
doubleBoxSize(page, "/TrimBox");
|
||||
doubleBoxSize(page, "/ArtBox");
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
w.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
//
|
||||
// This example illustrates the use of QPDFObjectHandle::TokenFilter
|
||||
// with addContentTokenFilter. Please see comments inline for details.
|
||||
// See also pdf-count-strings.cc for a use of
|
||||
// QPDFObjectHandle::TokenFilter with filterPageContents.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl
|
||||
<< "Applies token filters to infile and writes outfile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
// The StringReverser class is a trivial example of using a token
|
||||
// filter. This class only overrides the pure virtual handleToken
|
||||
// function and preserves the default handleEOF function.
|
||||
class StringReverser: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
public:
|
||||
virtual ~StringReverser()
|
||||
{
|
||||
}
|
||||
virtual void handleToken(QPDFTokenizer::Token const&);
|
||||
};
|
||||
|
||||
void
|
||||
StringReverser::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
// For string tokens, reverse the characters. For other tokens,
|
||||
// just pass them through. Notice that we construct a new string
|
||||
// token and write that, thus allowing the library to handle any
|
||||
// subtleties about properly encoding unprintable characters. This
|
||||
// function doesn't handle multibyte characters at all. It's not
|
||||
// intended to be an example of the correct way to reverse
|
||||
// strings. It's just intended to give a simple example of a
|
||||
// pretty minimal filter and to show an example of writing a
|
||||
// constructed token.
|
||||
if (token.getType() == QPDFTokenizer::tt_string)
|
||||
{
|
||||
std::string value = token.getValue();
|
||||
std::reverse(value.begin(), value.end());
|
||||
writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeToken(token);
|
||||
}
|
||||
}
|
||||
|
||||
// The ColorToGray filter finds all "rg" operators in the content
|
||||
// stream and replaces them with "g" operators, thus mapping color to
|
||||
// grayscale. Note that it only applies to content streams, not
|
||||
// images, so this will not replace color images with grayscale
|
||||
// images.
|
||||
class ColorToGray: public QPDFObjectHandle::TokenFilter
|
||||
{
|
||||
public:
|
||||
virtual ~ColorToGray()
|
||||
{
|
||||
}
|
||||
virtual void handleToken(QPDFTokenizer::Token const&);
|
||||
virtual void handleEOF();
|
||||
|
||||
private:
|
||||
bool isNumeric(QPDFTokenizer::token_type_e);
|
||||
bool isIgnorable(QPDFTokenizer::token_type_e);
|
||||
double numericValue(QPDFTokenizer::Token const&);
|
||||
|
||||
std::deque<QPDFTokenizer::Token> all_stack;
|
||||
std::deque<QPDFTokenizer::Token> stack;
|
||||
};
|
||||
|
||||
bool
|
||||
ColorToGray::isNumeric(QPDFTokenizer::token_type_e token_type)
|
||||
{
|
||||
return ((token_type == QPDFTokenizer::tt_integer) ||
|
||||
(token_type == QPDFTokenizer::tt_real));
|
||||
}
|
||||
|
||||
bool
|
||||
ColorToGray::isIgnorable(QPDFTokenizer::token_type_e token_type)
|
||||
{
|
||||
return ((token_type == QPDFTokenizer::tt_space) ||
|
||||
(token_type == QPDFTokenizer::tt_comment));
|
||||
}
|
||||
|
||||
double
|
||||
ColorToGray::numericValue(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
return QPDFObjectHandle::parse(token.getValue()).getNumericValue();
|
||||
}
|
||||
|
||||
void
|
||||
ColorToGray::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
// Track the number of non-ignorable tokens we've seen. If we see
|
||||
// an "rg" following three numbers, convert it to a grayscale
|
||||
// value. Keep writing tokens to the output as we can.
|
||||
|
||||
// There are several things to notice here. We keep two stacks:
|
||||
// one of "meaningful" tokens, and one of all tokens. This way we
|
||||
// can preserve whitespace or comments that we encounter in the
|
||||
// stream and there preserve layout. As we receive tokens, we keep
|
||||
// the last four meaningful tokens. If we see three numbers
|
||||
// followed by rg, we use the three numbers to calculate a gray
|
||||
// value that is perceptually similar to the color value and then
|
||||
// write the "g" operator to the output, discarding any spaces or
|
||||
// comments encountered embedded in the "rg" operator.
|
||||
|
||||
// The stack and all_stack members are updated in such a way that
|
||||
// they always contain exactly the same non-ignorable tokens. The
|
||||
// stack member contains the tokens that would be left if you
|
||||
// removed all space and comment tokens from all_stack.
|
||||
|
||||
// On each new token, flush out any space or comment tokens. Store
|
||||
// the incoming token. If we just got an rg preceded by the right
|
||||
// kinds of operands, replace the command. Flush any additional
|
||||
// accumulated tokens to keep the stack only four tokens deep.
|
||||
|
||||
while ((! this->all_stack.empty()) &&
|
||||
isIgnorable(this->all_stack.at(0).getType()))
|
||||
{
|
||||
writeToken(this->all_stack.at(0));
|
||||
this->all_stack.pop_front();
|
||||
}
|
||||
this->all_stack.push_back(token);
|
||||
QPDFTokenizer::token_type_e token_type = token.getType();
|
||||
if (! isIgnorable(token_type))
|
||||
{
|
||||
this->stack.push_back(token);
|
||||
if ((this->stack.size() == 4) &&
|
||||
(token == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "rg")) &&
|
||||
(isNumeric(this->stack.at(0).getType())) &&
|
||||
(isNumeric(this->stack.at(1).getType())) &&
|
||||
(isNumeric(this->stack.at(2).getType())))
|
||||
{
|
||||
double r = numericValue(this->stack.at(0));
|
||||
double g = numericValue(this->stack.at(1));
|
||||
double b = numericValue(this->stack.at(2));
|
||||
double gray = ((0.3 * r) + (0.59 * b) + (0.11 * g));
|
||||
if (gray > 1.0)
|
||||
{
|
||||
gray = 1.0;
|
||||
}
|
||||
if (gray < 0.0)
|
||||
{
|
||||
gray = 0.0;
|
||||
}
|
||||
write(QUtil::double_to_string(gray, 3));
|
||||
write(" g");
|
||||
this->stack.clear();
|
||||
this->all_stack.clear();
|
||||
}
|
||||
}
|
||||
if (this->stack.size() == 4)
|
||||
{
|
||||
writeToken(this->all_stack.at(0));
|
||||
this->all_stack.pop_front();
|
||||
this->stack.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ColorToGray::handleEOF()
|
||||
{
|
||||
// Flush out any remaining accumulated tokens.
|
||||
while (! this->all_stack.empty())
|
||||
{
|
||||
writeToken(this->all_stack.at(0));
|
||||
this->all_stack.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* infilename = argv[1];
|
||||
char const* outfilename = argv[2];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
// Attach two token filters to each page of this file.
|
||||
// When the file is written, or when the pages' contents
|
||||
// are retrieved in any other way, the filters will be
|
||||
// applied. See comments on the filters for additional
|
||||
// details.
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
page.addContentTokenFilter(new StringReverser);
|
||||
page.addContentTokenFilter(new ColorToGray);
|
||||
}
|
||||
|
||||
QPDFWriter w(pdf, outfilename);
|
||||
w.setStaticID(true); // for testing only
|
||||
w.write();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||
<< std::endl
|
||||
<< "Invert some images in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
// Derive a class from StreamDataProvider to provide updated stream
|
||||
// data. The main purpose of using this object is to avoid having to
|
||||
// allocate memory up front for the objects. A real application might
|
||||
// use temporary files in order to avoid having to allocate all the
|
||||
// memory. Here, we're not going to worry about that since the goal
|
||||
// is really to show how to use this facility rather than to show the
|
||||
// best possible way to write an image inverter. This class still
|
||||
// illustrates dynamic creation of the new stream data.
|
||||
class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
||||
{
|
||||
public:
|
||||
virtual ~ImageInverter()
|
||||
{
|
||||
}
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline);
|
||||
|
||||
// Map [og] = image object
|
||||
std::map<QPDFObjGen, QPDFObjectHandle> image_objects;
|
||||
// Map [og] = image data
|
||||
std::map<QPDFObjGen, PointerHolder<Buffer> > image_data;
|
||||
};
|
||||
|
||||
void
|
||||
ImageInverter::provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline)
|
||||
{
|
||||
// Use the object and generation number supplied to look up the
|
||||
// image data. Then invert the image data and write the inverted
|
||||
// data to the pipeline.
|
||||
PointerHolder<Buffer> data =
|
||||
this->image_data[QPDFObjGen(objid, generation)];
|
||||
size_t size = data->getSize();
|
||||
unsigned char* buf = data->getBuffer();
|
||||
unsigned char ch;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
ch = QIntC::to_uchar(0xff - buf[i]);
|
||||
pipeline->write(&ch, 1);
|
||||
}
|
||||
pipeline->finish();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
// For test suite
|
||||
bool static_id = false;
|
||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
||||
{
|
||||
static_id = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (! ((argc == 3) || (argc == 4)))
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* infilename = argv[1];
|
||||
char const* outfilename = argv[2];
|
||||
char const* password = (argc == 4) ? argv[3] : "";
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
|
||||
ImageInverter* inv = new ImageInverter;
|
||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> p = inv;
|
||||
|
||||
// For each page...
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(qpdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
// Get all images on the page.
|
||||
std::map<std::string, QPDFObjectHandle> images =
|
||||
page.getPageImages();
|
||||
for (std::map<std::string, QPDFObjectHandle>::iterator iter =
|
||||
images.begin();
|
||||
iter != images.end(); ++iter)
|
||||
{
|
||||
QPDFObjectHandle& image = (*iter).second;
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
QPDFObjectHandle color_space =
|
||||
image_dict.getKey("/ColorSpace");
|
||||
QPDFObjectHandle bits_per_component =
|
||||
image_dict.getKey("/BitsPerComponent");
|
||||
|
||||
// For our example, we can only work with images 8-bit
|
||||
// grayscale images that we can fully decode. Use
|
||||
// pipeStreamData with a null pipeline to determine
|
||||
// whether the image is filterable. Directly inspect
|
||||
// keys to determine the image type.
|
||||
if (image.pipeStreamData(0, qpdf_ef_compress,
|
||||
qpdf_dl_generalized) &&
|
||||
color_space.isName() &&
|
||||
bits_per_component.isInteger() &&
|
||||
(color_space.getName() == "/DeviceGray") &&
|
||||
(bits_per_component.getIntValue() == 8))
|
||||
{
|
||||
// Store information about the images based on the
|
||||
// object and generation number. Recall that a single
|
||||
// image object may be used more than once.
|
||||
QPDFObjGen og = image.getObjGen();
|
||||
if (inv->image_objects.count(og) == 0)
|
||||
{
|
||||
inv->image_objects[og] = image;
|
||||
inv->image_data[og] = image.getStreamData();
|
||||
|
||||
// Register our stream data provider for this
|
||||
// stream. Future calls to getStreamData or
|
||||
// pipeStreamData will use the new
|
||||
// information. Provide null for both filter
|
||||
// and decode parameters. Note that this does
|
||||
// not mean the image data will be
|
||||
// uncompressed when we write the file. By
|
||||
// default, QPDFWriter will use /FlateDecode
|
||||
// for anything that is uncompressed or
|
||||
// filterable in the input QPDF object, so we
|
||||
// don't have to deal with it explicitly here.
|
||||
image.replaceStreamData(
|
||||
p,
|
||||
QPDFObjectHandle::newNull(),
|
||||
QPDFObjectHandle::newNull());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* This is an example program to linearize a PDF file using the C API.
|
||||
*/
|
||||
|
||||
#include <qpdf/qpdf-c.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: %s infile infile-password outfile\n", whoami);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char* infile = NULL;
|
||||
char* password = NULL;
|
||||
char* outfile = NULL;
|
||||
qpdf_data qpdf = qpdf_init();
|
||||
int warnings = 0;
|
||||
int errors = 0;
|
||||
char* p = 0;
|
||||
|
||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
}
|
||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
whoami = argv[0];
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
infile = argv[1];
|
||||
password = argv[2];
|
||||
outfile = argv[3];
|
||||
|
||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0))
|
||||
{
|
||||
/* Use static ID for testing only. For production, a
|
||||
* non-static ID is used. See also
|
||||
* qpdf_set_deterministic_ID. */
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||
qpdf_set_linearization(qpdf, QPDF_TRUE);
|
||||
qpdf_write(qpdf);
|
||||
}
|
||||
while (qpdf_more_warnings(qpdf))
|
||||
{
|
||||
warnings = 1;
|
||||
printf("warning: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
}
|
||||
if (qpdf_has_error(qpdf))
|
||||
{
|
||||
errors = 1;
|
||||
printf("error: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
}
|
||||
qpdf_cleanup(&qpdf);
|
||||
if (errors)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (warnings)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
// Author: Vitaliy Pavlyuk
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static char const* version = "1.1";
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr
|
||||
<< "Usage: " << whoami
|
||||
<< " -in in_file [-out out_file] [-key key [-val val]?]+\n"
|
||||
<< "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
|
||||
<< "and stores the result in out_file\n"
|
||||
<< "Special mode: " << whoami << " --dump file\n"
|
||||
<< "dumps all /Info entries to stdout\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void dumpInfoDict(QPDF& pdf,
|
||||
std::ostream& os = std::cout,
|
||||
std::string const& sep = ":\t")
|
||||
{
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
if (trailer.hasKey("/Info"))
|
||||
{
|
||||
QPDFObjectHandle info = trailer.getKey("/Info");
|
||||
std::set<std::string> keys = info.getKeys();
|
||||
for (std::set<std::string>::const_iterator it = keys.begin();
|
||||
keys.end() != it; ++it)
|
||||
{
|
||||
QPDFObjectHandle elt = info.getKey(*it);
|
||||
std::string val;
|
||||
if (false) {}
|
||||
else if (elt.isString())
|
||||
{
|
||||
val = elt.getStringValue();
|
||||
}
|
||||
else if (elt.isName())
|
||||
{
|
||||
val = elt.getName();
|
||||
}
|
||||
else // according to PDF Spec 1.5, shouldn't happen
|
||||
{
|
||||
val = elt.unparseResolved();
|
||||
}
|
||||
os << it->substr(1) << sep << val << std::endl; // skip '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pdfDumpInfoDict(char const* fname)
|
||||
{
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(fname);
|
||||
dumpInfoDict(pdf);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
bool static_id = false;
|
||||
std::map<std::string, std::string> Keys;
|
||||
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (! strcmp(argv[1], "--version")) )
|
||||
{
|
||||
std::cout << whoami << " version " << version << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
if ((argc == 4) && (! strcmp(argv[1], "--dump")) &&
|
||||
(strcmp(argv[2], "-in") == 0) )
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info --dump");
|
||||
pdfDumpInfoDict(argv[3]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char* fl_in = 0;
|
||||
char* fl_out = 0;
|
||||
std::string cur_key;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if ((! strcmp(argv[i], "-in")) && (++i < argc))
|
||||
{
|
||||
fl_in = argv[i];
|
||||
}
|
||||
else if ((! strcmp(argv[i], "-out")) && (++i < argc))
|
||||
{
|
||||
fl_out = argv[i];
|
||||
}
|
||||
else if (! strcmp(argv[i], "--static-id")) // don't document
|
||||
{
|
||||
static_id = true; // this should be used in test suites only
|
||||
}
|
||||
else if ((! strcmp(argv[i], "-key")) && (++i < argc))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info -key");
|
||||
cur_key = argv[i];
|
||||
if (! ((cur_key.length() > 0) && (cur_key.at(0) == '/')))
|
||||
{
|
||||
cur_key = "/" + cur_key;
|
||||
}
|
||||
Keys[cur_key] = "";
|
||||
}
|
||||
else if ((! strcmp(argv[i], "-val")) && (++i < argc))
|
||||
{
|
||||
if (cur_key.empty())
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage wrong val");
|
||||
usage();
|
||||
}
|
||||
QTC::TC("examples", "pdf-mod-info -val");
|
||||
Keys[cur_key] = argv[i];
|
||||
cur_key.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage junk");
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if (! fl_in)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info no in file");
|
||||
usage();
|
||||
}
|
||||
if (! fl_out)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info in-place");
|
||||
fl_out = fl_in;
|
||||
}
|
||||
if (Keys.size() == 0)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info no keys");
|
||||
usage();
|
||||
}
|
||||
|
||||
std::string fl_tmp = fl_out;
|
||||
fl_tmp += ".tmp";
|
||||
|
||||
try
|
||||
{
|
||||
QPDF file;
|
||||
file.processFile(fl_in);
|
||||
|
||||
QPDFObjectHandle filetrailer = file.getTrailer();
|
||||
QPDFObjectHandle fileinfo;
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it =
|
||||
Keys.begin(); Keys.end() != it; ++it)
|
||||
{
|
||||
if (! fileinfo.isInitialized())
|
||||
{
|
||||
if (filetrailer.hasKey("/Info"))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info has info");
|
||||
fileinfo = filetrailer.getKey("/Info");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info file no info");
|
||||
fileinfo = QPDFObjectHandle::newDictionary();
|
||||
filetrailer.replaceKey("/Info", fileinfo);
|
||||
}
|
||||
}
|
||||
if (it->second == "")
|
||||
{
|
||||
fileinfo.removeKey(it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPDFObjectHandle elt = fileinfo.newString(it->second);
|
||||
elt.makeDirect();
|
||||
fileinfo.replaceKey(it->first, elt);
|
||||
}
|
||||
}
|
||||
QPDFWriter w(file, fl_tmp.c_str());
|
||||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.setLinearization(true);
|
||||
w.setStaticID(static_id); // for testing only
|
||||
w.write();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
(void) remove(fl_out);
|
||||
QUtil::os_wrapper("rename " + fl_tmp + " " + std::string(fl_out),
|
||||
rename(fl_tmp.c_str(), fl_out));
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
||||
<< "Prints the number of pages in filename" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
||||
{
|
||||
std::cout << whoami << " version 1.3" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle pages = root.getKey("/Pages");
|
||||
QPDFObjectHandle count = pages.getKey("/Count");
|
||||
std::cout << count.getIntValue() << std::endl;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
// This program demonstrates use of form XObjects to overlay a page
|
||||
// from one file onto all pages of another file. The qpdf program's
|
||||
// --overlay and --underlay options provide a more general version of
|
||||
// this capability.
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile pagefile outfile"
|
||||
<< std::endl
|
||||
<< "Stamp page 1 of pagefile on every page of infile,"
|
||||
<< " writing to outfile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void stamp_page(char const* infile,
|
||||
char const* stampfile,
|
||||
char const* outfile)
|
||||
{
|
||||
QPDF inpdf;
|
||||
inpdf.processFile(infile);
|
||||
QPDF stamppdf;
|
||||
stamppdf.processFile(stampfile);
|
||||
|
||||
// Get first page from other file
|
||||
QPDFPageObjectHelper stamp_page_1 =
|
||||
QPDFPageDocumentHelper(stamppdf).getAllPages().at(0);
|
||||
// Convert page to a form XObject
|
||||
QPDFObjectHandle foreign_fo = stamp_page_1.getFormXObjectForPage();
|
||||
// Copy form XObject to the input file
|
||||
QPDFObjectHandle stamp_fo = inpdf.copyForeignObject(foreign_fo);
|
||||
|
||||
// For each page...
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(inpdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& ph = *iter;
|
||||
|
||||
// Find a unique resource name for the new form XObject
|
||||
QPDFObjectHandle resources = ph.getAttribute("/Resources", true);
|
||||
int min_suffix = 1;
|
||||
std::string name = resources.getUniqueResourceName("/Fx", min_suffix);
|
||||
|
||||
// Generate content to place the form XObject centered within
|
||||
// destination page's trim box.
|
||||
std::string content =
|
||||
ph.placeFormXObject(
|
||||
stamp_fo, name, ph.getTrimBox().getArrayAsRectangle());
|
||||
if (! content.empty())
|
||||
{
|
||||
// Append the content to the page's content. Surround the
|
||||
// original content with q...Q to the new content from the
|
||||
// page's original content.
|
||||
resources.mergeResources(
|
||||
QPDFObjectHandle::parse("<< /XObject << >> >>"));
|
||||
resources.getKey("/XObject").replaceKey(name, stamp_fo);
|
||||
ph.addPageContents(
|
||||
QPDFObjectHandle::newStream(&inpdf, "q\n"), true);
|
||||
ph.addPageContents(
|
||||
QPDFObjectHandle::newStream(&inpdf, "\nQ\n" + content), false);
|
||||
}
|
||||
}
|
||||
|
||||
QPDFWriter w(inpdf, outfile);
|
||||
w.setStaticID(true); // for testing only
|
||||
w.write();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* infile = argv[1];
|
||||
char const* stampfile = argv[2];
|
||||
char const* outfile = argv[3];
|
||||
|
||||
try
|
||||
{
|
||||
stamp_page(infile, stampfile, outfile);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename page-number" << std::endl
|
||||
<< "Prints a dump of the objects in the content streams"
|
||||
<< " of the given page." << std::endl
|
||||
<< "Pages are numbered from 1." << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
class ParserCallbacks: public QPDFObjectHandle::ParserCallbacks
|
||||
{
|
||||
public:
|
||||
virtual ~ParserCallbacks()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void contentSize(size_t);
|
||||
virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length);
|
||||
virtual void handleEOF();
|
||||
};
|
||||
|
||||
void
|
||||
ParserCallbacks::contentSize(size_t size)
|
||||
{
|
||||
std::cout << "content size: " << size << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
ParserCallbacks::handleObject(QPDFObjectHandle obj,
|
||||
size_t offset, size_t length)
|
||||
{
|
||||
std::cout << obj.getTypeName() << ", offset=" << offset
|
||||
<< ", length=" << length << ": ";
|
||||
if (obj.isInlineImage())
|
||||
{
|
||||
std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << obj.unparse() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ParserCallbacks::handleEOF()
|
||||
{
|
||||
std::cout << "-EOF-" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
int pageno = QUtil::string_to_int(argv[2]);
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
if ((pageno < 1) || (QIntC::to_size(pageno) > pages.size()))
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
QPDFPageObjectHelper& page = pages.at(QIntC::to_size(pageno-1));
|
||||
ParserCallbacks cb;
|
||||
page.parsePageContents(&cb);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
static char const* whoami = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf value"
|
||||
<< std::endl
|
||||
<< "Set the value of all text fields to a specified value"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* infilename = argv[1];
|
||||
char const* outfilename = argv[2];
|
||||
char const* value = argv[3];
|
||||
|
||||
// This is a contrived example that just goes through a file page
|
||||
// by page and sets the value of any text fields it finds to a
|
||||
// fixed value as given on the command line. The purpose here is
|
||||
// to illustrate use of the helper classes around interactive
|
||||
// forms.
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename);
|
||||
|
||||
// We will iterate through form fields by starting at the page
|
||||
// level and looking at each field for each page. We could
|
||||
// also called QPDFAcroFormDocumentHelper::getFormFields to
|
||||
// iterate at the field level, but doing it as below
|
||||
// illustrates how we can map from annotations to fields.
|
||||
|
||||
QPDFAcroFormDocumentHelper afdh(qpdf);
|
||||
QPDFPageDocumentHelper pdh(qpdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
|
||||
pages.begin();
|
||||
page_iter != pages.end(); ++page_iter)
|
||||
{
|
||||
// Get all widget annotations for each page. Widget
|
||||
// annotations are the ones that contain the details of
|
||||
// what's in a form field.
|
||||
std::vector<QPDFAnnotationObjectHelper> annotations =
|
||||
afdh.getWidgetAnnotationsForPage(*page_iter);
|
||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
||||
annotations.begin();
|
||||
annot_iter != annotations.end(); ++annot_iter)
|
||||
{
|
||||
// For each annotation, find its associated field. If
|
||||
// it's a text field, set its value. This will
|
||||
// automatically update the document to indicate that
|
||||
// appearance streams need to be regenerated. At the
|
||||
// time of this writing, qpdf doesn't have any helper
|
||||
// code to assist with appearance stream generation,
|
||||
// though there's nothing that prevents it from being
|
||||
// possible.
|
||||
QPDFFormFieldObjectHelper ffh =
|
||||
afdh.getFieldForAnnotation(*annot_iter);
|
||||
if (ffh.getFieldType() == "/Tx")
|
||||
{
|
||||
// Set the value. This will automatically set
|
||||
// /NeedAppearances to true. If you don't want to
|
||||
// do that, pass false as the second argument. For
|
||||
// details see comments in
|
||||
// QPDFFormFieldObjectHelper.hh.
|
||||
ffh.setV(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
w.setStaticID(true); // for testing only
|
||||
w.write();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
//
|
||||
// This is a stand-alone example of splitting a PDF into individual
|
||||
// pages. It does essentially the same thing that qpdf --split-pages
|
||||
// does.
|
||||
//
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
static char const* whoami = 0;
|
||||
static bool static_id = false;
|
||||
|
||||
static void process(char const* whoami,
|
||||
char const* infile,
|
||||
std::string outprefix)
|
||||
{
|
||||
QPDF inpdf;
|
||||
inpdf.processFile(infile);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(inpdf).getAllPages();
|
||||
int pageno_len =
|
||||
QIntC::to_int(QUtil::uint_to_string(pages.size()).length());
|
||||
int pageno = 0;
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
std::string outfile =
|
||||
outprefix + QUtil::int_to_string(++pageno, pageno_len) + ".pdf";
|
||||
QPDF outpdf;
|
||||
outpdf.emptyPDF();
|
||||
QPDFPageDocumentHelper(outpdf).addPage(page, false);
|
||||
QPDFWriter outpdfw(outpdf, outfile.c_str());
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
outpdfw.setStaticID(true); // for testing only
|
||||
outpdfw.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
outpdfw.write();
|
||||
}
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile outprefix" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
}
|
||||
// For test suite
|
||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
||||
{
|
||||
static_id = true;
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
try
|
||||
{
|
||||
process(whoami, argv[1], argv[2]);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
BEGIN { $^W = 1; }
|
||||
use strict;
|
||||
|
||||
chdir("bookmarks");
|
||||
|
||||
require TestDriver;
|
||||
|
||||
my $td = new TestDriver('pdf-bookmarks');
|
||||
|
||||
foreach my $show ("", " -show-open")
|
||||
{
|
||||
foreach my $style ("", " -lines", " -numbers")
|
||||
{
|
||||
my $xshow = $show ? $show : "x";
|
||||
my $xstyle = $style ? $style : "x";
|
||||
my $out = "test.$xshow.$xstyle.out";
|
||||
$out =~ s/ //g;
|
||||
$td->runtest("show:$show, style:$style",
|
||||
{$td->COMMAND => "pdf-bookmarks $show $style 1.pdf"},
|
||||
{$td->FILE => $out, $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
}
|
||||
$td->runtest("no bookmarks",
|
||||
{$td->COMMAND => "pdf-bookmarks 2.pdf"},
|
||||
{$td->STRING => "2.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("bad",
|
||||
{$td->COMMAND => "pdf-bookmarks 3.pdf"},
|
||||
{$td->REGEXP => "pdf-bookmarks processing file 3.pdf: " .
|
||||
".*unable to find trailer.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("encrypted, targets",
|
||||
{$td->COMMAND => "pdf-bookmarks -show-targets 4.pdf user"},
|
||||
{$td->FILE => "encrypted.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("bookmarks deleted",
|
||||
{$td->COMMAND => "pdf-bookmarks 5.pdf user"},
|
||||
{$td->STRING => "5.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("non-trivial pdf doc to unicode",
|
||||
{$td->COMMAND => "pdf-bookmarks issue-179.pdf"},
|
||||
{$td->FILE => "issue-179.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->report(11);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,79 +0,0 @@
|
|||
%PDF-1.3
|
||||
1 0 obj
|
||||
<<
|
||||
/Type /Catalog
|
||||
/Pages 2 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Type /Pages
|
||||
/Kids [
|
||||
3 0 R
|
||||
]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/Parent 2 0 R
|
||||
/MediaBox [0 0 612 792]
|
||||
/Contents 4 0 R
|
||||
/Resources <<
|
||||
/ProcSet 5 0 R
|
||||
/Font <<
|
||||
/F1 6 0 R
|
||||
>>
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/Length 44
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/Type /Font
|
||||
/Subtype /Type1
|
||||
/Name /F1
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000009 00000 n
|
||||
0000000063 00000 n
|
||||
0000000135 00000 n
|
||||
0000000307 00000 n
|
||||
0000000403 00000 n
|
||||
0000000438 00000 n
|
||||
trailer <<
|
||||
/Size 7
|
||||
/Root 1 0 R
|
||||
>>
|
||||
startxref
|
||||
556
|
||||
%%EOF
|
|
@ -1 +0,0 @@
|
|||
potato salad
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +0,0 @@
|
|||
[ -> 6 ] Isís 1 -> 5: /XYZ null null null
|
||||
[ -> 12 ] Amanda 1.1 -> 11: /Fit
|
||||
[ -> 13 ] Isosicle 1.1.1 -> 12: /FitV 100
|
||||
[ -> 19 ] Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
[ -> 20 ] Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
[ -> 13 ] Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
[ -> 23 ] Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
[ -> 14 ] Sandy ÷Σανδι÷ 1.2 -> 13: /FitH 792
|
||||
[ -> 2 ] Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
[ -> 1 ] Trepsicle 1.2.2 -> 0: /XYZ null null null
|
||||
[ -> 16 ] Trepak 2 -> 15: /XYZ 66 756 3
|
|
@ -1,12 +0,0 @@
|
|||
ž
|
||||
žč
|
||||
žđ
|
||||
žć
|
||||
žš
|
||||
ž ajklyghvbnmxcseqwuioprtzdf
|
||||
š
|
||||
šč
|
||||
šđ
|
||||
šć
|
||||
šž
|
||||
š ajklyghvbnmxcseqwuioprtzdf
|
Binary file not shown.
|
@ -1,22 +0,0 @@
|
|||
|
|
||||
+-+ ( ) Trepak 2 -> 15: /XYZ 66 756 3
|
||||
|
|
||||
+-+ (v) Isis 1 -> 5: /XYZ null null null
|
||||
|
|
||||
+-+ (>) Amanda 1.1 -> 11: /Fit
|
||||
| |
|
||||
| +-+ (>) Isosicle 1.1.1 -> 12: /FitV 100
|
||||
| | |
|
||||
| | +-+ ( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
| | |
|
||||
| | +-+ ( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
| |
|
||||
| +-+ (v) Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
| |
|
||||
| +-+ ( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
|
|
||||
+-+ (v) Sandy 1.2 -> 13: /FitH 792
|
||||
|
|
||||
+-+ ( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
|
|
||||
+-+ ( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,11 +0,0 @@
|
|||
1. ( ) Trepak 2 -> 15: /XYZ 66 756 3
|
||||
2. (v) Isis 1 -> 5: /XYZ null null null
|
||||
2.1. (>) Amanda 1.1 -> 11: /Fit
|
||||
2.1.1. (>) Isosicle 1.1.1 -> 12: /FitV 100
|
||||
2.1.1.1. ( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
2.1.1.2. ( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
2.1.2. (v) Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
2.1.2.1. ( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
2.2. (v) Sandy 1.2 -> 13: /FitH 792
|
||||
2.2.1. ( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
2.2.2. ( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,11 +0,0 @@
|
|||
( ) Trepak 2 -> 15: /XYZ 66 756 3
|
||||
(v) Isis 1 -> 5: /XYZ null null null
|
||||
(>) Amanda 1.1 -> 11: /Fit
|
||||
(>) Isosicle 1.1.1 -> 12: /FitV 100
|
||||
( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
(v) Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
(v) Sandy 1.2 -> 13: /FitH 792
|
||||
( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,22 +0,0 @@
|
|||
|
|
||||
+-+ Trepak 2 -> 15: /XYZ 66 756 3
|
||||
|
|
||||
+-+ Isis 1 -> 5: /XYZ null null null
|
||||
|
|
||||
+-+ Amanda 1.1 -> 11: /Fit
|
||||
| |
|
||||
| +-+ Isosicle 1.1.1 -> 12: /FitV 100
|
||||
| | |
|
||||
| | +-+ Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
| | |
|
||||
| | +-+ Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
| |
|
||||
| +-+ Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
| |
|
||||
| +-+ Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
|
|
||||
+-+ Sandy 1.2 -> 13: /FitH 792
|
||||
|
|
||||
+-+ Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
|
|
||||
+-+ Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,11 +0,0 @@
|
|||
1. Trepak 2 -> 15: /XYZ 66 756 3
|
||||
2. Isis 1 -> 5: /XYZ null null null
|
||||
2.1. Amanda 1.1 -> 11: /Fit
|
||||
2.1.1. Isosicle 1.1.1 -> 12: /FitV 100
|
||||
2.1.1.1. Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
2.1.1.2. Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
2.1.2. Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
2.1.2.1. Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
2.2. Sandy 1.2 -> 13: /FitH 792
|
||||
2.2.1. Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
2.2.2. Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,11 +0,0 @@
|
|||
Trepak 2 -> 15: /XYZ 66 756 3
|
||||
Isis 1 -> 5: /XYZ null null null
|
||||
Amanda 1.1 -> 11: /Fit
|
||||
Isosicle 1.1.1 -> 12: /FitV 100
|
||||
Isosicle 1.1.1.1 -> 18: /XYZ null null null
|
||||
Isosicle 1.1.1.2 -> 19: /XYZ null null null
|
||||
Isosicle 1.1.2 -> 12: /XYZ null null null
|
||||
Isosicle 1.1.2.1 -> 22: /XYZ null null null
|
||||
Sandy 1.2 -> 13: /FitH 792
|
||||
Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
|
||||
Trepsicle 1.2.2 -> 0: /XYZ null null null
|
|
@ -1,17 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
BEGIN { $^W = 1; }
|
||||
use strict;
|
||||
|
||||
chdir("count-strings");
|
||||
|
||||
require TestDriver;
|
||||
|
||||
my $td = new TestDriver('pdf-count-strings');
|
||||
|
||||
$td->runtest("filter tokens",
|
||||
{$td->COMMAND => "pdf-count-strings in.pdf"},
|
||||
{$td->FILE => "out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->report(1);
|
Binary file not shown.
|
@ -1,16 +0,0 @@
|
|||
Page 1: strings = 3
|
||||
% Contents of page 2
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Four ) Tj
|
||||
(Five ) Tj
|
||||
(Six )
|
||||
(beautiful ) Tj
|
||||
(strings) Tj
|
||||
(!) Tj
|
||||
ET
|
||||
|
||||
% strings found: 6
|
||||
% end 2
|
||||
Page 2: strings = 6
|
|
@ -1,27 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
chdir("create") or die "chdir testdir failed: $!\n";
|
||||
|
||||
require TestDriver;
|
||||
|
||||
cleanup();
|
||||
|
||||
my $td = new TestDriver('create');
|
||||
|
||||
$td->runtest("create a simple PDF",
|
||||
{$td->COMMAND => "pdf-create a.pdf"},
|
||||
{$td->FILE => "create.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
cleanup();
|
||||
|
||||
$td->report(1);
|
||||
|
||||
sub cleanup
|
||||
{
|
||||
unlink "a.pdf";
|
||||
unlink "tmp.out";
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue