mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
Generate help content from manual
This is a massive rewrite of the help text and cli.rst section of the manual. All command-line flags now have their own help and are specifically index. qpdf --help is completely redone.
This commit is contained in:
parent
b4bd124be4
commit
c8729398dd
4
Makefile
4
Makefile
@ -127,7 +127,9 @@ check: $(TEST_TARGETS)
|
||||
.PHONY: spell
|
||||
# npm install -g cspell; add exceptions to cSpell.json
|
||||
spell:
|
||||
cspell **/*.hh include/qpdf/*.h **/*.cc manual/* ChangeLog README* TODO
|
||||
cspell **/*.hh include/qpdf/*.h **/*.cc \
|
||||
manual/*.rst manual/*.in manual/_ext/*.py \
|
||||
ChangeLog README* TODO
|
||||
|
||||
# Install targets are in the make directory in the rules-specific make
|
||||
# fragments.
|
||||
|
6
TODO
6
TODO
@ -34,16 +34,14 @@ Documentation
|
||||
* Consider which parts might be good candidates for moving to the
|
||||
wiki.
|
||||
|
||||
* See #530 -- add an appendix explaining PDF encryption in general
|
||||
plus how it's handled by qpdf. Or maybe this should go on the wiki.
|
||||
|
||||
Document-level work
|
||||
===================
|
||||
|
||||
* Ideas here may by superseded by #593.
|
||||
|
||||
* QPDFPageCopier -- object for moving pages around within files or
|
||||
between files and performing various transformations
|
||||
between files and performing various transformations. Reread/rewrite
|
||||
_page-selection in the manual if needed.
|
||||
|
||||
* Handle all the stuff of pages and split-pages
|
||||
* Do n-up, booklet, collation
|
||||
|
@ -54,6 +54,7 @@
|
||||
"cerr",
|
||||
"cfis",
|
||||
"cflags",
|
||||
"ciphertext",
|
||||
"classname",
|
||||
"clearsign",
|
||||
"cleartext",
|
||||
@ -149,6 +150,7 @@
|
||||
"hosoda",
|
||||
"htcondor",
|
||||
"htdocs",
|
||||
"idempotency",
|
||||
"ifdefs",
|
||||
"ifeq",
|
||||
"ifstream",
|
||||
|
@ -19,10 +19,16 @@ def warn(*args, **kwargs):
|
||||
|
||||
|
||||
class Main:
|
||||
SOURCES = [whoami, 'job.yml', 'manual/cli.rst']
|
||||
SOURCES = [
|
||||
whoami,
|
||||
'manual/_ext/qpdf.py',
|
||||
'job.yml',
|
||||
'manual/cli.rst',
|
||||
]
|
||||
DESTS = {
|
||||
'decl': 'libqpdf/qpdf/auto_job_decl.hh',
|
||||
'init': 'libqpdf/qpdf/auto_job_init.hh',
|
||||
'help': 'libqpdf/qpdf/auto_job_help.hh',
|
||||
}
|
||||
SUMS = 'job.sums'
|
||||
|
||||
@ -100,14 +106,22 @@ class Main:
|
||||
short_text = None
|
||||
long_text = None
|
||||
|
||||
print('this->ap.addHelpFooter("For detailed help, visit'
|
||||
' the qpdf manual: https://qpdf.readthedocs.io\\n");', file=f)
|
||||
# Generate a bunch of short static functions rather than a big
|
||||
# member function for help. Some compilers have problems with
|
||||
# very large member functions in classes in anonymous
|
||||
# namespaces.
|
||||
|
||||
help_files = 0
|
||||
help_lines = 0
|
||||
|
||||
self.all_topics = set(self.options_without_help)
|
||||
self.referenced_topics = set()
|
||||
|
||||
def set_indent(x):
|
||||
nonlocal indent
|
||||
indent = ' ' * len(x)
|
||||
|
||||
def append_long_text(line):
|
||||
def append_long_text(line, topic):
|
||||
nonlocal indent, long_text
|
||||
if line == '\n':
|
||||
long_text += '\n'
|
||||
@ -115,13 +129,23 @@ class Main:
|
||||
long_text += line[len(indent):]
|
||||
else:
|
||||
long_text = long_text.strip()
|
||||
if long_text != '':
|
||||
if long_text == '':
|
||||
raise Exception(f'missing long text for {topic}')
|
||||
long_text += '\n'
|
||||
for i in re.finditer(r'--help=([^\.\s]+)', long_text):
|
||||
self.referenced_topics.add(i.group(1))
|
||||
return True
|
||||
return False
|
||||
|
||||
lineno = 0
|
||||
for line in df.readlines():
|
||||
if help_lines == 0:
|
||||
if help_files > 0:
|
||||
print('}', file=f)
|
||||
help_files += 1
|
||||
help_lines += 1
|
||||
print(f'static void add_help_{help_files}(QPDFArgParser& ap)\n'
|
||||
'{', file=f)
|
||||
lineno += 1
|
||||
if state == st_top:
|
||||
m = re.match(r'^(\s*\.\. )help-topic (\S+): (.*)$', line)
|
||||
@ -132,7 +156,8 @@ class Main:
|
||||
long_text = ''
|
||||
state = st_topic
|
||||
continue
|
||||
m = re.match(r'^(\s*\.\. )qpdf:option:: (([^=\s]+)(=(\S+))?)$',
|
||||
m = re.match(
|
||||
r'^(\s*\.\. )qpdf:option:: (([^=\s]+)([= ](.+))?)$',
|
||||
line)
|
||||
if m:
|
||||
if topic is None:
|
||||
@ -150,9 +175,11 @@ class Main:
|
||||
state = st_option
|
||||
continue
|
||||
elif state == st_topic:
|
||||
if append_long_text(line):
|
||||
print(f'this->ap.addHelpTopic("{topic}", "{short_text}",'
|
||||
if append_long_text(line, topic):
|
||||
self.all_topics.add(topic)
|
||||
print(f'ap.addHelpTopic("{topic}", "{short_text}",'
|
||||
f' R"({long_text})");', file=f)
|
||||
help_lines += 1
|
||||
state = st_top
|
||||
elif state == st_option:
|
||||
if line == '\n' or line.startswith(indent):
|
||||
@ -162,12 +189,36 @@ class Main:
|
||||
short_text = m.group(2)
|
||||
state = st_option_help
|
||||
else:
|
||||
raise Exception('option without help text')
|
||||
state = st_top
|
||||
elif state == st_option_help:
|
||||
if append_long_text(line):
|
||||
print(f'this->ap.addOptionHelp("{option}", "{topic}",'
|
||||
if append_long_text(line, option):
|
||||
if option in self.options_without_help:
|
||||
self.options_without_help.remove(option)
|
||||
else:
|
||||
raise Exception(
|
||||
f'help for unknown option {option},'
|
||||
f' lineno={lineno}')
|
||||
print(f'ap.addOptionHelp("{option}", "{topic}",'
|
||||
f' "{short_text}", R"({long_text})");', file=f)
|
||||
help_lines += 1
|
||||
state = st_top
|
||||
if help_lines == 20:
|
||||
help_lines = 0
|
||||
print('}', file=f)
|
||||
print('static void add_help(QPDFArgParser& ap)\n{', file=f)
|
||||
for i in range(help_files):
|
||||
print(f' add_help_{i+1}(ap);', file=f)
|
||||
print('ap.addHelpFooter("For detailed help, visit'
|
||||
' the qpdf manual: https://qpdf.readthedocs.io\\n");', file=f)
|
||||
print('}\n', file=f)
|
||||
for i in self.referenced_topics:
|
||||
if i not in self.all_topics:
|
||||
raise Exception(f'help text referenced --help={i}')
|
||||
for i in self.options_without_help:
|
||||
raise Exception(
|
||||
'Options without help: ' +
|
||||
', '.join(self.options_without_help))
|
||||
|
||||
def generate(self):
|
||||
warn(f'{whoami}: regenerating auto job files')
|
||||
@ -175,12 +226,19 @@ class Main:
|
||||
with open('job.yml', 'r') as f:
|
||||
data = yaml.safe_load(f.read())
|
||||
self.validate(data)
|
||||
self.options_without_help = set(
|
||||
['--completion-bash', '--completion-zsh', '--help']
|
||||
)
|
||||
with open(self.DESTS['decl'], 'w') as f:
|
||||
print(BANNER, file=f)
|
||||
self.generate_decl(data, f)
|
||||
with open(self.DESTS['init'], 'w') as f:
|
||||
print(BANNER, file=f)
|
||||
self.generate_init(data, f)
|
||||
with open(self.DESTS['help'], 'w') as f:
|
||||
with open('manual/cli.rst', 'r') as df:
|
||||
print(BANNER, file=f)
|
||||
self.generate_doc(df, f)
|
||||
|
||||
# Update hashes last to ensure that this will be rerun in the
|
||||
# event of a failure.
|
||||
@ -275,24 +333,29 @@ class Main:
|
||||
print('this->ap.addPositional('
|
||||
f'p(&ArgParser::{prefix}Positional));', file=f)
|
||||
for i in o.get('bare', []):
|
||||
self.options_without_help.add(f'--{i}')
|
||||
identifier = self.to_identifier(i, prefix, False)
|
||||
print(f'this->ap.addBare("{i}", '
|
||||
f'b(&ArgParser::{identifier}));', file=f)
|
||||
for i in o.get('optional_parameter', []):
|
||||
self.options_without_help.add(f'--{i}')
|
||||
identifier = self.to_identifier(i, prefix, False)
|
||||
print(f'this->ap.addOptionalParameter("{i}", '
|
||||
f'p(&ArgParser::{identifier}));', file=f)
|
||||
for k, v in o.get('required_parameter', {}).items():
|
||||
self.options_without_help.add(f'--{k}')
|
||||
identifier = self.to_identifier(k, prefix, False)
|
||||
print(f'this->ap.addRequiredParameter("{k}", '
|
||||
f'p(&ArgParser::{identifier})'
|
||||
f', "{v}");', file=f)
|
||||
for k, v in o.get('required_choices', {}).items():
|
||||
self.options_without_help.add(f'--{k}')
|
||||
identifier = self.to_identifier(k, prefix, False)
|
||||
print(f'this->ap.addChoices("{k}", '
|
||||
f'p(&ArgParser::{identifier})'
|
||||
f', true, {v}_choices);', file=f)
|
||||
for k, v in o.get('optional_choices', {}).items():
|
||||
self.options_without_help.add(f'--{k}')
|
||||
identifier = self.to_identifier(k, prefix, False)
|
||||
print(f'this->ap.addChoices("{k}", '
|
||||
f'p(&ArgParser::{identifier})'
|
||||
@ -312,8 +375,6 @@ class Main:
|
||||
for j in ft['options']:
|
||||
print('this->ap.copyFromOtherTable'
|
||||
f'("{j}", "{other_table}");', file=f)
|
||||
with open('manual/cli.rst', 'r') as df:
|
||||
self.generate_doc(df, f)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
8
job.sums
8
job.sums
@ -1,6 +1,8 @@
|
||||
# Generated by generate_auto_job
|
||||
generate_auto_job 1f42fc554778d95210d11c44e858214b4854ead907d1c9ea84fe37f993ea1a23
|
||||
generate_auto_job 466aa9211549cebeb3fedc6413108981aeeddd89936621095f5f5223cee9880b
|
||||
job.yml 25c85cba1ae01dac9cd0f9cb7b734e7e3e531c0023ea2b892dc0d40bda1c1146
|
||||
libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
|
||||
libqpdf/qpdf/auto_job_init.hh 2afffb5002ff28a3909f709709f65d77bf2289dd72d5ea3d1598a36664a49c73
|
||||
manual/cli.rst f0109cca3366a9da4b0a05e3cce996ece2d776321a3f689aeaa2d6af599eee88
|
||||
libqpdf/qpdf/auto_job_help.hh fa7ff1d1f6289881ac3a485107d15240c4992c59cff506be425354557108d184
|
||||
libqpdf/qpdf/auto_job_init.hh 465bf46769559ceb77110d1b9d3293ba9b3595850b49848c31aeabd10aadb4ad
|
||||
manual/_ext/qpdf.py 855fe12de5af7a10bb24be6ecc4d5dff4c84ac58cf388a13be6bbb394346a67d
|
||||
manual/cli.rst c26e877d2065ac917edffdd6a037d2191b64d7c25beb4e8df1acc174b20b3ff4
|
||||
|
@ -967,21 +967,20 @@ void
|
||||
QPDFArgParser::getAllHelp(std::ostringstream& msg)
|
||||
{
|
||||
getTopHelp(msg);
|
||||
auto show = [this, &msg](std::map<std::string, HelpTopic>& topics,
|
||||
std::string const& label) {
|
||||
auto show = [this, &msg](std::map<std::string, HelpTopic>& topics) {
|
||||
for (auto const& i: topics)
|
||||
{
|
||||
auto const& topic = i.first;
|
||||
msg << std::endl
|
||||
<< "== " << label << " " << topic
|
||||
<< "== " << topic
|
||||
<< " (" << i.second.short_text << ") =="
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
getTopicHelp(topic, i.second, msg);
|
||||
}
|
||||
};
|
||||
show(this->m->help_topics, "topic");
|
||||
show(this->m->option_help, "option");
|
||||
show(this->m->help_topics);
|
||||
show(this->m->option_help);
|
||||
msg << std::endl << "====" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,8 @@ ArgParser::ArgParser(QPDFArgParser& ap, QPDFJob& o) :
|
||||
initOptionTables();
|
||||
}
|
||||
|
||||
#include <qpdf/auto_job_help.hh>
|
||||
|
||||
void
|
||||
ArgParser::initOptionTables()
|
||||
{
|
||||
@ -55,6 +57,8 @@ ArgParser::initOptionTables()
|
||||
# include <qpdf/auto_job_init.hh>
|
||||
this->ap.addFinalCheck(
|
||||
QPDFArgParser::bindBare(&ArgParser::doFinalChecks, this));
|
||||
// add_help is defined in auto_job_help.hh
|
||||
add_help(this->ap);
|
||||
}
|
||||
|
||||
void
|
||||
@ -127,513 +131,6 @@ ArgParser::argCopyright()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
ArgParser::argHelp()
|
||||
{
|
||||
// QXXXQ
|
||||
std::cout
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
<< "Usage: qpdf [options] {infile | --empty} [page_selection_options] outfile\n"
|
||||
<< "\n"
|
||||
<< "An option summary appears below. Please see the documentation for details.\n"
|
||||
<< "\n"
|
||||
<< "If @filename appears anywhere in the command-line, each line of filename\n"
|
||||
<< "will be interpreted as an argument. No interpolation is done. Line\n"
|
||||
<< "terminators are stripped, but leading and trailing whitespace is\n"
|
||||
<< "intentionally preserved. @- can be specified to read from standard input.\n"
|
||||
<< "\n"
|
||||
<< "The output file can be - to indicate writing to standard output, or it can\n"
|
||||
<< "be --replace-input to cause qpdf to replace the input file with the output.\n"
|
||||
<< "\n"
|
||||
<< "Note that when contradictory options are provided, whichever options are\n"
|
||||
<< "provided last take precedence.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Basic Options\n"
|
||||
<< "-------------\n"
|
||||
<< "\n"
|
||||
<< "--version show version of qpdf\n"
|
||||
<< "--copyright show qpdf's copyright and license information\n"
|
||||
<< "--help show command-line argument help\n"
|
||||
<< "--show-crypto show supported crypto providers; default is first\n"
|
||||
<< "--completion-bash output a bash complete command you can eval\n"
|
||||
<< "--completion-zsh output a zsh complete command you can eval\n"
|
||||
<< "--password=password specify a password for accessing encrypted files\n"
|
||||
<< "--password-file=file get the password the first line \"file\"; use \"-\"\n"
|
||||
<< " to read the password from stdin (without prompt or\n"
|
||||
<< " disabling echo, so use with caution)\n"
|
||||
<< "--is-encrypted silently exit 0 if the file is encrypted or 2\n"
|
||||
<< " if not; useful for shell scripts\n"
|
||||
<< "--requires-password silently exit 0 if a password (other than as\n"
|
||||
<< " supplied) is required, 2 if the file is not\n"
|
||||
<< " encrypted, or 3 if the file is encrypted\n"
|
||||
<< " but requires no password or the supplied password\n"
|
||||
<< " is correct; useful for shell scripts\n"
|
||||
<< "--verbose provide additional informational output\n"
|
||||
<< "--progress give progress indicators while writing output\n"
|
||||
<< "--no-warn suppress warnings\n"
|
||||
<< "--warning-exit-0 exit with code 0 instead of 3 if there are warnings\n"
|
||||
<< "--linearize generated a linearized (web optimized) file\n"
|
||||
<< "--replace-input use in place of specifying an output file; qpdf will\n"
|
||||
<< " replace the input file with the output\n"
|
||||
<< "--copy-encryption=file copy encryption parameters from specified file\n"
|
||||
<< "--encryption-file-password=password\n"
|
||||
<< " password used to open the file from which encryption\n"
|
||||
<< " parameters are being copied\n"
|
||||
<< "--allow-weak-crypto allow creation of files using weak cryptographic\n"
|
||||
<< " algorithms\n"
|
||||
<< "--encrypt options -- generate an encrypted file\n"
|
||||
<< "--decrypt remove any encryption on the file\n"
|
||||
<< "--password-is-hex-key treat primary password option as a hex-encoded key\n"
|
||||
<< "--suppress-password-recovery\n"
|
||||
<< " do not attempt recovering from password string\n"
|
||||
<< " encoding errors\n"
|
||||
<< "--password-mode=mode control qpdf's encoding of passwords\n"
|
||||
<< "--pages options -- select specific pages from one or more files\n"
|
||||
<< "--collate=n causes files specified in --pages to be collated\n"
|
||||
<< " in groups of n pages (default 1) rather than\n"
|
||||
<< " concatenated\n"
|
||||
<< "--flatten-rotation move page rotation from /Rotate key to content\n"
|
||||
<< "--rotate=[+|-]angle[:page-range]\n"
|
||||
<< " rotate each specified page 0, 90, 180, or 270\n"
|
||||
<< " degrees; rotate all pages if no page range is given\n"
|
||||
<< "--split-pages=[n] write each output page to a separate file\n"
|
||||
<< "--overlay options -- overlay pages from another file\n"
|
||||
<< "--underlay options -- underlay pages from another file\n"
|
||||
<< "\n"
|
||||
<< "Note that you can use the @filename or @- syntax for any argument at any\n"
|
||||
<< "point in the command. This provides a good way to specify a password without\n"
|
||||
<< "having to explicitly put it on the command line. @filename or @- must be a\n"
|
||||
<< "word by itself. Syntax such as --arg=@filename doesn't work.\n"
|
||||
<< "\n"
|
||||
<< "If none of --copy-encryption, --encrypt or --decrypt are given, qpdf will\n"
|
||||
<< "preserve any encryption data associated with a file.\n"
|
||||
<< "\n"
|
||||
<< "Note that when copying encryption parameters from another file, all\n"
|
||||
<< "parameters will be copied, including both user and owner passwords, even\n"
|
||||
<< "if the user password is used to open the other file. This works even if\n"
|
||||
<< "the owner password is not known.\n"
|
||||
<< "\n"
|
||||
<< "The --password-is-hex-key option overrides the normal computation of\n"
|
||||
<< "encryption keys. It only applies to the password used to open the main\n"
|
||||
<< "file. This option is not ordinarily useful but can be helpful for forensic\n"
|
||||
<< "or investigatory purposes. See manual for further discussion.\n"
|
||||
<< "\n"
|
||||
<< "The --rotate flag can be used to specify pages to rotate pages either\n"
|
||||
<< "0, 90, 180, or 270 degrees. The page range is specified in the same\n"
|
||||
<< "format as with the --pages option, described below. Repeat the option\n"
|
||||
<< "to rotate multiple groups of pages. If the angle is preceded by + or -,\n"
|
||||
<< "it is added to or subtracted from the original rotation. Otherwise, the\n"
|
||||
<< "rotation angle is set explicitly to the given value. You almost always\n"
|
||||
<< "want to use + or - unless you are certain about the internals of the PDF\n"
|
||||
<< "you are working with.\n"
|
||||
<< "\n"
|
||||
<< "If --split-pages is specified, each page is written to a separate output\n"
|
||||
<< "file. File names are generated as follows:\n"
|
||||
<< "* If the string %d appears in the output file name, it is replaced with a\n"
|
||||
<< " zero-padded page range starting from 1\n"
|
||||
<< "* Otherwise, if the output file name ends in .pdf (case insensitive), a\n"
|
||||
<< " zero-padded page range, preceded by a dash, is inserted before the file\n"
|
||||
<< " extension\n"
|
||||
<< "* Otherwise, the file name is appended with a zero-padded page range\n"
|
||||
<< " preceded by a dash.\n"
|
||||
<< "Page ranges are single page numbers for single-page groups or first-last\n"
|
||||
<< "for multipage groups.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Encryption Options\n"
|
||||
<< "------------------\n"
|
||||
<< "\n"
|
||||
<< " --encrypt user-password owner-password key-length flags --\n"
|
||||
<< "\n"
|
||||
<< "Note that -- terminates parsing of encryption flags.\n"
|
||||
<< "\n"
|
||||
<< "Either or both of the user password and the owner password may be\n"
|
||||
<< "empty strings.\n"
|
||||
<< "\n"
|
||||
<< "key-length may be 40, 128, or 256\n"
|
||||
<< "\n"
|
||||
<< "Additional flags are dependent upon key length.\n"
|
||||
<< "\n"
|
||||
<< " If 40:\n"
|
||||
<< "\n"
|
||||
<< " --print=[yn] allow printing\n"
|
||||
<< " --modify=[yn] allow document modification\n"
|
||||
<< " --extract=[yn] allow text/graphic extraction\n"
|
||||
<< " --annotate=[yn] allow comments and form fill-in and signing\n"
|
||||
<< "\n"
|
||||
<< " If 128:\n"
|
||||
<< "\n"
|
||||
<< " --accessibility=[yn] allow accessibility to visually impaired\n"
|
||||
<< " --extract=[yn] allow other text/graphic extraction\n"
|
||||
<< " --print=print-opt control printing access\n"
|
||||
<< " --assemble=[yn] allow document assembly\n"
|
||||
<< " --annotate=[yn] allow commenting/filling form fields\n"
|
||||
<< " --form=[yn] allow filling form fields\n"
|
||||
<< " --modify-other=[yn] allow other modifications\n"
|
||||
<< " --modify=modify-opt control modify access (old way)\n"
|
||||
<< " --cleartext-metadata prevents encryption of metadata\n"
|
||||
<< " --use-aes=[yn] indicates whether to use AES encryption\n"
|
||||
<< " --force-V4 forces use of V=4 encryption handler\n"
|
||||
<< "\n"
|
||||
<< " If 256, options are the same as 128 with these exceptions:\n"
|
||||
<< " --force-V4 this option is not available with 256-bit keys\n"
|
||||
<< " --use-aes this option is always on with 256-bit keys\n"
|
||||
<< " --force-R5 forces use of deprecated R=5 encryption\n"
|
||||
<< " --allow-insecure allow the owner password to be empty when the\n"
|
||||
<< " user password is not empty\n"
|
||||
<< "\n"
|
||||
<< " print-opt may be:\n"
|
||||
<< "\n"
|
||||
<< " full allow full printing\n"
|
||||
<< " low allow only low-resolution printing\n"
|
||||
<< " none disallow printing\n"
|
||||
<< "\n"
|
||||
<< " modify-opt may be:\n"
|
||||
<< "\n"
|
||||
<< " all allow full document modification\n"
|
||||
<< " annotate allow comment authoring and form operations\n"
|
||||
<< " form allow form field fill-in and signing\n"
|
||||
<< " assembly allow document assembly only\n"
|
||||
<< " none allow no modifications\n"
|
||||
<< "\n"
|
||||
<< "The default for each permission option is to be fully permissive. Please\n"
|
||||
<< "refer to the manual for more details on the modify options.\n"
|
||||
<< "\n"
|
||||
<< "Specifying cleartext-metadata forces the PDF version to at least 1.5.\n"
|
||||
<< "Specifying use of AES forces the PDF version to at least 1.6. These\n"
|
||||
<< "options are both off by default.\n"
|
||||
<< "\n"
|
||||
<< "The --force-V4 flag forces the V=4 encryption handler introduced in PDF 1.5\n"
|
||||
<< "to be used even if not otherwise needed. This option is primarily useful\n"
|
||||
<< "for testing qpdf and has no other practical use.\n"
|
||||
<< "\n"
|
||||
<< "A warning will be issued if you attempt to encrypt a file with a format that\n"
|
||||
<< "uses a weak cryptographic algorithm such as RC4. To suppress the warning,\n"
|
||||
<< "specify the option --allow-weak-crypto. This option is outside of encryption\n"
|
||||
<< "options (e.g. --allow-week-crypto --encrypt u o 128 --)\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Password Modes\n"
|
||||
<< "--------------\n"
|
||||
<< "\n"
|
||||
<< "The --password-mode controls how qpdf interprets passwords supplied\n"
|
||||
<< "on the command-line. qpdf's default behavior is correct in almost all\n"
|
||||
<< "cases, but you can fine-tune with this option.\n"
|
||||
<< "\n"
|
||||
<< " bytes: use the password literally as supplied\n"
|
||||
<< " hex-bytes: interpret the password as a hex-encoded byte string\n"
|
||||
<< " unicode: interpret the password as a UTF-8 encoded string\n"
|
||||
<< " auto: attempt to infer the encoding and adjust as needed\n"
|
||||
<< "\n"
|
||||
<< "This is a complex topic. See the manual for a complete discussion.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Page Selection Options\n"
|
||||
<< "----------------------\n"
|
||||
<< "\n"
|
||||
<< "These options allow pages to be selected from one or more PDF files.\n"
|
||||
<< "Whatever file is given as the primary input file is used as the\n"
|
||||
<< "starting point, but its pages are replaced with pages as specified.\n"
|
||||
<< "\n"
|
||||
<< "--keep-files-open=[yn]\n"
|
||||
<< "--keep-files-open-threshold=count\n"
|
||||
<< "--pages file [ --password=password ] [ page-range ] ... --\n"
|
||||
<< "\n"
|
||||
<< "For each file that pages should be taken from, specify the file, a\n"
|
||||
<< "password needed to open the file (if any), and a page range. The\n"
|
||||
<< "password needs to be given only once per file. If any of the input\n"
|
||||
<< "files are the same as the primary input file or the file used to copy\n"
|
||||
<< "encryption parameters (if specified), you do not need to repeat the\n"
|
||||
<< "password here. The same file can be repeated multiple times. The\n"
|
||||
<< "filename \".\" may be used to refer to the current input file. All\n"
|
||||
<< "non-page data (info, outlines, page numbers, etc. are taken from the\n"
|
||||
<< "primary input file. To discard this, use --empty as the primary\n"
|
||||
<< "input.\n"
|
||||
<< "\n"
|
||||
<< "By default, when more than 200 distinct files are specified, qpdf will\n"
|
||||
<< "close each file when not being referenced. With 200 files or fewer, all\n"
|
||||
<< "files will be kept open at the same time. This behavior can be overridden\n"
|
||||
<< "by specifying --keep-files-open=[yn]. Closing and opening files can have\n"
|
||||
<< "very high overhead on certain file systems, especially networked file\n"
|
||||
<< "systems. The threshold of 200 can be modified with\n"
|
||||
<< "--keep-files-open-threshold\n"
|
||||
<< "\n"
|
||||
<< "The page range is a set of numbers separated by commas, ranges of\n"
|
||||
<< "numbers separated dashes, or combinations of those. The character\n"
|
||||
<< "\"z\" represents the last page. A number preceded by an \"r\" indicates\n"
|
||||
<< "to count from the end, so \"r3-r1\" would be the last three pages of the\n"
|
||||
<< "document. Pages can appear in any order. Ranges can appear with a\n"
|
||||
<< "high number followed by a low number, which causes the pages to appear in\n"
|
||||
<< "reverse. Numbers may be repeated. A page range may be appended with :odd\n"
|
||||
<< "to indicate odd pages in the selected range or :even to indicate even\n"
|
||||
<< "pages.\n"
|
||||
<< "\n"
|
||||
<< "If the page range is omitted, the range of 1-z is assumed. qpdf decides\n"
|
||||
<< "that the page range is omitted if the range argument is either -- or a\n"
|
||||
<< "valid file name and not a valid range.\n"
|
||||
<< "\n"
|
||||
<< "The usual behavior of --pages is to add all pages from the first file,\n"
|
||||
<< "then all pages from the second file, and so on. If the --collate option\n"
|
||||
<< "is specified, then pages are collated instead. In other words, qpdf takes\n"
|
||||
<< "the first page from the first file, the first page from the second file,\n"
|
||||
<< "and so on until it runs out of files; then it takes the second page from\n"
|
||||
<< "each file, etc. When a file runs out of pages, it is skipped until all\n"
|
||||
<< "specified pages are taken from all files.\n"
|
||||
<< "\n"
|
||||
<< "See the manual for examples and a discussion of additional subtleties.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Overlay and Underlay Options\n"
|
||||
<< "----------------------------\n"
|
||||
<< "\n"
|
||||
<< "These options allow pages from another file to be overlaid or underlaid\n"
|
||||
<< "on the primary output. Overlaid pages are drawn on top of the destination\n"
|
||||
<< "page and may obscure the page. Underlaid pages are drawn below the\n"
|
||||
<< "destination page.\n"
|
||||
<< "\n"
|
||||
<< "{--overlay | --underlay } file\n"
|
||||
" [ --password=password ]\n"
|
||||
" [ --to=page-range ]\n"
|
||||
" [ --from=[page-range] ]\n"
|
||||
" [ --repeat=page-range ]\n"
|
||||
" --\n"
|
||||
<< "\n"
|
||||
<< "For overlay and underlay, a file and optional password are specified, along\n"
|
||||
<< "with a series of optional page ranges. The default behavior is that each\n"
|
||||
<< "page of the overlay or underlay file is imposed on the corresponding page\n"
|
||||
<< "of the primary output until it runs out of pages, and any extra pages are\n"
|
||||
<< "ignored. The page range options all take page ranges in the same form as\n"
|
||||
<< "the --pages option. They have the following meanings:\n"
|
||||
<< "\n"
|
||||
<< " --to: the pages in the primary output to which overlay/underlay is\n"
|
||||
<< " applied\n"
|
||||
<< " --from: the pages from the overlay/underlay file that are used\n"
|
||||
<< " --repeat: pages from the overlay/underlay that are repeated after\n"
|
||||
<< " any \"from\" pages have been exhausted\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Embedded Files/Attachments Options\n"
|
||||
<< "----------------------------------\n"
|
||||
<< "\n"
|
||||
<< "These options can be used to work with embedded files, also known as\n"
|
||||
<< "attachments.\n"
|
||||
<< "\n"
|
||||
<< "--list-attachments show key and stream number for embedded files;\n"
|
||||
<< " combine with --verbose for more detailed information\n"
|
||||
<< "--show-attachment=key write the contents of the specified attachment to\n"
|
||||
<< " standard output as binary data\n"
|
||||
<< "--add-attachment file options --\n"
|
||||
<< " add or replace an attachment\n"
|
||||
<< "--remove-attachment=key remove the specified attachment; repeatable\n"
|
||||
<< "--copy-attachments-from file options --\n"
|
||||
<< " copy attachments from another file\n"
|
||||
<< "\n"
|
||||
<< "The \"key\" option is the unique name under which the attachment is registered\n"
|
||||
<< "within the PDF file. You can get this using the --list-attachments option. This\n"
|
||||
<< "is usually the same as the filename, but it doesn't have to be.\n"
|
||||
<< "\n"
|
||||
<< "Options for adding attachments:\n"
|
||||
<< "\n"
|
||||
<< " file path to the file to attach\n"
|
||||
<< " --key=key the name of this in the embedded files table;\n"
|
||||
<< " defaults to the last path element of file\n"
|
||||
<< " --filename=name the file name of the attachment; this is what is\n"
|
||||
<< " usually displayed to the user; defaults to the\n"
|
||||
<< " last path element of file\n"
|
||||
<< " --creationdate=date creation date in PDF format; defaults to the\n"
|
||||
<< " current time\n"
|
||||
<< " --moddate=date modification date in PDF format; defaults to the\n"
|
||||
<< " current time\n"
|
||||
<< " --mimetype=type/subtype mime type of attachment (e.g. application/pdf)\n"
|
||||
<< " --description=\"text\" attachment description\n"
|
||||
<< " --replace replace any existing attachment with the same key\n"
|
||||
<< "\n"
|
||||
<< "Options for copying attachments:\n"
|
||||
<< "\n"
|
||||
<< " file file whose attachments should be copied\n"
|
||||
<< " --password=password password to open the other file, if needed\n"
|
||||
<< " --prefix=prefix a prefix to insert in front of each key;\n"
|
||||
<< " required if needed to ensure each attachment\n"
|
||||
<< " has a unique key\n"
|
||||
<< "\n"
|
||||
<< "Date format: D:yyyymmddhhmmss<z> where <z> is either Z for UTC or a timezone\n"
|
||||
<< "offset in the form -hh'mm' or +hh'mm'.\n"
|
||||
<< "Examples: D:20210207161528-05'00', D:20210207211528Z\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Advanced Parsing Options\n"
|
||||
<< "------------------------\n"
|
||||
<< "\n"
|
||||
<< "These options control aspects of how qpdf reads PDF files. Mostly these are\n"
|
||||
<< "of use to people who are working with damaged files. There is little reason\n"
|
||||
<< "to use these options unless you are trying to solve specific problems.\n"
|
||||
<< "\n"
|
||||
<< "--suppress-recovery prevents qpdf from attempting to recover damaged files\n"
|
||||
<< "--ignore-xref-streams tells qpdf to ignore any cross-reference streams\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Advanced Transformation Options\n"
|
||||
<< "-------------------------------\n"
|
||||
<< "\n"
|
||||
<< "These transformation options control fine points of how qpdf creates\n"
|
||||
<< "the output file. Mostly these are of use only to people who are very\n"
|
||||
<< "familiar with the PDF file format or who are PDF developers.\n"
|
||||
<< "\n"
|
||||
<< "--stream-data=option controls transformation of stream data (below)\n"
|
||||
<< "--compress-streams=[yn] controls whether to compress streams on output\n"
|
||||
<< "--decode-level=option controls how to filter streams from the input\n"
|
||||
<< "--recompress-flate recompress streams already compressed with Flate\n"
|
||||
<< "--compression-level=n set zlib compression level; most effective with\n"
|
||||
<< " --recompress-flate --object-streams=generate\n"
|
||||
<< "--normalize-content=[yn] enables or disables normalization of content streams\n"
|
||||
<< "--object-streams=mode controls handing of object streams\n"
|
||||
<< "--preserve-unreferenced preserve unreferenced objects\n"
|
||||
<< "--remove-unreferenced-resources={auto,yes,no}\n"
|
||||
<< " whether to remove unreferenced page resources\n"
|
||||
<< "--preserve-unreferenced-resources\n"
|
||||
<< " synonym for --remove-unreferenced-resources=no\n"
|
||||
<< "--newline-before-endstream always put a newline before endstream\n"
|
||||
<< "--coalesce-contents force all pages' content to be a single stream\n"
|
||||
<< "--flatten-annotations=option\n"
|
||||
<< " incorporate rendering of annotations into page\n"
|
||||
<< " contents including those for interactive form\n"
|
||||
<< " fields; may also want --generate-appearances\n"
|
||||
<< "--generate-appearances generate appearance streams for form fields\n"
|
||||
<< "--optimize-images compress images with DCT (JPEG) when advantageous\n"
|
||||
<< "--oi-min-width=w do not optimize images whose width is below w;\n"
|
||||
<< " default is 128. Use 0 to mean no minimum\n"
|
||||
<< "--oi-min-height=h do not optimize images whose height is below h\n"
|
||||
<< " default is 128. Use 0 to mean no minimum\n"
|
||||
<< "--oi-min-area=a do not optimize images whose pixel count is below a\n"
|
||||
<< " default is 16,384. Use 0 to mean no minimum\n"
|
||||
<< "--externalize-inline-images convert inline images to regular images; by\n"
|
||||
<< " default, images of at least 1,024 bytes are\n"
|
||||
<< " externalized\n"
|
||||
<< "--ii-min-bytes=bytes specify minimum size of inline images to be\n"
|
||||
<< " converted to regular images\n"
|
||||
<< "--keep-inline-images exclude inline images from image optimization\n"
|
||||
<< "--remove-page-labels remove any page labels present in the output file\n"
|
||||
<< "--qdf turns on \"QDF mode\" (below)\n"
|
||||
<< "--linearize-pass1=file write intermediate pass of linearized file\n"
|
||||
<< " for debugging\n"
|
||||
<< "--min-version=version sets the minimum PDF version of the output file\n"
|
||||
<< "--force-version=version forces this to be the PDF version of the output file\n"
|
||||
<< "\n"
|
||||
<< "Options for --flatten-annotations are all, print, or screen. If the option\n"
|
||||
<< "is print, only annotations marked as print are included. If the option is\n"
|
||||
<< "screen, options marked as \"no view\" are excluded. Otherwise, annotations\n"
|
||||
<< "are flattened regardless of the presence of print or NoView flags. It is\n"
|
||||
<< "common for PDF files to have a flag set that appearance streams need to be\n"
|
||||
<< "regenerated. This happens when someone changes a form value with software\n"
|
||||
<< "that does not know how to render the new value. qpdf will not flatten form\n"
|
||||
<< "fields in files like this. If you get this warning, you have two choices:\n"
|
||||
<< "either use qpdf's --generate-appearances flag to tell qpdf to go ahead and\n"
|
||||
<< "regenerate appearances, or use some other tool to generate the appearances.\n"
|
||||
<< "qpdf does a pretty good job with most forms when only ASCII and \"Windows\n"
|
||||
<< "ANSI\" characters are used in form field values, but if your form fields\n"
|
||||
<< "contain other characters, rich text, or are other than left justified, you\n"
|
||||
<< "will get better results first saving with other software.\n"
|
||||
<< "\n"
|
||||
<< "Version numbers may be expressed as major.minor.extension-level, so 1.7.3\n"
|
||||
<< "means PDF version 1.7 at extension level 3.\n"
|
||||
<< "\n"
|
||||
<< "Values for stream data options:\n"
|
||||
<< "\n"
|
||||
<< " compress recompress stream data when possible (default)\n"
|
||||
<< " preserve leave all stream data as is\n"
|
||||
<< " uncompress uncompress stream data when possible\n"
|
||||
<< "\n"
|
||||
<< "Values for object stream mode:\n"
|
||||
<< "\n"
|
||||
<< " preserve preserve original object streams (default)\n"
|
||||
<< " disable don't write any object streams\n"
|
||||
<< " generate use object streams wherever possible\n"
|
||||
<< "\n"
|
||||
<< "When --compress-streams=n is specified, this overrides the default behavior\n"
|
||||
<< "of qpdf, which is to attempt compress uncompressed streams. Setting\n"
|
||||
<< "stream data mode to uncompress or preserve has the same effect.\n"
|
||||
<< "\n"
|
||||
<< "The --decode-level parameter may be set to one of the following values:\n"
|
||||
<< " none do not decode streams\n"
|
||||
<< " generalized decode streams compressed with generalized filters\n"
|
||||
<< " including LZW, Flate, and the ASCII encoding filters.\n"
|
||||
<< " specialized additionally decode streams with non-lossy specialized\n"
|
||||
<< " filters including RunLength\n"
|
||||
<< " all additionally decode streams with lossy filters\n"
|
||||
<< " including DCT (JPEG)\n"
|
||||
<< "\n"
|
||||
<< "In qdf mode, by default, content normalization is turned on, and the\n"
|
||||
<< "stream data mode is set to uncompress. QDF mode does not support\n"
|
||||
<< "linearized files. The --linearize flag disables qdf mode.\n"
|
||||
<< "\n"
|
||||
<< "Setting the minimum PDF version of the output file may raise the version\n"
|
||||
<< "but will never lower it. Forcing the PDF version of the output file may\n"
|
||||
<< "set the PDF version to a lower value than actually allowed by the file's\n"
|
||||
<< "contents. You should only do this if you have no other possible way to\n"
|
||||
<< "open the file or if you know that the file definitely doesn't include\n"
|
||||
<< "features not supported later versions.\n"
|
||||
<< "\n"
|
||||
<< "Testing, Inspection, and Debugging Options\n"
|
||||
<< "------------------------------------------\n"
|
||||
<< "\n"
|
||||
<< "These options can be useful for digging into PDF files or for use in\n"
|
||||
<< "automated test suites for software that uses the qpdf library.\n"
|
||||
<< "\n"
|
||||
<< "--deterministic-id generate deterministic /ID\n"
|
||||
<< "--static-id generate static /ID: FOR TESTING ONLY!\n"
|
||||
<< "--static-aes-iv use a static initialization vector for AES-CBC\n"
|
||||
<< " This is option is not secure! FOR TESTING ONLY!\n"
|
||||
<< "--no-original-object-ids suppress original object ID comments in qdf mode\n"
|
||||
<< "--show-encryption quickly show encryption parameters\n"
|
||||
<< "--show-encryption-key when showing encryption, reveal the actual key\n"
|
||||
<< "--check-linearization check file integrity and linearization status\n"
|
||||
<< "--show-linearization check and show all linearization data\n"
|
||||
<< "--show-xref show the contents of the cross-reference table\n"
|
||||
<< "--show-object=trailer|obj[,gen]\n"
|
||||
<< " show the contents of the given object\n"
|
||||
<< " --raw-stream-data show raw stream data instead of object contents\n"
|
||||
<< " --filtered-stream-data show filtered stream data instead of object contents\n"
|
||||
<< "--show-npages print the number of pages in the file\n"
|
||||
<< "--show-pages shows the object/generation number for each page\n"
|
||||
<< " --with-images also shows the object IDs for images on each page\n"
|
||||
<< "--check check file structure + encryption, linearization\n"
|
||||
<< "--json generate a json representation of the file\n"
|
||||
<< "--json-help describe the format of the json representation\n"
|
||||
<< "--json-key=key repeatable; prune json structure to include only\n"
|
||||
<< " specified keys. If absent, all keys are shown\n"
|
||||
<< "--json-object=trailer|[obj,gen]\n"
|
||||
<< " repeatable; include only specified objects in the\n"
|
||||
<< " \"objects\" section of the json. If absent, all\n"
|
||||
<< " objects are shown\n"
|
||||
<< "\n"
|
||||
<< "The json representation generated by qpdf is designed to facilitate\n"
|
||||
<< "processing of qpdf from other programming languages that have a hard\n"
|
||||
<< "time calling C++ APIs. Run qpdf --json-help for details on the format.\n"
|
||||
<< "The manual has more in-depth information about the json representation\n"
|
||||
<< "and certain compatibility guarantees that qpdf provides.\n"
|
||||
<< "\n"
|
||||
<< "The --raw-stream-data and --filtered-stream-data options are ignored\n"
|
||||
<< "unless --show-object is given. Either of these options will cause the\n"
|
||||
<< "stream data to be written to standard output.\n"
|
||||
<< "\n"
|
||||
<< "If --filtered-stream-data is given and --normalize-content=y is also\n"
|
||||
<< "given, qpdf will attempt to normalize the stream data as if it is a\n"
|
||||
<< "page content stream. This attempt will be made even if it is not a\n"
|
||||
<< "page content stream, in which case it will produce unusable results.\n"
|
||||
<< "\n"
|
||||
<< "Ordinarily, qpdf exits with a status of 0 on success or a status of 2\n"
|
||||
<< "if any errors occurred. If there were warnings but not errors, qpdf\n"
|
||||
<< "exits with a status of 3. If warnings would have been issued but --no-warn\n"
|
||||
<< "was given, an exit status of 3 is still used. If you want qpdf to exit\n"
|
||||
<< "with status 0 when there are warnings, use the --warning-exit-0 flag.\n"
|
||||
<< "When --no-warn and --warning-exit-0 are used together, the effect is for\n"
|
||||
<< "qpdf to completely ignore warnings. qpdf does not use exit status 1,\n"
|
||||
<< "since that is used by the shell if it can't execute qpdf.\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ArgParser::argJsonHelp()
|
||||
{
|
||||
|
822
libqpdf/qpdf/auto_job_help.hh
Normal file
822
libqpdf/qpdf/auto_job_help.hh
Normal file
@ -0,0 +1,822 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
static void add_help_1(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addHelpTopic("usage", "basic invocation", R"(Read a PDF file, apply transformations or modifications, and write
|
||||
a new PDF file.
|
||||
|
||||
Usage: qpdf infile [options] [outfile]
|
||||
OR qpdf help-option
|
||||
|
||||
- infile, options, and outfile may be in any order as long as infile
|
||||
precedes outfile.
|
||||
- Use --empty in place of an input file for a zero-page, empty input
|
||||
- Use --replace-input in place of an output file to overwrite the
|
||||
input file with the output
|
||||
- outfile may be - to write to stdout; reading from stdin is not supported
|
||||
- @filename is an argument file; each line is treated as a separate
|
||||
command-line argument
|
||||
- @- may be used to read arguments from stdin
|
||||
- Later options may override earlier options if contradictory
|
||||
)");
|
||||
ap.addOptionHelp("--empty", "usage", "empty input file", R"(Use in place of infile for an empty input. Especially useful
|
||||
with --pages.
|
||||
)");
|
||||
ap.addOptionHelp("--replace-input", "usage", "replace input with output", R"(Use in place of outfile to overwrite the input file with the output.
|
||||
)");
|
||||
ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
|
||||
|
||||
0: no errors or warnings
|
||||
1: not used by qpdf but may be used by the shell if unable to invoke qpdf
|
||||
2: errors detected
|
||||
3: warnings detected, unless --warning-exit-0 is given
|
||||
)");
|
||||
ap.addOptionHelp("--warning-exit-0", "exit-status", "exit 0 even with warnings", R"(Use exit status 0 instead of 3 when warnings are present. When
|
||||
combined with --no-warn, warnings are completely ignored.
|
||||
)");
|
||||
ap.addHelpTopic("completion", "shell completion", R"(Shell completion is supported with bash and zsh. Use
|
||||
eval $(qpdf --completion-bash) or eval $(qpdf --completion-zsh)
|
||||
to enable. The QPDF_EXECUTABLE environment variable overrides the
|
||||
path to qpdf that these commands output.
|
||||
)");
|
||||
ap.addOptionHelp("--completion-bash", "completion", "enable bash completion", R"(Output a command that enables bash completion
|
||||
)");
|
||||
ap.addOptionHelp("--completion-zsh", "completion", "enable zsh completion", R"(Output a command that enables zsh completion
|
||||
)");
|
||||
ap.addHelpTopic("help", "information about qpdf", R"(Help options provide some information about qpdf itself. Help
|
||||
options are only valid as the first and only command-line argument.
|
||||
)");
|
||||
ap.addOptionHelp("--help", "help", "provide help", R"(Display help information. Run qpdf --help for information about
|
||||
how to get help on various topics.
|
||||
)");
|
||||
ap.addOptionHelp("--version", "help", "show qpdf version", R"(Display the version of qpdf.
|
||||
)");
|
||||
ap.addOptionHelp("--copyright", "help", "show copyright information", R"(Display copyright and license information.
|
||||
)");
|
||||
ap.addOptionHelp("--show-crypto", "help", "show available crypto providers", R"(Show a list of available crypto providers, one per line. The
|
||||
default provider is shown first.
|
||||
)");
|
||||
ap.addHelpTopic("general", "general options", R"(General options control qpdf's behavior in ways that are not
|
||||
directly related to the operation it is performing.
|
||||
)");
|
||||
ap.addOptionHelp("--password", "general", "specify password", R"(--password=password
|
||||
|
||||
Specify a password for an encrypted, password-protected file.
|
||||
Not needed for encrypted files with no password.
|
||||
)");
|
||||
ap.addOptionHelp("--password-file", "general", "read password from a file", R"(--password-file=filename
|
||||
|
||||
The first line of the specified file is used as the password.
|
||||
This is used in place of the --password option.
|
||||
)");
|
||||
ap.addOptionHelp("--verbose", "general", "print additional information", R"(Output additional information about various things qpdf is
|
||||
doing, including information about files created and operations
|
||||
performed.
|
||||
)");
|
||||
ap.addOptionHelp("--progress", "general", "show progress when writing", R"(Indicate progress when writing files.
|
||||
)");
|
||||
ap.addOptionHelp("--no-warn", "general", "suppress printing warning messages", R"(Suppress printing warning messages. If warnings were
|
||||
encountered, qpdf still exits with exit status 3.
|
||||
Use --warning-exit-0 with --no-warn to completely ignore
|
||||
warnings.
|
||||
)");
|
||||
}
|
||||
static void add_help_2(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addOptionHelp("--deterministic-id", "general", "generate ID deterministically", R"(Generate a secure, random document ID only using static
|
||||
information, such as the page contents. Does not use the file's
|
||||
name or attributes or the current time.
|
||||
)");
|
||||
ap.addOptionHelp("--allow-weak-crypto", "general", "allow insecure cryptographic algorithms", R"(All creation of files with weak cryptographic algorithms. This
|
||||
option is necessary to create 40-bit files or 128-bit files that
|
||||
use RC4 encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--keep-files-open", "general", "manage keeping multiple files open", R"(--keep-files-open=[yn]
|
||||
|
||||
When qpdf needs to work with many files, as when merging large
|
||||
numbers of files, explicitly indicate whether files should be
|
||||
kept open. The default behavior is to determine this based on
|
||||
the number of files.
|
||||
)");
|
||||
ap.addOptionHelp("--keep-files-open-threshold", "general", "set threshold for --keep-files-open", R"(--keep-files-open-threshold=count
|
||||
|
||||
Set the threshold used by --keep-files-open, overriding the
|
||||
default value of 200.
|
||||
)");
|
||||
ap.addHelpTopic("advanced-control", "tweak qpdf's behavior", R"(Advanced control options control qpdf's behavior in ways that would
|
||||
normally never be needed by a user but that may be useful to
|
||||
developers or people investigating problems with specific files.
|
||||
)");
|
||||
ap.addOptionHelp("--password-is-hex-key", "advanced-control", "provide hex-encoded encryption key", R"(Provide the underlying file encryption key has a hex-encoded
|
||||
string rather than supplying a password. This is an expert
|
||||
option.
|
||||
)");
|
||||
ap.addOptionHelp("--suppress-password-recovery", "advanced-control", "don't try different password encodings", R"(Suppress qpdf's behavior of attempting different encodings of a
|
||||
password that contains non-ASCII Unicode characters if the first
|
||||
attempt doesn't succeed.
|
||||
)");
|
||||
ap.addOptionHelp("--password-mode", "advanced-control", "tweak how qpdf encodes passwords", R"(--password-mode={mode}
|
||||
|
||||
Fine-tune how qpdf controls encoding of Unicode passwords. Valid
|
||||
options are auto, bytes, hex-bytes, and unicode.
|
||||
)");
|
||||
ap.addOptionHelp("--suppress-recovery", "advanced-control", "suppress error recovery", R"(Avoid attempting to recover when errors are found in a file's
|
||||
cross reference table or stream lengths.
|
||||
)");
|
||||
ap.addOptionHelp("--ignore-xref-streams", "advanced-control", "use xref tables rather than streams", R"(Ignore any cross-reference streams in the file, falling back to
|
||||
cross-reference tables or triggering document recovery.
|
||||
)");
|
||||
ap.addHelpTopic("transformation", "make structural PDF changes", R"(The options below tell qpdf to apply transformations that change
|
||||
the structure without changing the content.
|
||||
)");
|
||||
ap.addOptionHelp("--linearize", "transformation", "linearize (web-optimize) output", R"(Create linearized (web-optimized) output files.
|
||||
)");
|
||||
ap.addOptionHelp("--encrypt", "transformation", "start encryption options", R"(--encrypt user owner key-length [ options ] --
|
||||
|
||||
Run qpdf --help=encryption for details.
|
||||
)");
|
||||
ap.addOptionHelp("--decrypt", "transformation", "remove encryption from input file", R"(Create an unencrypted output file even if the input file was
|
||||
encrypted. Normally qpdf preserves whatever encryption was
|
||||
present on the input file. This option overrides that behavior.
|
||||
)");
|
||||
ap.addOptionHelp("--copy-encryption", "transformation", "copy another file's encryption details", R"(--copy-encryption=file
|
||||
|
||||
Copy encryption details from the specified file instead of
|
||||
preserving the input file's encryption. Use --encryption-file-password
|
||||
to specify the encryption file's password.
|
||||
)");
|
||||
ap.addOptionHelp("--encryption-file-password", "transformation", "supply password for --copy-encryption", R"(--encryption-file-password=password
|
||||
|
||||
If the file named in --copy-encryption requires a password, use
|
||||
this option to specify the password.
|
||||
)");
|
||||
ap.addOptionHelp("--qdf", "transformation", "enable viewing PDF code in a text editor", R"(Create a PDF file suitable for viewing in a text editor and even
|
||||
editing. This is to edit the PDF code, not the page contents.
|
||||
All streams that can be uncompressed are uncompressed, and
|
||||
content streams are normalized, among other changes. The
|
||||
companion tool "fix-qdf" can be used to repair hand-edited QDF
|
||||
files. QDF is a feature specific to the qpdf tool. There is a
|
||||
chapter about it in the manual.
|
||||
)");
|
||||
ap.addOptionHelp("--no-original-object-ids", "transformation", "omit original object ID in qdf", R"(Omit comments in a QDF file indicating the object ID an object
|
||||
had in the original file.
|
||||
)");
|
||||
ap.addOptionHelp("--compress-streams", "transformation", "compress uncompressed streams", R"(--compress-streams=[yn]
|
||||
|
||||
Setting --compress-streams=n prevents qpdf from compressing
|
||||
uncompressed streams. This can be useful if you are leaving some
|
||||
streams uncompressed intentionally.
|
||||
)");
|
||||
}
|
||||
static void add_help_3(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addOptionHelp("--decode-level", "transformation", "control which streams to uncompress", R"(--decode-level=option
|
||||
|
||||
When uncompressing streams, control which types of compression
|
||||
schemes should be uncompressed:
|
||||
- none: don't uncompress anything
|
||||
- generalized: uncompress streams compressed with a
|
||||
general-purpose compression algorithm. This is the default.
|
||||
- specialized: in addition to generalized, also uncompress
|
||||
streams compressed with a special-purpose but non-lossy
|
||||
compression scheme
|
||||
- all: in addition to specialized, uncompress streams compressed
|
||||
with lossy compression schemes like JPEG (DCT)
|
||||
qpdf does not know how to uncompress all compression schemes.
|
||||
)");
|
||||
ap.addOptionHelp("--stream-data", "transformation", "control stream compression", R"(--stream-data=option
|
||||
|
||||
This option controls how streams are compressed in the output.
|
||||
It is less granular than the newer options, --compress-streams
|
||||
and --decode-level.
|
||||
|
||||
Options:
|
||||
- compress: same as --compress-streams=y --decode-level=generalized
|
||||
- preserve: same as --compress-streams=n --decode-level=none
|
||||
- uncompress: same as --compress-streams=n --decode-level=generalized
|
||||
)");
|
||||
ap.addOptionHelp("--recompress-flate", "transformation", "uncompress and recompress flate", R"(The default generalized compression scheme used by PDF is flate,
|
||||
which is the same as used by zip and gzip. Usually qpdf just
|
||||
leaves these alone. This option tells qpdf to uncompress and
|
||||
recompress streams compressed with flate. This can be useful
|
||||
when combined with --compression-level.
|
||||
)");
|
||||
ap.addOptionHelp("--compression-level", "transformation", "set compression level for flate", R"(--compression-level=level
|
||||
|
||||
Set a compression level from 1 (least, fastest) to 9 (most,
|
||||
slowest) when compressing files with flate (used in zip and
|
||||
gzip), which is the default compression for most PDF files.
|
||||
You need --recompress-flate with this option if you want to
|
||||
change already compressed streams.
|
||||
)");
|
||||
ap.addOptionHelp("--normalize-content", "transformation", "fix newlines in content streams", R"(--normalize-content=[yn]
|
||||
|
||||
Normalize newlines to UNIX-style newlines in PDF content
|
||||
streams, which is useful for viewing them in a programmer's text
|
||||
editor across multiple platforms. This is also turned on by
|
||||
--qdf.
|
||||
)");
|
||||
ap.addOptionHelp("--object-streams", "transformation", "control use of object streams", R"(--object-streams=mode
|
||||
|
||||
Control what qpdf does regarding object streams. Options:
|
||||
- preserve: preserve original object streams, if any (the default)
|
||||
- disable: create output files with no object streams
|
||||
- generate: create object streams, and compress objects when possible
|
||||
)");
|
||||
ap.addOptionHelp("--preserve-unreferenced", "transformation", "preserve unreferenced objects", R"(Preserve all objects from the input even if not referenced.
|
||||
)");
|
||||
ap.addOptionHelp("--remove-unreferenced-resources", "transformation", "remove unreferenced page resources", R"(--remove-unreferenced-resources=option
|
||||
|
||||
Remove from a page's resource dictionary any resources that are
|
||||
not referenced in the page's contents. Options: "auto"
|
||||
(default), "yes", "no".
|
||||
)");
|
||||
ap.addOptionHelp("--preserve-unreferenced-resources", "transformation", "use --remove-unreferenced-resources=no", R"(Synonym for --remove-unreferenced-resources=no. Use that instead.
|
||||
)");
|
||||
ap.addOptionHelp("--newline-before-endstream", "transformation", "force a newline before endstream", R"(For an extra newline before endstream. Using this option enables
|
||||
qpdf to preserve PDF/A when rewriting such files.
|
||||
)");
|
||||
ap.addOptionHelp("--coalesce-contents", "transformation", "combine content streams", R"(If a page has an array of content streams, concatenate them into
|
||||
a single content stream.
|
||||
)");
|
||||
ap.addOptionHelp("--externalize-inline-images", "transformation", "convert inline to regular images", R"(Convert inline images to regular images.
|
||||
)");
|
||||
ap.addOptionHelp("--ii-min-bytes", "transformation", "set minimum size for --externalize-inline-images", R"(--ii-min-bytes=size-in-bytes
|
||||
|
||||
Don't externalize inline images smaller than this size. The
|
||||
default is 1,024. Use 0 for no minimum.
|
||||
)");
|
||||
ap.addOptionHelp("--min-version", "transformation", "set minimum PDF version", R"(--min-version=version
|
||||
|
||||
Force the PDF version of the output to be at least the
|
||||
specified version.
|
||||
)");
|
||||
ap.addOptionHelp("--force-version", "transformation", "set output PDF version", R"(--force-version=version
|
||||
|
||||
Force the output PDF file's PDF version header to be the specified
|
||||
value, even if the file uses features that may not be available
|
||||
in that version.
|
||||
)");
|
||||
ap.addHelpTopic("page-ranges", "page range syntax", R"(A full description of the page range syntax, with examples, can be
|
||||
found in the manual. Summary:
|
||||
|
||||
- a,b,c pages a, b, and c
|
||||
- a-b pages a through b inclusive; if a > b, this counts down
|
||||
- r<n> where <n> represents a number is the <n>th page from the end
|
||||
- z the last page, same as r1
|
||||
|
||||
You can append :even or :odd to select every other page from the
|
||||
resulting set of pages, where :odd starts with the first page and
|
||||
:even starts with the second page. These are odd and even pages
|
||||
from the resulting set, not based on the original page numbers.
|
||||
)");
|
||||
ap.addHelpTopic("modification", "change parts of the PDF", R"(Modification options make systematic changes to certain parts of
|
||||
the PDF, causing the PDF to render differently from the original.
|
||||
)");
|
||||
ap.addOptionHelp("--pages", "modification", "begin page selection", R"(--pages file [ --password=password ] [ page-range ] [ ... ] --
|
||||
|
||||
Run qpdf --help=page-selection for details.
|
||||
)");
|
||||
ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate=n
|
||||
|
||||
Collate rather than concatenate pages specified with --pages.
|
||||
With a numeric argument, collate in groups of n. The default
|
||||
is 1. Run qpdf --help=page-selection for additional details.
|
||||
)");
|
||||
}
|
||||
static void add_help_4(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addOptionHelp("--split-pages", "modification", "write pages to separate files", R"(--split-pages=[n]
|
||||
|
||||
This option causes qpdf to create separate output files for each
|
||||
page or group of pages rather than a single output file.
|
||||
|
||||
File names are generated from the specified output file as follows:
|
||||
|
||||
- If the string %d appears in the output file name, it is replaced with a
|
||||
zero-padded page range starting from 1
|
||||
- Otherwise, if the output file name ends in .pdf (case insensitive), a
|
||||
zero-padded page range, preceded by a dash, is inserted before the file
|
||||
extension
|
||||
- Otherwise, the file name is appended with a zero-padded page range
|
||||
preceded by a dash.
|
||||
|
||||
Page ranges are single page numbers for single-page groups or first-last
|
||||
for multi-page groups.
|
||||
)");
|
||||
ap.addOptionHelp("--overlay", "modification", "begin overlay options", R"(--overlay file [ options ] --
|
||||
|
||||
Overlay pages from another file on the output.
|
||||
Run qpdf --help=overlay-underlay for details.
|
||||
)");
|
||||
ap.addOptionHelp("--underlay", "modification", "begin underlay options", R"(--underlay file [ options ] --
|
||||
|
||||
Underlay pages from another file on the output.
|
||||
Run qpdf --help=overlay-underlay for details.
|
||||
)");
|
||||
ap.addOptionHelp("--flatten-rotation", "modification", "remove rotation from page dictionary", R"(Rotate a page using content commands instead of page-level
|
||||
metadata. This can be useful if a broken PDF viewer fails to
|
||||
properly consider page rotation metadata.
|
||||
)");
|
||||
ap.addOptionHelp("--flatten-annotations", "modification", "push annotations into content", R"(--flatten-annotations=option
|
||||
|
||||
Push page annotations into the content streams. This may be
|
||||
necessary in some case when printing or splitting files.
|
||||
Options: "all", "print", "screen".
|
||||
)");
|
||||
ap.addOptionHelp("--rotate", "modification", "rotate pages", R"(--rotate=[+|-]angle[:page-range]
|
||||
|
||||
Rotate specified pages by multiples of 90 degrees specifying
|
||||
either absolute or relative angles. "angle" may be 0, 90, 180,
|
||||
or 270. You almost always want to use +angle or -angle rather
|
||||
than just angle, as discussed in the manual. Run
|
||||
qpdf --help=page-ranges for help with page ranges.
|
||||
)");
|
||||
ap.addOptionHelp("--generate-appearances", "modification", "generate appearances for form fields", R"(PDF form fields consist of values and appearances, which may be
|
||||
inconsistent with each other if a form field value has been
|
||||
modified without updating its appearance. This option tells qpdf
|
||||
to generate new appearance streams. There are some limitations,
|
||||
which are discussed in the manual.
|
||||
)");
|
||||
ap.addOptionHelp("--optimize-images", "modification", "use efficient compression for images", R"(Attempt to use DCT (JPEG) compression for images that fall
|
||||
within certain constraints as long as doing so decreases the
|
||||
size in bytes of the image. See also help for the following
|
||||
options:
|
||||
--oi-min-width
|
||||
--oi-min-height
|
||||
--oi-min-area
|
||||
--keep-inline-images
|
||||
|
||||
The --verbose flag is useful with this option.
|
||||
)");
|
||||
ap.addOptionHelp("--oi-min-width", "modification", "minimum width for --optimize-images", R"(--oi-min-width=width
|
||||
|
||||
Don't optimize images whose width is below the specified value.
|
||||
)");
|
||||
ap.addOptionHelp("--oi-min-height", "modification", "minimum height for --optimize-images", R"(--oi-min-height=height
|
||||
|
||||
Don't optimize images whose height is below the specified value.
|
||||
)");
|
||||
ap.addOptionHelp("--oi-min-area", "modification", "minimum area for --optimize-images", R"(--oi-min-area=area-in-pixels
|
||||
|
||||
Don't optimize images whose area in pixels is below the specified value.
|
||||
)");
|
||||
ap.addOptionHelp("--keep-inline-images", "modification", "exclude inline images from optimization", R"(Prevent inline images from being considered by --optimize-images.
|
||||
)");
|
||||
ap.addOptionHelp("--remove-page-labels", "modification", "remove page labels (numbers)", R"(Exclude page labels (explicit page numbers) from the output file.
|
||||
)");
|
||||
ap.addHelpTopic("encryption", "create encrypted files", R"(Create encrypted files. Usage:
|
||||
|
||||
--encrypt user-password owner-password key-length [ options ] --
|
||||
|
||||
Either or both of user-password and owner-password may be empty
|
||||
strings. key-length may be 40, 128, or 256. Encryption options are
|
||||
terminated by "--" by itself.
|
||||
|
||||
40-bit encryption is insecure, as is 128-bit encryption without
|
||||
AES. Use 256-bit encryption unless you have a specific reason to
|
||||
use an insecure format, such as testing or compatibility with very
|
||||
old viewers. You must use the --allow-weak-crypto to create
|
||||
encrypted files that use insecure cryptographic algorithms. The
|
||||
--allow-weak-crypto flag appears outside of --encrypt ... --
|
||||
(before --encrypt or after --).
|
||||
|
||||
Available options vary by key length. Not all readers respect all
|
||||
restrictions. Different PDF readers respond differently to various
|
||||
combinations of options. Sometimes a PDF viewer may show you
|
||||
restrictions that differ from what you selected. This is probably
|
||||
not a bug in qpdf.
|
||||
|
||||
Options for 40-bit only:
|
||||
--annotate=[yn] restrict comments, filling forms, and signing
|
||||
--extract=[yn] restrict text/graphic extraction
|
||||
--modify=[yn] restrict document modification
|
||||
--print=[yn] restrict printing
|
||||
|
||||
Options for 128-bit or 256-bit:
|
||||
--accessibility=[yn] restrict accessibility (usually ignored)
|
||||
--annotate=[yn] restrict commenting/filling form fields
|
||||
--assemble=[yn] restrict document assembly
|
||||
--extract=[yn] restrict text/graphic extraction
|
||||
--form=[yn] restrict filling form fields
|
||||
--modify-other=[yn] restrict other modifications
|
||||
--modify=modify-opt control modify access by level
|
||||
--print=print-opt control printing access
|
||||
--cleartext-metadata prevent encryption of metadata
|
||||
|
||||
For 128-bit only:
|
||||
--use-aes=[yn] indicates whether to use AES encryption
|
||||
--force-V4 forces use of V=4 encryption handler
|
||||
|
||||
For 256-bit only:
|
||||
--force-R5 forces use of deprecated R=5 encryption
|
||||
--allow-insecure allow user password with empty owner password
|
||||
|
||||
Values for print-opt:
|
||||
none disallow printing
|
||||
low allow only low-resolution printing
|
||||
full allow full printing
|
||||
|
||||
Values for modify-opt:
|
||||
none allow no modifications
|
||||
assembly allow document assembly only
|
||||
form assembly + filling in form fields and signing
|
||||
annotate form + commenting and modifying forms
|
||||
all allow full document modification
|
||||
)");
|
||||
ap.addOptionHelp("--accessibility", "encryption", "restrict document accessibility", R"(--accessibility=[yn]
|
||||
|
||||
This option is ignored except with very old encryption formats.
|
||||
The current PDF specification does not allow restriction of
|
||||
document accessibility. This option is not available with 40-bit
|
||||
encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--annotate", "encryption", "restrict document annotation", R"(--annotate=[yn]
|
||||
|
||||
Enable/disable modifying annotations including making comments
|
||||
and filling in form fields. For 128-bit and 256-bit encryption,
|
||||
this also enables editing, creating, and deleting form fields
|
||||
unless --modify-other=n or --modify=none is also specified.
|
||||
)");
|
||||
ap.addOptionHelp("--assemble", "encryption", "restrict document assembly", R"(--assemble=[yn]
|
||||
|
||||
Enable/disable document assembly (rotation and reordering of
|
||||
pages). This option is not available with 40-bit encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--extract", "encryption", "restrict text/graphic extraction", R"(--extract=[yn]
|
||||
|
||||
Enable/disable text/graphic extraction for purposes other than
|
||||
accessibility.
|
||||
)");
|
||||
ap.addOptionHelp("--form", "encryption", "restrict form filling", R"(--form=[yn]
|
||||
|
||||
Enable/disable whether filling form fields is allowed even if
|
||||
modification of annotations is disabled. This option is not
|
||||
available with 40-bit encryption.
|
||||
)");
|
||||
}
|
||||
static void add_help_5(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addOptionHelp("--modify-other", "encryption", "restrict other modifications", R"(--modify-other=[yn]
|
||||
|
||||
Enable/disable modifications not controlled by --assemble,
|
||||
--annotate, or --form. --modify-other=n is implied by any of the
|
||||
other --modify options. This option is not available with 40-bit
|
||||
encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--modify", "encryption", "restrict document modification", R"(--modify=modify-opt
|
||||
|
||||
For 40-bit files, modify-opt may only be y or n and controls all
|
||||
aspects of document modification.
|
||||
|
||||
For 128-bit and 256-bit encryption, modify-opt values allow
|
||||
enabling and disabling levels of restriction in a manner similar
|
||||
to how some PDF creation tools do it. modify-opt values map to
|
||||
other combinations of options as follows:
|
||||
|
||||
all: allow full modification (the default)
|
||||
annotate: --modify-other=n
|
||||
form: --modify-other=n --annotate=n
|
||||
assembly: --modify-other=n --annotate=n --form=n
|
||||
none: --modify-other=n --annotate=n --form=n --assemble=n
|
||||
)");
|
||||
ap.addOptionHelp("--print", "encryption", "restrict printing", R"(--print=print-opt
|
||||
|
||||
Control what kind of printing is allowed. For 40-bit encryption,
|
||||
print-opt may only be y or n and enables or disables all
|
||||
printing. For 128-bit and 256-bit encryption, print-opt may have
|
||||
the following values:
|
||||
|
||||
none: disallow printing
|
||||
low: allow low-resolution printing only
|
||||
full: allow full printing (the default)
|
||||
)");
|
||||
ap.addOptionHelp("--cleartext-metadata", "encryption", "don't encrypt metadata", R"(If specified, don't encrypt document metadata even when
|
||||
encrypting the rest of the document. This option is not
|
||||
available with 40-bit encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--use-aes", "encryption", "use AES with 128-bit encryption", R"(--use-aes=[yn]
|
||||
|
||||
Enables/disables use of the more secure AES encryption with
|
||||
128-bit encryption. Specifying --use-aes=y forces the PDF
|
||||
version to be at least 1.6. This option is only available with
|
||||
128-bit encryption. The default is "n" for compatibility
|
||||
reasons. Use 256-bit encryption instead.
|
||||
)");
|
||||
ap.addOptionHelp("--allow-insecure", "encryption", "allow empty owner passwords", R"(Allow creation of PDF files with empty owner passwords and
|
||||
non-empty user passwords when using 256-bit encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--force-V4", "encryption", "force V=4 in encryption dictionary", R"(This option is for testing and is never needed in practice since
|
||||
qpdf does this automatically when needed.
|
||||
)");
|
||||
ap.addOptionHelp("--force-R5", "encryption", "use unsupported R=5 encryption", R"(Use an undocumented, unsupported, deprecated encryption
|
||||
algorithm that existed only in Acrobat version IX. This option
|
||||
should not be used except for compatibility testing.
|
||||
)");
|
||||
ap.addHelpTopic("page-selection", "select pages from one or more files", R"(Use the --pages option to select pages from multiple files. Usage:
|
||||
|
||||
qpdf in.pdf --pages input-file [ --password=password ] [ page-range ] \
|
||||
[ ... ] -- out.pdf
|
||||
|
||||
Between --pages and the -- that terminates pages option, repeat
|
||||
the following:
|
||||
|
||||
filename [ --password=password ] [ page-range ]
|
||||
|
||||
Document-level information, such as outlines, tags, etc., is taken
|
||||
from in.pdf is preserved in out.pdf. You can use --empty in place
|
||||
of an input file to start from an empty file and just copy pages
|
||||
equally from all files. You can use "." as a shorthand for the
|
||||
primary input file (if not --empty). In the above example, "."
|
||||
would refer to in.pdf.
|
||||
|
||||
Use --password=password to specify the password for a
|
||||
password-protected input file. If the same input file is used more
|
||||
than once, you only need to supply the password the first time. If
|
||||
the page range is omitted, all pages are selected.
|
||||
|
||||
Run qpdf --help=page-ranges for help with page ranges.
|
||||
|
||||
Use --collate=n to cause pages to be collated in groups of n pages
|
||||
(default 1) instead of concatenating the input.
|
||||
|
||||
Examples:
|
||||
|
||||
- Start with in.pdf and append all pages from a.pdf and the even
|
||||
pages from b.pdf, and write the output to out.pdf. Document-level
|
||||
information from in.pdf is retained. Note the use of "." to refer
|
||||
to in.pdf.
|
||||
|
||||
qpdf in.pdf --pages . a.pdf b.pdf:even -- out.pdf
|
||||
|
||||
- Take all the pages from a.pdf, all the pages from b.pdf in
|
||||
reverse, and only pages 3 and 6 from c.pdf and write the result
|
||||
to out.pdf. Use password "x" to open b.pdf:
|
||||
|
||||
qpdf --empty --pages a.pdf b.pdf --password=x z-1 c.pdf 3,6
|
||||
|
||||
More examples are in the manual.
|
||||
)");
|
||||
ap.addHelpTopic("overlay-underlay", "overlay/underlay pages from other files", R"(These options allow pages from another file to be overlaid or
|
||||
underlaid on the primary output. Overlaid pages are drawn on top of
|
||||
the destination page and may obscure the page. Underlaid pages are
|
||||
drawn below the destination page. Usage:
|
||||
|
||||
{--overlay | --underlay } file
|
||||
[ --password=password ]
|
||||
[ --to=page-range ]
|
||||
[ --from=[page-range] ]
|
||||
[ --repeat=page-range ]
|
||||
--
|
||||
|
||||
Note the use of "--" by itself to terminate overlay/underlay options.
|
||||
|
||||
For overlay and underlay, a file and optional password are specified, along
|
||||
with a series of optional page ranges. The default behavior is that each
|
||||
page of the overlay or underlay file is imposed on the corresponding page
|
||||
of the primary output until it runs out of pages, and any extra pages are
|
||||
ignored. You can also give a page range with --repeat to cause
|
||||
those pages to be repeated after the original pages are exhausted.
|
||||
|
||||
Run qpdf --help=page-ranges for help with page ranges.
|
||||
)");
|
||||
ap.addOptionHelp("--to", "overlay-underlay", "destination pages for underlay/overlay", R"(--to=page-range
|
||||
|
||||
Specify the range of pages in the primary output to apply
|
||||
overlay/underlay to. See qpdf --help=page-ranges for help with
|
||||
the page range syntax.
|
||||
)");
|
||||
ap.addOptionHelp("--from", "overlay-underlay", "source pages for underlay/overlay", R"(--from=[page-range]
|
||||
|
||||
Specify pages from the overlay/underlay file that are applied to
|
||||
the destination pages. See qpdf --help=page-ranges for help
|
||||
with the page range syntax. The page range may be omitted
|
||||
if --repeat is used.
|
||||
)");
|
||||
ap.addOptionHelp("--repeat", "overlay-underlay", "overlay/underlay pages to repeat", R"(--repeat=page-range
|
||||
|
||||
Specify pages from the overlay/underlay that are repeated after
|
||||
"from" pages have been exhausted. See qpdf --help=page-ranges
|
||||
for help with the page range syntax.
|
||||
)");
|
||||
ap.addHelpTopic("attachments", "work with embedded files", R"(It is possible to list, add, or delete embedded files (also known
|
||||
as attachments) and to copy attachments from other files. See help
|
||||
on individual options for details. Run qpdf --help=add-attachment
|
||||
for additional details about adding attachments.
|
||||
)");
|
||||
ap.addOptionHelp("--list-attachments", "attachments", "list embedded files", R"(Show the key and stream number for each embedded file. Combine
|
||||
with --verbose for more detailed information.
|
||||
)");
|
||||
ap.addOptionHelp("--show-attachment", "attachments", "export an embedded file", R"(--show-attachment=key
|
||||
|
||||
Write the contents of the specified attachment to standard
|
||||
output as binary data. Get the key with --list-attachments.
|
||||
)");
|
||||
ap.addOptionHelp("--add-attachment", "attachments", "start add attachment options", R"(--add-attachment file options --
|
||||
|
||||
The --add-attachment flag and its options may be repeated to add
|
||||
multiple attachments. Run qpdf --help=add-attachment for details.
|
||||
)");
|
||||
ap.addOptionHelp("--remove-attachment", "attachments", "remove an embedded file", R"(--remove-attachment=key
|
||||
|
||||
Remove an embedded file using its key. Get the key with
|
||||
--list-attachments.
|
||||
)");
|
||||
ap.addOptionHelp("--copy-attachments-from", "attachments", "start copy attachment options", R"(--copy-attachments-from file options --
|
||||
|
||||
The --copy-attachments-from flag and its options may be repeated
|
||||
to copy attachments from multiple files. Run
|
||||
qpdf --help=copy-attachments for details.
|
||||
)");
|
||||
}
|
||||
static void add_help_6(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addHelpTopic("pdf-dates", "PDF date format", R"(When a date is required, the date should conform to the PDF date
|
||||
format specification, which is "D:yyyymmddhhmmssz" where "z" is
|
||||
either literally upper case "Z" for UTC or a timezone offset in
|
||||
the form "-hh'mm'" or "+hh'mm'". Negative timezone offsets indicate
|
||||
time before UTC. Positive offsets indicate how far after. For
|
||||
example, US Eastern Standard Time (America/New_York) is "-05'00'",
|
||||
and Indian Standard Time (Asia/Calcutta) is "+05'30'".
|
||||
|
||||
Examples:
|
||||
- D:20210207161528-05'00' February 7, 2021 at 4:15:28 p.m.
|
||||
- D:20210207211528Z February 7, 2021 at 21:15:28 UTC
|
||||
)");
|
||||
ap.addHelpTopic("add-attachment", "attach (embed) files", R"(The options listed below appear between --add-attachment and its
|
||||
terminating "--".
|
||||
)");
|
||||
ap.addOptionHelp("--key", "add-attachment", "specify attachment key", R"(--key=key
|
||||
|
||||
Specify the key to use for the attachment in the embedded files
|
||||
table. It defaults to the last element of the attached file's
|
||||
filename.
|
||||
)");
|
||||
ap.addOptionHelp("--filename", "add-attachment", "set attachment's displayed filename", R"(--filename=name
|
||||
|
||||
Specify the filename to be used for the attachment. This is what
|
||||
is usually displayed to the user and is the name most graphical
|
||||
PDF viewers will use when saving a file. It defaults to the last
|
||||
element of the attached file's filename.
|
||||
)");
|
||||
ap.addOptionHelp("--creationdate", "add-attachment", "set attachment's creation date", R"(--creationdate=date
|
||||
|
||||
Specify the attachment's creation date in PDF format; defaults
|
||||
to the current time. Run qpdf --help=pdf-dates for information
|
||||
about the date format.
|
||||
)");
|
||||
ap.addOptionHelp("--moddate", "add-attachment", "set attachment's modification date", R"(--moddate=date
|
||||
|
||||
Specify the attachment's modification date in PDF format;
|
||||
defaults to the current time. Run qpdf --help=pdf-dates for
|
||||
information about the date format.
|
||||
)");
|
||||
ap.addOptionHelp("--mimetype", "add-attachment", "attachment mime type (e.g. application/pdf)", R"(--mimetype=type/subtype
|
||||
|
||||
Specify the mime type for the attachment, such as text/plain,
|
||||
application/pdf, image/png, etc.
|
||||
)");
|
||||
ap.addOptionHelp("--description", "add-attachment", "set attachment's description", R"(--description="text"
|
||||
|
||||
Supply descriptive text for the attachment, displayed by some
|
||||
PDF viewers.
|
||||
)");
|
||||
ap.addOptionHelp("--replace", "add-attachment", "replace attachment with same key", R"(Indicate that any existing attachment with the same key should
|
||||
be replaced by the new attachment. Otherwise, qpdf gives an
|
||||
error if an attachment with that key is already present.
|
||||
)");
|
||||
ap.addHelpTopic("copy-attachments", "copy attachments from another file", R"(The options listed below appear between --copy-attachments-from and
|
||||
its terminating "--".
|
||||
|
||||
To copy attachments from a password-protected file, use
|
||||
the --password option after the file name.
|
||||
)");
|
||||
ap.addOptionHelp("--prefix", "copy-attachments", "key prefix for copying attachments", R"(--prefix=prefix
|
||||
|
||||
Prepend a prefix to each key; may be needed if there are
|
||||
duplicate attachment keys. This affects the key only, not the
|
||||
file name.
|
||||
)");
|
||||
ap.addOptionHelp("--is-encrypted", "copy-attachments", "silently test whether a file is encrypted", R"(Silently exit with a code indicating the file's encryption status:
|
||||
|
||||
0: the file is encrypted
|
||||
1: not used
|
||||
2: the file is not encrypted
|
||||
|
||||
This can be used with password-protected files even if you don't
|
||||
know the password.
|
||||
)");
|
||||
ap.addOptionHelp("--requires-password", "copy-attachments", "silently test a file's password", R"(Silently exit with a code indicating the file's password status:
|
||||
|
||||
0: a password, other than as supplied, is required
|
||||
1: not used
|
||||
2: the file is not encrypted
|
||||
3: the file is encrypted, and correct password (if any) has been supplied
|
||||
)");
|
||||
ap.addOptionHelp("--check", "copy-attachments", "partially check whether PDF is valid", R"(Check the structure of the PDF file as well as a number of other
|
||||
aspects of the file, and write information about the file to
|
||||
standard output. Note that qpdf does not perform any validation
|
||||
of the actual PDF page content or semantic correctness of the
|
||||
PDF file. It merely checks that the PDF file is syntactically
|
||||
valid.
|
||||
)");
|
||||
ap.addOptionHelp("--show-encryption", "copy-attachments", "information about encrypted files", R"(Show document encryption parameters. Also show the document's
|
||||
user password if the owner password is given and the file was
|
||||
encrypted using older encryption formats that allow user
|
||||
password recovery.
|
||||
)");
|
||||
ap.addOptionHelp("--show-encryption-key", "copy-attachments", "show key with --show-encryption", R"(When used with --show-encryption, causes the underlying
|
||||
encryption key to be displayed.
|
||||
)");
|
||||
ap.addOptionHelp("--check-linearization", "copy-attachments", "check linearization tables", R"(Check to see whether a file is linearized and, if so, whether
|
||||
the linearization hint tables are correct.
|
||||
)");
|
||||
ap.addOptionHelp("--show-linearization", "copy-attachments", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
|
||||
)");
|
||||
ap.addOptionHelp("--show-xref", "copy-attachments", "show cross reference data", R"(Show the contents of the cross-reference table or stream (object
|
||||
locations in the file) in a human-readable form. This is
|
||||
especially useful for files with cross-reference streams, which
|
||||
are stored in a binary format.
|
||||
)");
|
||||
}
|
||||
static void add_help_7(QPDFArgParser& ap)
|
||||
{
|
||||
ap.addOptionHelp("--show-object", "copy-attachments", "show contents of an object", R"(--show-object=trailer|obj[,gen]
|
||||
|
||||
Show the contents of the given object. This is especially useful
|
||||
for inspecting objects that are inside of object streams (also
|
||||
known as "compressed objects").
|
||||
)");
|
||||
ap.addOptionHelp("--raw-stream-data", "copy-attachments", "show raw stream data", R"(When used with --show-object, if the object is a stream, write
|
||||
the raw (compressed) binary stream data to standard output
|
||||
instead of the object's contents. See also
|
||||
--filtered-stream-data.
|
||||
)");
|
||||
ap.addOptionHelp("--filtered-stream-data", "copy-attachments", "show filtered stream data", R"(When used with --show-object, if the object is a stream, write
|
||||
the filtered (uncompressed, potentially binary) stream data to
|
||||
standard output instead of the object's contents. See also
|
||||
--raw-stream-data.
|
||||
)");
|
||||
ap.addOptionHelp("--show-npages", "copy-attachments", "show number of pages", R"(Print the number of pages in the input file on a line by itself.
|
||||
Useful for scripts.
|
||||
)");
|
||||
ap.addOptionHelp("--show-pages", "copy-attachments", "display page dictionary information", R"(Show the object and generation number for each page dictionary
|
||||
object and for each content stream associated with the page.
|
||||
)");
|
||||
ap.addOptionHelp("--with-images", "copy-attachments", "include image details with --show-pages", R"(When used with --show-pages, also shows the object and
|
||||
generation numbers for the image objects on each page.
|
||||
)");
|
||||
ap.addHelpTopic("json", "JSON output for PDF information", R"(Show information about the PDF file in JSON format. Please see the
|
||||
JSON chapter in the qpdf manual for details.
|
||||
)");
|
||||
ap.addOptionHelp("--json", "json", "show file in json format", R"(Generate a JSON representation of the file. This is described in
|
||||
depth in the JSON section of the manual.
|
||||
)");
|
||||
ap.addOptionHelp("--json-help", "json", "show format of json output", R"(Describe the format of the JSON output.
|
||||
)");
|
||||
ap.addOptionHelp("--json-key", "json", "restrict which keys are in json output", R"(--json-key=key
|
||||
|
||||
This option is repeatable. If given, only the specified
|
||||
top-level keys will be included in the JSON output. Otherwise,
|
||||
all keys will be included.
|
||||
)");
|
||||
ap.addOptionHelp("--json-object", "json", "restrict which objects are in JSON", R"(--json-object=trailer|obj[,gen]
|
||||
|
||||
This option is repeatable. If given, only specified objects will
|
||||
be shown in the "objects" key of the JSON output. Otherwise, all
|
||||
objects will be shown.
|
||||
)");
|
||||
ap.addHelpTopic("testing", "options for testing or debugging", R"(The options below are useful when writing automated test code that
|
||||
includes files created by qpdf or when testing qpdf itself.
|
||||
)");
|
||||
ap.addOptionHelp("--static-id", "testing", "use a fixed document ID", R"(Use a fixed value for the document ID. This is intended for
|
||||
testing only. Never use it for production files. See also
|
||||
qpdf --help=--deterministic-id.
|
||||
)");
|
||||
ap.addOptionHelp("--static-aes-iv", "testing", "use a fixed AES vector", R"(Use a static initialization vector for AES-CBC. This is intended
|
||||
for testing only so that output files can be reproducible. Never
|
||||
use it for production files. This option is not secure since it
|
||||
significantly weakens the encryption.
|
||||
)");
|
||||
ap.addOptionHelp("--linearize-pass1", "testing", "save pass 1 of linearization", R"(--linearize-pass1=file
|
||||
|
||||
Write the first pass of linearization to the named file. The
|
||||
resulting file is not a valid PDF file. This option is useful only
|
||||
for debugging qpdf.
|
||||
)");
|
||||
}
|
||||
static void add_help(QPDFArgParser& ap)
|
||||
{
|
||||
add_help_1(ap);
|
||||
add_help_2(ap);
|
||||
add_help_3(ap);
|
||||
add_help_4(ap);
|
||||
add_help_5(ap);
|
||||
add_help_6(ap);
|
||||
add_help_7(ap);
|
||||
ap.addHelpFooter("For detailed help, visit the qpdf manual: https://qpdf.readthedocs.io\n");
|
||||
}
|
||||
|
@ -162,4 +162,3 @@ this->ap.copyFromOtherTable("annotate", "128-bit encryption");
|
||||
this->ap.copyFromOtherTable("form", "128-bit encryption");
|
||||
this->ap.copyFromOtherTable("modify-other", "128-bit encryption");
|
||||
this->ap.copyFromOtherTable("modify", "128-bit encryption");
|
||||
this->ap.addHelpFooter("For detailed help, visit the qpdf manual: https://qpdf.readthedocs.io\n");
|
||||
|
@ -6,7 +6,7 @@ Topics:
|
||||
baaa: Baaa Options
|
||||
quack: Quack Options
|
||||
|
||||
== topic baaa (Baaa Options) ==
|
||||
== baaa (Baaa Options) ==
|
||||
|
||||
Ewe can do sheepish things.
|
||||
For example, ewe can add more ram to your computer.
|
||||
@ -15,15 +15,15 @@ Related options:
|
||||
--ewe: just for ewe
|
||||
--ram: curly horns
|
||||
|
||||
== topic quack (Quack Options) ==
|
||||
== quack (Quack Options) ==
|
||||
|
||||
Just put stuff after quack to get a count at the end.
|
||||
|
||||
== option --ewe (just for ewe) ==
|
||||
== --ewe (just for ewe) ==
|
||||
|
||||
You are not a ewe.
|
||||
|
||||
== option --ram (curly horns) ==
|
||||
== --ram (curly horns) ==
|
||||
|
||||
curly horns
|
||||
|
||||
|
1
manual/.gitignore
vendored
Normal file
1
manual/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
__pycache__
|
125
manual/_ext/qpdf.py
Normal file
125
manual/_ext/qpdf.py
Normal file
@ -0,0 +1,125 @@
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
import re
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, Index
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util.nodes import make_refnode
|
||||
|
||||
# Reference:
|
||||
# https://www.sphinx-doc.org/en/master/development/tutorials/todo.html
|
||||
# https://www.sphinx-doc.org/en/master/development/tutorials/recipe.html
|
||||
|
||||
|
||||
class OptionDirective(ObjectDescription):
|
||||
has_content = True
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
signode += addnodes.desc_name(text=sig)
|
||||
return sig
|
||||
|
||||
def add_target_and_index(self, name_cls, sig, signode):
|
||||
m = re.match(r'^--([^= ]+)', sig)
|
||||
if not m:
|
||||
raise Exception('option must start with --')
|
||||
option_name = m.group(1)
|
||||
signode['ids'].append(f'option-{option_name}')
|
||||
qpdf = self.env.get_domain('qpdf')
|
||||
qpdf.add_option(sig, option_name)
|
||||
|
||||
|
||||
class OptionIndex(Index):
|
||||
name = 'options'
|
||||
localname = 'qpdf Command-line Options'
|
||||
shortname = 'Options'
|
||||
|
||||
def generate(self, docnames=None):
|
||||
content = defaultdict(list)
|
||||
options = self.domain.get_objects()
|
||||
options = sorted(options, key=itemgetter(0))
|
||||
|
||||
# name, subtype, docname, anchor, extra, qualifier, description
|
||||
for name, display_name, typ, docname, anchor, _ in options:
|
||||
m = re.match(r'^(--([^= ]+))', display_name)
|
||||
if not m:
|
||||
raise Exception(
|
||||
'OptionIndex.generate: display name not as expected')
|
||||
content[m.group(2)[0].lower()].append(
|
||||
(m.group(1), 0, docname, anchor, '', '', typ))
|
||||
|
||||
content = sorted(content.items())
|
||||
return content, True
|
||||
|
||||
|
||||
class QpdfDomain(Domain):
|
||||
name = 'qpdf'
|
||||
label = 'qpdf documentation domain'
|
||||
roles = {
|
||||
'ref': XRefRole()
|
||||
}
|
||||
directives = {
|
||||
'option': OptionDirective,
|
||||
}
|
||||
indices = {
|
||||
OptionIndex,
|
||||
}
|
||||
initial_data = {
|
||||
'options': [], # object list
|
||||
}
|
||||
|
||||
def get_full_qualified_name(self, node):
|
||||
return '{}.{}'.format('option', node.arguments[0])
|
||||
|
||||
def get_objects(self):
|
||||
for obj in self.data['options']:
|
||||
yield(obj)
|
||||
|
||||
def resolve_xref(self, env, from_doc_name, builder, typ, target, node,
|
||||
contnode):
|
||||
match = [(docname, anchor)
|
||||
for name, sig, typ, docname, anchor, priority
|
||||
in self.get_objects() if name == f'option.{target[2:]}']
|
||||
|
||||
if len(match) > 0:
|
||||
to_doc_name = match[0][0]
|
||||
match_target = match[0][1]
|
||||
return make_refnode(builder, from_doc_name, to_doc_name,
|
||||
match_target, contnode, match_target)
|
||||
else:
|
||||
raise Exception(f'invalid option xref ({target})')
|
||||
|
||||
def add_option(self, signature, option_name):
|
||||
if self.env.docname != 'cli':
|
||||
raise Exception(
|
||||
'qpdf:option directives don\'t work outside of cli.rst')
|
||||
|
||||
name = f'option.{option_name}'
|
||||
anchor = f'option-{option_name}'
|
||||
|
||||
# name, display_name, type, docname, anchor, priority
|
||||
self.data['options'].append(
|
||||
(name, signature, '', self.env.docname, anchor, 0))
|
||||
|
||||
def purge_options(self, docname):
|
||||
self.data['options'] = list([
|
||||
x for x in self.data['options']
|
||||
if x[3] != docname
|
||||
])
|
||||
|
||||
|
||||
def purge_options(app, env, docname):
|
||||
option = env.get_domain('qpdf')
|
||||
option.purge_options(docname)
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_domain(QpdfDomain)
|
||||
app.connect('env-purge-doc', purge_options)
|
||||
|
||||
return {
|
||||
'version': '0.1',
|
||||
'parallel_read_safe': True,
|
||||
'parallel_write_safe': True,
|
||||
}
|
@ -17,7 +17,7 @@ ifeq ($(BUILD_PDF),1)
|
||||
TARGETS_manual += $(PDF_TARGET)
|
||||
endif
|
||||
|
||||
MANUAL_DEPS = $(wildcard manual/*.rst) manual/conf.py
|
||||
MANUAL_DEPS = $(wildcard manual/*.rst) manual/conf.py manual/_ext/qpdf.py
|
||||
|
||||
# Prevent targets that run $(SPHINX) from running in parallel by using
|
||||
# order-only dependencies (the dependencies listed after the |) to
|
||||
|
4171
manual/cli.rst
4171
manual/cli.rst
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,10 @@
|
||||
# To see the default sample conf.py, run sphinx-quickstart in an empty
|
||||
# directory. Most of the original comments and options were removed.
|
||||
import sphinx_rtd_theme # noQA F401
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.abspath("./_ext"))
|
||||
|
||||
project = 'QPDF'
|
||||
copyright = '2005-2021, Jay Berkenbilt'
|
||||
@ -16,6 +20,7 @@ release = '10.5.0'
|
||||
version = release
|
||||
extensions = [
|
||||
'sphinx_rtd_theme',
|
||||
'qpdf',
|
||||
]
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_options = {
|
||||
|
327
manual/encryption.rst
Normal file
327
manual/encryption.rst
Normal file
@ -0,0 +1,327 @@
|
||||
.. _pdf-encryption:
|
||||
|
||||
PDF Encryption
|
||||
==============
|
||||
|
||||
This chapter discusses PDF encryption in a general way with an angle
|
||||
toward how it works in :command:`qpdf`. This chapter is not intended
|
||||
to replace the PDF specification. Please consult the spec for full
|
||||
details.
|
||||
|
||||
PDF Encryption Concepts
|
||||
-----------------------
|
||||
|
||||
Encryption
|
||||
Encryption is the replacement of *clear text* with encrypted text,
|
||||
also known as *ciphertext*. The clear text may be retrieved from the
|
||||
ciphertext if the encryption key is known.
|
||||
|
||||
PDF files consist of an object structure. PDF objects may be of a
|
||||
variety of types including (among others) numbers, boolean values,
|
||||
names, arrays, dictionaries, strings, and streams. In a PDF file,
|
||||
only strings and streams are encrypted.
|
||||
|
||||
Security Handler
|
||||
Since the inception of PDF, there have been several modifications to
|
||||
the way files are encrypted. Encryption is handled by a *security
|
||||
handler*. The *standard security handler* is password-based. This is
|
||||
the only security handler implemented by qpdf, and this material is
|
||||
all focused on the standard security handler. There are various
|
||||
flags that control the specific details of encryption with the
|
||||
standard security handler. These are discussed below.
|
||||
|
||||
Encryption Key
|
||||
This refers to the actual key used by the encryption and decryption
|
||||
algorithms. It is distinct from the password. The main encryption
|
||||
key is generated at random and stored encrypted in the PDF file. The
|
||||
passwords used to protect a PDF file, if any, are used to protect
|
||||
the encryption key. This design makes it possible to use different
|
||||
passwords (e.g., user and owner passwords) to retrieve the
|
||||
encryption key or even to change the password on a file without
|
||||
changing the encryption key. qpdf can expose the encryption key when
|
||||
run with the :qpdf:ref:`--show-encryption-key` option and can accept
|
||||
a hex-encoded encryption key in place of a password when run with
|
||||
the :qpdf:ref:`--password-is-hex-key` option.
|
||||
|
||||
Password Protection
|
||||
Password protection is distinct from encryption. This point is often
|
||||
misunderstood. A PDF file can be encrypted without being
|
||||
password-protected. The intent of PDF encryption was that there
|
||||
would be two passwords: a *user password* and an *owner password*.
|
||||
Either password can be used to retrieve the encryption key. A
|
||||
conforming reader is supposed to obey the security restrictions
|
||||
if the file is opened using the user password but not if the file is
|
||||
opened with the owner password. :command:`qpdf` makes no distinction
|
||||
between which password is used to open the file. The distinction
|
||||
made by conforming readers between the user and owner password is
|
||||
what makes it common to create encrypted files with no password
|
||||
protection. This is done by using the empty string as the user
|
||||
password and some secret string as the owner password. When a user
|
||||
opens the PDF file, the empty string is used to retrieve the
|
||||
encryption key, making the file usable, but a conforming reader
|
||||
restricts certain operations from the user.
|
||||
|
||||
What does all this mean? Here are a few things to realize.
|
||||
|
||||
- Since the user password and the owner password are both used to
|
||||
recover the single encryption key, there is *fundamentally no way*
|
||||
to prevent an application from disregarding the security
|
||||
restrictions on a file. Any software that can read the encrypted
|
||||
file at all has the encryption key. Therefore, the security of the
|
||||
restrictions placed on PDF files is solely enforced by the software.
|
||||
Any open source PDF reader could be trivially modified to ignore the
|
||||
security restrictions on a file. The PDF specification is clear
|
||||
about this point. This means that PDF restrictions on
|
||||
non-password-protected files only restrict users who don't know how
|
||||
to circumvent them.
|
||||
|
||||
- If a file is password-protected, you have to know at least one of
|
||||
the user or owner password to retrieve the encryption key. However,
|
||||
in the case of 40-bit encryption, the actual encryption key is only
|
||||
5 bytes long and can be easily brute-forced. As such, files
|
||||
encrypted with 40-bit encryption are not secure regardless of how
|
||||
strong the password is. With 128-bit encryption, the default
|
||||
security handler uses RC4 encryption, which is also known be
|
||||
insecure. As such, the only way to securely encrypt a PDF file using
|
||||
the standard security handler (as of the last review of this chapter
|
||||
in 2022) is to use AES encryption. This is the only supported
|
||||
algorithm with 256-bit encryption, and it can be selected to be used
|
||||
with 128-bit encryption as well. However there is no reason to use
|
||||
128-bit encryption with AES. If you are going to use AES, just use
|
||||
256-bit encryption instead. The security of a 256-bit AES-encrypted
|
||||
PDF file with a strong password is comparable to using a
|
||||
general-purpose encryption tool like :command:`gpg` or
|
||||
:command:`openssl` to encrypt the PDF file with the same password,
|
||||
but the advantage of using PDF encryption is that no software is
|
||||
required beyond a regular PDF viewer.
|
||||
|
||||
PDF Encryption Details
|
||||
----------------------
|
||||
|
||||
This section describes a few details about PDF encryption. It does not
|
||||
describe all the details. For that, read the PDF specification. The
|
||||
details presented here, however, should go a long way toward helping a
|
||||
casual user/developer understand what's going on with encrypted PDF
|
||||
files.
|
||||
|
||||
Here are more concepts to understand.
|
||||
|
||||
Algorithm parameters ``V`` and ``R``
|
||||
There are two parameters that control the details of encryption
|
||||
using the standard security handler: ``V`` and ``R``.
|
||||
|
||||
``V`` is a code specifying the algorithms that are used for
|
||||
encrypting the file, handling keys, etc. It may have any of the
|
||||
following values:
|
||||
|
||||
- 1: The original algorithm, which encrypted files using 40-bit keys.
|
||||
|
||||
- 2: An extension of the original algorithm allowing longer keys.
|
||||
Introduced in PDF 1.4.
|
||||
|
||||
- 3: An unpublished algorithm that permits file encryption key
|
||||
lengths ranging from 40 to 128 bits. Introduced in PDF 1.4. qpdf
|
||||
is believed to be able to read files with ``V`` = 3 but does not
|
||||
write such files.
|
||||
|
||||
- 4: An extension of the algorithm that allows it to be
|
||||
parameterized by additional rules for handling strings and
|
||||
streams. Introduced in PDF 1.5.
|
||||
|
||||
- 5: An algorithm that allows specification of separate security
|
||||
handlers for strings and streams as well as embedded files, and
|
||||
which supports 256-bit keys. Introduced in PDF 1.7 extension level
|
||||
3 and later extended in extension level 8. This is the encryption
|
||||
system in the PDF 2.0 specification, ISO-32000.
|
||||
|
||||
``R`` is a code specifying the revision of the standard handler. It
|
||||
is tightly coupled with the value of ``V``. ``R`` may have any of
|
||||
the following values:
|
||||
|
||||
- 2: ``V`` must be 1
|
||||
|
||||
- 3: ``V`` must be 2 or 3
|
||||
|
||||
- 4: ``V`` must be 4
|
||||
|
||||
- 5: ``V`` must be 5; this extension was never fully specified and
|
||||
existed for a short time in some versions of Acrobat.
|
||||
:command:`qpdf` is able to read and write this format, but it
|
||||
should not be used for any purpose other than testing
|
||||
compatibility with the format.
|
||||
|
||||
- 6: ``V`` must be 5. This is the only value that is not deprecated
|
||||
in the PDF 2.0 specification, ISO-32000.
|
||||
|
||||
Encryption Dictionary
|
||||
Encrypted PDF files have an encryption dictionary. There are several
|
||||
fields, but these are the important ones for our purposes:
|
||||
|
||||
- ``V`` and ``R`` as described above
|
||||
|
||||
- ``O``, ``U``, ``OE``, ``UE``: values used by the algorithms that
|
||||
recover the encryption key from the user and owner password. Which
|
||||
of these are defined and how they are used vary based on the value
|
||||
of ``R``.
|
||||
|
||||
- ``P``: a bit field that describes which restrictions are in place.
|
||||
This is discussed below in :ref:`security-restrictions`
|
||||
|
||||
Encryption Algorithms
|
||||
PDF files may be encrypted with the obsolete, insecure RC4 algorithm
|
||||
or the more secure AES algorithm. See also :ref:`weak-crypto` for a
|
||||
discussion. 40-bit encryption always uses RC4. 128-bit can use
|
||||
either RC4 (the default for compatibility reasons) or, starting with
|
||||
PDF 1.6, AES. 256-bit encryption always uses AES.
|
||||
|
||||
.. _security-restrictions:
|
||||
|
||||
PDF Security Restrictions
|
||||
-------------------------
|
||||
|
||||
PDF security restrictions are described by a bit field whose value is
|
||||
stored in the ``P`` field in the encryption dictionary. The value of
|
||||
``P`` is used by the algorithms to recover the encryption key given
|
||||
the password, which makes the value of ``P`` tamper-resistent.
|
||||
|
||||
``P`` is a 32-bit integer, treated as a signed twos-complement number.
|
||||
A 1 in any bit position means the permission is granted. The PDF
|
||||
specification numbers the bits from 1 (least significant bit) to 32
|
||||
(most significant bit) rather than the more customary 0 to 31. For
|
||||
consistency with the spec, the remainder of this section uses the
|
||||
1-based numbering.
|
||||
|
||||
Only bits 3, 4, 5, 6, 9, 10, 11, and 12 are used. All other bits are
|
||||
set to 1. Since bit 32 is always set to 1, the value of ``P`` is
|
||||
always a negative number. (:command:`qpdf` recognizes a positive
|
||||
number on behalf of buggy writers that treat ``P`` as unsigned. Such
|
||||
files have been seen in the wild.)
|
||||
|
||||
Here are the meanings of the bit positions. All bits not listed must
|
||||
have the value 1 except bits 1 and 2, which must have the value 0.
|
||||
However, the values of bits other than those in the table are ignored,
|
||||
so having incorrect values probably doesn't break anything in most
|
||||
cases. A value of 1 indicates that the permission is granted.
|
||||
|
||||
- 3: for ``R`` = 2 printing; for ``R`` >= 3, printing at low
|
||||
resolution
|
||||
|
||||
- 4: modifying the document except as controlled by bits 6,
|
||||
9, and 11
|
||||
|
||||
- 5: extracting text and graphics for purposes other than
|
||||
accessibility to visually impaired users
|
||||
|
||||
- 6: add or modify annotations, fill in interactive form fields;
|
||||
if bit 4 is also set, create or modify interactive form fields
|
||||
|
||||
- 9: for ``R`` >= 3, fill in interactive form fields even if bit 6 is
|
||||
clear
|
||||
|
||||
- 10: not used; formerly granted permission to extract material
|
||||
for accessibility, but the specification now disallows restriction
|
||||
of accessibility, and conforming readers are to treat this bit as if
|
||||
it is set regardless of its value
|
||||
|
||||
- 11: for ``R`` >= 3, assemble document including inserting, rotating,
|
||||
or deleting pages or creating document outlines or thumbnail images
|
||||
|
||||
- 12: for ``R`` >= 3, allow printing at full resolution
|
||||
|
||||
.. _qpdf-P:
|
||||
|
||||
How qpdf handles security restrictions
|
||||
--------------------------------------
|
||||
|
||||
The section describes exactly what the qpdf library does with regard
|
||||
to ``P`` based on the various settings of different security options.
|
||||
|
||||
- Start with all bits set except bits 1 and 2, which are cleared
|
||||
|
||||
- For ``R`` = 2:
|
||||
|
||||
- ``--print=n``: clear bit 3
|
||||
|
||||
- ``--modify=n``: clear bit 4
|
||||
|
||||
- ``--extract=n``: clear bit 5
|
||||
|
||||
- ``--annotate=n``: clear bit 6
|
||||
|
||||
- For ``R >= 3``:
|
||||
|
||||
- ``--accessibility=n``: for ``R`` = 3, clear bit 10; otherwise,
|
||||
ignore so bit 10 is always clear if ``R`` >= 4. qpdf allows
|
||||
creating files with bit 10 clear so that it can be used to create
|
||||
test files to ensure that a conforming reader ignores the value of
|
||||
the bit. You should never intentionally clear accessibility.
|
||||
|
||||
- ``--extract=n``: clear bit 5
|
||||
|
||||
- ``--print=none``: clear bits 3 and 12
|
||||
|
||||
- ``--print=low``: clear bit 12
|
||||
|
||||
- ``--modify=none``: clear bits 4, 6, 9, and 11
|
||||
|
||||
- ``--modify=assembly``: clear bits 4, 6, and 9
|
||||
|
||||
- ``--modify=form``: clear bits 4 and 6
|
||||
|
||||
- ``--modify=annotate``: clear bit 4
|
||||
|
||||
- ``--assemble=n``: clear bit 11
|
||||
|
||||
- ``--annotate=n``: clear bit 6
|
||||
|
||||
- ``--form=n``: clear bit 9
|
||||
|
||||
- ``--modify-other=n``: clear bit 4
|
||||
|
||||
Options to :command:`qpdf`, both at the CLI and library level, allow
|
||||
more granular clearing of permission bits than do most tools,
|
||||
including Adobe Acrobat. As such, PDF viewers may respond in
|
||||
surprising ways based on options passed to qpdf. If you observe this,
|
||||
it is probably not because of a bug in qpdf.
|
||||
|
||||
.. _pdf-passwords:
|
||||
|
||||
User and Owner Passwords
|
||||
------------------------
|
||||
|
||||
When you use qpdf to show encryption parameters and you open a file
|
||||
with the owner password, sometimes qpdf reveals the user password, and
|
||||
sometimes it doesn't. Here's why.
|
||||
|
||||
For ``V`` < 5, the user password is actually stored in the PDF file
|
||||
encrypted with a key that is derived from the owner password, and the
|
||||
main encryption key is encrypted using a key derived from the user
|
||||
password. When you open a PDF file, the reader first tries to treat
|
||||
the given password as the user password, using it to recover the
|
||||
encryption key. If that works, you're in with restrictions (assuming
|
||||
the reader chooses to enforce them). If it doesn't work, then the
|
||||
reader treats the password as the owner password, using it to recover
|
||||
the user password, and then uses the user password to retrieve the
|
||||
encryption key. This is why creating a file with the same user
|
||||
password and owner password with ``V`` < 5 results in a file that some
|
||||
readers will never allow you to open as the owner. Typically when a
|
||||
reader encounters a file with ``V`` < 5, it will first attempt to
|
||||
treat the empty string as a user password. If that works, the file is
|
||||
encrypted but not password-protected. If it doesn't work, then a
|
||||
password prompt is given. Creating a file with an empty owner password
|
||||
is like creating a file with the same owner and user password: there
|
||||
is no way to open the file as an owner.
|
||||
|
||||
For ``V`` >= 5, the main encryption key is independently encrypted
|
||||
using the user password and the owner password. There is no way to
|
||||
recover the user password from the owner password. Restrictions are
|
||||
imposed or not depending on which password was used. In this case, the
|
||||
password supplied, if any, is tried both as the user password and the
|
||||
owner password, and whichever works is used. Typically the password is
|
||||
tried as the owner password first. (This is what the PDF specification
|
||||
says to do.) As such, specifying a user password and leaving the owner
|
||||
password blank results in a file that is opened as owner with no
|
||||
password, effectively rendering the security restrictions useless.
|
||||
This is why :command:`qpdf` requires you to pass
|
||||
:qpdf:ref:`--allow-insecure` to create a file with an empty owner
|
||||
password when 256-bit encryption is in use.
|
@ -30,5 +30,11 @@ documentation, please visit `https://qpdf.readthedocs.io
|
||||
design
|
||||
linearization
|
||||
object-streams
|
||||
encryption
|
||||
release-notes
|
||||
acknowledgement
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`qpdf-options`
|
||||
|
@ -208,7 +208,7 @@ files you need to build.
|
||||
Runtime Crypto Provider Selection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use the :samp:`--show-crypto` option to
|
||||
You can use the :qpdf:ref:`--show-crypto` option to
|
||||
:command:`qpdf` to get a list of available crypto
|
||||
providers. The default provider is always listed first, and the rest are
|
||||
listed in lexical order. Each crypto provider is listed on a line by
|
||||
|
@ -51,7 +51,7 @@ Compatibility
|
||||
|
||||
Documentation
|
||||
The :command:`qpdf` command can be invoked with the
|
||||
:samp:`--json-help` option. This will output a JSON
|
||||
:qpdf:ref:`--json-help` option. This will output a JSON
|
||||
structure that has the same structure as the JSON output that qpdf
|
||||
generates, except that each field in the help output is a description
|
||||
of the corresponding field in the JSON output. The specific
|
||||
@ -134,7 +134,7 @@ There are a few limitations to be aware of with the JSON structure:
|
||||
encoding. In other words, it's best if you don't try to use the JSON
|
||||
format to extract binary strings from the PDF file, but if you really
|
||||
had to, it could be done. Note that qpdf's
|
||||
:samp:`--show-object` option does not have this
|
||||
:qpdf:ref:`--show-object` option does not have this
|
||||
limitation and will reveal the string as encoded in the original
|
||||
file.
|
||||
|
||||
@ -150,9 +150,9 @@ be aware of:
|
||||
- While qpdf guarantees that keys present in the help will be present
|
||||
in the output, those fields may be null or empty if the information
|
||||
is not known or absent in the file. Also, if you specify
|
||||
:samp:`--json-keys`, the keys that are not listed
|
||||
:qpdf:ref:`--json-key`, the keys that are not listed
|
||||
will be excluded entirely except for those that
|
||||
:samp:`--json-help` says are always present.
|
||||
:qpdf:ref:`--json-help` says are always present.
|
||||
|
||||
- In a few places, there are keys with names containing
|
||||
``pageposfrom1``. The values of these keys are null or an integer. If
|
||||
@ -168,7 +168,7 @@ be aware of:
|
||||
|
||||
- The image information included in the ``page`` section of the JSON
|
||||
output includes the key "``filterable``". Note that the value of this
|
||||
field may depend on the :samp:`--decode-level` that
|
||||
field may depend on the :qpdf:ref:`--decode-level` that
|
||||
you invoke qpdf with. The JSON output includes a top-level key
|
||||
"``parameters``" that indicates the decode level used for computing
|
||||
whether a stream was filterable. For example, jpeg images will be
|
||||
|
@ -90,7 +90,7 @@ For a detailed list of changes, please see the file
|
||||
- Handling of Weak Cryptography Algorithms
|
||||
|
||||
- From the qpdf CLI, the
|
||||
:samp:`--allow-weak-crypto` is now required to
|
||||
:qpdf:ref:`--allow-weak-crypto` is now required to
|
||||
suppress a warning when explicitly creating PDF files using RC4
|
||||
encryption. While qpdf will always retain the ability to read
|
||||
and write such files, doing so will require explicit
|
||||
@ -108,7 +108,7 @@ For a detailed list of changes, please see the file
|
||||
(with no resource dictionary).
|
||||
|
||||
- Fix crash that could occur under certain conditions when using
|
||||
:samp:`--pages` with files that had form
|
||||
:qpdf:ref:`--pages` with files that had form
|
||||
fields.
|
||||
|
||||
- Library Enhancements
|
||||
@ -127,7 +127,7 @@ For a detailed list of changes, please see the file
|
||||
- CLI Enhancements
|
||||
|
||||
- Improve diagnostics around parsing
|
||||
:samp:`--pages` command-line options
|
||||
:qpdf:ref:`--pages` command-line options
|
||||
|
||||
- Packaging Changes
|
||||
|
||||
@ -139,7 +139,7 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- When generating a file while preserving object streams,
|
||||
unreferenced objects are correctly removed unless
|
||||
:samp:`--preserve-unreferenced` is specified.
|
||||
:qpdf:ref:`--preserve-unreferenced` is specified.
|
||||
|
||||
- Library Enhancements
|
||||
|
||||
@ -202,19 +202,19 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- Operations that work on combining pages are much better about
|
||||
protecting form fields. In particular,
|
||||
:samp:`--split-pages` and
|
||||
:samp:`--pages` now preserve interaction form
|
||||
:qpdf:ref:`--split-pages` and
|
||||
:qpdf:ref:`--pages` now preserve interaction form
|
||||
functionality by copying the relevant form field information
|
||||
from the original files. Additionally, if you use
|
||||
:samp:`--pages` to select only some pages from
|
||||
:qpdf:ref:`--pages` to select only some pages from
|
||||
the original input file, unused form fields are removed, which
|
||||
prevents lots of unused annotations from being retained.
|
||||
|
||||
- By default, :command:`qpdf` no longer allows
|
||||
creation of encrypted PDF files whose user password is
|
||||
non-empty and owner password is empty when a 256-bit key is in
|
||||
use. The :samp:`--allow-insecure` option,
|
||||
specified inside the :samp:`--encrypt` options,
|
||||
use. The :qpdf:ref:`--allow-insecure` option,
|
||||
specified inside the :qpdf:ref:`--encrypt` options,
|
||||
allows creation of such files. Behavior changes in the CLI are
|
||||
avoided when possible, but an exception was made here because
|
||||
this is security-related. qpdf must always allow creation of
|
||||
@ -255,7 +255,7 @@ For a detailed list of changes, please see the file
|
||||
removing, and and copying file attachments. See :ref:`attachments` for details.
|
||||
|
||||
- Page splitting and merging operations, as well as
|
||||
:samp:`--flatten-rotation`, are better behaved
|
||||
:qpdf:ref:`--flatten-rotation`, are better behaved
|
||||
with respect to annotations and interactive form fields. In
|
||||
most cases, interactive form field functionality and proper
|
||||
formatting and functionality of annotations is preserved by
|
||||
@ -284,7 +284,7 @@ For a detailed list of changes, please see the file
|
||||
extraction of attachments. More detailed information can be
|
||||
obtained by following the reference to the file spec object.
|
||||
|
||||
- Add numeric option to :samp:`--collate`. If
|
||||
- Add numeric option to :qpdf:ref:`--collate`. If
|
||||
:samp:`--collate={n}`
|
||||
is given, take pages in groups of
|
||||
:samp:`{n}` from the given files.
|
||||
@ -367,7 +367,7 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- Bug Fixes
|
||||
|
||||
- The :samp:`--flatten-rotation` option applies
|
||||
- The :qpdf:ref:`--flatten-rotation` option applies
|
||||
transformations to any annotations that may be on the page.
|
||||
|
||||
- If a form XObject lacks a resources dictionary, consider any
|
||||
@ -390,7 +390,7 @@ For a detailed list of changes, please see the file
|
||||
10.1.0: January 5, 2021
|
||||
- CLI Enhancements
|
||||
|
||||
- Add :samp:`--flatten-rotation` command-line
|
||||
- Add :qpdf:ref:`--flatten-rotation` command-line
|
||||
option, which causes all pages that are rotated using
|
||||
parameters in the page's dictionary to instead be identically
|
||||
rotated in the page's contents. The change is not user-visible
|
||||
@ -510,7 +510,7 @@ For a detailed list of changes, please see the file
|
||||
- Bug Fixes
|
||||
|
||||
- When concatenating content streams, as with
|
||||
:samp:`--coalesce-contents`, there were cases
|
||||
:qpdf:ref:`--coalesce-contents`, there were cases
|
||||
in which qpdf would merge two lexical tokens together, creating
|
||||
invalid results. A newline is now inserted between merged
|
||||
content streams if one is not already present.
|
||||
@ -527,7 +527,7 @@ For a detailed list of changes, please see the file
|
||||
already ignored the user's locale for numeric conversion.
|
||||
|
||||
- Fix several instances in which warnings were not suppressed in
|
||||
spite of :samp:`--no-warn` and/or errors or
|
||||
spite of :qpdf:ref:`--no-warn` and/or errors or
|
||||
warnings were written to standard output rather than standard
|
||||
error.
|
||||
|
||||
@ -540,10 +540,10 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- Enhancements
|
||||
|
||||
- New option :samp:`--warning-exit-0` causes qpdf
|
||||
- New option :qpdf:ref:`--warning-exit-0` causes qpdf
|
||||
to exit with a status of ``0`` rather than ``3`` if there are
|
||||
warnings but no errors. Combine with
|
||||
:samp:`--no-warn` to completely ignore
|
||||
:qpdf:ref:`--no-warn` to completely ignore
|
||||
warnings.
|
||||
|
||||
- Performance improvements have been made to
|
||||
@ -656,17 +656,16 @@ For a detailed list of changes, please see the file
|
||||
:command:`qpdf --json-help` for details.
|
||||
|
||||
- Add new option
|
||||
:samp:`--remove-unreferenced-resources` which
|
||||
:qpdf:ref:`--remove-unreferenced-resources` which
|
||||
takes ``auto``, ``yes``, or ``no`` as arguments. The new
|
||||
``auto`` mode, which is the default, performs a fast heuristic
|
||||
over a PDF file when splitting pages to determine whether the
|
||||
expensive process of finding and removing unreferenced
|
||||
resources is likely to be of benefit. For most files, this new
|
||||
default will result in a significant performance improvement
|
||||
for splitting pages. See :ref:`advanced-transformation` for a more detailed
|
||||
discussion.
|
||||
for splitting pages.
|
||||
|
||||
- The :samp:`--preserve-unreferenced-resources`
|
||||
- The :qpdf:ref:`--preserve-unreferenced-resources`
|
||||
is now just a synonym for
|
||||
:samp:`--remove-unreferenced-resources=no`.
|
||||
|
||||
@ -760,8 +759,8 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- CLI Enhancements
|
||||
|
||||
- Added options :samp:`--is-encrypted` and
|
||||
:samp:`--requires-password` for testing whether
|
||||
- Added options :qpdf:ref:`--is-encrypted` and
|
||||
:qpdf:ref:`--requires-password` for testing whether
|
||||
a file is encrypted or requires a password other than the
|
||||
supplied (or empty) password. These communicate via exit
|
||||
status, making them useful for shell scripts. They also work on
|
||||
@ -770,7 +769,7 @@ For a detailed list of changes, please see the file
|
||||
- Added ``encrypt`` key to JSON options. With the exception of
|
||||
the reconstructed user password for older encryption formats,
|
||||
this provides the same information as
|
||||
:samp:`--show-encryption` but in a consistent,
|
||||
:qpdf:ref:`--show-encryption` but in a consistent,
|
||||
parseable format. See output of :command:`qpdf
|
||||
--json-help` for details.
|
||||
|
||||
@ -778,7 +777,7 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- In QDF mode, be sure not to write more than one XRef stream to
|
||||
a file, even when
|
||||
:samp:`--preserve-unreferenced` is used.
|
||||
:qpdf:ref:`--preserve-unreferenced` is used.
|
||||
:command:`fix-qdf` assumes that there is only
|
||||
one XRef stream, and that it appears at the end of the file.
|
||||
|
||||
@ -824,7 +823,7 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- CLI Enhancements
|
||||
|
||||
- Addition of the :samp:`--show-crypto` option in
|
||||
- Addition of the :qpdf:ref:`--show-crypto` option in
|
||||
support of selectable crypto providers, as described in :ref:`crypto`.
|
||||
|
||||
- Allow ``:even`` or ``:odd`` to be appended to numeric ranges
|
||||
@ -838,7 +837,7 @@ For a detailed list of changes, please see the file
|
||||
- Bug Fix
|
||||
|
||||
- Fix the name of the temporary file used by
|
||||
:samp:`--replace-input` so that it doesn't
|
||||
:qpdf:ref:`--replace-input` so that it doesn't
|
||||
require path splitting and works with paths include
|
||||
directories.
|
||||
|
||||
@ -891,21 +890,21 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- CLI Enhancements
|
||||
|
||||
- The :samp:`--replace-input` option may be given
|
||||
- The :qpdf:ref:`--replace-input` option may be given
|
||||
in place of an output file name. This causes qpdf to overwrite
|
||||
the input file with the output. See the description of
|
||||
:samp:`--replace-input` in :ref:`basic-options` for more details.
|
||||
:qpdf:ref:`--replace-input` for more details.
|
||||
|
||||
- The :samp:`--recompress-flate` instructs
|
||||
- The :qpdf:ref:`--recompress-flate` instructs
|
||||
:command:`qpdf` to recompress streams that are
|
||||
already compressed with ``/FlateDecode``. Useful with
|
||||
:samp:`--compression-level`.
|
||||
:qpdf:ref:`--compression-level`.
|
||||
|
||||
- The
|
||||
:samp:`--compression-level={level}`
|
||||
sets the zlib compression level used for any streams compressed
|
||||
by ``/FlateDecode``. Most effective when combined with
|
||||
:samp:`--recompress-flate`.
|
||||
:qpdf:ref:`--recompress-flate`.
|
||||
|
||||
- Library Enhancements
|
||||
|
||||
@ -998,8 +997,8 @@ For a detailed list of changes, please see the file
|
||||
a file with linearization warnings but not errors, it now
|
||||
properly exits with exit code 3 instead of 2.
|
||||
|
||||
- The :samp:`--completion-bash` and
|
||||
:samp:`--completion-zsh` options now work
|
||||
- The :qpdf:ref:`--completion-bash` and
|
||||
:qpdf:ref:`--completion-zsh` options now work
|
||||
properly when qpdf is invoked as an AppImage.
|
||||
|
||||
- Calling ``QPDFWriter::set*EncryptionParameters`` on a
|
||||
@ -1063,7 +1062,7 @@ For a detailed list of changes, please see the file
|
||||
qpdf than the library, which may indicate a problem with the
|
||||
installation.
|
||||
|
||||
- New option :samp:`--remove-page-labels` will
|
||||
- New option :qpdf:ref:`--remove-page-labels` will
|
||||
remove page labels before generating output. This used to
|
||||
happen if you ran :command:`qpdf --empty --pages ..
|
||||
--`, but the behavior changed in qpdf 8.3.0. This
|
||||
@ -1090,7 +1089,7 @@ For a detailed list of changes, please see the file
|
||||
during page splitting operations.
|
||||
|
||||
- Revert change that included preservation of outlines
|
||||
(bookmarks) in :samp:`--split-pages`. The way
|
||||
(bookmarks) in :qpdf:ref:`--split-pages`. The way
|
||||
it was implemented in 8.3.0 and 8.4.0 caused a very significant
|
||||
degradation of performance for splitting certain files. A
|
||||
future release of qpdf may re-introduce the behavior in a more
|
||||
@ -1143,16 +1142,16 @@ For a detailed list of changes, please see the file
|
||||
depth in :ref:`unicode-passwords`.
|
||||
|
||||
- New options
|
||||
:samp:`--externalize-inline-images`,
|
||||
:samp:`--ii-min-bytes`, and
|
||||
:samp:`--keep-inline-images` control qpdf's
|
||||
:qpdf:ref:`--externalize-inline-images`,
|
||||
:qpdf:ref:`--ii-min-bytes`, and
|
||||
:qpdf:ref:`--keep-inline-images` control qpdf's
|
||||
handling of inline images and possible conversion of them to
|
||||
regular images. By default,
|
||||
:samp:`--optimize-images` now also applies to
|
||||
inline images. These options are discussed in :ref:`advanced-transformation`.
|
||||
:qpdf:ref:`--optimize-images` now also applies to
|
||||
inline images.
|
||||
|
||||
- Add options :samp:`--overlay` and
|
||||
:samp:`--underlay` for overlaying or
|
||||
- Add options :qpdf:ref:`--overlay` and
|
||||
:qpdf:ref:`--underlay` for overlaying or
|
||||
underlaying pages of other files onto output pages. See
|
||||
:ref:`overlay-underlay` for
|
||||
details.
|
||||
@ -1162,32 +1161,32 @@ For a detailed list of changes, please see the file
|
||||
non-ASCII characters, qpdf will try a number of alternative
|
||||
passwords to try to compensate for possible character encoding
|
||||
errors. This behavior can be suppressed with the
|
||||
:samp:`--suppress-password-recovery` option.
|
||||
:qpdf:ref:`--suppress-password-recovery` option.
|
||||
See :ref:`unicode-passwords` for a full
|
||||
discussion.
|
||||
|
||||
- Add the :samp:`--password-mode` option to
|
||||
- Add the :qpdf:ref:`--password-mode` option to
|
||||
fine-tune how qpdf interprets password arguments, especially
|
||||
when they contain non-ASCII characters. See :ref:`unicode-passwords` for more information.
|
||||
|
||||
- In the :samp:`--pages` option, it is now
|
||||
- In the :qpdf:ref:`--pages` option, it is now
|
||||
possible to copy the same page more than once from the same
|
||||
file without using the previous workaround of specifying two
|
||||
different paths to the same file.
|
||||
|
||||
- In the :samp:`--pages` option, allow use of "."
|
||||
- In the :qpdf:ref:`--pages` option, allow use of "."
|
||||
as a shortcut for the primary input file. That way, you can do
|
||||
:command:`qpdf in.pdf --pages . 1-2 -- out.pdf`
|
||||
instead of having to repeat :file:`in.pdf`
|
||||
in the command.
|
||||
|
||||
- When encrypting with 128-bit and 256-bit encryption, new
|
||||
encryption options :samp:`--assemble`,
|
||||
:samp:`--annotate`,
|
||||
:samp:`--form`, and
|
||||
:samp:`--modify-other` allow more fine-grained
|
||||
encryption options :qpdf:ref:`--assemble`,
|
||||
:qpdf:ref:`--annotate`,
|
||||
:qpdf:ref:`--form`, and
|
||||
:qpdf:ref:`--modify-other` allow more fine-grained
|
||||
granularity in configuring options. Before, the
|
||||
:samp:`--modify` option only configured certain
|
||||
:qpdf:ref:`--modify` option only configured certain
|
||||
predefined groups of permissions.
|
||||
|
||||
- Bug Fixes and Enhancements
|
||||
@ -1198,7 +1197,7 @@ For a detailed list of changes, please see the file
|
||||
file's internal structure shared these resource lists across
|
||||
pages and if some but not all of the pages in the output did
|
||||
not reference all the fonts and images. Using the
|
||||
:samp:`--preserve-unreferenced-resources`
|
||||
:qpdf:ref:`--preserve-unreferenced-resources`
|
||||
option would work around the incorrect behavior. This bug was
|
||||
the result of a typo in the code and a deficiency in the test
|
||||
suite. The case that triggered the error was known, just not
|
||||
@ -1326,11 +1325,11 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- Page numbers (also known as page labels) are now preserved when
|
||||
merging and splitting files with the
|
||||
:samp:`--pages` and
|
||||
:samp:`--split-pages` options.
|
||||
:qpdf:ref:`--pages` and
|
||||
:qpdf:ref:`--split-pages` options.
|
||||
|
||||
- Bookmarks are partially preserved when splitting pages with the
|
||||
:samp:`--split-pages` option. Specifically, the
|
||||
:qpdf:ref:`--split-pages` option. Specifically, the
|
||||
outlines dictionary and some supporting metadata are copied
|
||||
into the split files. The result is that all bookmarks from the
|
||||
original file appear, those that point to pages that are
|
||||
@ -1340,48 +1339,48 @@ For a detailed list of changes, please see the file
|
||||
operations.
|
||||
|
||||
- Page collation: add new option
|
||||
:samp:`--collate`. When specified, the
|
||||
semantics of :samp:`--pages` change from
|
||||
:qpdf:ref:`--collate`. When specified, the
|
||||
semantics of :qpdf:ref:`--pages` change from
|
||||
concatenation to collation. See :ref:`page-selection` for examples and discussion.
|
||||
|
||||
- Generation of information in JSON format, primarily to
|
||||
facilitate use of qpdf from languages other than C++. Add new
|
||||
options :samp:`--json`,
|
||||
:samp:`--json-key`, and
|
||||
:samp:`--json-object` to generate a JSON
|
||||
options :qpdf:ref:`--json`,
|
||||
:qpdf:ref:`--json-key`, and
|
||||
:qpdf:ref:`--json-object` to generate a JSON
|
||||
representation of the PDF file. Run :command:`qpdf
|
||||
--json-help` to get a description of the JSON
|
||||
format. For more information, see :ref:`json`.
|
||||
|
||||
- The :samp:`--generate-appearances` flag will
|
||||
- The :qpdf:ref:`--generate-appearances` flag will
|
||||
cause qpdf to generate appearances for form fields if the PDF
|
||||
file indicates that form field appearances are out of date.
|
||||
This can happen when PDF forms are filled in by a program that
|
||||
doesn't know how to regenerate the appearances of the filled-in
|
||||
fields.
|
||||
|
||||
- The :samp:`--flatten-annotations` flag can be
|
||||
- The :qpdf:ref:`--flatten-annotations` flag can be
|
||||
used to *flatten* annotations, including form fields.
|
||||
Ordinarily, annotations are drawn separately from the page.
|
||||
Flattening annotations is the process of combining their
|
||||
appearances into the page's contents. You might want to do this
|
||||
if you are going to rotate or combine pages using a tool that
|
||||
doesn't understand about annotations. You may also want to use
|
||||
:samp:`--generate-appearances` when using this
|
||||
:qpdf:ref:`--generate-appearances` when using this
|
||||
flag since annotations for outdated form fields are not
|
||||
flattened as that would cause loss of information.
|
||||
|
||||
- The :samp:`--optimize-images` flag tells qpdf
|
||||
- The :qpdf:ref:`--optimize-images` flag tells qpdf
|
||||
to recompresses every image using DCT (JPEG) compression as
|
||||
long as the image is not already compressed with lossy
|
||||
compression and recompressing the image reduces its size. The
|
||||
additional options :samp:`--oi-min-width`,
|
||||
:samp:`--oi-min-height`, and
|
||||
:samp:`--oi-min-area` prevent recompression of
|
||||
additional options :qpdf:ref:`--oi-min-width`,
|
||||
:qpdf:ref:`--oi-min-height`, and
|
||||
:qpdf:ref:`--oi-min-area` prevent recompression of
|
||||
images whose width, height, or pixel area (width × height) are
|
||||
below a specified threshold.
|
||||
|
||||
- The :samp:`--show-object` option can now be
|
||||
- The :qpdf:ref:`--show-object` option can now be
|
||||
given as :samp:`--show-object=trailer` to show
|
||||
the trailer dictionary.
|
||||
|
||||
@ -1531,12 +1530,12 @@ For a detailed list of changes, please see the file
|
||||
:samp:`--keep-files-open={[yn]}`
|
||||
to override default determination of whether to keep files open
|
||||
when merging. Please see the discussion of
|
||||
:samp:`--keep-files-open` in :ref:`basic-options` for additional details.
|
||||
:qpdf:ref:`--keep-files-open` for additional details.
|
||||
|
||||
8.2.0: August 16, 2018
|
||||
- Command-line Enhancements
|
||||
|
||||
- Add :samp:`--no-warn` option to suppress
|
||||
- Add :qpdf:ref:`--no-warn` option to suppress
|
||||
issuing warning messages. If there are any conditions that
|
||||
would have caused warnings to be issued, the exit status is
|
||||
still 3.
|
||||
@ -1556,7 +1555,7 @@ For a detailed list of changes, please see the file
|
||||
- Bug fix: end of line characters were not properly handled
|
||||
inside strings in some cases.
|
||||
|
||||
- Bug fix: using :samp:`--progress` on very small
|
||||
- Bug fix: using :qpdf:ref:`--progress` on very small
|
||||
files could cause an infinite loop.
|
||||
|
||||
- API enhancements
|
||||
@ -1596,15 +1595,14 @@ For a detailed list of changes, please see the file
|
||||
old behavior should be desired, or if you have a case where
|
||||
page splitting is very slow, the old behavior (and speed) can
|
||||
be enabled by specifying
|
||||
:samp:`--preserve-unreferenced-resources`. For
|
||||
additional details, please see :ref:`advanced-transformation`.
|
||||
:qpdf:ref:`--preserve-unreferenced-resources`.
|
||||
|
||||
- When merging multiple PDF files, qpdf no longer leaves all the
|
||||
files open. This makes it possible to merge numbers of files
|
||||
that may exceed the operating system's limit for the maximum
|
||||
number of open files.
|
||||
|
||||
- The :samp:`--rotate` option's syntax has been
|
||||
- The :qpdf:ref:`--rotate` option's syntax has been
|
||||
extended to make the page range optional. If you specify
|
||||
:samp:`--rotate={angle}`
|
||||
without specifying a page range, the rotation will be applied
|
||||
@ -1613,10 +1611,10 @@ For a detailed list of changes, please see the file
|
||||
down.
|
||||
|
||||
- When merging multiple files, the
|
||||
:samp:`--verbose` option now prints information
|
||||
:qpdf:ref:`--verbose` option now prints information
|
||||
about each file as it operates on that file.
|
||||
|
||||
- When the :samp:`--progress` option is
|
||||
- When the :qpdf:ref:`--progress` option is
|
||||
specified, qpdf will print a running indicator of its best
|
||||
guess at how far through the writing process it is. Note that,
|
||||
as with all progress meters, it's an approximation. This option
|
||||
@ -1672,7 +1670,7 @@ For a detailed list of changes, please see the file
|
||||
it thinks it is through writing its output. Client programs can
|
||||
use this to implement reasonably accurate progress meters. The
|
||||
:command:`qpdf` command line tool uses this to
|
||||
implement its :samp:`--progress` option.
|
||||
implement its :qpdf:ref:`--progress` option.
|
||||
|
||||
- New methods ``QPDFObjectHandle::newUnicodeString`` and
|
||||
``QPDFObject::unparseBinary`` have been added to allow for more
|
||||
@ -1733,7 +1731,7 @@ For a detailed list of changes, please see the file
|
||||
:samp:`--linearize-pass1={file}`
|
||||
has been added for debugging qpdf's linearization code.
|
||||
|
||||
- The option :samp:`--coalesce-contents` can be
|
||||
- The option :qpdf:ref:`--coalesce-contents` can be
|
||||
used to combine content streams of a page whose contents are an
|
||||
array of streams into a single stream.
|
||||
|
||||
@ -1782,8 +1780,7 @@ For a detailed list of changes, please see the file
|
||||
password when opening encrypted files, and will optionally display
|
||||
the encryption key used by a file. This is a non-standard
|
||||
operation, but it can be useful in certain situations. Please see
|
||||
the discussion of :samp:`--password-is-hex-key` in
|
||||
:ref:`basic-options` or the comments around
|
||||
the discussion of :qpdf:ref:`--password-is-hex-key` or the comments around
|
||||
``QPDF::setPasswordIsHexKey`` in
|
||||
:file:`QPDF.hh` for additional details.
|
||||
|
||||
@ -1820,8 +1817,8 @@ For a detailed list of changes, please see the file
|
||||
or RunLength encoding. Library API enhancements and
|
||||
command-line options have been added to control this behavior.
|
||||
See command-line options
|
||||
:samp:`--compress-streams` and
|
||||
:samp:`--decode-level` and methods
|
||||
:qpdf:ref:`--compress-streams` and
|
||||
:qpdf:ref:`--decode-level` and methods
|
||||
``QPDFWriter::setCompressStreams`` and
|
||||
``QPDFWriter::setDecodeLevel``.
|
||||
|
||||
@ -1846,27 +1843,27 @@ For a detailed list of changes, please see the file
|
||||
- Command-line arguments can now be read from files or standard
|
||||
input using ``@file`` or ``@-`` syntax. Please see :ref:`invocation`.
|
||||
|
||||
- :samp:`--rotate`: request page rotation
|
||||
- :qpdf:ref:`--rotate`: request page rotation
|
||||
|
||||
- :samp:`--newline-before-endstream`: ensure that
|
||||
- :qpdf:ref:`--newline-before-endstream`: ensure that
|
||||
a newline appears before every ``endstream`` keyword in the
|
||||
file; used to prevent qpdf from breaking PDF/A compliance on
|
||||
already compliant files.
|
||||
|
||||
- :samp:`--preserve-unreferenced`: preserve
|
||||
- :qpdf:ref:`--preserve-unreferenced`: preserve
|
||||
unreferenced objects in the input PDF
|
||||
|
||||
- :samp:`--split-pages`: break output into chunks
|
||||
- :qpdf:ref:`--split-pages`: break output into chunks
|
||||
with fixed numbers of pages
|
||||
|
||||
- :samp:`--verbose`: print the name of each
|
||||
- :qpdf:ref:`--verbose`: print the name of each
|
||||
output file that is created
|
||||
|
||||
- :samp:`--compress-streams` and
|
||||
:samp:`--decode-level` replace
|
||||
:samp:`--stream-data` for improving granularity
|
||||
- :qpdf:ref:`--compress-streams` and
|
||||
:qpdf:ref:`--decode-level` replace
|
||||
:qpdf:ref:`--stream-data` for improving granularity
|
||||
of controlling compression and decompression of stream data.
|
||||
The :samp:`--stream-data` option will remain
|
||||
The :qpdf:ref:`--stream-data` option will remain
|
||||
available.
|
||||
|
||||
- When running :command:`qpdf --check` with other
|
||||
@ -1877,8 +1874,8 @@ For a detailed list of changes, please see the file
|
||||
reference table, or other similar operations.
|
||||
|
||||
- Process :command:`--pages` earlier so that other
|
||||
options like :samp:`--show-pages` or
|
||||
:samp:`--split-pages` can operate on the file
|
||||
options like :qpdf:ref:`--show-pages` or
|
||||
:qpdf:ref:`--split-pages` can operate on the file
|
||||
after page splitting/merging has occurred.
|
||||
|
||||
- API Changes. All new API calls are documented in their respective
|
||||
@ -1911,7 +1908,7 @@ For a detailed list of changes, please see the file
|
||||
``QPDFWriter`` methods.
|
||||
|
||||
6.0.0: November 10, 2015
|
||||
- Implement :samp:`--deterministic-id` command-line
|
||||
- Implement :qpdf:ref:`--deterministic-id` command-line
|
||||
option and ``QPDFWriter::setDeterministicID`` as well as C API
|
||||
function ``qpdf_set_deterministic_ID`` for generating a
|
||||
deterministic ID for non-encrypted files. When this option is
|
||||
@ -2024,12 +2021,12 @@ For a detailed list of changes, please see the file
|
||||
:file:`QPDFObjectHandle.hh` for additional
|
||||
notes.
|
||||
|
||||
- Add :samp:`--show-npages` command-line option to
|
||||
- Add :qpdf:ref:`--show-npages` command-line option to
|
||||
the :command:`qpdf` command to show the number of
|
||||
pages in a file.
|
||||
|
||||
- Allow omission of the page range within
|
||||
:samp:`--pages` for the
|
||||
:qpdf:ref:`--pages` for the
|
||||
:command:`qpdf` command. When omitted, the page
|
||||
range is implicitly taken to be all the pages in the file.
|
||||
|
||||
@ -2156,8 +2153,9 @@ For a detailed list of changes, please see the file
|
||||
``QPDFWriter::setMinimumPDFVersion`` and
|
||||
``QPDFWriter::forcePDFVersion`` that accept an extension level,
|
||||
and extended syntax for specifying forced and minimum versions on
|
||||
the command line as described in :ref:`advanced-transformation`. Corresponding functions
|
||||
have been added to the C API as well.
|
||||
the command line as described in :qpdf:ref:`--force-version` and
|
||||
:qpdf:ref:`--min-version`. Corresponding functions have been added
|
||||
to the C API as well.
|
||||
|
||||
- Minor fixes to prevent qpdf from referencing objects in the file
|
||||
that are not referenced in the file's overall structure. Most
|
||||
@ -2213,12 +2211,12 @@ For a detailed list of changes, please see the file
|
||||
``QPDFWriter``.
|
||||
|
||||
- Removed the method ``decodeStreams``. This method was used by
|
||||
the :samp:`--check` option of the
|
||||
the :qpdf:ref:`--check` option of the
|
||||
:command:`qpdf` command-line tool to force all
|
||||
streams in the file to be decoded, but it also suffered from
|
||||
the problem of opening otherwise unreferenced streams and thus
|
||||
could report false positive. The
|
||||
:samp:`--check` option now causes qpdf to go
|
||||
:qpdf:ref:`--check` option now causes qpdf to go
|
||||
through all the motions of writing a new file based on the
|
||||
original one, so it will always reference and check exactly
|
||||
those parts of a file that any ordinary viewer would check.
|
||||
@ -2307,7 +2305,7 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- Options have been added to the :command:`qpdf`
|
||||
command-line tool for copying encryption parameters from another
|
||||
file. See :ref:`basic-options`.
|
||||
file. (QXXXQ Link)
|
||||
|
||||
- New methods have been added to the ``QPDF`` object for adding and
|
||||
removing pages. See :ref:`adding-and-remove-pages`.
|
||||
@ -2571,7 +2569,7 @@ For a detailed list of changes, please see the file
|
||||
permissions, it does make them available so that applications that
|
||||
use qpdf can enforce permissions.
|
||||
|
||||
- The :samp:`--check` option to
|
||||
- The :qpdf:ref:`--check` option to
|
||||
:command:`qpdf` has been extended to include some
|
||||
additional information.
|
||||
|
||||
|
@ -13,12 +13,12 @@ cryptography algorithm, and MD5, which is a weak hashing algorithm. In
|
||||
version 10.4, qpdf generates warnings for some (but not all) cases of
|
||||
writing files with weak cryptography when invoked from the command-line.
|
||||
These warnings can be suppressed using the
|
||||
:samp:`--allow-weak-crypto` option.
|
||||
:qpdf:ref:`--allow-weak-crypto` option.
|
||||
|
||||
It is planned for qpdf version 11 to be stricter, making it an error to
|
||||
write files with insecure cryptography from the command-line tool in
|
||||
most cases without specifying the
|
||||
:samp:`--allow-weak-crypto` flag and also to require
|
||||
:qpdf:ref:`--allow-weak-crypto` flag and also to require
|
||||
explicit steps when using the C++ library to enable use of insecure
|
||||
cryptography.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user