Commit fcdbc8a102ca258d105ebd2f41bbf17b29c817fd

Authored by Jay Berkenbilt
1 parent c4e56fa5

Move doFinalChecks to QPDFJob::checkConfiguration

include/qpdf/QPDFJob.hh
@@ -85,6 +85,14 @@ class QPDFJob @@ -85,6 +85,14 @@ class QPDFJob
85 QPDF_DLL 85 QPDF_DLL
86 void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); 86 void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
87 87
  88 + // Check to make sure no contradictory options have been
  89 + // specified. This is called automatically after initializing from
  90 + // argv or json and is also called by run, but you can call it
  91 + // manually as well. It throws a Usage exception if there are any
  92 + // errors.
  93 + QPDF_DLL
  94 + void checkConfiguration();
  95 +
88 // Returns true if output is created by the specified job. 96 // Returns true if output is created by the specified job.
89 QPDF_DLL 97 QPDF_DLL
90 bool createsOutput() const; 98 bool createsOutput() const;
libqpdf/QPDFJob.cc
@@ -530,6 +530,93 @@ QPDFJob::createsOutput() const @@ -530,6 +530,93 @@ QPDFJob::createsOutput() const
530 return ((o.outfilename != nullptr) || o.replace_input); 530 return ((o.outfilename != nullptr) || o.replace_input);
531 } 531 }
532 532
  533 +void
  534 +QPDFJob::checkConfiguration()
  535 +{
  536 + auto usage = [](char const* msg){
  537 + throw std::runtime_error(msg);
  538 + };
  539 +
  540 + QPDFJob& o = *this; // QXXXQ
  541 + // QXXXQ messages are CLI-centric
  542 + if (o.replace_input)
  543 + {
  544 + if (o.outfilename)
  545 + {
  546 + usage("--replace-input may not be used when"
  547 + " an output file is specified");
  548 + }
  549 + else if (o.split_pages)
  550 + {
  551 + usage("--split-pages may not be used with --replace-input");
  552 + }
  553 + }
  554 + if (o.infilename == 0)
  555 + {
  556 + usage("an input file name is required");
  557 + }
  558 + else if (o.require_outfile && (o.outfilename == 0) && (! o.replace_input))
  559 + {
  560 + usage("an output file name is required; use - for standard output");
  561 + }
  562 + else if ((! o.require_outfile) &&
  563 + ((o.outfilename != 0) || o.replace_input))
  564 + {
  565 + usage("no output file may be given for this option");
  566 + }
  567 + if (o.check_requires_password && o.check_is_encrypted)
  568 + {
  569 + usage("--requires-password and --is-encrypted may not be given"
  570 + " together");
  571 + }
  572 +
  573 + if (o.encrypt && (! o.allow_insecure) &&
  574 + (o.owner_password.empty() &&
  575 + (! o.user_password.empty()) &&
  576 + (o.keylen == 256)))
  577 + {
  578 + // Note that empty owner passwords for R < 5 are copied from
  579 + // the user password, so this lack of security is not an issue
  580 + // for those files. Also we are consider only the ability to
  581 + // open the file without a password to be insecure. We are not
  582 + // concerned about whether the viewer enforces security
  583 + // settings when the user and owner password match.
  584 + usage("A PDF with a non-empty user password and an empty owner"
  585 + " password encrypted with a 256-bit key is insecure as it"
  586 + " can be opened without a password. If you really want to"
  587 + " do this, you must also give the --allow-insecure option"
  588 + " before the -- that follows --encrypt.");
  589 + }
  590 +
  591 + if (o.require_outfile && o.outfilename &&
  592 + (strcmp(o.outfilename.get(), "-") == 0))
  593 + {
  594 + if (o.split_pages)
  595 + {
  596 + usage("--split-pages may not be used when"
  597 + " writing to standard output");
  598 + }
  599 + if (o.verbose)
  600 + {
  601 + usage("--verbose may not be used when"
  602 + " writing to standard output");
  603 + }
  604 + if (o.progress)
  605 + {
  606 + usage("--progress may not be used when"
  607 + " writing to standard output");
  608 + }
  609 + }
  610 +
  611 + if ((! o.split_pages) &&
  612 + QUtil::same_file(o.infilename.get(), o.outfilename.get()))
  613 + {
  614 + QTC::TC("qpdf", "qpdf same file error");
  615 + usage("input file and output file are the same;"
  616 + " use --replace-input to intentionally overwrite the input file");
  617 + }
  618 +}
  619 +
533 bool 620 bool
534 QPDFJob::suppressWarnings() 621 QPDFJob::suppressWarnings()
535 { 622 {
libqpdf/QPDFJob_argv.cc
@@ -1474,81 +1474,13 @@ ArgParser::parseOptions() @@ -1474,81 +1474,13 @@ ArgParser::parseOptions()
1474 void 1474 void
1475 ArgParser::doFinalChecks() 1475 ArgParser::doFinalChecks()
1476 { 1476 {
1477 - if (o.replace_input)  
1478 - {  
1479 - if (o.outfilename)  
1480 - {  
1481 - usage("--replace-input may not be used when"  
1482 - " an output file is specified");  
1483 - }  
1484 - else if (o.split_pages)  
1485 - {  
1486 - usage("--split-pages may not be used with --replace-input");  
1487 - }  
1488 - }  
1489 - if (o.infilename == 0)  
1490 - {  
1491 - usage("an input file name is required");  
1492 - }  
1493 - else if (o.require_outfile && (o.outfilename == 0) && (! o.replace_input))  
1494 - {  
1495 - usage("an output file name is required; use - for standard output");  
1496 - }  
1497 - else if ((! o.require_outfile) &&  
1498 - ((o.outfilename != 0) || o.replace_input))  
1499 - {  
1500 - usage("no output file may be given for this option");  
1501 - }  
1502 - if (o.check_requires_password && o.check_is_encrypted)  
1503 - {  
1504 - usage("--requires-password and --is-encrypted may not be given"  
1505 - " together");  
1506 - }  
1507 -  
1508 - if (o.encrypt && (! o.allow_insecure) &&  
1509 - (o.owner_password.empty() &&  
1510 - (! o.user_password.empty()) &&  
1511 - (o.keylen == 256)))  
1512 - {  
1513 - // Note that empty owner passwords for R < 5 are copied from  
1514 - // the user password, so this lack of security is not an issue  
1515 - // for those files. Also we are consider only the ability to  
1516 - // open the file without a password to be insecure. We are not  
1517 - // concerned about whether the viewer enforces security  
1518 - // settings when the user and owner password match.  
1519 - usage("A PDF with a non-empty user password and an empty owner"  
1520 - " password encrypted with a 256-bit key is insecure as it"  
1521 - " can be opened without a password. If you really want to"  
1522 - " do this, you must also give the --allow-insecure option"  
1523 - " before the -- that follows --encrypt.");  
1524 - }  
1525 -  
1526 - if (o.require_outfile && o.outfilename &&  
1527 - (strcmp(o.outfilename.get(), "-") == 0)) 1477 + try
1528 { 1478 {
1529 - if (o.split_pages)  
1530 - {  
1531 - usage("--split-pages may not be used when"  
1532 - " writing to standard output");  
1533 - }  
1534 - if (o.verbose)  
1535 - {  
1536 - usage("--verbose may not be used when"  
1537 - " writing to standard output");  
1538 - }  
1539 - if (o.progress)  
1540 - {  
1541 - usage("--progress may not be used when"  
1542 - " writing to standard output");  
1543 - } 1479 + o.checkConfiguration();
1544 } 1480 }
1545 -  
1546 - if ((! o.split_pages) &&  
1547 - QUtil::same_file(o.infilename.get(), o.outfilename.get())) 1481 + catch (std::runtime_error& e)
1548 { 1482 {
1549 - QTC::TC("qpdf", "qpdf same file error");  
1550 - usage("input file and output file are the same;"  
1551 - " use --replace-input to intentionally overwrite the input file"); 1483 + usage(e.what());
1552 } 1484 }
1553 } 1485 }
1554 1486