Commit 68e721981a1fe4f1398d811bb8ed99af0e100da8
1 parent
696ca532
Add new QPDF::warn that takes most of QPDFExc's arguments
Showing
13 changed files
with
93 additions
and
113 deletions
ChangeLog
| 1 | 2022-04-23 Jay Berkenbilt <ejb@ql.org> | 1 | 2022-04-23 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | ||
| 3 | + * Add a new QPDF::warn method that takes the parameters of | ||
| 4 | + QPDFExc's constructor except for the filename, which is taken from | ||
| 5 | + the QPDF object. This is a shorter way to issue warnings on behalf | ||
| 6 | + of a QPDF object. | ||
| 7 | + | ||
| 3 | * Add new method QUtil::is_explicit_utf8 that tests whether a | 8 | * Add new method QUtil::is_explicit_utf8 that tests whether a |
| 4 | string is explicitly marked as being UTF-8 encoded, as allowed by | 9 | string is explicitly marked as being UTF-8 encoded, as allowed by |
| 5 | the PDF 2.0 spec. Such a string starts with the bytes 0xEF 0xBB | 10 | the PDF 2.0 spec. Such a string starts with the bytes 0xEF 0xBB |
TODO
| @@ -21,8 +21,6 @@ Misc | @@ -21,8 +21,6 @@ Misc | ||
| 21 | --show-encryption could potentially retry with this option if the | 21 | --show-encryption could potentially retry with this option if the |
| 22 | first time doesn't work. Then, with the file open, we can read the | 22 | first time doesn't work. Then, with the file open, we can read the |
| 23 | encryption dictionary normally. | 23 | encryption dictionary normally. |
| 24 | -* Have a warn in QPDF that passes its variable arguments onto QPDFExc | ||
| 25 | - so you don't have to do warn(QPDFExc(...)) | ||
| 26 | * Find all places in the code that write to std::cout, std::err, | 24 | * Find all places in the code that write to std::cout, std::err, |
| 27 | stdout, or stderr to make sure they obey default output stream | 25 | stdout, or stderr to make sure they obey default output stream |
| 28 | settings for QPDF and QPDFJob. This probably includes adding a | 26 | settings for QPDF and QPDFJob. This probably includes adding a |
include/qpdf/QPDF.hh
| @@ -262,6 +262,16 @@ class QPDF | @@ -262,6 +262,16 @@ class QPDF | ||
| 262 | // rules, and it will be available with getWarnings(). | 262 | // rules, and it will be available with getWarnings(). |
| 263 | QPDF_DLL | 263 | QPDF_DLL |
| 264 | void warn(QPDFExc const& e); | 264 | void warn(QPDFExc const& e); |
| 265 | + // Same as above but creates the QPDFExc object using the | ||
| 266 | + // arguments passed to warn. The filename argument to QPDFExc is | ||
| 267 | + // omitted. This method uses the filename associated with the QPDF | ||
| 268 | + // object. | ||
| 269 | + QPDF_DLL | ||
| 270 | + void warn( | ||
| 271 | + qpdf_error_code_e error_code, | ||
| 272 | + std::string const& object, | ||
| 273 | + qpdf_offset_t offset, | ||
| 274 | + std::string const& message); | ||
| 265 | 275 | ||
| 266 | QPDF_DLL | 276 | QPDF_DLL |
| 267 | std::string getFilename() const; | 277 | std::string getFilename() const; |
libqpdf/NNTree.cc
| @@ -18,14 +18,7 @@ get_description(QPDFObjectHandle& node) | @@ -18,14 +18,7 @@ get_description(QPDFObjectHandle& node) | ||
| 18 | static void | 18 | static void |
| 19 | warn(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg) | 19 | warn(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg) |
| 20 | { | 20 | { |
| 21 | - qpdf.warn( | ||
| 22 | - // line-break | ||
| 23 | - QPDFExc( | ||
| 24 | - qpdf_e_damaged_pdf, | ||
| 25 | - qpdf.getFilename(), | ||
| 26 | - get_description(node), | ||
| 27 | - 0, | ||
| 28 | - msg)); | 21 | + qpdf.warn(qpdf_e_damaged_pdf, get_description(node), 0, msg); |
| 29 | } | 22 | } |
| 30 | 23 | ||
| 31 | static void | 24 | static void |
libqpdf/QPDF.cc
| @@ -459,12 +459,7 @@ QPDF::parse(char const* password) | @@ -459,12 +459,7 @@ QPDF::parse(char const* password) | ||
| 459 | PatternFinder hf(*this, &QPDF::findHeader); | 459 | PatternFinder hf(*this, &QPDF::findHeader); |
| 460 | if (!this->m->file->findFirst("%PDF-", 0, 1024, hf)) { | 460 | if (!this->m->file->findFirst("%PDF-", 0, 1024, hf)) { |
| 461 | QTC::TC("qpdf", "QPDF not a pdf file"); | 461 | QTC::TC("qpdf", "QPDF not a pdf file"); |
| 462 | - warn(QPDFExc( | ||
| 463 | - qpdf_e_damaged_pdf, | ||
| 464 | - this->m->file->getName(), | ||
| 465 | - "", | ||
| 466 | - 0, | ||
| 467 | - "can't find PDF header")); | 462 | + warn(qpdf_e_damaged_pdf, "", 0, "can't find PDF header"); |
| 468 | // QPDFWriter writes files that usually require at least | 463 | // QPDFWriter writes files that usually require at least |
| 469 | // version 1.2 for /FlateDecode | 464 | // version 1.2 for /FlateDecode |
| 470 | this->m->pdf_version = "1.2"; | 465 | this->m->pdf_version = "1.2"; |
| @@ -542,6 +537,16 @@ QPDF::warn(QPDFExc const& e) | @@ -542,6 +537,16 @@ QPDF::warn(QPDFExc const& e) | ||
| 542 | } | 537 | } |
| 543 | 538 | ||
| 544 | void | 539 | void |
| 540 | +QPDF::warn( | ||
| 541 | + qpdf_error_code_e error_code, | ||
| 542 | + std::string const& object, | ||
| 543 | + qpdf_offset_t offset, | ||
| 544 | + std::string const& message) | ||
| 545 | +{ | ||
| 546 | + warn(QPDFExc(error_code, this->getFilename(), object, offset, message)); | ||
| 547 | +} | ||
| 548 | + | ||
| 549 | +void | ||
| 545 | QPDF::setTrailer(QPDFObjectHandle obj) | 550 | QPDF::setTrailer(QPDFObjectHandle obj) |
| 546 | { | 551 | { |
| 547 | if (this->m->trailer.isInitialized()) { | 552 | if (this->m->trailer.isInitialized()) { |
| @@ -562,19 +567,13 @@ QPDF::reconstruct_xref(QPDFExc& e) | @@ -562,19 +567,13 @@ QPDF::reconstruct_xref(QPDFExc& e) | ||
| 562 | 567 | ||
| 563 | this->m->reconstructed_xref = true; | 568 | this->m->reconstructed_xref = true; |
| 564 | 569 | ||
| 565 | - warn(QPDFExc( | ||
| 566 | - qpdf_e_damaged_pdf, | ||
| 567 | - this->m->file->getName(), | ||
| 568 | - "", | ||
| 569 | - 0, | ||
| 570 | - "file is damaged")); | 570 | + warn(qpdf_e_damaged_pdf, "", 0, "file is damaged"); |
| 571 | warn(e); | 571 | warn(e); |
| 572 | - warn(QPDFExc( | 572 | + warn( |
| 573 | qpdf_e_damaged_pdf, | 573 | qpdf_e_damaged_pdf, |
| 574 | - this->m->file->getName(), | ||
| 575 | "", | 574 | "", |
| 576 | 0, | 575 | 0, |
| 577 | - "Attempting to reconstruct cross-reference table")); | 576 | + "Attempting to reconstruct cross-reference table"); |
| 578 | 577 | ||
| 579 | // Delete all references to type 1 (uncompressed) objects | 578 | // Delete all references to type 1 (uncompressed) objects |
| 580 | std::set<QPDFObjGen> to_delete; | 579 | std::set<QPDFObjGen> to_delete; |
| @@ -700,12 +699,11 @@ QPDF::read_xref(qpdf_offset_t xref_offset) | @@ -700,12 +699,11 @@ QPDF::read_xref(qpdf_offset_t xref_offset) | ||
| 700 | if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { | 699 | if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { |
| 701 | if (skipped_space) { | 700 | if (skipped_space) { |
| 702 | QTC::TC("qpdf", "QPDF xref skipped space"); | 701 | QTC::TC("qpdf", "QPDF xref skipped space"); |
| 703 | - warn(QPDFExc( | 702 | + warn( |
| 704 | qpdf_e_damaged_pdf, | 703 | qpdf_e_damaged_pdf, |
| 705 | - this->m->file->getName(), | ||
| 706 | "", | 704 | "", |
| 707 | 0, | 705 | 0, |
| 708 | - "extraneous whitespace seen before xref")); | 706 | + "extraneous whitespace seen before xref"); |
| 709 | } | 707 | } |
| 710 | QTC::TC( | 708 | QTC::TC( |
| 711 | "qpdf", | 709 | "qpdf", |
| @@ -753,15 +751,14 @@ QPDF::read_xref(qpdf_offset_t xref_offset) | @@ -753,15 +751,14 @@ QPDF::read_xref(qpdf_offset_t xref_offset) | ||
| 753 | } | 751 | } |
| 754 | if ((size < 1) || (size - 1 != max_obj)) { | 752 | if ((size < 1) || (size - 1 != max_obj)) { |
| 755 | QTC::TC("qpdf", "QPDF xref size mismatch"); | 753 | QTC::TC("qpdf", "QPDF xref size mismatch"); |
| 756 | - warn(QPDFExc( | 754 | + warn( |
| 757 | qpdf_e_damaged_pdf, | 755 | qpdf_e_damaged_pdf, |
| 758 | - this->m->file->getName(), | ||
| 759 | "", | 756 | "", |
| 760 | 0, | 757 | 0, |
| 761 | (std::string("reported number of objects (") + | 758 | (std::string("reported number of objects (") + |
| 762 | QUtil::int_to_string(size) + | 759 | QUtil::int_to_string(size) + |
| 763 | ") is not one plus the highest object number (" + | 760 | ") is not one plus the highest object number (" + |
| 764 | - QUtil::int_to_string(max_obj) + ")"))); | 761 | + QUtil::int_to_string(max_obj) + ")")); |
| 765 | } | 762 | } |
| 766 | 763 | ||
| 767 | // We no longer need the deleted_objects table, so go ahead and | 764 | // We no longer need the deleted_objects table, so go ahead and |
| @@ -885,12 +882,11 @@ QPDF::parse_xrefEntry( | @@ -885,12 +882,11 @@ QPDF::parse_xrefEntry( | ||
| 885 | } | 882 | } |
| 886 | 883 | ||
| 887 | if (invalid) { | 884 | if (invalid) { |
| 888 | - warn(QPDFExc( | 885 | + warn( |
| 889 | qpdf_e_damaged_pdf, | 886 | qpdf_e_damaged_pdf, |
| 890 | - this->m->file->getName(), | ||
| 891 | "xref table", | 887 | "xref table", |
| 892 | this->m->file->getLastOffset(), | 888 | this->m->file->getLastOffset(), |
| 893 | - "accepting invalid xref table entry")); | 889 | + "accepting invalid xref table entry"); |
| 894 | } | 890 | } |
| 895 | 891 | ||
| 896 | f1 = QUtil::string_to_ll(f1_str.c_str()); | 892 | f1 = QUtil::string_to_ll(f1_str.c_str()); |
| @@ -1813,12 +1809,11 @@ QPDF::readObjectAtOffset( | @@ -1813,12 +1809,11 @@ QPDF::readObjectAtOffset( | ||
| 1813 | // ignore these. | 1809 | // ignore these. |
| 1814 | if (offset == 0) { | 1810 | if (offset == 0) { |
| 1815 | QTC::TC("qpdf", "QPDF bogus 0 offset", 0); | 1811 | QTC::TC("qpdf", "QPDF bogus 0 offset", 0); |
| 1816 | - warn(QPDFExc( | 1812 | + warn( |
| 1817 | qpdf_e_damaged_pdf, | 1813 | qpdf_e_damaged_pdf, |
| 1818 | - this->m->file->getName(), | ||
| 1819 | this->m->last_object_description, | 1814 | this->m->last_object_description, |
| 1820 | 0, | 1815 | 0, |
| 1821 | - "object has offset 0")); | 1816 | + "object has offset 0"); |
| 1822 | return QPDFObjectHandle::newNull(); | 1817 | return QPDFObjectHandle::newNull(); |
| 1823 | } | 1818 | } |
| 1824 | 1819 | ||
| @@ -1898,16 +1893,15 @@ QPDF::readObjectAtOffset( | @@ -1898,16 +1893,15 @@ QPDF::readObjectAtOffset( | ||
| 1898 | return result; | 1893 | return result; |
| 1899 | } else { | 1894 | } else { |
| 1900 | QTC::TC("qpdf", "QPDF object gone after xref reconstruction"); | 1895 | QTC::TC("qpdf", "QPDF object gone after xref reconstruction"); |
| 1901 | - warn(QPDFExc( | 1896 | + warn( |
| 1902 | qpdf_e_damaged_pdf, | 1897 | qpdf_e_damaged_pdf, |
| 1903 | - this->m->file->getName(), | ||
| 1904 | "", | 1898 | "", |
| 1905 | 0, | 1899 | 0, |
| 1906 | std::string( | 1900 | std::string( |
| 1907 | "object " + QUtil::int_to_string(exp_objid) + " " + | 1901 | "object " + QUtil::int_to_string(exp_objid) + " " + |
| 1908 | QUtil::int_to_string(exp_generation) + | 1902 | QUtil::int_to_string(exp_generation) + |
| 1909 | " not found in file after regenerating" | 1903 | " not found in file after regenerating" |
| 1910 | - " cross reference table"))); | 1904 | + " cross reference table")); |
| 1911 | return QPDFObjectHandle::newNull(); | 1905 | return QPDFObjectHandle::newNull(); |
| 1912 | } | 1906 | } |
| 1913 | } else { | 1907 | } else { |
| @@ -1921,12 +1915,11 @@ QPDF::readObjectAtOffset( | @@ -1921,12 +1915,11 @@ QPDF::readObjectAtOffset( | ||
| 1921 | if (!(readToken(this->m->file) == | 1915 | if (!(readToken(this->m->file) == |
| 1922 | QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { | 1916 | QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { |
| 1923 | QTC::TC("qpdf", "QPDF err expected endobj"); | 1917 | QTC::TC("qpdf", "QPDF err expected endobj"); |
| 1924 | - warn(QPDFExc( | 1918 | + warn( |
| 1925 | qpdf_e_damaged_pdf, | 1919 | qpdf_e_damaged_pdf, |
| 1926 | - this->m->file->getName(), | ||
| 1927 | this->m->last_object_description, | 1920 | this->m->last_object_description, |
| 1928 | this->m->file->getLastOffset(), | 1921 | this->m->file->getLastOffset(), |
| 1929 | - "expected endobj")); | 1922 | + "expected endobj"); |
| 1930 | } | 1923 | } |
| 1931 | 1924 | ||
| 1932 | QPDFObjGen og(objid, generation); | 1925 | QPDFObjGen og(objid, generation); |
| @@ -2005,13 +1998,12 @@ QPDF::resolve(int objid, int generation) | @@ -2005,13 +1998,12 @@ QPDF::resolve(int objid, int generation) | ||
| 2005 | // indirectly in some key that has to be resolved during | 1998 | // indirectly in some key that has to be resolved during |
| 2006 | // object parsing, such as stream length. | 1999 | // object parsing, such as stream length. |
| 2007 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); | 2000 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); |
| 2008 | - warn(QPDFExc( | 2001 | + warn( |
| 2009 | qpdf_e_damaged_pdf, | 2002 | qpdf_e_damaged_pdf, |
| 2010 | - this->m->file->getName(), | ||
| 2011 | "", | 2003 | "", |
| 2012 | this->m->file->getLastOffset(), | 2004 | this->m->file->getLastOffset(), |
| 2013 | ("loop detected resolving object " + QUtil::int_to_string(objid) + | 2005 | ("loop detected resolving object " + QUtil::int_to_string(objid) + |
| 2014 | - " " + QUtil::int_to_string(generation)))); | 2006 | + " " + QUtil::int_to_string(generation))); |
| 2015 | return std::shared_ptr<QPDFObject>(new QPDF_Null); | 2007 | return std::shared_ptr<QPDFObject>(new QPDF_Null); |
| 2016 | } | 2008 | } |
| 2017 | ResolveRecorder rr(this, og); | 2009 | ResolveRecorder rr(this, og); |
| @@ -2054,14 +2046,13 @@ QPDF::resolve(int objid, int generation) | @@ -2054,14 +2046,13 @@ QPDF::resolve(int objid, int generation) | ||
| 2054 | } catch (QPDFExc& e) { | 2046 | } catch (QPDFExc& e) { |
| 2055 | warn(e); | 2047 | warn(e); |
| 2056 | } catch (std::exception& e) { | 2048 | } catch (std::exception& e) { |
| 2057 | - warn(QPDFExc( | 2049 | + warn( |
| 2058 | qpdf_e_damaged_pdf, | 2050 | qpdf_e_damaged_pdf, |
| 2059 | - this->m->file->getName(), | ||
| 2060 | "", | 2051 | "", |
| 2061 | 0, | 2052 | 0, |
| 2062 | ("object " + QUtil::int_to_string(objid) + "/" + | 2053 | ("object " + QUtil::int_to_string(objid) + "/" + |
| 2063 | QUtil::int_to_string(generation) + | 2054 | QUtil::int_to_string(generation) + |
| 2064 | - ": error reading object: " + e.what()))); | 2055 | + ": error reading object: " + e.what())); |
| 2065 | } | 2056 | } |
| 2066 | } | 2057 | } |
| 2067 | if (this->m->obj_cache.count(og) == 0) { | 2058 | if (this->m->obj_cache.count(og) == 0) { |
| @@ -2112,13 +2103,12 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | @@ -2112,13 +2103,12 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | ||
| 2112 | QPDFObjectHandle dict = obj_stream.getDict(); | 2103 | QPDFObjectHandle dict = obj_stream.getDict(); |
| 2113 | if (!dict.isDictionaryOfType("/ObjStm")) { | 2104 | if (!dict.isDictionaryOfType("/ObjStm")) { |
| 2114 | QTC::TC("qpdf", "QPDF ERR object stream with wrong type"); | 2105 | QTC::TC("qpdf", "QPDF ERR object stream with wrong type"); |
| 2115 | - warn(QPDFExc( | 2106 | + warn( |
| 2116 | qpdf_e_damaged_pdf, | 2107 | qpdf_e_damaged_pdf, |
| 2117 | - this->m->file->getName(), | ||
| 2118 | this->m->last_object_description, | 2108 | this->m->last_object_description, |
| 2119 | this->m->file->getLastOffset(), | 2109 | this->m->file->getLastOffset(), |
| 2120 | ("supposed object stream " + | 2110 | ("supposed object stream " + |
| 2121 | - QUtil::int_to_string(obj_stream_number) + " has wrong type"))); | 2111 | + QUtil::int_to_string(obj_stream_number) + " has wrong type")); |
| 2122 | } | 2112 | } |
| 2123 | 2113 | ||
| 2124 | if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) { | 2114 | if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) { |
libqpdf/QPDFJob.cc
| @@ -2677,14 +2677,13 @@ QPDFJob::handlePageSpecs( | @@ -2677,14 +2677,13 @@ QPDFJob::handlePageSpecs( | ||
| 2677 | *other_afdh, | 2677 | *other_afdh, |
| 2678 | &referenced_fields); | 2678 | &referenced_fields); |
| 2679 | } catch (std::exception& e) { | 2679 | } catch (std::exception& e) { |
| 2680 | - pdf.warn(QPDFExc( | 2680 | + pdf.warn( |
| 2681 | qpdf_e_damaged_pdf, | 2681 | qpdf_e_damaged_pdf, |
| 2682 | - pdf.getFilename(), | ||
| 2683 | "", | 2682 | "", |
| 2684 | 0, | 2683 | 0, |
| 2685 | ("Exception caught while fixing copied" | 2684 | ("Exception caught while fixing copied" |
| 2686 | " annotations. This may be a qpdf bug. " + | 2685 | " annotations. This may be a qpdf bug. " + |
| 2687 | - std::string("Exception: ") + e.what()))); | 2686 | + std::string("Exception: ") + e.what())); |
| 2688 | } | 2687 | } |
| 2689 | } | 2688 | } |
| 2690 | } | 2689 | } |
| @@ -3127,14 +3126,13 @@ QPDFJob::doSplitPages(QPDF& pdf, bool& warnings) | @@ -3127,14 +3126,13 @@ QPDFJob::doSplitPages(QPDF& pdf, bool& warnings) | ||
| 3127 | try { | 3126 | try { |
| 3128 | out_afdh->fixCopiedAnnotations(new_page, page, afdh); | 3127 | out_afdh->fixCopiedAnnotations(new_page, page, afdh); |
| 3129 | } catch (std::exception& e) { | 3128 | } catch (std::exception& e) { |
| 3130 | - pdf.warn(QPDFExc( | 3129 | + pdf.warn( |
| 3131 | qpdf_e_damaged_pdf, | 3130 | qpdf_e_damaged_pdf, |
| 3132 | - pdf.getFilename(), | ||
| 3133 | "", | 3131 | "", |
| 3134 | 0, | 3132 | 0, |
| 3135 | - "Exception caught while fixing copied" | ||
| 3136 | - " annotations. This may be a qpdf bug." + | ||
| 3137 | - std::string("Exception: ") + e.what())); | 3133 | + ("Exception caught while fixing copied" |
| 3134 | + " annotations. This may be a qpdf bug." + | ||
| 3135 | + std::string("Exception: ") + e.what())); | ||
| 3138 | } | 3136 | } |
| 3139 | } | 3137 | } |
| 3140 | } | 3138 | } |
libqpdf/QPDFObjectHandle.cc
| @@ -1556,8 +1556,9 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | @@ -1556,8 +1556,9 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | ||
| 1556 | item.getOwningQPDF(), | 1556 | item.getOwningQPDF(), |
| 1557 | QPDFExc( | 1557 | QPDFExc( |
| 1558 | qpdf_e_damaged_pdf, | 1558 | qpdf_e_damaged_pdf, |
| 1559 | - description, | ||
| 1560 | - "item index " + QUtil::int_to_string(i) + " (from 0)", | 1559 | + "", |
| 1560 | + description + ": item index " + | ||
| 1561 | + QUtil::int_to_string(i) + " (from 0)", | ||
| 1561 | 0, | 1562 | 0, |
| 1562 | "ignoring non-stream in an array of streams")); | 1563 | "ignoring non-stream in an array of streams")); |
| 1563 | } | 1564 | } |
libqpdf/QPDF_Stream.cc
| @@ -302,12 +302,10 @@ QPDF_Stream::filterable( | @@ -302,12 +302,10 @@ QPDF_Stream::filterable( | ||
| 302 | 302 | ||
| 303 | if (!filters_okay) { | 303 | if (!filters_okay) { |
| 304 | QTC::TC("qpdf", "QPDF_Stream invalid filter"); | 304 | QTC::TC("qpdf", "QPDF_Stream invalid filter"); |
| 305 | - warn(QPDFExc( | 305 | + warn( |
| 306 | qpdf_e_damaged_pdf, | 306 | qpdf_e_damaged_pdf, |
| 307 | - qpdf->getFilename(), | ||
| 308 | - "", | ||
| 309 | this->offset, | 307 | this->offset, |
| 310 | - "stream filter type is not name or array")); | 308 | + "stream filter type is not name or array"); |
| 311 | return false; | 309 | return false; |
| 312 | } | 310 | } |
| 313 | 311 | ||
| @@ -355,13 +353,11 @@ QPDF_Stream::filterable( | @@ -355,13 +353,11 @@ QPDF_Stream::filterable( | ||
| 355 | // one case of a file whose /DecodeParms was [ << >> ] when | 353 | // one case of a file whose /DecodeParms was [ << >> ] when |
| 356 | // /Filters was empty has been seen in the wild. | 354 | // /Filters was empty has been seen in the wild. |
| 357 | if ((filters.size() != 0) && (decode_parms.size() != filters.size())) { | 355 | if ((filters.size() != 0) && (decode_parms.size() != filters.size())) { |
| 358 | - warn(QPDFExc( | 356 | + warn( |
| 359 | qpdf_e_damaged_pdf, | 357 | qpdf_e_damaged_pdf, |
| 360 | - qpdf->getFilename(), | ||
| 361 | - "", | ||
| 362 | this->offset, | 358 | this->offset, |
| 363 | "stream /DecodeParms length is" | 359 | "stream /DecodeParms length is" |
| 364 | - " inconsistent with filters")); | 360 | + " inconsistent with filters"); |
| 365 | filterable = false; | 361 | filterable = false; |
| 366 | } | 362 | } |
| 367 | 363 | ||
| @@ -474,12 +470,7 @@ QPDF_Stream::pipeStreamData( | @@ -474,12 +470,7 @@ QPDF_Stream::pipeStreamData( | ||
| 474 | Pl_Flate* flate = dynamic_cast<Pl_Flate*>(pipeline); | 470 | Pl_Flate* flate = dynamic_cast<Pl_Flate*>(pipeline); |
| 475 | if (flate != nullptr) { | 471 | if (flate != nullptr) { |
| 476 | flate->setWarnCallback([this](char const* msg, int code) { | 472 | flate->setWarnCallback([this](char const* msg, int code) { |
| 477 | - warn(QPDFExc( | ||
| 478 | - qpdf_e_damaged_pdf, | ||
| 479 | - qpdf->getFilename(), | ||
| 480 | - "", | ||
| 481 | - this->offset, | ||
| 482 | - msg)); | 473 | + warn(qpdf_e_damaged_pdf, this->offset, msg); |
| 483 | }); | 474 | }); |
| 484 | } | 475 | } |
| 485 | } | 476 | } |
| @@ -551,34 +542,28 @@ QPDF_Stream::pipeStreamData( | @@ -551,34 +542,28 @@ QPDF_Stream::pipeStreamData( | ||
| 551 | 542 | ||
| 552 | if (filter && (!suppress_warnings) && normalizer.get() && | 543 | if (filter && (!suppress_warnings) && normalizer.get() && |
| 553 | normalizer->anyBadTokens()) { | 544 | normalizer->anyBadTokens()) { |
| 554 | - warn(QPDFExc( | 545 | + warn( |
| 555 | qpdf_e_damaged_pdf, | 546 | qpdf_e_damaged_pdf, |
| 556 | - qpdf->getFilename(), | ||
| 557 | - "", | ||
| 558 | this->offset, | 547 | this->offset, |
| 559 | - "content normalization encountered bad tokens")); | 548 | + "content normalization encountered bad tokens"); |
| 560 | if (normalizer->lastTokenWasBad()) { | 549 | if (normalizer->lastTokenWasBad()) { |
| 561 | QTC::TC("qpdf", "QPDF_Stream bad token at end during normalize"); | 550 | QTC::TC("qpdf", "QPDF_Stream bad token at end during normalize"); |
| 562 | - warn(QPDFExc( | 551 | + warn( |
| 563 | qpdf_e_damaged_pdf, | 552 | qpdf_e_damaged_pdf, |
| 564 | - qpdf->getFilename(), | ||
| 565 | - "", | ||
| 566 | this->offset, | 553 | this->offset, |
| 567 | "normalized content ended with a bad token;" | 554 | "normalized content ended with a bad token;" |
| 568 | " you may be able to resolve this by" | 555 | " you may be able to resolve this by" |
| 569 | " coalescing content streams in combination" | 556 | " coalescing content streams in combination" |
| 570 | " with normalizing content. From the command" | 557 | " with normalizing content. From the command" |
| 571 | - " line, specify --coalesce-contents")); | 558 | + " line, specify --coalesce-contents"); |
| 572 | } | 559 | } |
| 573 | - warn(QPDFExc( | 560 | + warn( |
| 574 | qpdf_e_damaged_pdf, | 561 | qpdf_e_damaged_pdf, |
| 575 | - qpdf->getFilename(), | ||
| 576 | - "", | ||
| 577 | this->offset, | 562 | this->offset, |
| 578 | "Resulting stream data may be corrupted but is" | 563 | "Resulting stream data may be corrupted but is" |
| 579 | " may still useful for manual inspection." | 564 | " may still useful for manual inspection." |
| 580 | " For more information on this warning, search" | 565 | " For more information on this warning, search" |
| 581 | - " for content normalization in the manual.")); | 566 | + " for content normalization in the manual."); |
| 582 | } | 567 | } |
| 583 | 568 | ||
| 584 | return success; | 569 | return success; |
| @@ -645,7 +630,10 @@ QPDF_Stream::replaceDict(QPDFObjectHandle new_dict) | @@ -645,7 +630,10 @@ QPDF_Stream::replaceDict(QPDFObjectHandle new_dict) | ||
| 645 | } | 630 | } |
| 646 | 631 | ||
| 647 | void | 632 | void |
| 648 | -QPDF_Stream::warn(QPDFExc const& e) | 633 | +QPDF_Stream::warn( |
| 634 | + qpdf_error_code_e error_code, | ||
| 635 | + qpdf_offset_t offset, | ||
| 636 | + std::string const& message) | ||
| 649 | { | 637 | { |
| 650 | - this->qpdf->warn(e); | 638 | + this->qpdf->warn(error_code, "", offset, message); |
| 651 | } | 639 | } |
libqpdf/QPDF_encryption.cc
| @@ -803,12 +803,11 @@ QPDF::initializeEncryption() | @@ -803,12 +803,11 @@ QPDF::initializeEncryption() | ||
| 803 | // Treating a missing ID as the empty string enables qpdf to | 803 | // Treating a missing ID as the empty string enables qpdf to |
| 804 | // decrypt some invalid encrypted files with no /ID that | 804 | // decrypt some invalid encrypted files with no /ID that |
| 805 | // poppler can read but Adobe Reader can't. | 805 | // poppler can read but Adobe Reader can't. |
| 806 | - warn(QPDFExc( | 806 | + warn( |
| 807 | qpdf_e_damaged_pdf, | 807 | qpdf_e_damaged_pdf, |
| 808 | - this->m->file->getName(), | ||
| 809 | "trailer", | 808 | "trailer", |
| 810 | this->m->file->getLastOffset(), | 809 | this->m->file->getLastOffset(), |
| 811 | - "invalid /ID in trailer dictionary")); | 810 | + "invalid /ID in trailer dictionary"); |
| 812 | } | 811 | } |
| 813 | 812 | ||
| 814 | QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt"); | 813 | QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt"); |
| @@ -831,13 +830,12 @@ QPDF::initializeEncryption() | @@ -831,13 +830,12 @@ QPDF::initializeEncryption() | ||
| 831 | "unsupported encryption filter"); | 830 | "unsupported encryption filter"); |
| 832 | } | 831 | } |
| 833 | if (!encryption_dict.getKey("/SubFilter").isNull()) { | 832 | if (!encryption_dict.getKey("/SubFilter").isNull()) { |
| 834 | - warn(QPDFExc( | 833 | + warn( |
| 835 | qpdf_e_unsupported, | 834 | qpdf_e_unsupported, |
| 836 | - this->m->file->getName(), | ||
| 837 | "encryption dictionary", | 835 | "encryption dictionary", |
| 838 | this->m->file->getLastOffset(), | 836 | this->m->file->getLastOffset(), |
| 839 | "file uses encryption SubFilters," | 837 | "file uses encryption SubFilters," |
| 840 | - " which qpdf does not support")); | 838 | + " which qpdf does not support"); |
| 841 | } | 839 | } |
| 842 | 840 | ||
| 843 | if (!(encryption_dict.getKey("/V").isInteger() && | 841 | if (!(encryption_dict.getKey("/V").isInteger() && |
| @@ -1067,13 +1065,12 @@ QPDF::initializeEncryption() | @@ -1067,13 +1065,12 @@ QPDF::initializeEncryption() | ||
| 1067 | this->m->encp->encryption_key = recover_encryption_key_with_password( | 1065 | this->m->encp->encryption_key = recover_encryption_key_with_password( |
| 1068 | this->m->encp->provided_password, data, perms_valid); | 1066 | this->m->encp->provided_password, data, perms_valid); |
| 1069 | if (!perms_valid) { | 1067 | if (!perms_valid) { |
| 1070 | - warn(QPDFExc( | 1068 | + warn( |
| 1071 | qpdf_e_damaged_pdf, | 1069 | qpdf_e_damaged_pdf, |
| 1072 | - this->m->file->getName(), | ||
| 1073 | "encryption dictionary", | 1070 | "encryption dictionary", |
| 1074 | this->m->file->getLastOffset(), | 1071 | this->m->file->getLastOffset(), |
| 1075 | "/Perms field in encryption dictionary" | 1072 | "/Perms field in encryption dictionary" |
| 1076 | - " doesn't match expected value")); | 1073 | + " doesn't match expected value"); |
| 1077 | } | 1074 | } |
| 1078 | } | 1075 | } |
| 1079 | } | 1076 | } |
| @@ -1130,14 +1127,13 @@ QPDF::decryptString(std::string& str, int objid, int generation) | @@ -1130,14 +1127,13 @@ QPDF::decryptString(std::string& str, int objid, int generation) | ||
| 1130 | break; | 1127 | break; |
| 1131 | 1128 | ||
| 1132 | default: | 1129 | default: |
| 1133 | - warn(QPDFExc( | 1130 | + warn( |
| 1134 | qpdf_e_damaged_pdf, | 1131 | qpdf_e_damaged_pdf, |
| 1135 | - this->m->file->getName(), | ||
| 1136 | this->m->last_object_description, | 1132 | this->m->last_object_description, |
| 1137 | this->m->file->getLastOffset(), | 1133 | this->m->file->getLastOffset(), |
| 1138 | "unknown encryption filter for strings" | 1134 | "unknown encryption filter for strings" |
| 1139 | " (check /StrF in /Encrypt dictionary);" | 1135 | " (check /StrF in /Encrypt dictionary);" |
| 1140 | - " strings may be decrypted improperly")); | 1136 | + " strings may be decrypted improperly"); |
| 1141 | // To avoid repeated warnings, reset cf_string. Assume | 1137 | // To avoid repeated warnings, reset cf_string. Assume |
| 1142 | // we'd want to use AES if V == 4. | 1138 | // we'd want to use AES if V == 4. |
| 1143 | this->m->encp->cf_string = e_aes; | 1139 | this->m->encp->cf_string = e_aes; |
libqpdf/QPDF_optimization.cc
| @@ -266,15 +266,14 @@ QPDF::pushInheritedAttributesToPageInternal( | @@ -266,15 +266,14 @@ QPDF::pushInheritedAttributesToPageInternal( | ||
| 266 | "Pages object", | 266 | "Pages object", |
| 267 | cur_pages.getObjectID(), | 267 | cur_pages.getObjectID(), |
| 268 | cur_pages.getGeneration()); | 268 | cur_pages.getGeneration()); |
| 269 | - warn(QPDFExc( | 269 | + warn( |
| 270 | qpdf_e_pages, | 270 | qpdf_e_pages, |
| 271 | - this->m->file->getName(), | ||
| 272 | this->m->last_object_description, | 271 | this->m->last_object_description, |
| 273 | 0, | 272 | 0, |
| 274 | - "Unknown key " + key + | ||
| 275 | - " in /Pages object" | ||
| 276 | - " is being discarded as a result of" | ||
| 277 | - " flattening the /Pages tree")); | 273 | + ("Unknown key " + key + |
| 274 | + " in /Pages object" | ||
| 275 | + " is being discarded as a result of" | ||
| 276 | + " flattening the /Pages tree")); | ||
| 278 | } | 277 | } |
| 279 | } | 278 | } |
| 280 | } | 279 | } |
libqpdf/QPDF_pages.cc
| @@ -130,12 +130,11 @@ QPDF::getAllPagesInternal( | @@ -130,12 +130,11 @@ QPDF::getAllPagesInternal( | ||
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | if (!cur_node.isDictionaryOfType(wanted_type)) { | 132 | if (!cur_node.isDictionaryOfType(wanted_type)) { |
| 133 | - warn(QPDFExc( | 133 | + warn( |
| 134 | qpdf_e_damaged_pdf, | 134 | qpdf_e_damaged_pdf, |
| 135 | - this->m->file->getName(), | ||
| 136 | "page tree node", | 135 | "page tree node", |
| 137 | this->m->file->getLastOffset(), | 136 | this->m->file->getLastOffset(), |
| 138 | - "/Type key should be " + wanted_type + " but is not; overriding")); | 137 | + "/Type key should be " + wanted_type + " but is not; overriding"); |
| 139 | cur_node.replaceKey("/Type", QPDFObjectHandle::newName(wanted_type)); | 138 | cur_node.replaceKey("/Type", QPDFObjectHandle::newName(wanted_type)); |
| 140 | } | 139 | } |
| 141 | visited.erase(this_og); | 140 | visited.erase(this_og); |
libqpdf/qpdf/QPDF_Stream.hh
| @@ -90,7 +90,10 @@ class QPDF_Stream: public QPDFObject | @@ -90,7 +90,10 @@ class QPDF_Stream: public QPDFObject | ||
| 90 | std::vector<std::shared_ptr<QPDFStreamFilter>>& filters, | 90 | std::vector<std::shared_ptr<QPDFStreamFilter>>& filters, |
| 91 | bool& specialized_compression, | 91 | bool& specialized_compression, |
| 92 | bool& lossy_compression); | 92 | bool& lossy_compression); |
| 93 | - void warn(QPDFExc const& e); | 93 | + void warn( |
| 94 | + qpdf_error_code_e error_code, | ||
| 95 | + qpdf_offset_t offset, | ||
| 96 | + std::string const& message); | ||
| 94 | void setDictDescription(); | 97 | void setDictDescription(); |
| 95 | void setStreamDescription(); | 98 | void setStreamDescription(); |
| 96 | 99 |
qpdf/qtest/qpdf/split-content-stream-errors.out
| @@ -4,7 +4,7 @@ File is not encrypted | @@ -4,7 +4,7 @@ File is not encrypted | ||
| 4 | File is not linearized | 4 | File is not linearized |
| 5 | WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received | 5 | WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received |
| 6 | WARNING: split-content-stream-errors.pdf (offset 557): stream will be re-processed without filtering to avoid data loss | 6 | WARNING: split-content-stream-errors.pdf (offset 557): stream will be re-processed without filtering to avoid data loss |
| 7 | -WARNING: page object 3 0 (item index 0 (from 0)): ignoring non-stream in an array of streams | 7 | +WARNING: page object 3 0: item index 0 (from 0): ignoring non-stream in an array of streams |
| 8 | WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received | 8 | WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received |
| 9 | ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream | 9 | ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream |
| 10 | qpdf: errors detected | 10 | qpdf: errors detected |