Commit bde98044f4acd5ce0e1965ad28a6854c31aa29a1

Authored by Jay Berkenbilt
1 parent f83bddf8

Improve password handling

Use --encryption-file-password, if given, in addition to --password as
a source for passwords for files specified in --pages.
manual/qpdf-manual.xml
... ... @@ -586,20 +586,16 @@ make
586 586 </para>
587 587 <para>
588 588 For each file that pages should be taken from, specify the file, a
589   - password needed to open the file (if needed), and a page range.
590   - If the primary input file file requires a password, that password
591   - must be specified outside the <option>--pages</option> option and
592   - does not need to be repeated inside the <option>--pages</option>.
593   - The same file can be repeated multiple times. If a file that is
594   - repeated has a password, the password only has to be given the
595   - first time. All non-page data (info, outlines, page numbers,
596   - etc.) are taken from the primary input file. To discard these,
597   - use <option>--empty</option> as the primary input. One subtlety
598   - about specifying passwords is that specifying a password as
599   - <option>--encryption-file-password</option> doesn't prevent you
600   - from having to repeat that password of that is also one of the
601   - input files. If in doubt, it's never an error to specify the
602   - password multiple times.
  589 + password needed to open the file (if any), and a page range. The
  590 + password needs to be given only once per file. If any of the
  591 + input files are the same as the primary input file or the file
  592 + used to copy encryption parameters (if specified), you do not need
  593 + to repeat the password here. The same file can be repeated
  594 + multiple times. If a file that is repeated has a password, the
  595 + password only has to be given the first time. All non-page data
  596 + (info, outlines, page numbers, etc.) are taken from the primary
  597 + input file. To discard these, use <option>--empty</option> as the
  598 + primary input.
603 599 </para>
604 600 <para>
605 601 It is not presently possible to specify the same page from the
... ...
qpdf/qpdf.cc
... ... @@ -152,13 +152,14 @@ starting point, but its pages are replaced with pages as specified.\n\
152 152 --pages file [ --password=password ] page-range ... --\n\
153 153 \n\
154 154 For each file that pages should be taken from, specify the file, a\n\
155   -password needed to open the file (if needed), and a page range. The\n\
156   -password needs to be given only once per file. If the input file file\n\
157   -requires a password, that password must be specified outside the\n\
158   ---pages option and does not need to be repeated. The same file can be\n\
159   -repeated multiple times. All non-page data (info, outlines, page numbers,\n\
160   -etc. are taken from the primary input file. To discard this, use --empty\n\
161   -as the primary input.\n\
  155 +password needed to open the file (if any), and a page range. The\n\
  156 +password needs to be given only once per file. If any of the input\n\
  157 +files are the same as the primary input file or the file used to copy\n\
  158 +encryption parameters (if specified), you do not need to repeat the\n\
  159 +password here. The same file can be repeated multiple times. All\n\
  160 +non-page data (info, outlines, page numbers, etc. are taken from the\n\
  161 +primary input file. To discard this, use --empty as the primary\n\
  162 +input.\n\
162 163 \n\
163 164 The page range is a set of numbers separated by commas, ranges of\n\
164 165 numbers separated dashes, or combinations of those. The character\n\
... ... @@ -880,13 +881,13 @@ int main(int argc, char* argv[])
880 881 exit(0);
881 882 }
882 883  
883   - char const* password = "";
  884 + char const* password = 0;
884 885 bool linearize = false;
885 886 bool decrypt = false;
886 887  
887 888 bool copy_encryption = false;
888 889 char const* encryption_file = 0;
889   - char const* encryption_file_password = "";
  890 + char const* encryption_file_password = 0;
890 891  
891 892 bool encrypt = false;
892 893 std::string user_password;
... ... @@ -1282,7 +1283,7 @@ int main(int argc, char* argv[])
1282 1283 if (filter &&
1283 1284 (! obj.pipeStreamData(0, true, false, false)))
1284 1285 {
1285   - QTC::TC("qpdf", "unable to filter");
  1286 + QTC::TC("qpdf", "qpdf unable to filter");
1286 1287 std::cerr << "Unable to filter stream data."
1287 1288 << std::endl;
1288 1289 exit(EXIT_ERROR);
... ... @@ -1445,8 +1446,15 @@ int main(int argc, char* argv[])
1445 1446 PointerHolder<QPDF> qpdf_ph = new QPDF();
1446 1447 page_heap.push_back(qpdf_ph);
1447 1448 QPDF* qpdf = qpdf_ph.getPointer();
  1449 + char const* password = page_spec.password;
  1450 + if (encryption_file && (password == 0) &&
  1451 + (page_spec.filename == encryption_file))
  1452 + {
  1453 + QTC::TC("qpdf", "qpdf pages encryption password");
  1454 + password = encryption_file_password;
  1455 + }
1448 1456 qpdf->processFile(
1449   - page_spec.filename.c_str(), page_spec.password);
  1457 + page_spec.filename.c_str(), password);
1450 1458 page_spec_qpdfs[page_spec.filename] = qpdf;
1451 1459 }
1452 1460  
... ...
qpdf/qpdf.testcov
... ... @@ -113,7 +113,7 @@ QPDFObjectHandle indirect to unknown 0
113 113 QPDF_Stream pipeStreamData with null pipeline 0
114 114 QPDFWriter not recompressing /FlateDecode 0
115 115 QPDF_encryption xref stream from encrypted file 0
116   -unable to filter 0
  116 +qpdf unable to filter 0
117 117 QPDF_String non-trivial UTF-16 0
118 118 QPDF xref overwrite object 0
119 119 QPDF decoding error warning 0
... ... @@ -237,3 +237,4 @@ QPDFWriter foreign object 0
237 237 QPDFWriter copy use_aes 1
238 238 QPDFObjectHandle indirect without context 0
239 239 QPDFObjectHandle trailing data in parse 0
  240 +qpdf pages encryption password 0
... ...
qpdf/qtest/qpdf.test
... ... @@ -424,7 +424,7 @@ foreach my $d (@nrange_tests)
424 424  
425 425 # ----------
426 426 $td->notify("--- Merging and Splitting ---");
427   -$n_tests += 4;
  427 +$n_tests += 6;
428 428  
429 429 # Select pages from the same file multiple times including selecting
430 430 # twice from an encrypted file and specifying the password only the
... ... @@ -460,6 +460,15 @@ $td-&gt;runtest(&quot;merge three files&quot;,
460 460 $td->runtest("check output",
461 461 {$td->FILE => "a.pdf"},
462 462 {$td->FILE => "merge-three-files-2.pdf"});
  463 +$td->runtest("avoid respecification of password",
  464 + {$td->COMMAND =>
  465 + "qpdf --empty a.pdf --copy-encryption=20-pages.pdf" .
  466 + " --encryption-file-password=user" .
  467 + " --pages 20-pages.pdf 1,z -- --static-id"},
  468 + {$td->STRING => "", $td->EXIT_STATUS => 0});
  469 +$td->runtest("check output",
  470 + {$td->FILE => "a.pdf"},
  471 + {$td->FILE => "pages-copy-encryption.pdf"});
463 472 # ----------
464 473 $td->notify("--- PDF From Scratch ---");
465 474 $n_tests += 2;
... ...
qpdf/qtest/qpdf/pages-copy-encryption.pdf 0 → 100644
No preview for this file type