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,20 +586,16 @@ make
586 </para> 586 </para>
587 <para> 587 <para>
588 For each file that pages should be taken from, specify the file, a 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 </para> 599 </para>
604 <para> 600 <para>
605 It is not presently possible to specify the same page from the 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,13 +152,14 @@ starting point, but its pages are replaced with pages as specified.\n\
152 --pages file [ --password=password ] page-range ... --\n\ 152 --pages file [ --password=password ] page-range ... --\n\
153 \n\ 153 \n\
154 For each file that pages should be taken from, specify the file, a\n\ 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 \n\ 163 \n\
163 The page range is a set of numbers separated by commas, ranges of\n\ 164 The page range is a set of numbers separated by commas, ranges of\n\
164 numbers separated dashes, or combinations of those. The character\n\ 165 numbers separated dashes, or combinations of those. The character\n\
@@ -880,13 +881,13 @@ int main(int argc, char* argv[]) @@ -880,13 +881,13 @@ int main(int argc, char* argv[])
880 exit(0); 881 exit(0);
881 } 882 }
882 883
883 - char const* password = ""; 884 + char const* password = 0;
884 bool linearize = false; 885 bool linearize = false;
885 bool decrypt = false; 886 bool decrypt = false;
886 887
887 bool copy_encryption = false; 888 bool copy_encryption = false;
888 char const* encryption_file = 0; 889 char const* encryption_file = 0;
889 - char const* encryption_file_password = ""; 890 + char const* encryption_file_password = 0;
890 891
891 bool encrypt = false; 892 bool encrypt = false;
892 std::string user_password; 893 std::string user_password;
@@ -1282,7 +1283,7 @@ int main(int argc, char* argv[]) @@ -1282,7 +1283,7 @@ int main(int argc, char* argv[])
1282 if (filter && 1283 if (filter &&
1283 (! obj.pipeStreamData(0, true, false, false))) 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 std::cerr << "Unable to filter stream data." 1287 std::cerr << "Unable to filter stream data."
1287 << std::endl; 1288 << std::endl;
1288 exit(EXIT_ERROR); 1289 exit(EXIT_ERROR);
@@ -1445,8 +1446,15 @@ int main(int argc, char* argv[]) @@ -1445,8 +1446,15 @@ int main(int argc, char* argv[])
1445 PointerHolder<QPDF> qpdf_ph = new QPDF(); 1446 PointerHolder<QPDF> qpdf_ph = new QPDF();
1446 page_heap.push_back(qpdf_ph); 1447 page_heap.push_back(qpdf_ph);
1447 QPDF* qpdf = qpdf_ph.getPointer(); 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 qpdf->processFile( 1456 qpdf->processFile(
1449 - page_spec.filename.c_str(), page_spec.password); 1457 + page_spec.filename.c_str(), password);
1450 page_spec_qpdfs[page_spec.filename] = qpdf; 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,7 +113,7 @@ QPDFObjectHandle indirect to unknown 0
113 QPDF_Stream pipeStreamData with null pipeline 0 113 QPDF_Stream pipeStreamData with null pipeline 0
114 QPDFWriter not recompressing /FlateDecode 0 114 QPDFWriter not recompressing /FlateDecode 0
115 QPDF_encryption xref stream from encrypted file 0 115 QPDF_encryption xref stream from encrypted file 0
116 -unable to filter 0 116 +qpdf unable to filter 0
117 QPDF_String non-trivial UTF-16 0 117 QPDF_String non-trivial UTF-16 0
118 QPDF xref overwrite object 0 118 QPDF xref overwrite object 0
119 QPDF decoding error warning 0 119 QPDF decoding error warning 0
@@ -237,3 +237,4 @@ QPDFWriter foreign object 0 @@ -237,3 +237,4 @@ QPDFWriter foreign object 0
237 QPDFWriter copy use_aes 1 237 QPDFWriter copy use_aes 1
238 QPDFObjectHandle indirect without context 0 238 QPDFObjectHandle indirect without context 0
239 QPDFObjectHandle trailing data in parse 0 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,7 +424,7 @@ foreach my $d (@nrange_tests)
424 424
425 # ---------- 425 # ----------
426 $td->notify("--- Merging and Splitting ---"); 426 $td->notify("--- Merging and Splitting ---");
427 -$n_tests += 4; 427 +$n_tests += 6;
428 428
429 # Select pages from the same file multiple times including selecting 429 # Select pages from the same file multiple times including selecting
430 # twice from an encrypted file and specifying the password only the 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,6 +460,15 @@ $td-&gt;runtest(&quot;merge three files&quot;,
460 $td->runtest("check output", 460 $td->runtest("check output",
461 {$td->FILE => "a.pdf"}, 461 {$td->FILE => "a.pdf"},
462 {$td->FILE => "merge-three-files-2.pdf"}); 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 $td->notify("--- PDF From Scratch ---"); 473 $td->notify("--- PDF From Scratch ---");
465 $n_tests += 2; 474 $n_tests += 2;
qpdf/qtest/qpdf/pages-copy-encryption.pdf 0 → 100644
No preview for this file type