summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2023-12-22 22:27:56 +0100
committerJay Berkenbilt <ejb@ql.org>2023-12-23 00:13:05 +0100
commit1173a0bdfc56a08eedafc06afcd37f0b35ac3ea2 (patch)
tree8fea9180275ab264ec20381a6a41d6b42e923532
parent17703a8dcd74bc0baab044aa13f09b909e72bdcb (diff)
downloadqpdf-1173a0bdfc56a08eedafc06afcd37f0b35ac3ea2.tar.zst
Add --user-password, --owner-password, --bits to --encrypt
Add the command-line arguments. They don't do anything yet.
-rwxr-xr-xgenerate_auto_job5
-rw-r--r--job.sums16
-rw-r--r--job.yml31
-rw-r--r--libqpdf/QPDFJob_argv.cc18
-rw-r--r--libqpdf/QPDFJob_json.cc4
-rw-r--r--libqpdf/qpdf/auto_job_decl.hh3
-rw-r--r--libqpdf/qpdf/auto_job_help.hh48
-rw-r--r--libqpdf/qpdf/auto_job_init.hh4
-rw-r--r--libqpdf/qpdf/auto_job_json_init.hh3
-rw-r--r--libqpdf/qpdf/auto_job_schema.hh5
-rw-r--r--manual/cli.rst26
11 files changed, 129 insertions, 34 deletions
diff --git a/generate_auto_job b/generate_auto_job
index f6bb908b..10d74d89 100755
--- a/generate_auto_job
+++ b/generate_auto_job
@@ -738,6 +738,11 @@ class Main:
if flag in expected:
options_seen.add(flag)
+ elif flag.startswith('__'):
+ # This marks a flag that has no JSON equivalent because it
+ # is handled in some other fashion.
+ options_seen.add(flag[2:])
+ return
elif isinstance(j, str):
if not flag.startswith('_'):
raise Exception(f'json: {flag} has a description'
diff --git a/job.sums b/job.sums
index 8ab0d576..43318803 100644
--- a/job.sums
+++ b/job.sums
@@ -1,17 +1,17 @@
# Generated by generate_auto_job
-generate_auto_job 9abe2ec994fb98526f5e3c0c199ce2e61a868463cb522a5bc6e9730b65534187
+generate_auto_job bf44181b610d335511a41b6c2b9c3497d0b023a1ca2c8e4537b34cb6262ce173
include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5
include/qpdf/auto_job_c_main.hh dbfc221d1533120d1aa9c361d8d2483dea5fcb1c0fd95144d98d305e64ed32a6
include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c18911614fe8e568ec
include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1
-job.yml 1f5db325600a763692034835117ac6b1a4b6aba8e73faa13a004ddc086834545
-libqpdf/qpdf/auto_job_decl.hh 7844eba58edffb9494b19e8eca6fd59a24d6e152ca606c3b07da569f753df2da
-libqpdf/qpdf/auto_job_help.hh 319c7bd0bfe2f3cb96bb16b66a9331a81b312805a64acaad54737b5623773e31
-libqpdf/qpdf/auto_job_init.hh e6c09e94c92bd17e9c728b11437e3c98266c93c42c3efbce050c8d288e6b3473
+job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c
+libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2
+libqpdf/qpdf/auto_job_help.hh 788320d439519ecd284621531e96ee698965a9ad342fd423c5fb1de75d2a06b1
+libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065
libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297
-libqpdf/qpdf/auto_job_json_init.hh 85ac7e5c66f14c767419823eac84bdea4bd72d690bfe12b533321e5708e644b7
-libqpdf/qpdf/auto_job_schema.hh 5e0f5cb7d462716fe52548b2ae1a8eb6f3c900016e915140eea37f78cee45b2b
+libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f
+libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
-manual/cli.rst 4f2806f7cf77f167fd41b065a8916f02fdfaab35ad1a74587578bf2954228464
+manual/cli.rst b524f96f2a6f338f3e4350703598c56ba22e8f12a8efb7a441648c6dbf0a455e
diff --git a/job.yml b/job.yml
index fb754b44..d342e7a2 100644
--- a/job.yml
+++ b/job.yml
@@ -60,6 +60,10 @@ choices:
- 1
- 2
- latest
+ enc_bits:
+ - 40
+ - 128
+ - 256
print128:
- full
- low
@@ -194,8 +198,18 @@ options:
required_parameter:
password: password
- table: encryption
+ config: c_main
prefix: Enc
positional: true
+ manual:
+ - user-password
+ - owner-password
+ - bits
+ required_parameter:
+ user-password: user_password
+ owner-password: owner_password
+ required_choices:
+ bits: enc_bits
- table: 40-bit encryption
config: c_enc
config_prefix: Enc
@@ -276,10 +290,14 @@ json:
# match a command-line option, and its properties and help come from
# other information known by generate_auto_job. This information is
# used to construct a "schema" (as in JSON.hh) for the json input to
- # QPDFJob. The leading underscore is removed. *NOTE*: all keys are
- # converted to camelCase for the schema and must appear that way
- # in the user-supplied json. This makes it more convenient to
- # populate JSON objects in some languages.
+ # QPDFJob. The leading underscore is removed. If a key starts with a
+ # double underscore, it corresponds to a command-line argument that
+ # does not have a counterpart in the JSON. This signals that the
+ # command-line argument was not forgotten, but it is otherwise
+ # ignored by the JSON. *NOTE*: all keys are converted to camelCase
+ # for the schema and must appear that way in the user-supplied json.
+ # This makes it more convenient to populate JSON objects in some
+ # languages.
# input
_inputFile: "input filename"
@@ -316,8 +334,9 @@ json:
json-output:
remove-restrictions:
encrypt:
- _user-password: "user password"
- _owner-password: "owner password"
+ user-password:
+ owner-password:
+ __bits:
_40bit:
Enc40.annotate:
Enc40.extract:
diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc
index e7bc1ea8..adf7ba64 100644
--- a/libqpdf/QPDFJob_argv.cc
+++ b/libqpdf/QPDFJob_argv.cc
@@ -204,6 +204,24 @@ ArgParser::argEncPositional(std::string const& arg)
}
void
+ArgParser::argEncUserPassword(std::string const& arg)
+{
+ // QXXXQ
+}
+
+void
+ArgParser::argEncOwnerPassword(std::string const& arg)
+{
+ // QXXXQ
+}
+
+void
+ArgParser::argEncBits(std::string const& arg)
+{
+ // QXXXQ
+}
+
+void
ArgParser::argPages()
{
this->accumulated_args.clear();
diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc
index 932cc84c..d44652f4 100644
--- a/libqpdf/QPDFJob_json.cc
+++ b/libqpdf/QPDFJob_json.cc
@@ -109,6 +109,10 @@ Handlers::initHandlers()
#include <qpdf/auto_job_json_init.hh>
+ // We have `bits` in the CLI but not in the JSON. Reference this variable so it doesn't generate
+ // a warning.
+ [](char const**) {}(enc_bits_choices);
+
if (this->json_handlers.size() != 1) {
throw std::logic_error("QPDFJob_json: json_handlers size != 1 at end");
}
diff --git a/libqpdf/qpdf/auto_job_decl.hh b/libqpdf/qpdf/auto_job_decl.hh
index 196a4fe7..31ea5086 100644
--- a/libqpdf/qpdf/auto_job_decl.hh
+++ b/libqpdf/qpdf/auto_job_decl.hh
@@ -32,6 +32,9 @@ void argPagesPositional(std::string const&);
void argPagesPassword(std::string const&);
void argEndPages();
void argEncPositional(std::string const&);
+void argEncUserPassword(std::string const&);
+void argEncOwnerPassword(std::string const&);
+void argEncBits(std::string const&);
void argEndEncryption();
void argEnd40BitEncryption();
void argEnd128BitEncryption();
diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh
index a21fe3c1..9f7cadfe 100644
--- a/libqpdf/qpdf/auto_job_help.hh
+++ b/libqpdf/qpdf/auto_job_help.hh
@@ -152,10 +152,25 @@ ap.addOptionHelp("--encrypt", "transformation", "start encryption options", R"(-
Run qpdf --help=encryption for details.
)");
+ap.addOptionHelp("--user-password", "transformation", "specify user password", R"(--user-password=user-password
+
+Set the user password.
+)");
+ap.addOptionHelp("--owner-password", "transformation", "specify owner password", R"(--owner-password=owner-password
+
+Set the owner password.
+)");
+ap.addOptionHelp("--bits", "transformation", "specify encryption bit depth", R"(--bits={48|128|256}
+
+Set the encrypt bit depth. Use 256.
+)");
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.
)");
+}
+static void add_help_3(QPDFArgParser& ap)
+{
ap.addOptionHelp("--remove-restrictions", "transformation", "remove security restrictions from input file", R"(Remove restrictions associated with digitally signed PDF files.
This may be combined with --decrypt to allow free editing of
previously signed/encrypted files. This option invalidates the
@@ -172,9 +187,6 @@ ap.addOptionHelp("--encryption-file-password", "transformation", "supply passwor
If the file named in --copy-encryption requires a password, use
this option to supply the password.
)");
-}
-static void add_help_3(QPDFArgParser& ap)
-{
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 for editing the PDF code, not the page contents.
All streams that can be uncompressed are uncompressed, and
@@ -270,6 +282,9 @@ ap.addOptionHelp("--ii-min-bytes", "transformation", "set minimum size for --ext
Don't externalize inline images smaller than this size. The
default is 1,024. Use 0 for no minimum.
)");
+}
+static void add_help_4(QPDFArgParser& ap)
+{
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
@@ -297,9 +312,6 @@ 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.
)");
-}
-static void add_help_4(QPDFArgParser& ap)
-{
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.
)");
@@ -392,6 +404,9 @@ ap.addOptionHelp("--keep-inline-images", "modification", "exclude inline images
)");
ap.addOptionHelp("--remove-page-labels", "modification", "remove explicit page numbers", R"(Exclude page labels (explicit page numbers) from the output file.
)");
+}
+static void add_help_5(QPDFArgParser& ap)
+{
ap.addHelpTopic("encryption", "create encrypted files", R"(Create encrypted files. Usage:
--encrypt user-password owner-password key-length [options] --
@@ -467,9 +482,6 @@ 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.
)");
-}
-static void add_help_5(QPDFArgParser& ap)
-{
ap.addOptionHelp("--assemble", "encryption", "restrict document assembly", R"(--assemble=[y|n]
Enable/disable document assembly (rotation and reordering of
@@ -628,6 +640,9 @@ 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.
)");
+}
+static void add_help_6(QPDFArgParser& ap)
+{
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
@@ -645,9 +660,6 @@ 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.addOptionHelp("--remove-attachment", "attachments", "remove an embedded file", R"(--remove-attachment=key
Remove an embedded file using its key. Get the key with
@@ -746,6 +758,9 @@ of the actual PDF page content or semantic correctness of the
PDF file. It merely checks that the PDF file is syntactically
valid. See also qpdf --help=exit-status.
)");
+}
+static void add_help_7(QPDFArgParser& ap)
+{
ap.addOptionHelp("--show-encryption", "inspection", "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
@@ -757,9 +772,6 @@ underlying encryption key to be displayed.
ap.addOptionHelp("--check-linearization", "inspection", "check linearization tables", R"(Check to see whether a file is linearized and, if so, whether
the linearization hint tables are correct.
)");
-}
-static void add_help_7(QPDFArgParser& ap)
-{
ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
)");
ap.addOptionHelp("--show-xref", "inspection", "show cross reference data", R"(Show the contents of the cross-reference table or stream (object
@@ -840,6 +852,9 @@ object number. The prefix can be overridden with
when --json-output is specified, in which case the default is
"inline".
)");
+}
+static void add_help_8(QPDFArgParser& ap)
+{
ap.addOptionHelp("--json-stream-prefix", "json", "prefix for json stream data files", R"(--json-stream-prefix=file-prefix
When used with --json-stream-data=file, --json-stream-data=file-prefix
@@ -860,9 +875,6 @@ ap.addOptionHelp("--json-input", "json", "input file is qpdf JSON", R"(Treat the
"qpdf JSON Format" section of the manual for information about
how to use this option.
)");
-}
-static void add_help_8(QPDFArgParser& ap)
-{
ap.addOptionHelp("--update-from-json", "json", "update a PDF from qpdf JSON", R"(--update-from-json=qpdf-json-file
Update a PDF file from a JSON file. Please see the "qpdf JSON"
diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh
index 177f2105..23b55c7f 100644
--- a/libqpdf/qpdf/auto_job_init.hh
+++ b/libqpdf/qpdf/auto_job_init.hh
@@ -23,6 +23,7 @@ static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "
static char const* json_output_choices[] = {"2", "latest", 0};
static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
static char const* json_version_choices[] = {"1", "2", "latest", 0};
+static char const* enc_bits_choices[] = {"40", "128", "256", 0};
static char const* print128_choices[] = {"full", "low", "none", 0};
static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
@@ -128,6 +129,9 @@ this->ap.addPositional(p(&ArgParser::argPagesPositional));
this->ap.addRequiredParameter("password", p(&ArgParser::argPagesPassword), "password");
this->ap.registerOptionTable("encryption", b(&ArgParser::argEndEncryption));
this->ap.addPositional(p(&ArgParser::argEncPositional));
+this->ap.addRequiredParameter("user-password", p(&ArgParser::argEncUserPassword), "user_password");
+this->ap.addRequiredParameter("owner-password", p(&ArgParser::argEncOwnerPassword), "owner_password");
+this->ap.addChoices("bits", p(&ArgParser::argEncBits), true, enc_bits_choices);
this->ap.registerOptionTable("40-bit encryption", b(&ArgParser::argEnd40BitEncryption));
this->ap.addChoices("extract", [this](std::string const& x){c_enc->extract(x);}, true, yn_choices);
this->ap.addChoices("annotate", [this](std::string const& x){c_enc->annotate(x);}, true, yn_choices);
diff --git a/libqpdf/qpdf/auto_job_json_init.hh b/libqpdf/qpdf/auto_job_json_init.hh
index 8f642d7c..135a5159 100644
--- a/libqpdf/qpdf/auto_job_json_init.hh
+++ b/libqpdf/qpdf/auto_job_json_init.hh
@@ -16,6 +16,7 @@ static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "
static char const* json_output_choices[] = {"2", "latest", 0};
static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
static char const* json_version_choices[] = {"1", "2", "latest", 0};
+static char const* enc_bits_choices[] = {"40", "128", "256", 0};
static char const* print128_choices[] = {"full", "low", "none", 0};
static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
@@ -120,6 +121,8 @@ popHandler(); // key: userPassword
pushKey("ownerPassword");
setupEncryptOwnerPassword();
popHandler(); // key: ownerPassword
+pushKey("Bits");
+popHandler(); // key: Bits
pushKey("40bit");
beginDict(bindJSON(&Handlers::beginEncrypt40bit), bindBare(&Handlers::endEncrypt40bit)); // .encrypt.40bit
pushKey("annotate");
diff --git a/libqpdf/qpdf/auto_job_schema.hh b/libqpdf/qpdf/auto_job_schema.hh
index fbc13d8c..84f4cd4a 100644
--- a/libqpdf/qpdf/auto_job_schema.hh
+++ b/libqpdf/qpdf/auto_job_schema.hh
@@ -31,8 +31,9 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
"jsonOutput": "apply defaults for JSON serialization",
"removeRestrictions": "remove security restrictions from input file",
"encrypt": {
- "userPassword": "user password",
- "ownerPassword": "owner password",
+ "userPassword": "specify user password",
+ "ownerPassword": "specify owner password",
+ "Bits": null,
"40bit": {
"annotate": "restrict document annotation",
"extract": "restrict text/graphic extraction",
diff --git a/manual/cli.rst b/manual/cli.rst
index 482d65f9..943b404e 100644
--- a/manual/cli.rst
+++ b/manual/cli.rst
@@ -723,6 +723,32 @@ Related Options
This flag starts encryption options, used to create encrypted
files. Please see :ref:`encryption-options` for details.
+.. qpdf:option:: --user-password=user-password
+
+ .. help: specify user password
+
+ Set the user password.
+
+ Set the user password for the encrypted file.
+
+.. qpdf:option:: --owner-password=owner-password
+
+ .. help: specify owner password
+
+ Set the owner password.
+
+ Set the owner password for the encrypted file.
+
+.. qpdf:option:: --bits={48|128|256}
+
+ .. help: specify encryption bit depth
+
+ Set the encrypt bit depth. Use 256.
+
+ Set the bit depth for encrypted files. You should always use
+ ``--bits=256`` unless you have a strong reason to create a file
+ with weaker encryption.
+
.. qpdf:option:: --decrypt
.. help: remove encryption from input file