Commit 3c075fc01740a955eb8f192f565bf1f6c029c73e
1 parent
245723c5
Table-driven parsing of encrypt options
Showing
1 changed file
with
277 additions
and
384 deletions
qpdf/qpdf.cc
| @@ -329,13 +329,25 @@ class ArgParser | @@ -329,13 +329,25 @@ class ArgParser | ||
| 329 | void argWithImages(); | 329 | void argWithImages(); |
| 330 | void argShowJson(); | 330 | void argShowJson(); |
| 331 | void argCheck(); | 331 | void argCheck(); |
| 332 | + void arg40Print(char* parameter); | ||
| 333 | + void arg40Modify(char* parameter); | ||
| 334 | + void arg40Extract(char* parameter); | ||
| 335 | + void arg40Annotate(char* parameter); | ||
| 336 | + void arg128Accessibility(char* parameter); | ||
| 337 | + void arg128Extract(char* parameter); | ||
| 338 | + void arg128Print(char* parameter); | ||
| 339 | + void arg128Modify(char* parameter); | ||
| 340 | + void arg128ClearTextMetadata(); | ||
| 341 | + void arg128UseAes(char* parameter); | ||
| 342 | + void arg128ForceV4(); | ||
| 343 | + void arg256ForceR5(); | ||
| 344 | + void argEndEncrypt(); | ||
| 332 | 345 | ||
| 333 | void usage(std::string const& message); | 346 | void usage(std::string const& message); |
| 334 | void initOptionTable(); | 347 | void initOptionTable(); |
| 335 | void handleHelpVersion(); | 348 | void handleHelpVersion(); |
| 336 | void handleArgFileArguments(); | 349 | void handleArgFileArguments(); |
| 337 | void readArgsFromFile(char const* filename); | 350 | void readArgsFromFile(char const* filename); |
| 338 | - void parseEncryptOptions(); | ||
| 339 | std::vector<PageSpec> parsePagesOptions(); | 351 | std::vector<PageSpec> parsePagesOptions(); |
| 340 | void parseRotationParameter(std::string const&); | 352 | void parseRotationParameter(std::string const&); |
| 341 | std::vector<int> parseNumrange(char const* range, int max, | 353 | std::vector<int> parseNumrange(char const* range, int max, |
| @@ -348,7 +360,11 @@ class ArgParser | @@ -348,7 +360,11 @@ class ArgParser | ||
| 348 | Options& o; | 360 | Options& o; |
| 349 | int cur_arg; | 361 | int cur_arg; |
| 350 | 362 | ||
| 351 | - std::map<std::string, OptionEntry> option_table; | 363 | + std::map<std::string, OptionEntry>* option_table; |
| 364 | + std::map<std::string, OptionEntry> main_option_table; | ||
| 365 | + std::map<std::string, OptionEntry> encrypt40_option_table; | ||
| 366 | + std::map<std::string, OptionEntry> encrypt128_option_table; | ||
| 367 | + std::map<std::string, OptionEntry> encrypt256_option_table; | ||
| 352 | std::vector<PointerHolder<char> > new_argv; | 368 | std::vector<PointerHolder<char> > new_argv; |
| 353 | PointerHolder<char*> argv_ph; | 369 | PointerHolder<char*> argv_ph; |
| 354 | }; | 370 | }; |
| @@ -359,6 +375,7 @@ ArgParser::ArgParser(int argc, char* argv[], Options& o) : | @@ -359,6 +375,7 @@ ArgParser::ArgParser(int argc, char* argv[], Options& o) : | ||
| 359 | o(o), | 375 | o(o), |
| 360 | cur_arg(0) | 376 | cur_arg(0) |
| 361 | { | 377 | { |
| 378 | + option_table = &main_option_table; | ||
| 362 | initOptionTable(); | 379 | initOptionTable(); |
| 363 | } | 380 | } |
| 364 | 381 | ||
| @@ -414,75 +431,107 @@ ArgParser::oe_requiredChoices(param_arg_handler_t h, char const** choices) | @@ -414,75 +431,107 @@ ArgParser::oe_requiredChoices(param_arg_handler_t h, char const** choices) | ||
| 414 | void | 431 | void |
| 415 | ArgParser::initOptionTable() | 432 | ArgParser::initOptionTable() |
| 416 | { | 433 | { |
| 417 | - std::map<std::string, OptionEntry>& t = this->option_table; | 434 | + std::map<std::string, OptionEntry>* t = &this->main_option_table; |
| 418 | char const* yn[] = {"y", "n", 0}; | 435 | char const* yn[] = {"y", "n", 0}; |
| 419 | - t[""] = oe_positional(&ArgParser::argPositional); | ||
| 420 | - t["password"] = oe_requiredParameter(&ArgParser::argPassword, "pass"); | ||
| 421 | - t["empty"] = oe_bare(&ArgParser::argEmpty); | ||
| 422 | - t["linearize"] = oe_bare(&ArgParser::argLinearize); | ||
| 423 | - t["encrypt"] = oe_bare(&ArgParser::argEncrypt); | ||
| 424 | - t["decrypt"] = oe_bare(&ArgParser::argDecrypt); | ||
| 425 | - t["password-is-hex-key"] = oe_bare(&ArgParser::argPasswordIsHexKey); | ||
| 426 | - t["copy-encryption"] = oe_requiredParameter( | 436 | + (*t)[""] = oe_positional(&ArgParser::argPositional); |
| 437 | + (*t)["password"] = oe_requiredParameter(&ArgParser::argPassword, "pass"); | ||
| 438 | + (*t)["empty"] = oe_bare(&ArgParser::argEmpty); | ||
| 439 | + (*t)["linearize"] = oe_bare(&ArgParser::argLinearize); | ||
| 440 | + (*t)["encrypt"] = oe_bare(&ArgParser::argEncrypt); | ||
| 441 | + (*t)["decrypt"] = oe_bare(&ArgParser::argDecrypt); | ||
| 442 | + (*t)["password-is-hex-key"] = oe_bare(&ArgParser::argPasswordIsHexKey); | ||
| 443 | + (*t)["copy-encryption"] = oe_requiredParameter( | ||
| 427 | &ArgParser::argCopyEncryption, "file"); | 444 | &ArgParser::argCopyEncryption, "file"); |
| 428 | - t["encryption-file-password"] = oe_requiredParameter( | 445 | + (*t)["encryption-file-password"] = oe_requiredParameter( |
| 429 | &ArgParser::argEncryptionFilePassword, "password"); | 446 | &ArgParser::argEncryptionFilePassword, "password"); |
| 430 | - t["pages"] = oe_bare(&ArgParser::argPages); | ||
| 431 | - t["rotate"] = oe_requiredParameter( | 447 | + (*t)["pages"] = oe_bare(&ArgParser::argPages); |
| 448 | + (*t)["rotate"] = oe_requiredParameter( | ||
| 432 | &ArgParser::argRotate, "[+|-]angle:page-range"); | 449 | &ArgParser::argRotate, "[+|-]angle:page-range"); |
| 433 | char const* streamDataChoices[] = | 450 | char const* streamDataChoices[] = |
| 434 | {"compress", "preserve", "uncompress", 0}; | 451 | {"compress", "preserve", "uncompress", 0}; |
| 435 | - t["stream-data"] = oe_requiredChoices( | 452 | + (*t)["stream-data"] = oe_requiredChoices( |
| 436 | &ArgParser::argStreamData, streamDataChoices); | 453 | &ArgParser::argStreamData, streamDataChoices); |
| 437 | - t["compress-streams"] = oe_requiredChoices( | 454 | + (*t)["compress-streams"] = oe_requiredChoices( |
| 438 | &ArgParser::argCompressStreams, yn); | 455 | &ArgParser::argCompressStreams, yn); |
| 439 | char const* decodeLevelChoices[] = | 456 | char const* decodeLevelChoices[] = |
| 440 | {"none", "generalized", "specialized", "all", 0}; | 457 | {"none", "generalized", "specialized", "all", 0}; |
| 441 | - t["decode-level"] = oe_requiredChoices( | 458 | + (*t)["decode-level"] = oe_requiredChoices( |
| 442 | &ArgParser::argDecodeLevel, decodeLevelChoices); | 459 | &ArgParser::argDecodeLevel, decodeLevelChoices); |
| 443 | - t["normalize-content"] = oe_requiredChoices( | 460 | + (*t)["normalize-content"] = oe_requiredChoices( |
| 444 | &ArgParser::argNormalizeContent, yn); | 461 | &ArgParser::argNormalizeContent, yn); |
| 445 | - t["suppress-recovery"] = oe_bare(&ArgParser::argSuppressRecovery); | 462 | + (*t)["suppress-recovery"] = oe_bare(&ArgParser::argSuppressRecovery); |
| 446 | char const* objectStreamsChoices[] = {"disable", "preserve", "generate", 0}; | 463 | char const* objectStreamsChoices[] = {"disable", "preserve", "generate", 0}; |
| 447 | - t["object-streams"] = oe_requiredChoices( | 464 | + (*t)["object-streams"] = oe_requiredChoices( |
| 448 | &ArgParser::argObjectStreams, objectStreamsChoices); | 465 | &ArgParser::argObjectStreams, objectStreamsChoices); |
| 449 | - t["ignore-xref-streams"] = oe_bare(&ArgParser::argIgnoreXrefStreams); | ||
| 450 | - t["qdf"] = oe_bare(&ArgParser::argQdf); | ||
| 451 | - t["preserve-unreferenced"] = oe_bare(&ArgParser::argPreserveUnreferenced); | ||
| 452 | - t["preserve-unreferenced-resources"] = oe_bare( | 466 | + (*t)["ignore-xref-streams"] = oe_bare(&ArgParser::argIgnoreXrefStreams); |
| 467 | + (*t)["qdf"] = oe_bare(&ArgParser::argQdf); | ||
| 468 | + (*t)["preserve-unreferenced"] = oe_bare( | ||
| 469 | + &ArgParser::argPreserveUnreferenced); | ||
| 470 | + (*t)["preserve-unreferenced-resources"] = oe_bare( | ||
| 453 | &ArgParser::argPreserveUnreferencedResources); | 471 | &ArgParser::argPreserveUnreferencedResources); |
| 454 | - t["keep-files-open"] = oe_requiredChoices(&ArgParser::argKeepFilesOpen, yn); | ||
| 455 | - t["newline-before-endstream"] = oe_bare( | 472 | + (*t)["keep-files-open"] = oe_requiredChoices( |
| 473 | + &ArgParser::argKeepFilesOpen, yn); | ||
| 474 | + (*t)["newline-before-endstream"] = oe_bare( | ||
| 456 | &ArgParser::argNewlineBeforeEndstream); | 475 | &ArgParser::argNewlineBeforeEndstream); |
| 457 | - t["linearize-pass1"] = oe_requiredParameter( | 476 | + (*t)["linearize-pass1"] = oe_requiredParameter( |
| 458 | &ArgParser::argLinearizePass1, "filename"); | 477 | &ArgParser::argLinearizePass1, "filename"); |
| 459 | - t["coalesce-contents"] = oe_bare(&ArgParser::argCoalesceContents); | ||
| 460 | - t["min-version"] = oe_requiredParameter( | 478 | + (*t)["coalesce-contents"] = oe_bare(&ArgParser::argCoalesceContents); |
| 479 | + (*t)["min-version"] = oe_requiredParameter( | ||
| 461 | &ArgParser::argMinVersion, "version"); | 480 | &ArgParser::argMinVersion, "version"); |
| 462 | - t["force-version"] = oe_requiredParameter( | 481 | + (*t)["force-version"] = oe_requiredParameter( |
| 463 | &ArgParser::argForceVersion, "version"); | 482 | &ArgParser::argForceVersion, "version"); |
| 464 | - t["split-pages"] = oe_optionalParameter(&ArgParser::argSplitPages); | ||
| 465 | - t["verbose"] = oe_bare(&ArgParser::argVerbose); | ||
| 466 | - t["progress"] = oe_bare(&ArgParser::argProgress); | ||
| 467 | - t["no-warn"] = oe_bare(&ArgParser::argNoWarn); | ||
| 468 | - t["deterministic-id"] = oe_bare(&ArgParser::argDeterministicId); | ||
| 469 | - t["static-id"] = oe_bare(&ArgParser::argStaticId); | ||
| 470 | - t["static-aes-iv"] = oe_bare(&ArgParser::argStaticAesIv); | ||
| 471 | - t["no-original-object-ids"] = oe_bare(&ArgParser::argNoOriginalObjectIds); | ||
| 472 | - t["show-encryption"] = oe_bare(&ArgParser::argShowEncryption); | ||
| 473 | - t["show-encryption-key"] = oe_bare(&ArgParser::argShowEncryptionKey); | ||
| 474 | - t["check-linearization"] = oe_bare(&ArgParser::argCheckLinearization); | ||
| 475 | - t["show-linearization"] = oe_bare(&ArgParser::argShowLinearization); | ||
| 476 | - t["show-xref"] = oe_bare(&ArgParser::argShowXref); | ||
| 477 | - t["show-object"] = oe_requiredParameter( | 483 | + (*t)["split-pages"] = oe_optionalParameter(&ArgParser::argSplitPages); |
| 484 | + (*t)["verbose"] = oe_bare(&ArgParser::argVerbose); | ||
| 485 | + (*t)["progress"] = oe_bare(&ArgParser::argProgress); | ||
| 486 | + (*t)["no-warn"] = oe_bare(&ArgParser::argNoWarn); | ||
| 487 | + (*t)["deterministic-id"] = oe_bare(&ArgParser::argDeterministicId); | ||
| 488 | + (*t)["static-id"] = oe_bare(&ArgParser::argStaticId); | ||
| 489 | + (*t)["static-aes-iv"] = oe_bare(&ArgParser::argStaticAesIv); | ||
| 490 | + (*t)["no-original-object-ids"] = oe_bare( | ||
| 491 | + &ArgParser::argNoOriginalObjectIds); | ||
| 492 | + (*t)["show-encryption"] = oe_bare(&ArgParser::argShowEncryption); | ||
| 493 | + (*t)["show-encryption-key"] = oe_bare(&ArgParser::argShowEncryptionKey); | ||
| 494 | + (*t)["check-linearization"] = oe_bare(&ArgParser::argCheckLinearization); | ||
| 495 | + (*t)["show-linearization"] = oe_bare(&ArgParser::argShowLinearization); | ||
| 496 | + (*t)["show-xref"] = oe_bare(&ArgParser::argShowXref); | ||
| 497 | + (*t)["show-object"] = oe_requiredParameter( | ||
| 478 | &ArgParser::argShowObject, "obj[,gen]"); | 498 | &ArgParser::argShowObject, "obj[,gen]"); |
| 479 | - t["raw-stream-data"] = oe_bare(&ArgParser::argShowObject); | ||
| 480 | - t["filtered-stream-data"] = oe_bare(&ArgParser::argFilteredStreamData); | ||
| 481 | - t["show-npages"] = oe_bare(&ArgParser::argShowNpages); | ||
| 482 | - t["show-pages"] = oe_bare(&ArgParser::argShowPages); | ||
| 483 | - t["with-images"] = oe_bare(&ArgParser::argWithImages); | ||
| 484 | - t["show-json"] = oe_bare(&ArgParser::argShowJson); | ||
| 485 | - t["check"] = oe_bare(&ArgParser::argCheck); | 499 | + (*t)["raw-stream-data"] = oe_bare(&ArgParser::argShowObject); |
| 500 | + (*t)["filtered-stream-data"] = oe_bare(&ArgParser::argFilteredStreamData); | ||
| 501 | + (*t)["show-npages"] = oe_bare(&ArgParser::argShowNpages); | ||
| 502 | + (*t)["show-pages"] = oe_bare(&ArgParser::argShowPages); | ||
| 503 | + (*t)["with-images"] = oe_bare(&ArgParser::argWithImages); | ||
| 504 | + (*t)["show-json"] = oe_bare(&ArgParser::argShowJson); | ||
| 505 | + (*t)["check"] = oe_bare(&ArgParser::argCheck); | ||
| 506 | + | ||
| 507 | + t = &this->encrypt40_option_table; | ||
| 508 | + (*t)["--"] = oe_bare(&ArgParser::argEndEncrypt); | ||
| 509 | + (*t)["print"] = oe_requiredChoices(&ArgParser::arg40Print, yn); | ||
| 510 | + (*t)["modify"] = oe_requiredChoices(&ArgParser::arg40Modify, yn); | ||
| 511 | + (*t)["extract"] = oe_requiredChoices(&ArgParser::arg40Extract, yn); | ||
| 512 | + (*t)["annotate"] = oe_requiredChoices(&ArgParser::arg40Annotate, yn); | ||
| 513 | + | ||
| 514 | + t = &this->encrypt128_option_table; | ||
| 515 | + (*t)["--"] = oe_bare(&ArgParser::argEndEncrypt); | ||
| 516 | + (*t)["accessibility"] = oe_requiredChoices( | ||
| 517 | + &ArgParser::arg128Accessibility, yn); | ||
| 518 | + (*t)["extract"] = oe_requiredChoices(&ArgParser::arg128Extract, yn); | ||
| 519 | + char const* print128Choices[] = {"full", "low", "none", 0}; | ||
| 520 | + (*t)["print"] = oe_requiredChoices( | ||
| 521 | + &ArgParser::arg128Print, print128Choices); | ||
| 522 | + char const* modify128Choices[] = | ||
| 523 | + {"all", "annotate", "form", "assembly", "none", 0}; | ||
| 524 | + (*t)["modify"] = oe_requiredChoices( | ||
| 525 | + &ArgParser::arg128Modify, modify128Choices); | ||
| 526 | + (*t)["cleartext-metadata"] = oe_bare(&ArgParser::arg128ClearTextMetadata); | ||
| 527 | + // The above 128-bit options are also 256-bit options, so copy | ||
| 528 | + // what we have so far. Then continue separately with 128 and 256. | ||
| 529 | + this->encrypt256_option_table = this->encrypt128_option_table; | ||
| 530 | + (*t)["use-aes"] = oe_requiredChoices(&ArgParser::arg128UseAes, yn); | ||
| 531 | + (*t)["force-V4"] = oe_bare(&ArgParser::arg128ForceV4); | ||
| 532 | + | ||
| 533 | + t = &this->encrypt256_option_table; | ||
| 534 | + (*t)["force-R5"] = oe_bare(&ArgParser::arg256ForceR5); | ||
| 486 | } | 535 | } |
| 487 | 536 | ||
| 488 | void | 537 | void |
| @@ -524,10 +573,33 @@ void | @@ -524,10 +573,33 @@ void | ||
| 524 | ArgParser::argEncrypt() | 573 | ArgParser::argEncrypt() |
| 525 | { | 574 | { |
| 526 | ++cur_arg; | 575 | ++cur_arg; |
| 527 | - parseEncryptOptions(); | ||
| 528 | - o.encrypt = true; | ||
| 529 | - o.decrypt = false; | ||
| 530 | - o.copy_encryption = false; | 576 | + if (cur_arg + 3 >= argc) |
| 577 | + { | ||
| 578 | + usage("insufficient arguments to --encrypt"); | ||
| 579 | + } | ||
| 580 | + o.user_password = argv[cur_arg++]; | ||
| 581 | + o.owner_password = argv[cur_arg++]; | ||
| 582 | + std::string len_str = argv[cur_arg]; | ||
| 583 | + if (len_str == "40") | ||
| 584 | + { | ||
| 585 | + o.keylen = 40; | ||
| 586 | + this->option_table = &(this->encrypt40_option_table); | ||
| 587 | + } | ||
| 588 | + else if (len_str == "128") | ||
| 589 | + { | ||
| 590 | + o.keylen = 128; | ||
| 591 | + this->option_table = &(this->encrypt128_option_table); | ||
| 592 | + } | ||
| 593 | + else if (len_str == "256") | ||
| 594 | + { | ||
| 595 | + o.keylen = 256; | ||
| 596 | + o.use_aes = true; | ||
| 597 | + this->option_table = &(this->encrypt256_option_table); | ||
| 598 | + } | ||
| 599 | + else | ||
| 600 | + { | ||
| 601 | + usage("encryption key length must be 40, 128, or 256"); | ||
| 602 | + } | ||
| 531 | } | 603 | } |
| 532 | 604 | ||
| 533 | void | 605 | void |
| @@ -878,6 +950,125 @@ ArgParser::argCheck() | @@ -878,6 +950,125 @@ ArgParser::argCheck() | ||
| 878 | } | 950 | } |
| 879 | 951 | ||
| 880 | void | 952 | void |
| 953 | +ArgParser::arg40Print(char* parameter) | ||
| 954 | +{ | ||
| 955 | + o.r2_print = (strcmp(parameter, "y") == 0); | ||
| 956 | +} | ||
| 957 | + | ||
| 958 | +void | ||
| 959 | +ArgParser::arg40Modify(char* parameter) | ||
| 960 | +{ | ||
| 961 | + o.r2_modify = (strcmp(parameter, "y") == 0); | ||
| 962 | +} | ||
| 963 | + | ||
| 964 | +void | ||
| 965 | +ArgParser::arg40Extract(char* parameter) | ||
| 966 | +{ | ||
| 967 | + o.r2_extract = (strcmp(parameter, "y") == 0); | ||
| 968 | +} | ||
| 969 | + | ||
| 970 | +void | ||
| 971 | +ArgParser::arg40Annotate(char* parameter) | ||
| 972 | +{ | ||
| 973 | + o.r2_annotate = (strcmp(parameter, "y") == 0); | ||
| 974 | +} | ||
| 975 | + | ||
| 976 | +void | ||
| 977 | +ArgParser::arg128Accessibility(char* parameter) | ||
| 978 | +{ | ||
| 979 | + o.r3_accessibility = (strcmp(parameter, "y") == 0); | ||
| 980 | +} | ||
| 981 | + | ||
| 982 | +void | ||
| 983 | +ArgParser::arg128Extract(char* parameter) | ||
| 984 | +{ | ||
| 985 | + o.r3_extract = (strcmp(parameter, "y") == 0); | ||
| 986 | +} | ||
| 987 | + | ||
| 988 | +void | ||
| 989 | +ArgParser::arg128Print(char* parameter) | ||
| 990 | +{ | ||
| 991 | + if (strcmp(parameter, "full") == 0) | ||
| 992 | + { | ||
| 993 | + o.r3_print = qpdf_r3p_full; | ||
| 994 | + } | ||
| 995 | + else if (strcmp(parameter, "low") == 0) | ||
| 996 | + { | ||
| 997 | + o.r3_print = qpdf_r3p_low; | ||
| 998 | + } | ||
| 999 | + else if (strcmp(parameter, "none") == 0) | ||
| 1000 | + { | ||
| 1001 | + o.r3_print = qpdf_r3p_none; | ||
| 1002 | + } | ||
| 1003 | + else | ||
| 1004 | + { | ||
| 1005 | + usage("invalid print option"); | ||
| 1006 | + } | ||
| 1007 | +} | ||
| 1008 | + | ||
| 1009 | +void | ||
| 1010 | +ArgParser::arg128Modify(char* parameter) | ||
| 1011 | +{ | ||
| 1012 | + if (strcmp(parameter, "all") == 0) | ||
| 1013 | + { | ||
| 1014 | + o.r3_modify = qpdf_r3m_all; | ||
| 1015 | + } | ||
| 1016 | + else if (strcmp(parameter, "annotate") == 0) | ||
| 1017 | + { | ||
| 1018 | + o.r3_modify = qpdf_r3m_annotate; | ||
| 1019 | + } | ||
| 1020 | + else if (strcmp(parameter, "form") == 0) | ||
| 1021 | + { | ||
| 1022 | + o.r3_modify = qpdf_r3m_form; | ||
| 1023 | + } | ||
| 1024 | + else if (strcmp(parameter, "assembly") == 0) | ||
| 1025 | + { | ||
| 1026 | + o.r3_modify = qpdf_r3m_assembly; | ||
| 1027 | + } | ||
| 1028 | + else if (strcmp(parameter, "none") == 0) | ||
| 1029 | + { | ||
| 1030 | + o.r3_modify = qpdf_r3m_none; | ||
| 1031 | + } | ||
| 1032 | + else | ||
| 1033 | + { | ||
| 1034 | + usage("invalid modify option"); | ||
| 1035 | + } | ||
| 1036 | +} | ||
| 1037 | + | ||
| 1038 | +void | ||
| 1039 | +ArgParser::arg128ClearTextMetadata() | ||
| 1040 | +{ | ||
| 1041 | + o.cleartext_metadata = true; | ||
| 1042 | +} | ||
| 1043 | + | ||
| 1044 | +void | ||
| 1045 | +ArgParser::arg128UseAes(char* parameter) | ||
| 1046 | +{ | ||
| 1047 | + o.use_aes = (strcmp(parameter, "y") == 0); | ||
| 1048 | +} | ||
| 1049 | + | ||
| 1050 | +void | ||
| 1051 | +ArgParser::arg128ForceV4() | ||
| 1052 | +{ | ||
| 1053 | + o.force_V4 = true; | ||
| 1054 | +} | ||
| 1055 | + | ||
| 1056 | +void | ||
| 1057 | +ArgParser::arg256ForceR5() | ||
| 1058 | +{ | ||
| 1059 | + o.force_R5 = true; | ||
| 1060 | +} | ||
| 1061 | + | ||
| 1062 | +void | ||
| 1063 | +ArgParser::argEndEncrypt() | ||
| 1064 | +{ | ||
| 1065 | + o.encrypt = true; | ||
| 1066 | + o.decrypt = false; | ||
| 1067 | + o.copy_encryption = false; | ||
| 1068 | + this->option_table = &(this->main_option_table); | ||
| 1069 | +} | ||
| 1070 | + | ||
| 1071 | +void | ||
| 881 | ArgParser::handleArgFileArguments() | 1072 | ArgParser::handleArgFileArguments() |
| 882 | { | 1073 | { |
| 883 | // Support reading arguments from files. Create a new argv. Ensure | 1074 | // Support reading arguments from files. Create a new argv. Ensure |
| @@ -1400,329 +1591,6 @@ ArgParser::parseNumrange(char const* range, int max, bool throw_error) | @@ -1400,329 +1591,6 @@ ArgParser::parseNumrange(char const* range, int max, bool throw_error) | ||
| 1400 | return std::vector<int>(); | 1591 | return std::vector<int>(); |
| 1401 | } | 1592 | } |
| 1402 | 1593 | ||
| 1403 | -void | ||
| 1404 | -ArgParser::parseEncryptOptions() | ||
| 1405 | -{ | ||
| 1406 | - if (cur_arg + 3 >= argc) | ||
| 1407 | - { | ||
| 1408 | - usage("insufficient arguments to --encrypt"); | ||
| 1409 | - } | ||
| 1410 | - o.user_password = argv[cur_arg++]; | ||
| 1411 | - o.owner_password = argv[cur_arg++]; | ||
| 1412 | - std::string len_str = argv[cur_arg++]; | ||
| 1413 | - if (len_str == "40") | ||
| 1414 | - { | ||
| 1415 | - o.keylen = 40; | ||
| 1416 | - } | ||
| 1417 | - else if (len_str == "128") | ||
| 1418 | - { | ||
| 1419 | - o.keylen = 128; | ||
| 1420 | - } | ||
| 1421 | - else if (len_str == "256") | ||
| 1422 | - { | ||
| 1423 | - o.keylen = 256; | ||
| 1424 | - o.use_aes = true; | ||
| 1425 | - } | ||
| 1426 | - else | ||
| 1427 | - { | ||
| 1428 | - usage("encryption key length must be 40, 128, or 256"); | ||
| 1429 | - } | ||
| 1430 | - while (1) | ||
| 1431 | - { | ||
| 1432 | - char* arg = argv[cur_arg]; | ||
| 1433 | - if (arg == 0) | ||
| 1434 | - { | ||
| 1435 | - usage("insufficient arguments to --encrypt"); | ||
| 1436 | - } | ||
| 1437 | - else if (strcmp(arg, "--") == 0) | ||
| 1438 | - { | ||
| 1439 | - return; | ||
| 1440 | - } | ||
| 1441 | - if (arg[0] == '-') | ||
| 1442 | - { | ||
| 1443 | - ++arg; | ||
| 1444 | - if (arg[0] == '-') | ||
| 1445 | - { | ||
| 1446 | - ++arg; | ||
| 1447 | - } | ||
| 1448 | - } | ||
| 1449 | - else | ||
| 1450 | - { | ||
| 1451 | - usage(std::string("invalid encryption parameter ") + arg); | ||
| 1452 | - } | ||
| 1453 | - ++cur_arg; | ||
| 1454 | - char* parameter = strchr(arg, '='); | ||
| 1455 | - if (parameter) | ||
| 1456 | - { | ||
| 1457 | - *parameter++ = 0; | ||
| 1458 | - } | ||
| 1459 | - if (strcmp(arg, "print") == 0) | ||
| 1460 | - { | ||
| 1461 | - if (parameter == 0) | ||
| 1462 | - { | ||
| 1463 | - usage("--print must be given as --print=option"); | ||
| 1464 | - } | ||
| 1465 | - std::string val = parameter; | ||
| 1466 | - if (o.keylen == 40) | ||
| 1467 | - { | ||
| 1468 | - if (val == "y") | ||
| 1469 | - { | ||
| 1470 | - o.r2_print = true; | ||
| 1471 | - } | ||
| 1472 | - else if (val == "n") | ||
| 1473 | - { | ||
| 1474 | - o.r2_print = false; | ||
| 1475 | - } | ||
| 1476 | - else | ||
| 1477 | - { | ||
| 1478 | - usage("invalid 40-bit -print parameter"); | ||
| 1479 | - } | ||
| 1480 | - } | ||
| 1481 | - else | ||
| 1482 | - { | ||
| 1483 | - if (val == "full") | ||
| 1484 | - { | ||
| 1485 | - o.r3_print = qpdf_r3p_full; | ||
| 1486 | - } | ||
| 1487 | - else if (val == "low") | ||
| 1488 | - { | ||
| 1489 | - o.r3_print = qpdf_r3p_low; | ||
| 1490 | - } | ||
| 1491 | - else if (val == "none") | ||
| 1492 | - { | ||
| 1493 | - o.r3_print = qpdf_r3p_none; | ||
| 1494 | - } | ||
| 1495 | - else | ||
| 1496 | - { | ||
| 1497 | - usage("invalid 128-bit -print parameter"); | ||
| 1498 | - } | ||
| 1499 | - } | ||
| 1500 | - } | ||
| 1501 | - else if (strcmp(arg, "modify") == 0) | ||
| 1502 | - { | ||
| 1503 | - if (parameter == 0) | ||
| 1504 | - { | ||
| 1505 | - usage("--modify must be given as --modify=option"); | ||
| 1506 | - } | ||
| 1507 | - std::string val = parameter; | ||
| 1508 | - if (o.keylen == 40) | ||
| 1509 | - { | ||
| 1510 | - if (val == "y") | ||
| 1511 | - { | ||
| 1512 | - o.r2_modify = true; | ||
| 1513 | - } | ||
| 1514 | - else if (val == "n") | ||
| 1515 | - { | ||
| 1516 | - o.r2_modify = false; | ||
| 1517 | - } | ||
| 1518 | - else | ||
| 1519 | - { | ||
| 1520 | - usage("invalid 40-bit -modify parameter"); | ||
| 1521 | - } | ||
| 1522 | - } | ||
| 1523 | - else | ||
| 1524 | - { | ||
| 1525 | - if (val == "all") | ||
| 1526 | - { | ||
| 1527 | - o.r3_modify = qpdf_r3m_all; | ||
| 1528 | - } | ||
| 1529 | - else if (val == "annotate") | ||
| 1530 | - { | ||
| 1531 | - o.r3_modify = qpdf_r3m_annotate; | ||
| 1532 | - } | ||
| 1533 | - else if (val == "form") | ||
| 1534 | - { | ||
| 1535 | - o.r3_modify = qpdf_r3m_form; | ||
| 1536 | - } | ||
| 1537 | - else if (val == "assembly") | ||
| 1538 | - { | ||
| 1539 | - o.r3_modify = qpdf_r3m_assembly; | ||
| 1540 | - } | ||
| 1541 | - else if (val == "none") | ||
| 1542 | - { | ||
| 1543 | - o.r3_modify = qpdf_r3m_none; | ||
| 1544 | - } | ||
| 1545 | - else | ||
| 1546 | - { | ||
| 1547 | - usage("invalid 128-bit -modify parameter"); | ||
| 1548 | - } | ||
| 1549 | - } | ||
| 1550 | - } | ||
| 1551 | - else if (strcmp(arg, "extract") == 0) | ||
| 1552 | - { | ||
| 1553 | - if (parameter == 0) | ||
| 1554 | - { | ||
| 1555 | - usage("--extract must be given as --extract=option"); | ||
| 1556 | - } | ||
| 1557 | - std::string val = parameter; | ||
| 1558 | - bool result = false; | ||
| 1559 | - if (val == "y") | ||
| 1560 | - { | ||
| 1561 | - result = true; | ||
| 1562 | - } | ||
| 1563 | - else if (val == "n") | ||
| 1564 | - { | ||
| 1565 | - result = false; | ||
| 1566 | - } | ||
| 1567 | - else | ||
| 1568 | - { | ||
| 1569 | - usage("invalid -extract parameter"); | ||
| 1570 | - } | ||
| 1571 | - if (o.keylen == 40) | ||
| 1572 | - { | ||
| 1573 | - o.r2_extract = result; | ||
| 1574 | - } | ||
| 1575 | - else | ||
| 1576 | - { | ||
| 1577 | - o.r3_extract = result; | ||
| 1578 | - } | ||
| 1579 | - } | ||
| 1580 | - else if (strcmp(arg, "annotate") == 0) | ||
| 1581 | - { | ||
| 1582 | - if (parameter == 0) | ||
| 1583 | - { | ||
| 1584 | - usage("--annotate must be given as --annotate=option"); | ||
| 1585 | - } | ||
| 1586 | - std::string val = parameter; | ||
| 1587 | - bool result = false; | ||
| 1588 | - if (val == "y") | ||
| 1589 | - { | ||
| 1590 | - result = true; | ||
| 1591 | - } | ||
| 1592 | - else if (val == "n") | ||
| 1593 | - { | ||
| 1594 | - result = false; | ||
| 1595 | - } | ||
| 1596 | - else | ||
| 1597 | - { | ||
| 1598 | - usage("invalid -annotate parameter"); | ||
| 1599 | - } | ||
| 1600 | - if (o.keylen == 40) | ||
| 1601 | - { | ||
| 1602 | - o.r2_annotate = result; | ||
| 1603 | - } | ||
| 1604 | - else | ||
| 1605 | - { | ||
| 1606 | - usage("-annotate invalid for 128-bit keys"); | ||
| 1607 | - } | ||
| 1608 | - } | ||
| 1609 | - else if (strcmp(arg, "accessibility") == 0) | ||
| 1610 | - { | ||
| 1611 | - if (parameter == 0) | ||
| 1612 | - { | ||
| 1613 | - usage("--accessibility must be given as" | ||
| 1614 | - " --accessibility=option"); | ||
| 1615 | - } | ||
| 1616 | - std::string val = parameter; | ||
| 1617 | - bool result = false; | ||
| 1618 | - if (val == "y") | ||
| 1619 | - { | ||
| 1620 | - result = true; | ||
| 1621 | - } | ||
| 1622 | - else if (val == "n") | ||
| 1623 | - { | ||
| 1624 | - result = false; | ||
| 1625 | - } | ||
| 1626 | - else | ||
| 1627 | - { | ||
| 1628 | - usage("invalid -accessibility parameter"); | ||
| 1629 | - } | ||
| 1630 | - if (o.keylen == 40) | ||
| 1631 | - { | ||
| 1632 | - usage("-accessibility invalid for 40-bit keys"); | ||
| 1633 | - } | ||
| 1634 | - else | ||
| 1635 | - { | ||
| 1636 | - o.r3_accessibility = result; | ||
| 1637 | - } | ||
| 1638 | - } | ||
| 1639 | - else if (strcmp(arg, "cleartext-metadata") == 0) | ||
| 1640 | - { | ||
| 1641 | - if (parameter) | ||
| 1642 | - { | ||
| 1643 | - usage("--cleartext-metadata does not take a parameter"); | ||
| 1644 | - } | ||
| 1645 | - if (o.keylen == 40) | ||
| 1646 | - { | ||
| 1647 | - usage("--cleartext-metadata is invalid for 40-bit keys"); | ||
| 1648 | - } | ||
| 1649 | - else | ||
| 1650 | - { | ||
| 1651 | - o.cleartext_metadata = true; | ||
| 1652 | - } | ||
| 1653 | - } | ||
| 1654 | - else if (strcmp(arg, "force-V4") == 0) | ||
| 1655 | - { | ||
| 1656 | - if (parameter) | ||
| 1657 | - { | ||
| 1658 | - usage("--force-V4 does not take a parameter"); | ||
| 1659 | - } | ||
| 1660 | - if (o.keylen != 128) | ||
| 1661 | - { | ||
| 1662 | - usage("--force-V4 is invalid only for 128-bit keys"); | ||
| 1663 | - } | ||
| 1664 | - else | ||
| 1665 | - { | ||
| 1666 | - o.force_V4 = true; | ||
| 1667 | - } | ||
| 1668 | - } | ||
| 1669 | - else if (strcmp(arg, "force-R5") == 0) | ||
| 1670 | - { | ||
| 1671 | - if (parameter) | ||
| 1672 | - { | ||
| 1673 | - usage("--force-R5 does not take a parameter"); | ||
| 1674 | - } | ||
| 1675 | - if (o.keylen != 256) | ||
| 1676 | - { | ||
| 1677 | - usage("--force-R5 is invalid only for 256-bit keys"); | ||
| 1678 | - } | ||
| 1679 | - else | ||
| 1680 | - { | ||
| 1681 | - o.force_R5 = true; | ||
| 1682 | - } | ||
| 1683 | - } | ||
| 1684 | - else if (strcmp(arg, "use-aes") == 0) | ||
| 1685 | - { | ||
| 1686 | - if (parameter == 0) | ||
| 1687 | - { | ||
| 1688 | - usage("--use-aes must be given as --extract=option"); | ||
| 1689 | - } | ||
| 1690 | - std::string val = parameter; | ||
| 1691 | - bool result = false; | ||
| 1692 | - if (val == "y") | ||
| 1693 | - { | ||
| 1694 | - result = true; | ||
| 1695 | - } | ||
| 1696 | - else if (val == "n") | ||
| 1697 | - { | ||
| 1698 | - result = false; | ||
| 1699 | - } | ||
| 1700 | - else | ||
| 1701 | - { | ||
| 1702 | - usage("invalid -use-aes parameter"); | ||
| 1703 | - } | ||
| 1704 | - if ((o.keylen == 40) && result) | ||
| 1705 | - { | ||
| 1706 | - usage("use-aes is invalid for 40-bit keys"); | ||
| 1707 | - } | ||
| 1708 | - else if ((o.keylen == 256) && (! result)) | ||
| 1709 | - { | ||
| 1710 | - // qpdf would happily create files encrypted with RC4 | ||
| 1711 | - // using /V=5, but Adobe reader can't read them. | ||
| 1712 | - usage("use-aes can't be disabled with 256-bit keys"); | ||
| 1713 | - } | ||
| 1714 | - else | ||
| 1715 | - { | ||
| 1716 | - o.use_aes = result; | ||
| 1717 | - } | ||
| 1718 | - } | ||
| 1719 | - else | ||
| 1720 | - { | ||
| 1721 | - usage(std::string("invalid encryption parameter --") + arg); | ||
| 1722 | - } | ||
| 1723 | - } | ||
| 1724 | -} | ||
| 1725 | - | ||
| 1726 | std::vector<PageSpec> | 1594 | std::vector<PageSpec> |
| 1727 | ArgParser::parsePagesOptions() | 1595 | ArgParser::parsePagesOptions() |
| 1728 | { | 1596 | { |
| @@ -1990,7 +1858,17 @@ ArgParser::parseOptions() | @@ -1990,7 +1858,17 @@ ArgParser::parseOptions() | ||
| 1990 | for (cur_arg = 1; cur_arg < argc; ++cur_arg) | 1858 | for (cur_arg = 1; cur_arg < argc; ++cur_arg) |
| 1991 | { | 1859 | { |
| 1992 | char* arg = argv[cur_arg]; | 1860 | char* arg = argv[cur_arg]; |
| 1993 | - if ((arg[0] == '-') && (strcmp(arg, "-") != 0)) | 1861 | + if (strcmp(arg, "--") == 0) |
| 1862 | + { | ||
| 1863 | + // Special case for -- option, which is used to break out | ||
| 1864 | + // of subparsers. | ||
| 1865 | + OptionEntry& oe = (*this->option_table)["--"]; | ||
| 1866 | + if (oe.bare_arg_handler) | ||
| 1867 | + { | ||
| 1868 | + (this->*(oe.bare_arg_handler))(); | ||
| 1869 | + } | ||
| 1870 | + } | ||
| 1871 | + else if ((arg[0] == '-') && (strcmp(arg, "-") != 0)) | ||
| 1994 | { | 1872 | { |
| 1995 | ++arg; | 1873 | ++arg; |
| 1996 | if (arg[0] == '-') | 1874 | if (arg[0] == '-') |
| @@ -1998,19 +1876,28 @@ ArgParser::parseOptions() | @@ -1998,19 +1876,28 @@ ArgParser::parseOptions() | ||
| 1998 | // Be lax about -arg vs --arg | 1876 | // Be lax about -arg vs --arg |
| 1999 | ++arg; | 1877 | ++arg; |
| 2000 | } | 1878 | } |
| 2001 | - char* parameter = const_cast<char*>(strchr(arg, '=')); | 1879 | + char* parameter = 0; |
| 1880 | + if (strlen(arg) > 0) | ||
| 1881 | + { | ||
| 1882 | + // Prevent --=something from being treated as an empty | ||
| 1883 | + // arg since the empty string in the option table is | ||
| 1884 | + // for positional arguments. | ||
| 1885 | + parameter = const_cast<char*>(strchr(1 + arg, '=')); | ||
| 1886 | + } | ||
| 2002 | if (parameter) | 1887 | if (parameter) |
| 2003 | { | 1888 | { |
| 2004 | *parameter++ = 0; | 1889 | *parameter++ = 0; |
| 2005 | } | 1890 | } |
| 2006 | 1891 | ||
| 2007 | std::string arg_s(arg); | 1892 | std::string arg_s(arg); |
| 2008 | - if (0 == this->option_table.count(arg_s)) | 1893 | + if (arg_s.empty() || |
| 1894 | + (arg_s.at(0) == '-') || | ||
| 1895 | + (0 == this->option_table->count(arg_s))) | ||
| 2009 | { | 1896 | { |
| 2010 | usage(std::string("unknown option --") + arg); | 1897 | usage(std::string("unknown option --") + arg); |
| 2011 | } | 1898 | } |
| 2012 | 1899 | ||
| 2013 | - OptionEntry& oe = this->option_table[arg_s]; | 1900 | + OptionEntry& oe = (*this->option_table)[arg_s]; |
| 2014 | if ((oe.parameter_needed && (0 == parameter)) || | 1901 | if ((oe.parameter_needed && (0 == parameter)) || |
| 2015 | ((! oe.choices.empty() && | 1902 | ((! oe.choices.empty() && |
| 2016 | ((0 == parameter) || | 1903 | ((0 == parameter) || |
| @@ -2055,9 +1942,11 @@ ArgParser::parseOptions() | @@ -2055,9 +1942,11 @@ ArgParser::parseOptions() | ||
| 2055 | (this->*(oe.param_arg_handler))(parameter); | 1942 | (this->*(oe.param_arg_handler))(parameter); |
| 2056 | } | 1943 | } |
| 2057 | } | 1944 | } |
| 2058 | - else if (0 != this->option_table.count("")) | 1945 | + else if (0 != this->option_table->count("")) |
| 2059 | { | 1946 | { |
| 2060 | - OptionEntry& oe = this->option_table[""]; | 1947 | + // The empty string maps to the positional argument |
| 1948 | + // handler. | ||
| 1949 | + OptionEntry& oe = (*this->option_table)[""]; | ||
| 2061 | if (oe.param_arg_handler) | 1950 | if (oe.param_arg_handler) |
| 2062 | { | 1951 | { |
| 2063 | (this->*(oe.param_arg_handler))(arg); | 1952 | (this->*(oe.param_arg_handler))(arg); |
| @@ -2069,6 +1958,10 @@ ArgParser::parseOptions() | @@ -2069,6 +1958,10 @@ ArgParser::parseOptions() | ||
| 2069 | } | 1958 | } |
| 2070 | } | 1959 | } |
| 2071 | 1960 | ||
| 1961 | + if (this->option_table != &(this->main_option_table)) | ||
| 1962 | + { | ||
| 1963 | + usage("missing -- at end of options"); | ||
| 1964 | + } | ||
| 2072 | if (o.infilename == 0) | 1965 | if (o.infilename == 0) |
| 2073 | { | 1966 | { |
| 2074 | usage("an input file name is required"); | 1967 | usage("an input file name is required"); |