Commit 7d7e2234a537b6cd2205fb5cf942d5a9e8a866e3
1 parent
1173a0bd
Implement new --encrypt args and completion (fixes #784)
Positional arguments are supported in a backward-compatible way, but completion no longer guides users to it.
Showing
12 changed files
with
224 additions
and
118 deletions
ChangeLog
| 1 | 1 | 2023-12-22 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | |
| 3 | + * Allow the syntax "--encrypt --user-password=user-password | |
| 4 | + --owner-password=owner-password --bits={40,128,256}" when | |
| 5 | + encrypting PDF files. This is an alternative to the syntax | |
| 6 | + "--encrypt user-password owner-password {40,128,256}", which will | |
| 7 | + continue to be supported. The new syntax works better with shell | |
| 8 | + completion and allows creation of passwords that start with "-". | |
| 9 | + Fixes #874. | |
| 10 | + | |
| 3 | 11 | * When setting a check box value, allow any value other than /Off |
| 4 | 12 | to mean checked. This is permitted by the spec. Previously, any |
| 5 | 13 | value other than /Yes or /Off was rejected. Fixes #1056. | ... | ... |
job.sums
| ... | ... | @@ -8,10 +8,10 @@ include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c |
| 8 | 8 | include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1 |
| 9 | 9 | job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c |
| 10 | 10 | libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2 |
| 11 | -libqpdf/qpdf/auto_job_help.hh 788320d439519ecd284621531e96ee698965a9ad342fd423c5fb1de75d2a06b1 | |
| 11 | +libqpdf/qpdf/auto_job_help.hh ea1fdca2aa405bdf193732c5a2789c602efe2add3aa6e2dceecfacee175ce65c | |
| 12 | 12 | libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065 |
| 13 | 13 | libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297 |
| 14 | 14 | libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f |
| 15 | 15 | libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9 |
| 16 | 16 | manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 |
| 17 | -manual/cli.rst b524f96f2a6f338f3e4350703598c56ba22e8f12a8efb7a441648c6dbf0a455e | |
| 17 | +manual/cli.rst 28cc6b36b26377404022bab467e6a16085023fdfa5d9d419595ffcae6c69d531 | ... | ... |
libqpdf/QPDFJob_argv.cc
| ... | ... | @@ -35,6 +35,9 @@ namespace |
| 35 | 35 | std::shared_ptr<QPDFJob::EncConfig> c_enc; |
| 36 | 36 | std::vector<std::string> accumulated_args; |
| 37 | 37 | std::shared_ptr<char> pages_password{nullptr}; |
| 38 | + std::string user_password; | |
| 39 | + std::string owner_password; | |
| 40 | + bool used_enc_password_args{false}; | |
| 38 | 41 | bool gave_input{false}; |
| 39 | 42 | bool gave_output{false}; |
| 40 | 43 | }; |
| ... | ... | @@ -161,64 +164,67 @@ void |
| 161 | 164 | ArgParser::argEncrypt() |
| 162 | 165 | { |
| 163 | 166 | this->accumulated_args.clear(); |
| 164 | - if (this->ap.isCompleting() && this->ap.argsLeft() == 0) { | |
| 165 | - this->ap.insertCompletion("user-password"); | |
| 166 | - } | |
| 167 | 167 | this->ap.selectOptionTable(O_ENCRYPTION); |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | void |
| 171 | 171 | ArgParser::argEncPositional(std::string const& arg) |
| 172 | 172 | { |
| 173 | + if (used_enc_password_args) { | |
| 174 | + usage("positional and dashed encryption arguments may not be mixed"); | |
| 175 | + } | |
| 176 | + | |
| 173 | 177 | this->accumulated_args.push_back(arg); |
| 174 | - size_t n_args = this->accumulated_args.size(); | |
| 175 | - if (n_args < 3) { | |
| 176 | - if (this->ap.isCompleting() && (this->ap.argsLeft() == 0)) { | |
| 177 | - if (n_args == 1) { | |
| 178 | - this->ap.insertCompletion("owner-password"); | |
| 179 | - } else if (n_args == 2) { | |
| 180 | - this->ap.insertCompletion("40"); | |
| 181 | - this->ap.insertCompletion("128"); | |
| 182 | - this->ap.insertCompletion("256"); | |
| 183 | - } | |
| 184 | - } | |
| 178 | + if (this->accumulated_args.size() < 3) { | |
| 185 | 179 | return; |
| 186 | 180 | } |
| 187 | - std::string user_password = this->accumulated_args.at(0); | |
| 188 | - std::string owner_password = this->accumulated_args.at(1); | |
| 189 | - std::string len_str = this->accumulated_args.at(2); | |
| 190 | - int keylen = 0; | |
| 191 | - if (len_str == "40") { | |
| 192 | - keylen = 40; | |
| 193 | - this->ap.selectOptionTable(O_40_BIT_ENCRYPTION); | |
| 194 | - } else if (len_str == "128") { | |
| 195 | - keylen = 128; | |
| 196 | - this->ap.selectOptionTable(O_128_BIT_ENCRYPTION); | |
| 197 | - } else if (len_str == "256") { | |
| 198 | - keylen = 256; | |
| 199 | - this->ap.selectOptionTable(O_256_BIT_ENCRYPTION); | |
| 200 | - } else { | |
| 201 | - usage("encryption key length must be 40, 128, or 256"); | |
| 202 | - } | |
| 203 | - this->c_enc = c_main->encrypt(keylen, user_password, owner_password); | |
| 181 | + user_password = this->accumulated_args.at(0); | |
| 182 | + owner_password = this->accumulated_args.at(1); | |
| 183 | + auto len_str = this->accumulated_args.at(2); | |
| 184 | + this->accumulated_args.clear(); | |
| 185 | + argEncBits(len_str); | |
| 204 | 186 | } |
| 205 | 187 | |
| 206 | 188 | void |
| 207 | 189 | ArgParser::argEncUserPassword(std::string const& arg) |
| 208 | 190 | { |
| 209 | - // QXXXQ | |
| 191 | + if (!accumulated_args.empty()) { | |
| 192 | + usage("positional and dashed encryption arguments may not be mixed"); | |
| 193 | + } | |
| 194 | + this->used_enc_password_args = true; | |
| 195 | + this->user_password = arg; | |
| 210 | 196 | } |
| 211 | 197 | |
| 212 | 198 | void |
| 213 | 199 | ArgParser::argEncOwnerPassword(std::string const& arg) |
| 214 | 200 | { |
| 215 | - // QXXXQ | |
| 201 | + if (!accumulated_args.empty()) { | |
| 202 | + usage("positional and dashed encryption arguments may not be mixed"); | |
| 203 | + } | |
| 204 | + this->used_enc_password_args = true; | |
| 205 | + this->owner_password = arg; | |
| 216 | 206 | } |
| 217 | 207 | |
| 218 | 208 | void |
| 219 | 209 | ArgParser::argEncBits(std::string const& arg) |
| 220 | 210 | { |
| 221 | - // QXXXQ | |
| 211 | + if (!accumulated_args.empty()) { | |
| 212 | + usage("positional and dashed encryption arguments may not be mixed"); | |
| 213 | + } | |
| 214 | + int keylen = 0; | |
| 215 | + if (arg == "40") { | |
| 216 | + keylen = 40; | |
| 217 | + this->ap.selectOptionTable(O_40_BIT_ENCRYPTION); | |
| 218 | + } else if (arg == "128") { | |
| 219 | + keylen = 128; | |
| 220 | + this->ap.selectOptionTable(O_128_BIT_ENCRYPTION); | |
| 221 | + } else if (arg == "256") { | |
| 222 | + keylen = 256; | |
| 223 | + this->ap.selectOptionTable(O_256_BIT_ENCRYPTION); | |
| 224 | + } else { | |
| 225 | + usage("encryption key length must be 40, 128, or 256"); | |
| 226 | + } | |
| 227 | + this->c_enc = c_main->encrypt(keylen, user_password, owner_password); | |
| 222 | 228 | } |
| 223 | 229 | |
| 224 | 230 | void | ... | ... |
libqpdf/qpdf/auto_job_help.hh
| ... | ... | @@ -148,29 +148,14 @@ the structure without changing the content. |
| 148 | 148 | )"); |
| 149 | 149 | ap.addOptionHelp("--linearize", "transformation", "linearize (web-optimize) output", R"(Create linearized (web-optimized) output files. |
| 150 | 150 | )"); |
| 151 | -ap.addOptionHelp("--encrypt", "transformation", "start encryption options", R"(--encrypt user-password owner-password key-length [options] -- | |
| 151 | +ap.addOptionHelp("--encrypt", "transformation", "start encryption options", R"(--encrypt [options] -- | |
| 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 | -)"); | |
| 167 | 155 | ap.addOptionHelp("--decrypt", "transformation", "remove encryption from input file", R"(Create an unencrypted output file even if the input file was |
| 168 | 156 | encrypted. Normally qpdf preserves whatever encryption was |
| 169 | 157 | present on the input file. This option overrides that behavior. |
| 170 | 158 | )"); |
| 171 | -} | |
| 172 | -static void add_help_3(QPDFArgParser& ap) | |
| 173 | -{ | |
| 174 | 159 | ap.addOptionHelp("--remove-restrictions", "transformation", "remove security restrictions from input file", R"(Remove restrictions associated with digitally signed PDF files. |
| 175 | 160 | This may be combined with --decrypt to allow free editing of |
| 176 | 161 | previously signed/encrypted files. This option invalidates the |
| ... | ... | @@ -187,6 +172,9 @@ ap.addOptionHelp("--encryption-file-password", "transformation", "supply passwor |
| 187 | 172 | If the file named in --copy-encryption requires a password, use |
| 188 | 173 | this option to supply the password. |
| 189 | 174 | )"); |
| 175 | +} | |
| 176 | +static void add_help_3(QPDFArgParser& ap) | |
| 177 | +{ | |
| 190 | 178 | 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 |
| 191 | 179 | editing. This is for editing the PDF code, not the page contents. |
| 192 | 180 | All streams that can be uncompressed are uncompressed, and |
| ... | ... | @@ -282,9 +270,6 @@ ap.addOptionHelp("--ii-min-bytes", "transformation", "set minimum size for --ext |
| 282 | 270 | Don't externalize inline images smaller than this size. The |
| 283 | 271 | default is 1,024. Use 0 for no minimum. |
| 284 | 272 | )"); |
| 285 | -} | |
| 286 | -static void add_help_4(QPDFArgParser& ap) | |
| 287 | -{ | |
| 288 | 273 | ap.addOptionHelp("--min-version", "transformation", "set minimum PDF version", R"(--min-version=version |
| 289 | 274 | |
| 290 | 275 | Force the PDF version of the output to be at least the specified |
| ... | ... | @@ -312,6 +297,9 @@ resulting set of pages, where :odd starts with the first page and |
| 312 | 297 | :even starts with the second page. These are odd and even pages |
| 313 | 298 | from the resulting set, not based on the original page numbers. |
| 314 | 299 | )"); |
| 300 | +} | |
| 301 | +static void add_help_4(QPDFArgParser& ap) | |
| 302 | +{ | |
| 315 | 303 | ap.addHelpTopic("modification", "change parts of the PDF", R"(Modification options make systematic changes to certain parts of |
| 316 | 304 | the PDF, causing the PDF to render differently from the original. |
| 317 | 305 | )"); |
| ... | ... | @@ -404,18 +392,33 @@ ap.addOptionHelp("--keep-inline-images", "modification", "exclude inline images |
| 404 | 392 | )"); |
| 405 | 393 | ap.addOptionHelp("--remove-page-labels", "modification", "remove explicit page numbers", R"(Exclude page labels (explicit page numbers) from the output file. |
| 406 | 394 | )"); |
| 407 | -} | |
| 408 | -static void add_help_5(QPDFArgParser& ap) | |
| 409 | -{ | |
| 410 | 395 | ap.addHelpTopic("encryption", "create encrypted files", R"(Create encrypted files. Usage: |
| 411 | 396 | |
| 397 | +--encrypt \ | |
| 398 | + [--user-password=user-password] \ | |
| 399 | + [--owner-password=owner-password] \ | |
| 400 | + --bits=key-length [options] -- | |
| 401 | + | |
| 402 | +OR | |
| 403 | + | |
| 412 | 404 | --encrypt user-password owner-password key-length [options] -- |
| 413 | 405 | |
| 414 | -Either or both of user-password and owner-password may be empty | |
| 415 | -strings, though setting either to the empty string enables the file | |
| 416 | -to be opened and decrypted without a password. key-length may be | |
| 417 | -40, 128, or 256. Encryption options are terminated by "--" by | |
| 418 | -itself. | |
| 406 | +The first form, with flags for the passwords and bit length, was | |
| 407 | +introduced in qpdf 11.7.0. Only the --bits option is is mandatory. | |
| 408 | +This form allows you to use any text as the password. If passwords | |
| 409 | +are specified, they must be given before the --bits option. | |
| 410 | + | |
| 411 | +The second form has been in qpdf since the beginning and wil | |
| 412 | +continue to be supported. Either or both of user-password and | |
| 413 | +owner-password may be empty strings. | |
| 414 | + | |
| 415 | +The key-length parameter must be either 40, 128, or 256. The user | |
| 416 | +and/or owner password may be omitted. Omitting either pasword | |
| 417 | +enables the PDF file to be opened without a password. Specifying | |
| 418 | +the same value for the user and owner password and specifying an | |
| 419 | +empty owner password are both considered insecure. | |
| 420 | + | |
| 421 | +Encryption options are terminated by "--" by itself. | |
| 419 | 422 | |
| 420 | 423 | 40-bit encryption is insecure, as is 128-bit encryption without |
| 421 | 424 | AES. Use 256-bit encryption unless you have a specific reason to |
| ... | ... | @@ -468,6 +471,22 @@ Values for modify-opt: |
| 468 | 471 | annotate form + commenting and modifying forms |
| 469 | 472 | all allow full document modification |
| 470 | 473 | )"); |
| 474 | +ap.addOptionHelp("--user-password", "encryption", "specify user password", R"(--user-password=user-password | |
| 475 | + | |
| 476 | +Set the user password of the encrypted file. | |
| 477 | +)"); | |
| 478 | +ap.addOptionHelp("--owner-password", "encryption", "specify owner password", R"(--owner-password=owner-password | |
| 479 | + | |
| 480 | +Set the owner password of the encrypted file. | |
| 481 | +)"); | |
| 482 | +} | |
| 483 | +static void add_help_5(QPDFArgParser& ap) | |
| 484 | +{ | |
| 485 | +ap.addOptionHelp("--bits", "encryption", "specify encryption key length", R"(--bits={48|128|256} | |
| 486 | + | |
| 487 | +Specify the encryption key length. For best security, always use | |
| 488 | +a key length of 256. | |
| 489 | +)"); | |
| 471 | 490 | ap.addOptionHelp("--accessibility", "encryption", "restrict document accessibility", R"(--accessibility=[y|n] |
| 472 | 491 | |
| 473 | 492 | This option is ignored except with very old encryption formats. | ... | ... |
manual/cli.rst
| ... | ... | @@ -714,7 +714,7 @@ Related Options |
| 714 | 714 | important cross-reference information typically appears at the end |
| 715 | 715 | of the file. |
| 716 | 716 | |
| 717 | -.. qpdf:option:: --encrypt user-password owner-password key-length [options] -- | |
| 717 | +.. qpdf:option:: --encrypt [options] -- | |
| 718 | 718 | |
| 719 | 719 | .. help: start encryption options |
| 720 | 720 | |
| ... | ... | @@ -723,32 +723,6 @@ 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 | - | |
| 752 | 726 | .. qpdf:option:: --decrypt |
| 753 | 727 | |
| 754 | 728 | .. help: remove encryption from input file |
| ... | ... | @@ -1758,13 +1732,31 @@ Encryption |
| 1758 | 1732 | |
| 1759 | 1733 | Create encrypted files. Usage: |
| 1760 | 1734 | |
| 1735 | + --encrypt \ | |
| 1736 | + [--user-password=user-password] \ | |
| 1737 | + [--owner-password=owner-password] \ | |
| 1738 | + --bits=key-length [options] -- | |
| 1739 | + | |
| 1740 | + OR | |
| 1741 | + | |
| 1761 | 1742 | --encrypt user-password owner-password key-length [options] -- |
| 1762 | 1743 | |
| 1763 | - Either or both of user-password and owner-password may be empty | |
| 1764 | - strings, though setting either to the empty string enables the file | |
| 1765 | - to be opened and decrypted without a password. key-length may be | |
| 1766 | - 40, 128, or 256. Encryption options are terminated by "--" by | |
| 1767 | - itself. | |
| 1744 | + The first form, with flags for the passwords and bit length, was | |
| 1745 | + introduced in qpdf 11.7.0. Only the --bits option is is mandatory. | |
| 1746 | + This form allows you to use any text as the password. If passwords | |
| 1747 | + are specified, they must be given before the --bits option. | |
| 1748 | + | |
| 1749 | + The second form has been in qpdf since the beginning and wil | |
| 1750 | + continue to be supported. Either or both of user-password and | |
| 1751 | + owner-password may be empty strings. | |
| 1752 | + | |
| 1753 | + The key-length parameter must be either 40, 128, or 256. The user | |
| 1754 | + and/or owner password may be omitted. Omitting either pasword | |
| 1755 | + enables the PDF file to be opened without a password. Specifying | |
| 1756 | + the same value for the user and owner password and specifying an | |
| 1757 | + empty owner password are both considered insecure. | |
| 1758 | + | |
| 1759 | + Encryption options are terminated by "--" by itself. | |
| 1768 | 1760 | |
| 1769 | 1761 | 40-bit encryption is insecure, as is 128-bit encryption without |
| 1770 | 1762 | AES. Use 256-bit encryption unless you have a specific reason to |
| ... | ... | @@ -1823,17 +1815,38 @@ and :qpdf:ref:`--copy-encryption`. For a more in-depth technical |
| 1823 | 1815 | discussion of how PDF encryption works internally, see |
| 1824 | 1816 | :ref:`pdf-encryption`. |
| 1825 | 1817 | |
| 1826 | -To create an encrypted file, use | |
| 1818 | +To create an encrypted file, use one of | |
| 1819 | + | |
| 1820 | +:: | |
| 1821 | + | |
| 1822 | + --encrypt \ | |
| 1823 | + [--user-password=user-password] \ | |
| 1824 | + [--owner-password=owner-password] \ | |
| 1825 | + --bits=key-length [options] -- | |
| 1826 | + | |
| 1827 | +OR | |
| 1827 | 1828 | |
| 1828 | 1829 | :: |
| 1829 | 1830 | |
| 1830 | 1831 | --encrypt user-password owner-password key-length [options] -- |
| 1831 | 1832 | |
| 1832 | -Either or both of :samp:`{user-password}` and :samp:`{owner-password}` | |
| 1833 | -may be empty strings, though setting either to the empty string | |
| 1834 | -enables the file to be opened and decrypted without a password.. | |
| 1835 | -:samp:`{key-length}` may be ``40``, ``128``, or ``256``. Encryption | |
| 1836 | -options are terminated by ``--`` by itself. | |
| 1833 | +The first form, with flags for the passwords and bit length, was | |
| 1834 | +introduced in qpdf 11.7.0. Only the :qpdf:ref:`--bits` option is is | |
| 1835 | +mandatory. This form allows you to use any text as the password. If | |
| 1836 | +passwords are specified, they must be given before the | |
| 1837 | +:qpdf:ref:`--bits` option. | |
| 1838 | + | |
| 1839 | +The second form has been in qpdf since the beginning and wil | |
| 1840 | +continue to be supported. Either or both of user-password and | |
| 1841 | +owner-password may be empty strings. | |
| 1842 | + | |
| 1843 | +The ``key-length`` parameter must be either ``40``, ``128``, or | |
| 1844 | +``256``. The user and/or owner password may be omitted. Omitting | |
| 1845 | +either pasword enables the PDF file to be opened without a password. | |
| 1846 | +Specifying the same value for the user and owner password and | |
| 1847 | +specifying an empty owner password are both considered insecure. | |
| 1848 | + | |
| 1849 | +Encryption options are terminated by ``--`` by itself. | |
| 1837 | 1850 | |
| 1838 | 1851 | 40-bit encryption is insecure, as is 128-bit encryption without AES. |
| 1839 | 1852 | Use 256-bit encryption unless you have a specific reason to use an |
| ... | ... | @@ -1971,6 +1984,36 @@ help for each option. |
| 1971 | 1984 | Related Options |
| 1972 | 1985 | ~~~~~~~~~~~~~~~ |
| 1973 | 1986 | |
| 1987 | +.. qpdf:option:: --user-password=user-password | |
| 1988 | + | |
| 1989 | + .. help: specify user password | |
| 1990 | + | |
| 1991 | + Set the user password of the encrypted file. | |
| 1992 | + | |
| 1993 | + Set the user passwrod of the encrypted file. Conforming readers | |
| 1994 | + apply security restrictions to files opened with the user password. | |
| 1995 | + | |
| 1996 | +.. qpdf:option:: --owner-password=owner-password | |
| 1997 | + | |
| 1998 | + .. help: specify owner password | |
| 1999 | + | |
| 2000 | + Set the owner password of the encrypted file. | |
| 2001 | + | |
| 2002 | + Set the owner passwrod of the encrypted file. Conforming readers | |
| 2003 | + apply allow security restrictions to be changed or overridden when | |
| 2004 | + files are opened with the owner password. | |
| 2005 | + | |
| 2006 | +.. qpdf:option:: --bits={48|128|256} | |
| 2007 | + | |
| 2008 | + .. help: specify encryption key length | |
| 2009 | + | |
| 2010 | + Specify the encryption key length. For best security, always use | |
| 2011 | + a key length of 256. | |
| 2012 | + | |
| 2013 | + Set the key length for encrypted files. You should always use | |
| 2014 | + ``--bits=256`` unless you have a strong reason to create a file | |
| 2015 | + with weaker encryption. | |
| 2016 | + | |
| 1974 | 2017 | .. qpdf:option:: --accessibility=[y|n] |
| 1975 | 2018 | |
| 1976 | 2019 | .. help: restrict document accessibility | ... | ... |
manual/release-notes.rst
| ... | ... | @@ -61,6 +61,16 @@ Planned changes for future 12.x (subject to change): |
| 61 | 61 | Previously, any value other than ``/Yes`` or ``/Off`` was |
| 62 | 62 | rejected. |
| 63 | 63 | |
| 64 | + - CLI Enhancements: | |
| 65 | + | |
| 66 | + - Allow the syntax ``--encrypt --user-password=user-password | |
| 67 | + --owner-password=owner-password --bits={40,128,256}`` when | |
| 68 | + encrypting PDF files. This is an alternative to the syntax | |
| 69 | + ``--encrypt user-password owner-password {40,128,256}``, which | |
| 70 | + will continue to be supported. The new syntax works better with | |
| 71 | + shell completion and allows creation of passwords that start | |
| 72 | + with ``-``. | |
| 73 | + | |
| 64 | 74 | - Build Enhancements: |
| 65 | 75 | |
| 66 | 76 | - The qpdf test suite now passes when qpdf is linked with an | ... | ... |
qpdf/qtest/arg-parsing.test
| ... | ... | @@ -15,7 +15,7 @@ cleanup(); |
| 15 | 15 | |
| 16 | 16 | my $td = new TestDriver('arg-parsing'); |
| 17 | 17 | |
| 18 | -my $n_tests = 17; | |
| 18 | +my $n_tests = 21; | |
| 19 | 19 | |
| 20 | 20 | $td->runtest("required argument", |
| 21 | 21 | {$td->COMMAND => "qpdf --password minimal.pdf"}, |
| ... | ... | @@ -108,5 +108,21 @@ $td->runtest("empty and replace-input", |
| 108 | 108 | $td->EXIT_STATUS => 2}, |
| 109 | 109 | $td->NORMALIZE_NEWLINES); |
| 110 | 110 | |
| 111 | +# Disallow mixing positional and flag-style encryption arguments. | |
| 112 | +my @bad_enc = ( | |
| 113 | + "u --owner-password=x", | |
| 114 | + "u o --bits=128", | |
| 115 | + "--user-password=u o", | |
| 116 | + "--user-password=u --owner-password=o 256", | |
| 117 | + ); | |
| 118 | +foreach my $arg (@bad_enc) | |
| 119 | +{ | |
| 120 | + $td->runtest("mixed encryption args ($arg)", | |
| 121 | + {$td->COMMAND => "qpdf --encrypt $arg"}, | |
| 122 | + {$td->REGEXP => ".*positional and dashed encryption arguments may not be mixed", | |
| 123 | + $td->EXIT_STATUS => 2}, | |
| 124 | + $td->NORMALIZE_NEWLINES); | |
| 125 | +} | |
| 126 | + | |
| 111 | 127 | cleanup(); |
| 112 | 128 | $td->report($n_tests); | ... | ... |
qpdf/qtest/completion.test
| ... | ... | @@ -29,14 +29,7 @@ my @completion_tests = ( |
| 29 | 29 | ['qpdf ', undef, 'top'], |
| 30 | 30 | ['qpdf -', undef, 'top-arg'], |
| 31 | 31 | ['qpdf --enc', undef, 'enc'], |
| 32 | - ['qpdf --encrypt ', undef, 'encrypt'], | |
| 33 | - ['qpdf --encrypt u ', undef, 'encrypt-u'], | |
| 34 | - ['qpdf --encrypt u o ', undef, 'encrypt-u-o'], | |
| 35 | - ['qpdf @encrypt-u o ', undef, 'encrypt-u-o'], | |
| 36 | - ['qpdf --encrypt u o 40 --', undef, 'encrypt-40'], | |
| 37 | - ['qpdf --encrypt u o 128 --', undef, 'encrypt-128'], | |
| 38 | - ['qpdf --encrypt u o 256 --', undef, 'encrypt-256'], | |
| 39 | - ['qpdf --encrypt u o bad --', undef, 'encrypt-bad'], | |
| 32 | + ['qpdf --encrypt -', undef, 'encrypt'], | |
| 40 | 33 | ['qpdf --split-pag', undef, 'split'], |
| 41 | 34 | ['qpdf --decode-l', undef, 'decode-l'], |
| 42 | 35 | ['qpdf --decode-lzzz', 15, 'decode-l'], |
| ... | ... | @@ -44,11 +37,11 @@ my @completion_tests = ( |
| 44 | 37 | ['qpdf --decode-level=g', undef, 'decode-level-g'], |
| 45 | 38 | ['qpdf --check -', undef, 'later-arg'], |
| 46 | 39 | ['qpdf infile outfile oops --ch', undef, 'usage-empty'], |
| 47 | - ['qpdf --encrypt \'user " password\' ', undef, 'quoting'], | |
| 48 | - ['qpdf --encrypt \'user password\' ', undef, 'quoting'], | |
| 49 | - ['qpdf --encrypt "user password" ', undef, 'quoting'], | |
| 50 | - ['qpdf --encrypt "user pass\'word" ', undef, 'quoting'], | |
| 51 | - ['qpdf --encrypt user\ password ', undef, 'quoting'], | |
| 40 | + ['qpdf \'input " file\' --q', undef, 'quoting'], | |
| 41 | + ['qpdf \'input file\' --q', undef, 'quoting'], | |
| 42 | + ['qpdf "input file" --q', undef, 'quoting'], | |
| 43 | + ['qpdf "input fi\'le" --q', undef, 'quoting'], | |
| 44 | + ['qpdf input\ file --q', undef, 'quoting'], | |
| 52 | 45 | ); |
| 53 | 46 | my $n_tests = 2 * scalar(@completion_tests); |
| 54 | 47 | my $completion_filter = | ... | ... |
qpdf/qtest/qpdf/completion-encrypt-zsh.out
0 → 100644
qpdf/qtest/qpdf/completion-encrypt.out
qpdf/qtest/qpdf/completion-quoting.out
qpdf/qtest/qpdf/encrypt-u