Compare commits

...

No commits in common. "openkylin/yangtze" and "pristine-tar" have entirely different histories.

1820 changed files with 1 additions and 589400 deletions

28
.gitignore vendored
View File

@ -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/

View File

@ -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

View File

@ -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.

2865
ChangeLog

File diff suppressed because it is too large Load Diff

216
INSTALL
View File

@ -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.

View File

@ -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
View File

@ -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_,,$@))

View File

@ -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.
```

View File

@ -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.

View File

@ -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;
}
```

View File

@ -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.

View File

@ -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.

View File

@ -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!

View File

@ -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
View File

@ -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
View File

@ -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.

22
aclocal.m4 vendored
View File

@ -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])

View File

@ -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

View File

@ -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" ]

View File

@ -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 ""

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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@

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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/*

View File

@ -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/

View File

@ -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/*

View File

@ -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

View File

@ -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

View File

@ -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/*

View File

@ -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
)

View File

@ -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

View File

@ -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.

View File

@ -1 +0,0 @@
eval $(/usr/bin/qpdf --completion-bash)

View File

@ -1,2 +0,0 @@
#compdef qpdf
eval $(/usr/bin/qpdf --completion-zsh)

View File

@ -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+"$@"}

View File

@ -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+"$@"}

1667
config.guess vendored

File diff suppressed because it is too large Load Diff

1793
config.sub vendored

File diff suppressed because it is too large Load Diff

20628
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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";
}

View File

@ -1 +0,0 @@
eval $(/usr/bin/qpdf --completion-bash)

17
debian/changelog vendored
View File

@ -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
debian/compat vendored
View File

@ -1 +0,0 @@
10

86
debian/control vendored
View File

@ -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.

296
debian/copyright vendored
View File

@ -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.

View File

@ -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

View File

@ -1 +0,0 @@
debian/tmp/usr/lib/*/libqpdf.so.*

View File

@ -1 +0,0 @@
libqpdf 26 libqpdf26 (>> 9.1~)

12
debian/qpdf.doc-base vendored
View File

@ -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

3
debian/qpdf.install vendored
View File

@ -1,3 +0,0 @@
debian/tmp/usr/bin
debian/tmp/usr/share/man/man1
debian/tmp/usr/share/doc/qpdf/*

View File

@ -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

37
debian/rules vendored
View File

@ -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

View File

@ -1 +0,0 @@
3.0 (native)

View File

@ -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-----

6
debian/watch vendored
View File

@ -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

View File

@ -1,2 +0,0 @@
#compdef qpdf
eval $(/usr/bin/qpdf --completion-zsh)

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -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;
}

View File

@ -1 +0,0 @@
include ../make/proxy.mk

View File

@ -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))))

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
potato salad

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -1,12 +0,0 @@
ž
žč
žđ
žć
žš
ž ajklyghvbnmxcseqwuioprtzdf
š
šč
šđ
šć
šž
š ajklyghvbnmxcseqwuioprtzdf

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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