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 469 qpdf_r3_modify_e modify);
470 470 void setEncryptionParameters(char const* user_password, char const* owner_password);
471 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 473 class Members;
484 474  
... ...
libqpdf/QPDFWriter.cc
... ... @@ -380,6 +380,13 @@ class QPDFWriter::Members
380 380 bool skip_compression,
381 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 390 private:
384 391 QPDFWriter& w;
385 392 QPDF& pdf;
... ... @@ -1102,16 +1109,11 @@ QPDFWriter::setEncryptionMinimumVersion()
1102 1109 }
1103 1110  
1104 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 1198 }
1197 1199  
1198 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 1204 // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will
1203 1205 // also be prepended by 16 bits of random data.
1204 1206 length += 32 - (length & 0xf);
... ... @@ -1220,15 +1222,15 @@ QPDFWriter::Members::write_encrypted(std::string_view str)
1220 1222 }
1221 1223  
1222 1224 void
1223   -QPDFWriter::computeDeterministicIDData()
  1225 +QPDFWriter::Members::computeDeterministicIDData()
1224 1226 {
1225   - if (!m->id2.empty()) {
  1227 + if (!id2.empty()) {
1226 1228 // Can't happen in the code
1227 1229 throw std::logic_error(
1228 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 1236 int
... ... @@ -1399,7 +1401,7 @@ QPDFWriter::Members::writeTrailer(
1399 1401 write("<00000000000000000000000000000000>");
1400 1402 } else {
1401 1403 if (linearization_pass == 0 && deterministic_id) {
1402   - w.computeDeterministicIDData();
  1404 + computeDeterministicIDData();
1403 1405 }
1404 1406 generateID(encryption.get());
1405 1407 write_string(id1, true).write_string(id2, true);
... ... @@ -1715,7 +1717,7 @@ QPDFWriter::Members::unparseObject(
1715 1717 // Don't encrypt stream data for the metadata stream
1716 1718 cur_data_key.clear();
1717 1719 }
1718   - w.adjustAESStreamLength(cur_stream_length);
  1720 + adjustAESStreamLength(cur_stream_length);
1719 1721 unparseObject(stream_dict, 0, flags, cur_stream_length, compress_stream);
1720 1722 char last_char = stream_data.empty() ? '\0' : stream_data.back();
1721 1723 write("\nstream\n").write_encrypted(stream_data);
... ... @@ -1821,7 +1823,7 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1821 1823 offsets.push_back(pipeline->getCount());
1822 1824 // To avoid double-counting objects being written in object streams for progress
1823 1825 // reporting, decrement in pass 1.
1824   - w.indicateProgress(true, false);
  1826 + indicateProgress(true, false);
1825 1827  
1826 1828 QPDFObjectHandle obj_to_write = pdf.getObject(og);
1827 1829 if (obj_to_write.isStream()) {
... ... @@ -1863,10 +1865,10 @@ QPDFWriter::Members::writeObjectStream(QPDFObjectHandle object)
1863 1865  
1864 1866 // Write the object
1865 1867 openObject(new_stream_id);
1866   - w.setDataKey(new_stream_id);
  1868 + setDataKey(new_stream_id);
1867 1869 write("<<").write_qdf("\n ").write(" /Type /ObjStm").write_qdf("\n ");
1868 1870 size_t length = stream_buffer_pass2.size();
1869   - w.adjustAESStreamLength(length);
  1871 + adjustAESStreamLength(length);
1870 1872 write(" /Length ").write(length).write_qdf("\n ");
1871 1873 if (compressed) {
1872 1874 write(" /Filter /FlateDecode");
... ... @@ -1901,7 +1903,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde
1901 1903 return;
1902 1904 }
1903 1905  
1904   - w.indicateProgress(false, false);
  1906 + indicateProgress(false, false);
1905 1907 auto new_id = obj[old_og].renumber;
1906 1908 if (qdf_mode) {
1907 1909 if (page_object_to_seq.contains(old_og)) {
... ... @@ -1916,7 +1918,7 @@ QPDFWriter::Members::writeObject(QPDFObjectHandle object, int object_stream_inde
1916 1918 write("%% Original object ID: ").write(object.getObjGen().unparse(' ')).write("\n");
1917 1919 }
1918 1920 openObject(new_id);
1919   - w.setDataKey(new_id);
  1921 + setDataKey(new_id);
1920 1922 unparseObject(object, 0, 0);
1921 1923 cur_data_key.clear();
1922 1924 closeObject(new_id);
... ... @@ -2367,7 +2369,7 @@ QPDFWriter::write()
2367 2369 m->output_buffer = m->buffer_pipeline->getBuffer();
2368 2370 m->buffer_pipeline = nullptr;
2369 2371 }
2370   - indicateProgress(false, true);
  2372 + m->indicateProgress(false, true);
2371 2373 }
2372 2374  
2373 2375 QPDFObjGen
... ... @@ -2475,7 +2477,7 @@ QPDFWriter::Members::writeHintStream(int hint_id)
2475 2477 QPDF::Writer::generateHintStream(pdf, new_obj, obj, hint_buffer, S, O, compressed);
2476 2478  
2477 2479 openObject(hint_id);
2478   - w.setDataKey(hint_id);
  2480 + setDataKey(hint_id);
2479 2481  
2480 2482 size_t hlen = hint_buffer.size();
2481 2483  
... ... @@ -2487,7 +2489,7 @@ QPDFWriter::Members::writeHintStream(int hint_id)
2487 2489 if (O) {
2488 2490 write(" /O ").write(O);
2489 2491 }
2490   - w.adjustAESStreamLength(hlen);
  2492 + adjustAESStreamLength(hlen);
2491 2493 write(" /Length ").write(hlen);
2492 2494 write(" >>\nstream\n").write_encrypted(hint_buffer);
2493 2495  
... ... @@ -2649,7 +2651,7 @@ QPDFWriter::Members::writeXRefStream(
2649 2651 }
2650 2652  
2651 2653 size_t
2652   -QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes)
  2654 +QPDFWriter::Members::calculateXrefStreamPadding(qpdf_offset_t xref_bytes)
2653 2655 {
2654 2656 // This routine is called right after a linearization first pass xref stream has been written
2655 2657 // without compression. Calculate the amount of padding that would be required in the worst
... ... @@ -2876,7 +2878,7 @@ QPDFWriter::Members::writeLinearized()
2876 2878 qpdf_offset_t endpos = pipeline->getCount();
2877 2879 if (pass == 1) {
2878 2880 // Pad so we have enough room for the real xref stream.
2879   - write(w.calculateXrefStreamPadding(endpos - pos), ' ');
  2881 + write(calculateXrefStreamPadding(endpos - pos), ' ');
2880 2882 first_xref_end = pipeline->getCount();
2881 2883 } else {
2882 2884 // Pad so that the next object starts at the same place as in pass 1.
... ... @@ -2953,7 +2955,7 @@ QPDFWriter::Members::writeLinearized()
2953 2955 if (pass == 1) {
2954 2956 // Pad so we have enough room for the real xref stream. See comments for previous
2955 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 2959 second_xref_end = pipeline->getCount();
2958 2960 } else {
2959 2961 // Make the file size the same.
... ... @@ -2976,7 +2978,7 @@ QPDFWriter::Members::writeLinearized()
2976 2978 if (pass == 1) {
2977 2979 if (deterministic_id) {
2978 2980 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
2979   - w.computeDeterministicIDData();
  2981 + computeDeterministicIDData();
2980 2982 pp_md5.pop();
2981 2983 }
2982 2984  
... ... @@ -3070,30 +3072,30 @@ QPDFWriter::Members::enqueueObjectsPCLm()
3070 3072 }
3071 3073  
3072 3074 void
3073   -QPDFWriter::indicateProgress(bool decrement, bool finished)
  3075 +QPDFWriter::Members::indicateProgress(bool decrement, bool finished)
3074 3076 {
3075 3077 if (decrement) {
3076   - --m->events_seen;
  3078 + --events_seen;
3077 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 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 3089 int percentage =
3088 3090 (finished ? 100
3089   - : m->next_progress_report == 0
  3091 + : next_progress_report == 0
3090 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  
... ...