Commit f37d399d825fc70155a3634c26463a24a2e17035

Authored by Jay Berkenbilt
1 parent 6a7d53ad

Add newline-before-endstream option (fixes #103)

ChangeLog
1 1 2017-07-29 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Add --newline-before-endstream command-line option and
  4 + setNewlineBeforeEndstream method to QPDFWriter. This forces qpdf
  5 + to always add a newline before the endstream keyword. It is a
  6 + necessary but not sufficient condition for PDF/A compliance. Fixes
  7 + #103.
  8 +
3 9 * Handle zlib data errors when decoding streams. Fixes #106.
4 10  
5 11 * Improve handling of files where the "stream" keyword is not
... ...
include/qpdf/QPDFWriter.hh
... ... @@ -161,6 +161,11 @@ class QPDFWriter
161 161 QPDF_DLL
162 162 void setPreserveUnreferencedObjects(bool);
163 163  
  164 + // Always write a newline before the endstream keyword. This helps
  165 + // with PDF/A compliance, though it is not sufficient for it.
  166 + QPDF_DLL
  167 + void setNewlineBeforeEndstream(bool);
  168 +
164 169 // Set the minimum PDF version. If the PDF version of the input
165 170 // file (or previously set minimum version) is less than the
166 171 // version passed to this method, the PDF version of the output
... ... @@ -434,6 +439,7 @@ class QPDFWriter
434 439 bool qdf_mode;
435 440 bool precheck_streams;
436 441 bool preserve_unreferenced_objects;
  442 + bool newline_before_endstream;
437 443 bool static_id;
438 444 bool suppress_original_object_ids;
439 445 bool direct_stream_lengths;
... ...
libqpdf/QPDFWriter.cc
... ... @@ -59,6 +59,7 @@ QPDFWriter::init()
59 59 qdf_mode = false;
60 60 precheck_streams = false;
61 61 preserve_unreferenced_objects = false;
  62 + newline_before_endstream = false;
62 63 static_id = false;
63 64 suppress_original_object_ids = false;
64 65 direct_stream_lengths = true;
... ... @@ -191,6 +192,12 @@ QPDFWriter::setPreserveUnreferencedObjects(bool val)
191 192 }
192 193  
193 194 void
  195 +QPDFWriter::setNewlineBeforeEndstream(bool val)
  196 +{
  197 + this->newline_before_endstream = val;
  198 +}
  199 +
  200 +void
194 201 QPDFWriter::setMinimumPDFVersion(std::string const& version)
195 202 {
196 203 setMinimumPDFVersion(version, 0);
... ... @@ -1580,7 +1587,7 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
1580 1587 char last_char = this->pipeline->getLastChar();
1581 1588 popPipelineStack();
1582 1589  
1583   - if (this->qdf_mode)
  1590 + if (this->qdf_mode || this->newline_before_endstream)
1584 1591 {
1585 1592 if (last_char != '\n')
1586 1593 {
... ...
qpdf/qpdf.cc
... ... @@ -204,6 +204,7 @@ familiar with the PDF file format or who are PDF developers.\n\
204 204 --ignore-xref-streams tells qpdf to ignore any cross-reference streams\n\
205 205 --precheck-streams precheck ability to decode streams\n\
206 206 --preserve-unreferenced preserve unreferenced objects\n\
  207 +--newline-before-endstream always put a newline before endstream\n\
207 208 --qdf turns on \"QDF mode\" (below)\n\
208 209 --min-version=version sets the minimum PDF version of the output file\n\
209 210 --force-version=version forces this to be the PDF version of the output file\n\
... ... @@ -1032,6 +1033,7 @@ int main(int argc, char* argv[])
1032 1033 bool qdf_mode = false;
1033 1034 bool precheck_streams = false;
1034 1035 bool preserve_unreferenced_objects = false;
  1036 + bool newline_before_endstream = false;
1035 1037 std::string min_version;
1036 1038 std::string force_version;
1037 1039  
... ... @@ -1225,6 +1227,10 @@ int main(int argc, char* argv[])
1225 1227 {
1226 1228 preserve_unreferenced_objects = true;
1227 1229 }
  1230 + else if (strcmp(arg, "newline-before-endstream") == 0)
  1231 + {
  1232 + newline_before_endstream = true;
  1233 + }
1228 1234 else if (strcmp(arg, "min-version") == 0)
1229 1235 {
1230 1236 if (parameter == 0)
... ... @@ -1724,6 +1730,10 @@ int main(int argc, char* argv[])
1724 1730 {
1725 1731 w.setPreserveUnreferencedObjects(true);
1726 1732 }
  1733 + if (newline_before_endstream)
  1734 + {
  1735 + w.setNewlineBeforeEndstream(true);
  1736 + }
1727 1737 if (normalize_set)
1728 1738 {
1729 1739 w.setContentNormalization(normalize);
... ...
qpdf/qtest/qpdf.test
... ... @@ -206,7 +206,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
206 206 show_ntests();
207 207 # ----------
208 208 $td->notify("--- Miscellaneous Tests ---");
209   -$n_tests += 89;
  209 +$n_tests += 91;
210 210  
211 211 $td->runtest("qpdf version",
212 212 {$td->COMMAND => "qpdf --version"},
... ... @@ -618,6 +618,16 @@ $td-&gt;runtest(&quot;split content stream errors&quot;,
618 618 $td->EXIT_STATUS => 3},
619 619 $td->NORMALIZE_NEWLINES);
620 620  
  621 +$td->runtest("newline before endstream",
  622 + {$td->COMMAND =>
  623 + "qpdf --static-id --newline-before-endstream" .
  624 + " minimal.pdf a.pdf"},
  625 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  626 + $td->NORMALIZE_NEWLINES);
  627 +$td->runtest("check output",
  628 + {$td->FILE => "a.pdf"},
  629 + {$td->FILE => "newline-before-endstream.pdf"});
  630 +
621 631  
622 632 show_ntests();
623 633 # ----------
... ...
qpdf/qtest/qpdf/newline-before-endstream.pdf 0 → 100644
No preview for this file type