Commit 1173a0bdfc56a08eedafc06afcd37f0b35ac3ea2

Authored by Jay Berkenbilt
1 parent 17703a8d

Add --user-password, --owner-password, --bits to --encrypt

Add the command-line arguments. They don't do anything yet.
generate_auto_job
... ... @@ -738,6 +738,11 @@ class Main:
738 738  
739 739 if flag in expected:
740 740 options_seen.add(flag)
  741 + elif flag.startswith('__'):
  742 + # This marks a flag that has no JSON equivalent because it
  743 + # is handled in some other fashion.
  744 + options_seen.add(flag[2:])
  745 + return
741 746 elif isinstance(j, str):
742 747 if not flag.startswith('_'):
743 748 raise Exception(f'json: {flag} has a description'
... ...
job.sums
1 1 # Generated by generate_auto_job
2   -generate_auto_job 9abe2ec994fb98526f5e3c0c199ce2e61a868463cb522a5bc6e9730b65534187
  2 +generate_auto_job bf44181b610d335511a41b6c2b9c3497d0b023a1ca2c8e4537b34cb6262ce173
3 3 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
4 4 include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
5 5 include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5
6 6 include/qpdf/auto_job_c_main.hh dbfc221d1533120d1aa9c361d8d2483dea5fcb1c0fd95144d98d305e64ed32a6
7 7 include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c18911614fe8e568ec
8 8 include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1
9   -job.yml 1f5db325600a763692034835117ac6b1a4b6aba8e73faa13a004ddc086834545
10   -libqpdf/qpdf/auto_job_decl.hh 7844eba58edffb9494b19e8eca6fd59a24d6e152ca606c3b07da569f753df2da
11   -libqpdf/qpdf/auto_job_help.hh 319c7bd0bfe2f3cb96bb16b66a9331a81b312805a64acaad54737b5623773e31
12   -libqpdf/qpdf/auto_job_init.hh e6c09e94c92bd17e9c728b11437e3c98266c93c42c3efbce050c8d288e6b3473
  9 +job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c
  10 +libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2
  11 +libqpdf/qpdf/auto_job_help.hh 788320d439519ecd284621531e96ee698965a9ad342fd423c5fb1de75d2a06b1
  12 +libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065
13 13 libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297
14   -libqpdf/qpdf/auto_job_json_init.hh 85ac7e5c66f14c767419823eac84bdea4bd72d690bfe12b533321e5708e644b7
15   -libqpdf/qpdf/auto_job_schema.hh 5e0f5cb7d462716fe52548b2ae1a8eb6f3c900016e915140eea37f78cee45b2b
  14 +libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f
  15 +libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9
16 16 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
17   -manual/cli.rst 4f2806f7cf77f167fd41b065a8916f02fdfaab35ad1a74587578bf2954228464
  17 +manual/cli.rst b524f96f2a6f338f3e4350703598c56ba22e8f12a8efb7a441648c6dbf0a455e
... ...
... ... @@ -60,6 +60,10 @@ choices:
60 60 - 1
61 61 - 2
62 62 - latest
  63 + enc_bits:
  64 + - 40
  65 + - 128
  66 + - 256
63 67 print128:
64 68 - full
65 69 - low
... ... @@ -194,8 +198,18 @@ options:
194 198 required_parameter:
195 199 password: password
196 200 - table: encryption
  201 + config: c_main
197 202 prefix: Enc
198 203 positional: true
  204 + manual:
  205 + - user-password
  206 + - owner-password
  207 + - bits
  208 + required_parameter:
  209 + user-password: user_password
  210 + owner-password: owner_password
  211 + required_choices:
  212 + bits: enc_bits
199 213 - table: 40-bit encryption
200 214 config: c_enc
201 215 config_prefix: Enc
... ... @@ -276,10 +290,14 @@ json:
276 290 # match a command-line option, and its properties and help come from
277 291 # other information known by generate_auto_job. This information is
278 292 # used to construct a "schema" (as in JSON.hh) for the json input to
279   - # QPDFJob. The leading underscore is removed. *NOTE*: all keys are
280   - # converted to camelCase for the schema and must appear that way
281   - # in the user-supplied json. This makes it more convenient to
282   - # populate JSON objects in some languages.
  293 + # QPDFJob. The leading underscore is removed. If a key starts with a
  294 + # double underscore, it corresponds to a command-line argument that
  295 + # does not have a counterpart in the JSON. This signals that the
  296 + # command-line argument was not forgotten, but it is otherwise
  297 + # ignored by the JSON. *NOTE*: all keys are converted to camelCase
  298 + # for the schema and must appear that way in the user-supplied json.
  299 + # This makes it more convenient to populate JSON objects in some
  300 + # languages.
283 301  
284 302 # input
285 303 _inputFile: "input filename"
... ... @@ -316,8 +334,9 @@ json:
316 334 json-output:
317 335 remove-restrictions:
318 336 encrypt:
319   - _user-password: "user password"
320   - _owner-password: "owner password"
  337 + user-password:
  338 + owner-password:
  339 + __bits:
321 340 _40bit:
322 341 Enc40.annotate:
323 342 Enc40.extract:
... ...
libqpdf/QPDFJob_argv.cc
... ... @@ -204,6 +204,24 @@ ArgParser::argEncPositional(std::string const& arg)
204 204 }
205 205  
206 206 void
  207 +ArgParser::argEncUserPassword(std::string const& arg)
  208 +{
  209 + // QXXXQ
  210 +}
  211 +
  212 +void
  213 +ArgParser::argEncOwnerPassword(std::string const& arg)
  214 +{
  215 + // QXXXQ
  216 +}
  217 +
  218 +void
  219 +ArgParser::argEncBits(std::string const& arg)
  220 +{
  221 + // QXXXQ
  222 +}
  223 +
  224 +void
207 225 ArgParser::argPages()
208 226 {
209 227 this->accumulated_args.clear();
... ...
libqpdf/QPDFJob_json.cc
... ... @@ -109,6 +109,10 @@ Handlers::initHandlers()
109 109  
110 110 #include <qpdf/auto_job_json_init.hh>
111 111  
  112 + // We have `bits` in the CLI but not in the JSON. Reference this variable so it doesn't generate
  113 + // a warning.
  114 + [](char const**) {}(enc_bits_choices);
  115 +
112 116 if (this->json_handlers.size() != 1) {
113 117 throw std::logic_error("QPDFJob_json: json_handlers size != 1 at end");
114 118 }
... ...
libqpdf/qpdf/auto_job_decl.hh
... ... @@ -32,6 +32,9 @@ void argPagesPositional(std::string const&amp;);
32 32 void argPagesPassword(std::string const&);
33 33 void argEndPages();
34 34 void argEncPositional(std::string const&);
  35 +void argEncUserPassword(std::string const&);
  36 +void argEncOwnerPassword(std::string const&);
  37 +void argEncBits(std::string const&);
35 38 void argEndEncryption();
36 39 void argEnd40BitEncryption();
37 40 void argEnd128BitEncryption();
... ...
libqpdf/qpdf/auto_job_help.hh
... ... @@ -152,10 +152,25 @@ ap.addOptionHelp(&quot;--encrypt&quot;, &quot;transformation&quot;, &quot;start encryption options&quot;, R&quot;(-
152 152  
153 153 Run qpdf --help=encryption for details.
154 154 )");
  155 +ap.addOptionHelp("--user-password", "transformation", "specify user password", R"(--user-password=user-password
  156 +
  157 +Set the user password.
  158 +)");
  159 +ap.addOptionHelp("--owner-password", "transformation", "specify owner password", R"(--owner-password=owner-password
  160 +
  161 +Set the owner password.
  162 +)");
  163 +ap.addOptionHelp("--bits", "transformation", "specify encryption bit depth", R"(--bits={48|128|256}
  164 +
  165 +Set the encrypt bit depth. Use 256.
  166 +)");
155 167 ap.addOptionHelp("--decrypt", "transformation", "remove encryption from input file", R"(Create an unencrypted output file even if the input file was
156 168 encrypted. Normally qpdf preserves whatever encryption was
157 169 present on the input file. This option overrides that behavior.
158 170 )");
  171 +}
  172 +static void add_help_3(QPDFArgParser& ap)
  173 +{
159 174 ap.addOptionHelp("--remove-restrictions", "transformation", "remove security restrictions from input file", R"(Remove restrictions associated with digitally signed PDF files.
160 175 This may be combined with --decrypt to allow free editing of
161 176 previously signed/encrypted files. This option invalidates the
... ... @@ -172,9 +187,6 @@ ap.addOptionHelp(&quot;--encryption-file-password&quot;, &quot;transformation&quot;, &quot;supply passwor
172 187 If the file named in --copy-encryption requires a password, use
173 188 this option to supply the password.
174 189 )");
175   -}
176   -static void add_help_3(QPDFArgParser& ap)
177   -{
178 190 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
179 191 editing. This is for editing the PDF code, not the page contents.
180 192 All streams that can be uncompressed are uncompressed, and
... ... @@ -270,6 +282,9 @@ ap.addOptionHelp(&quot;--ii-min-bytes&quot;, &quot;transformation&quot;, &quot;set minimum size for --ext
270 282 Don't externalize inline images smaller than this size. The
271 283 default is 1,024. Use 0 for no minimum.
272 284 )");
  285 +}
  286 +static void add_help_4(QPDFArgParser& ap)
  287 +{
273 288 ap.addOptionHelp("--min-version", "transformation", "set minimum PDF version", R"(--min-version=version
274 289  
275 290 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
297 312 :even starts with the second page. These are odd and even pages
298 313 from the resulting set, not based on the original page numbers.
299 314 )");
300   -}
301   -static void add_help_4(QPDFArgParser& ap)
302   -{
303 315 ap.addHelpTopic("modification", "change parts of the PDF", R"(Modification options make systematic changes to certain parts of
304 316 the PDF, causing the PDF to render differently from the original.
305 317 )");
... ... @@ -392,6 +404,9 @@ ap.addOptionHelp(&quot;--keep-inline-images&quot;, &quot;modification&quot;, &quot;exclude inline images
392 404 )");
393 405 ap.addOptionHelp("--remove-page-labels", "modification", "remove explicit page numbers", R"(Exclude page labels (explicit page numbers) from the output file.
394 406 )");
  407 +}
  408 +static void add_help_5(QPDFArgParser& ap)
  409 +{
395 410 ap.addHelpTopic("encryption", "create encrypted files", R"(Create encrypted files. Usage:
396 411  
397 412 --encrypt user-password owner-password key-length [options] --
... ... @@ -467,9 +482,6 @@ and filling in form fields. For 128-bit and 256-bit encryption,
467 482 this also enables editing, creating, and deleting form fields
468 483 unless --modify-other=n or --modify=none is also specified.
469 484 )");
470   -}
471   -static void add_help_5(QPDFArgParser& ap)
472   -{
473 485 ap.addOptionHelp("--assemble", "encryption", "restrict document assembly", R"(--assemble=[y|n]
474 486  
475 487 Enable/disable document assembly (rotation and reordering of
... ... @@ -628,6 +640,9 @@ Specify pages from the overlay/underlay that are repeated after
628 640 "from" pages have been exhausted. See qpdf --help=page-ranges
629 641 for help with the page range syntax.
630 642 )");
  643 +}
  644 +static void add_help_6(QPDFArgParser& ap)
  645 +{
631 646 ap.addHelpTopic("attachments", "work with embedded files", R"(It is possible to list, add, or delete embedded files (also known
632 647 as attachments) and to copy attachments from other files. See help
633 648 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
645 660 to copy attachments from multiple files. Run
646 661 qpdf --help=copy-attachments for details.
647 662 )");
648   -}
649   -static void add_help_6(QPDFArgParser& ap)
650   -{
651 663 ap.addOptionHelp("--remove-attachment", "attachments", "remove an embedded file", R"(--remove-attachment=key
652 664  
653 665 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
746 758 PDF file. It merely checks that the PDF file is syntactically
747 759 valid. See also qpdf --help=exit-status.
748 760 )");
  761 +}
  762 +static void add_help_7(QPDFArgParser& ap)
  763 +{
749 764 ap.addOptionHelp("--show-encryption", "inspection", "information about encrypted files", R"(Show document encryption parameters. Also show the document's
750 765 user password if the owner password is given and the file was
751 766 encrypted using older encryption formats that allow user
... ... @@ -757,9 +772,6 @@ underlying encryption key to be displayed.
757 772 ap.addOptionHelp("--check-linearization", "inspection", "check linearization tables", R"(Check to see whether a file is linearized and, if so, whether
758 773 the linearization hint tables are correct.
759 774 )");
760   -}
761   -static void add_help_7(QPDFArgParser& ap)
762   -{
763 775 ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
764 776 )");
765 777 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
840 852 when --json-output is specified, in which case the default is
841 853 "inline".
842 854 )");
  855 +}
  856 +static void add_help_8(QPDFArgParser& ap)
  857 +{
843 858 ap.addOptionHelp("--json-stream-prefix", "json", "prefix for json stream data files", R"(--json-stream-prefix=file-prefix
844 859  
845 860 When used with --json-stream-data=file, --json-stream-data=file-prefix
... ... @@ -860,9 +875,6 @@ ap.addOptionHelp(&quot;--json-input&quot;, &quot;json&quot;, &quot;input file is qpdf JSON&quot;, R&quot;(Treat the
860 875 "qpdf JSON Format" section of the manual for information about
861 876 how to use this option.
862 877 )");
863   -}
864   -static void add_help_8(QPDFArgParser& ap)
865   -{
866 878 ap.addOptionHelp("--update-from-json", "json", "update a PDF from qpdf JSON", R"(--update-from-json=qpdf-json-file
867 879  
868 880 Update a PDF file from a JSON file. Please see the "qpdf JSON"
... ...
libqpdf/qpdf/auto_job_init.hh
... ... @@ -23,6 +23,7 @@ static char const* json_key_choices[] = {&quot;acroform&quot;, &quot;attachments&quot;, &quot;encrypt&quot;, &quot;
23 23 static char const* json_output_choices[] = {"2", "latest", 0};
24 24 static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
25 25 static char const* json_version_choices[] = {"1", "2", "latest", 0};
  26 +static char const* enc_bits_choices[] = {"40", "128", "256", 0};
26 27 static char const* print128_choices[] = {"full", "low", "none", 0};
27 28 static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
28 29  
... ... @@ -128,6 +129,9 @@ this-&gt;ap.addPositional(p(&amp;ArgParser::argPagesPositional));
128 129 this->ap.addRequiredParameter("password", p(&ArgParser::argPagesPassword), "password");
129 130 this->ap.registerOptionTable("encryption", b(&ArgParser::argEndEncryption));
130 131 this->ap.addPositional(p(&ArgParser::argEncPositional));
  132 +this->ap.addRequiredParameter("user-password", p(&ArgParser::argEncUserPassword), "user_password");
  133 +this->ap.addRequiredParameter("owner-password", p(&ArgParser::argEncOwnerPassword), "owner_password");
  134 +this->ap.addChoices("bits", p(&ArgParser::argEncBits), true, enc_bits_choices);
131 135 this->ap.registerOptionTable("40-bit encryption", b(&ArgParser::argEnd40BitEncryption));
132 136 this->ap.addChoices("extract", [this](std::string const& x){c_enc->extract(x);}, true, yn_choices);
133 137 this->ap.addChoices("annotate", [this](std::string const& x){c_enc->annotate(x);}, true, yn_choices);
... ...
libqpdf/qpdf/auto_job_json_init.hh
... ... @@ -16,6 +16,7 @@ static char const* json_key_choices[] = {&quot;acroform&quot;, &quot;attachments&quot;, &quot;encrypt&quot;, &quot;
16 16 static char const* json_output_choices[] = {"2", "latest", 0};
17 17 static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
18 18 static char const* json_version_choices[] = {"1", "2", "latest", 0};
  19 +static char const* enc_bits_choices[] = {"40", "128", "256", 0};
19 20 static char const* print128_choices[] = {"full", "low", "none", 0};
20 21 static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
21 22  
... ... @@ -120,6 +121,8 @@ popHandler(); // key: userPassword
120 121 pushKey("ownerPassword");
121 122 setupEncryptOwnerPassword();
122 123 popHandler(); // key: ownerPassword
  124 +pushKey("Bits");
  125 +popHandler(); // key: Bits
123 126 pushKey("40bit");
124 127 beginDict(bindJSON(&Handlers::beginEncrypt40bit), bindBare(&Handlers::endEncrypt40bit)); // .encrypt.40bit
125 128 pushKey("annotate");
... ...
libqpdf/qpdf/auto_job_schema.hh
... ... @@ -31,8 +31,9 @@ static constexpr char const* JOB_SCHEMA_DATA = R&quot;({
31 31 "jsonOutput": "apply defaults for JSON serialization",
32 32 "removeRestrictions": "remove security restrictions from input file",
33 33 "encrypt": {
34   - "userPassword": "user password",
35   - "ownerPassword": "owner password",
  34 + "userPassword": "specify user password",
  35 + "ownerPassword": "specify owner password",
  36 + "Bits": null,
36 37 "40bit": {
37 38 "annotate": "restrict document annotation",
38 39 "extract": "restrict text/graphic extraction",
... ...
manual/cli.rst
... ... @@ -723,6 +723,32 @@ Related Options
723 723 This flag starts encryption options, used to create encrypted
724 724 files. Please see :ref:`encryption-options` for details.
725 725  
  726 +.. qpdf:option:: --user-password=user-password
  727 +
  728 + .. help: specify user password
  729 +
  730 + Set the user password.
  731 +
  732 + Set the user password for the encrypted file.
  733 +
  734 +.. qpdf:option:: --owner-password=owner-password
  735 +
  736 + .. help: specify owner password
  737 +
  738 + Set the owner password.
  739 +
  740 + Set the owner password for the encrypted file.
  741 +
  742 +.. qpdf:option:: --bits={48|128|256}
  743 +
  744 + .. help: specify encryption bit depth
  745 +
  746 + Set the encrypt bit depth. Use 256.
  747 +
  748 + Set the bit depth for encrypted files. You should always use
  749 + ``--bits=256`` unless you have a strong reason to create a file
  750 + with weaker encryption.
  751 +
726 752 .. qpdf:option:: --decrypt
727 753  
728 754 .. help: remove encryption from input file
... ...