Commit f52b984892bc4908ce14c4aa7ed881991cc38cf3

Authored by m-holger
1 parent ff09d994

Refactor `QPDFWriter`: move methods `setDataKey`, `indicateProgress`, `adjustAES…

…StreamLength`, `computeDeterministicIDData`, and `calculateXrefStreamPadding` to `QPDFWriter::Members`. Update related logic and remove obsolete declarations.
include/qpdf/QPDFWriter.hh
@@ -469,16 +469,6 @@ class QPDFWriter @@ -469,16 +469,6 @@ class QPDFWriter
469 qpdf_r3_modify_e modify); 469 qpdf_r3_modify_e modify);
470 void setEncryptionParameters(char const* user_password, char const* owner_password); 470 void setEncryptionParameters(char const* user_password, char const* owner_password);
471 void setEncryptionMinimumVersion(); 471 void setEncryptionMinimumVersion();
472 - void setDataKey(int objid);  
473 - void indicateProgress(bool decrement, bool finished);  
474 - size_t calculateXrefStreamPadding(qpdf_offset_t xref_bytes);  
475 -  
476 - // When filtering subsections, push additional pipelines to the stack. When ready to switch,  
477 - // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack  
478 - // is popped.  
479 -  
480 - void adjustAESStreamLength(size_t& length);  
481 - void computeDeterministicIDData();  
482 472
483 class Members; 473 class Members;
484 474
libqpdf/QPDFWriter.cc
@@ -380,6 +380,13 @@ class QPDFWriter::Members @@ -380,6 +380,13 @@ class QPDFWriter::Members
380 bool skip_compression, 380 bool skip_compression,
381 int linearization_pass); 381 int linearization_pass);
382 382
  383 + void setDataKey(int objid);
  384 + void indicateProgress(bool decrement, bool finished);
  385 + size_t calculateXrefStreamPadding(qpdf_offset_t xref_bytes);
  386 +
  387 + void adjustAESStreamLength(size_t& length);
  388 + void computeDeterministicIDData();
  389 +
383 private: 390 private:
384 QPDFWriter& w; 391 QPDFWriter& w;
385 QPDF& pdf; 392 QPDF& pdf;
@@ -1102,16 +1109,11 @@ QPDFWriter::setEncryptionMinimumVersion() @@ -1102,16 +1109,11 @@ QPDFWriter::setEncryptionMinimumVersion()
1102 } 1109 }
1103 1110
1104 void 1111 void
1105 -QPDFWriter::setDataKey(int objid) 1112 +QPDFWriter::Members::setDataKey(int objid)
1106 { 1113 {
1107 - if (m->encryption) {  
1108 - m->cur_data_key = QPDF::compute_data_key(  
1109 - m->encryption_key,  
1110 - objid,  
1111 - 0,  
1112 - m->encrypt_use_aes,  
1113 - m->encryption->getV(),  
1114 - m->encryption->getR()); 1114 + if (encryption) {
  1115 + cur_data_key = QPDF::compute_data_key(
  1116 + encryption_key, objid, 0, encrypt_use_aes, encryption->getV(), encryption->getR());
1115 } 1117 }
1116 } 1118 }
1117 1119
@@ -1196,9 +1198,9 @@ QPDFWriter::Members::write_no_qdf(Args&&... args) @@ -1196,9 +1198,9 @@ QPDFWriter::Members::write_no_qdf(Args&&... args)
1196 } 1198 }
1197 1199
1198 void 1200 void
1199 -QPDFWriter::adjustAESStreamLength(size_t& length) 1201 +QPDFWriter::Members::adjustAESStreamLength(size_t& length)
1200 { 1202 {
1201 - if (m->encryption && !m->cur_data_key.empty() && m->encrypt_use_aes) { 1203 + if (encryption && !cur_data_key.empty() && encrypt_use_aes) {
1202 // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will 1204 // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will
1203 // also be prepended by 16 bits of random data. 1205 // also be prepended by 16 bits of random data.
1204 length += 32 - (length & 0xf); 1206 length += 32 - (length & 0xf);
@@ -1220,15 +1222,15 @@ QPDFWriter::Members::write_encrypted(std::string_view str) @@ -1220,15 +1222,15 @@ QPDFWriter::Members::write_encrypted(std::string_view str)
1220 } 1222 }
1221 1223
1222 void 1224 void
1223 -QPDFWriter::computeDeterministicIDData() 1225 +QPDFWriter::Members::computeDeterministicIDData()
1224 { 1226 {
1225 - if (!m->id2.empty()) { 1227 + if (!id2.empty()) {
1226 // Can't happen in the code 1228 // Can't happen in the code
1227 throw std::logic_error( 1229 throw std::logic_error(
1228 "Deterministic ID computation enabled after ID generation has already occurred."); 1230 "Deterministic ID computation enabled after ID generation has already occurred.");
1229 } 1231 }
1230 - qpdf_assert_debug(m->deterministic_id_data.empty());  
1231 - m->deterministic_id_data = m->pipeline_stack.hex_digest(); 1232 + qpdf_assert_debug(deterministic_id_data.empty());
  1233 + deterministic_id_data = pipeline_stack.hex_digest();
1232 } 1234 }
1233 1235
1234 int 1236 int
@@ -1399,7 +1401,7 @@ QPDFWriter::Members::writeTrailer( @@ -1399,7 +1401,7 @@ QPDFWriter::Members::writeTrailer(
1399 write("<00000000000000000000000000000000>"); 1401 write("<00000000000000000000000000000000>");
1400 } else { 1402 } else {
1401 if (linearization_pass == 0 && deterministic_id) { 1403 if (linearization_pass == 0 && deterministic_id) {
1402 - w.computeDeterministicIDData(); 1404 + computeDeterministicIDData();
1403 } 1405 }
1404 generateID(encryption.get()); 1406 generateID(encryption.get());
1405 write_string(id1, true).write_string(id2, true); 1407 write_string(id1, true).write_string(id2, true);
@@ -1715,7 +1717,7 @@ QPDFWriter::Members::unparseObject( @@ -1715,7 +1717,7 @@ QPDFWriter::Members::unparseObject(
1715 // Don't encrypt stream data for the metadata stream 1717 // Don't encrypt stream data for the metadata stream
1716 cur_data_key.clear(); 1718 cur_data_key.clear();
1717 } 1719 }
1718 - w.adjustAESStreamLength(cur_stream_length); 1720 + adjustAESStreamLength(cur_stream_length);
1719 unparseObject(stream_dict, 0, flags, cur_stream_length, compress_stream); 1721 unparseObject(stream_dict, 0, flags, cur_stream_length, compress_stream);
1720 char last_char = stream_data.empty() ? '\0' : stream_data.back(); 1722 char last_char = stream_data.empty() ? '\0' : stream_data.back();
1721 write("\nstream\n").write_encrypted(stream_data); 1723 write("\nstream\n").write_encrypted(stream_data);
@@ -1821,7 +1823,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object) @@ -1821,7 +1823,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1821 offsets.push_back(pipeline->getCount()); 1823 offsets.push_back(pipeline->getCount());
1822 // To avoid double-counting objects being written in object streams for progress 1824 // To avoid double-counting objects being written in object streams for progress
1823 // reporting, decrement in pass 1. 1825 // reporting, decrement in pass 1.
1824 - w.indicateProgress(true, false); 1826 + indicateProgress(true, false);
1825 1827
1826 QPDFObjectHandle obj_to_write = pdf.getObject(og); 1828 QPDFObjectHandle obj_to_write = pdf.getObject(og);
1827 if (obj_to_write.isStream()) { 1829 if (obj_to_write.isStream()) {
@@ -1863,10 +1865,10 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object) @@ -1863,10 +1865,10 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1863 1865
1864 // Write the object 1866 // Write the object
1865 openObject(new_stream_id); 1867 openObject(new_stream_id);
1866 - w.setDataKey(new_stream_id); 1868 + setDataKey(new_stream_id);
1867 write("<<").write_qdf("\n ").write(" /Type /ObjStm").write_qdf("\n "); 1869 write("<<").write_qdf("\n ").write(" /Type /ObjStm").write_qdf("\n ");
1868 size_t length = stream_buffer_pass2.size(); 1870 size_t length = stream_buffer_pass2.size();
1869 - w.adjustAESStreamLength(length); 1871 + adjustAESStreamLength(length);
1870 write(" /Length ").write(length).write_qdf("\n "); 1872 write(" /Length ").write(length).write_qdf("\n ");
1871 if (compressed) { 1873 if (compressed) {
1872 write(" /Filter /FlateDecode"); 1874 write(" /Filter /FlateDecode");
@@ -1901,7 +1903,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde @@ -1901,7 +1903,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde
1901 return; 1903 return;
1902 } 1904 }
1903 1905
1904 - w.indicateProgress(false, false); 1906 + indicateProgress(false, false);
1905 auto new_id = obj[old_og].renumber; 1907 auto new_id = obj[old_og].renumber;
1906 if (qdf_mode) { 1908 if (qdf_mode) {
1907 if (page_object_to_seq.contains(old_og)) { 1909 if (page_object_to_seq.contains(old_og)) {
@@ -1916,7 +1918,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde @@ -1916,7 +1918,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde
1916 write("%% Original object ID: ").write(object.getObjGen().unparse(' ')).write("\n"); 1918 write("%% Original object ID: ").write(object.getObjGen().unparse(' ')).write("\n");
1917 } 1919 }
1918 openObject(new_id); 1920 openObject(new_id);
1919 - w.setDataKey(new_id); 1921 + setDataKey(new_id);
1920 unparseObject(object, 0, 0); 1922 unparseObject(object, 0, 0);
1921 cur_data_key.clear(); 1923 cur_data_key.clear();
1922 closeObject(new_id); 1924 closeObject(new_id);
@@ -2367,7 +2369,7 @@ QPDFWriter::write() @@ -2367,7 +2369,7 @@ QPDFWriter::write()
2367 m->output_buffer = m->buffer_pipeline->getBuffer(); 2369 m->output_buffer = m->buffer_pipeline->getBuffer();
2368 m->buffer_pipeline = nullptr; 2370 m->buffer_pipeline = nullptr;
2369 } 2371 }
2370 - indicateProgress(false, true); 2372 + m->indicateProgress(false, true);
2371 } 2373 }
2372 2374
2373 QPDFObjGen 2375 QPDFObjGen
@@ -2475,7 +2477,7 @@ QPDFWriter::Members::writeHintStream(int hint_id) @@ -2475,7 +2477,7 @@ QPDFWriter::Members::writeHintStream(int hint_id)
2475 QPDF::Writer::generateHintStream(pdf, new_obj, obj, hint_buffer, S, O, compressed); 2477 QPDF::Writer::generateHintStream(pdf, new_obj, obj, hint_buffer, S, O, compressed);
2476 2478
2477 openObject(hint_id); 2479 openObject(hint_id);
2478 - w.setDataKey(hint_id); 2480 + setDataKey(hint_id);
2479 2481
2480 size_t hlen = hint_buffer.size(); 2482 size_t hlen = hint_buffer.size();
2481 2483
@@ -2487,7 +2489,7 @@ QPDFWriter::Members::writeHintStream(int hint_id) @@ -2487,7 +2489,7 @@ QPDFWriter::Members::writeHintStream(int hint_id)
2487 if (O) { 2489 if (O) {
2488 write(" /O ").write(O); 2490 write(" /O ").write(O);
2489 } 2491 }
2490 - w.adjustAESStreamLength(hlen); 2492 + adjustAESStreamLength(hlen);
2491 write(" /Length ").write(hlen); 2493 write(" /Length ").write(hlen);
2492 write(" >>\nstream\n").write_encrypted(hint_buffer); 2494 write(" >>\nstream\n").write_encrypted(hint_buffer);
2493 2495
@@ -2649,7 +2651,7 @@ QPDFWriter::Members::writeXRefStream( @@ -2649,7 +2651,7 @@ QPDFWriter::Members::writeXRefStream(
2649 } 2651 }
2650 2652
2651 size_t 2653 size_t
2652 -QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes) 2654 +QPDFWriter::Members::calculateXrefStreamPadding(qpdf_offset_t xref_bytes)
2653 { 2655 {
2654 // This routine is called right after a linearization first pass xref stream has been written 2656 // This routine is called right after a linearization first pass xref stream has been written
2655 // without compression. Calculate the amount of padding that would be required in the worst 2657 // without compression. Calculate the amount of padding that would be required in the worst
@@ -2876,7 +2878,7 @@ QPDFWriter::Members::writeLinearized() @@ -2876,7 +2878,7 @@ QPDFWriter::Members::writeLinearized()
2876 qpdf_offset_t endpos = pipeline->getCount(); 2878 qpdf_offset_t endpos = pipeline->getCount();
2877 if (pass == 1) { 2879 if (pass == 1) {
2878 // Pad so we have enough room for the real xref stream. 2880 // Pad so we have enough room for the real xref stream.
2879 - write(w.calculateXrefStreamPadding(endpos - pos), ' '); 2881 + write(calculateXrefStreamPadding(endpos - pos), ' ');
2880 first_xref_end = pipeline->getCount(); 2882 first_xref_end = pipeline->getCount();
2881 } else { 2883 } else {
2882 // Pad so that the next object starts at the same place as in pass 1. 2884 // Pad so that the next object starts at the same place as in pass 1.
@@ -2953,7 +2955,7 @@ QPDFWriter::Members::writeLinearized() @@ -2953,7 +2955,7 @@ QPDFWriter::Members::writeLinearized()
2953 if (pass == 1) { 2955 if (pass == 1) {
2954 // Pad so we have enough room for the real xref stream. See comments for previous 2956 // Pad so we have enough room for the real xref stream. See comments for previous
2955 // xref stream on how we calculate the padding. 2957 // xref stream on how we calculate the padding.
2956 - write(w.calculateXrefStreamPadding(endpos - pos), ' ').write("\n"); 2958 + write(calculateXrefStreamPadding(endpos - pos), ' ').write("\n");
2957 second_xref_end = pipeline->getCount(); 2959 second_xref_end = pipeline->getCount();
2958 } else { 2960 } else {
2959 // Make the file size the same. 2961 // Make the file size the same.
@@ -2976,7 +2978,7 @@ QPDFWriter::Members::writeLinearized() @@ -2976,7 +2978,7 @@ QPDFWriter::Members::writeLinearized()
2976 if (pass == 1) { 2978 if (pass == 1) {
2977 if (deterministic_id) { 2979 if (deterministic_id) {
2978 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); 2980 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
2979 - w.computeDeterministicIDData(); 2981 + computeDeterministicIDData();
2980 pp_md5.pop(); 2982 pp_md5.pop();
2981 } 2983 }
2982 2984
@@ -3070,30 +3072,30 @@ QPDFWriter::Members::enqueueObjectsPCLm() @@ -3070,30 +3072,30 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3070 } 3072 }
3071 3073
3072 void 3074 void
3073 -QPDFWriter::indicateProgress(bool decrement, bool finished) 3075 +QPDFWriter::Members::indicateProgress(bool decrement, bool finished)
3074 { 3076 {
3075 if (decrement) { 3077 if (decrement) {
3076 - --m->events_seen; 3078 + --events_seen;
3077 return; 3079 return;
3078 } 3080 }
3079 3081
3080 - ++m->events_seen; 3082 + ++events_seen;
3081 3083
3082 - if (!m->progress_reporter.get()) { 3084 + if (!progress_reporter.get()) {
3083 return; 3085 return;
3084 } 3086 }
3085 3087
3086 - if (finished || (m->events_seen >= m->next_progress_report)) { 3088 + if (finished || events_seen >= next_progress_report) {
3087 int percentage = 3089 int percentage =
3088 (finished ? 100 3090 (finished ? 100
3089 - : m->next_progress_report == 0 3091 + : next_progress_report == 0
3090 ? 0 3092 ? 0
3091 - : std::min(99, 1 + ((100 * m->events_seen) / m->events_expected)));  
3092 - m->progress_reporter->reportProgress(percentage); 3093 + : std::min(99, 1 + ((100 * events_seen) / events_expected)));
  3094 + progress_reporter->reportProgress(percentage);
3093 } 3095 }
3094 - int increment = std::max(1, (m->events_expected / 100));  
3095 - while (m->events_seen >= m->next_progress_report) {  
3096 - m->next_progress_report += increment; 3096 + int increment = std::max(1, (events_expected / 100));
  3097 + while (events_seen >= next_progress_report) {
  3098 + next_progress_report += increment;
3097 } 3099 }
3098 } 3100 }
3099 3101