Commit d1f06c1a47e7381257e634d72a5df79d434776bc
Committed by
GitHub
Merge pull request #1622 from m-holger/tidy
Apply minor code and formatting fixes
Showing
12 changed files
with
62 additions
and
21 deletions
examples/pdf-custom-filter.cc
include/qpdf/QPDFFormFieldObjectHelper.hh
| @@ -111,7 +111,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper | @@ -111,7 +111,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper | ||
| 111 | std::string getDefaultAppearance(); | 111 | std::string getDefaultAppearance(); |
| 112 | 112 | ||
| 113 | // Return the default resource dictionary for the field. This comes not from the field but from | 113 | // Return the default resource dictionary for the field. This comes not from the field but from |
| 114 | - // the document-level /AcroForm dictionary. While several PDF generates put a /DR key in the | 114 | + // the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the |
| 115 | // form field's dictionary, experimentation suggests that many popular readers, including Adobe | 115 | // form field's dictionary, experimentation suggests that many popular readers, including Adobe |
| 116 | // Acrobat and Acrobat Reader, ignore any /DR item on the field. | 116 | // Acrobat and Acrobat Reader, ignore any /DR item on the field. |
| 117 | QPDF_DLL | 117 | QPDF_DLL |
| @@ -144,7 +144,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper | @@ -144,7 +144,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper | ||
| 144 | // Returns true if field is of type /Btn and flags indicate that it is a pushbutton | 144 | // Returns true if field is of type /Btn and flags indicate that it is a pushbutton |
| 145 | QPDF_DLL | 145 | QPDF_DLL |
| 146 | bool isPushbutton(); | 146 | bool isPushbutton(); |
| 147 | - // Returns true if fields if of type /Ch | 147 | + // Returns true if field is of type /Ch |
| 148 | QPDF_DLL | 148 | QPDF_DLL |
| 149 | bool isChoice(); | 149 | bool isChoice(); |
| 150 | // Returns choices display values as UTF-8 strings | 150 | // Returns choices display values as UTF-8 strings |
libqpdf/QPDFEmbeddedFileDocumentHelper.cc
| @@ -4,6 +4,8 @@ | @@ -4,6 +4,8 @@ | ||
| 4 | #include <qpdf/QPDFObjectHandle_private.hh> | 4 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 5 | #include <qpdf/QPDF_private.hh> | 5 | #include <qpdf/QPDF_private.hh> |
| 6 | 6 | ||
| 7 | +using namespace qpdf; | ||
| 8 | + | ||
| 7 | // File attachments are stored in the /EmbeddedFiles (name tree) key of the /Names dictionary from | 9 | // File attachments are stored in the /EmbeddedFiles (name tree) key of the /Names dictionary from |
| 8 | // the document catalog. Each entry points to a /FileSpec, which in turn points to one more Embedded | 10 | // the document catalog. Each entry points to a /FileSpec, which in turn points to one more Embedded |
| 9 | // File Streams. Note that file specs can appear in other places as well, such as file attachment | 11 | // File Streams. Note that file specs can appear in other places as well, such as file attachment |
libqpdf/QPDFFormFieldObjectHelper.cc
| @@ -605,7 +605,8 @@ FormNode::generateAppearance(QPDFAnnotationObjectHelper& aoh) | @@ -605,7 +605,8 @@ FormNode::generateAppearance(QPDFAnnotationObjectHelper& aoh) | ||
| 605 | { | 605 | { |
| 606 | // Ignore field types we don't know how to generate appearances for. Button fields don't really | 606 | // Ignore field types we don't know how to generate appearances for. Button fields don't really |
| 607 | // need them -- see code in QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded. | 607 | // need them -- see code in QPDFAcroFormDocumentHelper::generateAppearancesIfNeeded. |
| 608 | - if (FT() == "/Tx" || FT() == "/Ch") { | 608 | + auto ft = FT(); |
| 609 | + if (ft == "/Tx" || ft == "/Ch") { | ||
| 609 | generateTextAppearance(aoh); | 610 | generateTextAppearance(aoh); |
| 610 | } | 611 | } |
| 611 | } | 612 | } |
| @@ -914,6 +915,17 @@ FormNode::generateTextAppearance(QPDFAnnotationObjectHelper& aoh) | @@ -914,6 +915,17 @@ FormNode::generateTextAppearance(QPDFAnnotationObjectHelper& aoh) | ||
| 914 | } | 915 | } |
| 915 | 916 | ||
| 916 | if (AS.obj_sp().use_count() > 3) { | 917 | if (AS.obj_sp().use_count() > 3) { |
| 918 | + // The following check ensures that we only update the appearance stream if it is not | ||
| 919 | + // shared. The threshold of 3 is based on the current implementation details: | ||
| 920 | + // - One reference from the local variable AS | ||
| 921 | + // - One reference from the appearance dictionary (/AP) | ||
| 922 | + // - One reference from the object table | ||
| 923 | + // If use_count() is greater than 3, it means the appearance stream is shared elsewhere, | ||
| 924 | + // and updating it could have unintended side effects. This threshold may need to be updated | ||
| 925 | + // if the internal reference counting changes in the future. | ||
| 926 | + // The long-term solution will we to replace appearance streams at the point of flattening | ||
| 927 | + // annotations rather than attaching token filters that modify the streams at time of | ||
| 928 | + // writing. | ||
| 917 | aoh.warn("unable to generate text appearance from shared appearance stream for update"); | 929 | aoh.warn("unable to generate text appearance from shared appearance stream for update"); |
| 918 | return; | 930 | return; |
| 919 | } | 931 | } |
libqpdf/QPDFParser.cc
| @@ -172,7 +172,7 @@ QPDFParser::parse(bool content_stream) | @@ -172,7 +172,7 @@ QPDFParser::parse(bool content_stream) | ||
| 172 | } catch (std::logic_error& e) { | 172 | } catch (std::logic_error& e) { |
| 173 | throw e; | 173 | throw e; |
| 174 | } catch (std::exception& e) { | 174 | } catch (std::exception& e) { |
| 175 | - warn("treating object as null because of error during parsing : "s + e.what()); | 175 | + warn("treating object as null because of error during parsing: "s + e.what()); |
| 176 | return {}; | 176 | return {}; |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
libqpdf/QPDFWriter.cc
| @@ -2385,7 +2385,7 @@ impl::Writer::doWriteSetup() | @@ -2385,7 +2385,7 @@ impl::Writer::doWriteSetup() | ||
| 2385 | } | 2385 | } |
| 2386 | 2386 | ||
| 2387 | if (cfg.linearize() || encryption) { | 2387 | if (cfg.linearize() || encryption) { |
| 2388 | - // The document catalog is not allowed to be compressed in cfg.linearized_ files either. | 2388 | + // The document catalog is not allowed to be compressed in linearized files either. |
| 2389 | // It also appears that Adobe Reader 8.0.0 has a bug that prevents it from being able to | 2389 | // It also appears that Adobe Reader 8.0.0 has a bug that prevents it from being able to |
| 2390 | // handle encrypted files with compressed document catalogs, so we disable them in that | 2390 | // handle encrypted files with compressed document catalogs, so we disable them in that |
| 2391 | // case as well. | 2391 | // case as well. |
| @@ -2859,16 +2859,17 @@ impl::Writer::writeLinearized() | @@ -2859,16 +2859,17 @@ impl::Writer::writeLinearized() | ||
| 2859 | } | 2859 | } |
| 2860 | next_objid = part6_first_obj; | 2860 | next_objid = part6_first_obj; |
| 2861 | enqueuePart(part6); | 2861 | enqueuePart(part6); |
| 2862 | - if (next_objid != after_part6) { | ||
| 2863 | - throw std::runtime_error("error encountered after writing part 6 of linearized data"); | ||
| 2864 | - } | 2862 | + util::no_ci_rt_error_if( |
| 2863 | + next_objid != after_part6, "error encountered after writing part 6 of linearized data" // | ||
| 2864 | + ); | ||
| 2865 | next_objid = second_half_first_obj; | 2865 | next_objid = second_half_first_obj; |
| 2866 | enqueuePart(part7); | 2866 | enqueuePart(part7); |
| 2867 | enqueuePart(part8); | 2867 | enqueuePart(part8); |
| 2868 | enqueuePart(part9); | 2868 | enqueuePart(part9); |
| 2869 | - if (next_objid != after_second_half) { | ||
| 2870 | - throw std::runtime_error("error encountered after writing part 9 of cfg.linearized_ data"); | ||
| 2871 | - } | 2869 | + util::no_ci_rt_error_if( |
| 2870 | + next_objid != after_second_half, | ||
| 2871 | + "error encountered after writing part 9 of linearized data" // | ||
| 2872 | + ); | ||
| 2872 | 2873 | ||
| 2873 | qpdf_offset_t hint_length = 0; | 2874 | qpdf_offset_t hint_length = 0; |
| 2874 | std::string hint_buffer; | 2875 | std::string hint_buffer; |
libqpdf/QPDF_Dictionary.cc
| @@ -64,7 +64,7 @@ BaseHandle::contains(std::string const& key) const | @@ -64,7 +64,7 @@ BaseHandle::contains(std::string const& key) const | ||
| 64 | return !(*this)[key].null(); | 64 | return !(*this)[key].null(); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | -/// @brief Retrieves the value associated with the given key from dictionary. | 67 | +/// @brief Retrieves the value associated with the given key from a dictionary. |
| 68 | /// | 68 | /// |
| 69 | /// This method attempts to find the value corresponding to the specified key for objects that can | 69 | /// This method attempts to find the value corresponding to the specified key for objects that can |
| 70 | /// be interpreted as dictionaries. | 70 | /// be interpreted as dictionaries. |
| @@ -122,6 +122,19 @@ BaseHandle::erase(const std::string& key) | @@ -122,6 +122,19 @@ BaseHandle::erase(const std::string& key) | ||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | +/// @brief Replaces or removes the value associated with the given key in a dictionary. | ||
| 126 | +/// | ||
| 127 | +/// If the current object is a dictionary, this method updates the value at the specified key. | ||
| 128 | +/// If the value is a direct null object, the key is removed from the dictionary (since the PDF | ||
| 129 | +/// specification doesn't distinguish between keys with null values and missing keys). Indirect | ||
| 130 | +/// null values are preserved as they represent dangling references, which are permitted by the | ||
| 131 | +/// specification. | ||
| 132 | +/// | ||
| 133 | +/// @param key The key for which the value should be replaced. | ||
| 134 | +/// @param value The new value to associate with the key. If this is a direct null, the key is | ||
| 135 | +/// removed instead. | ||
| 136 | +/// @return Returns true if the operation was performed (i.e., the current object is a dictionary). | ||
| 137 | +/// Returns false if the current object is not a dictionary. | ||
| 125 | bool | 138 | bool |
| 126 | BaseHandle::replace(std::string const& key, QPDFObjectHandle value) | 139 | BaseHandle::replace(std::string const& key, QPDFObjectHandle value) |
| 127 | { | 140 | { |
| @@ -140,6 +153,20 @@ BaseHandle::replace(std::string const& key, QPDFObjectHandle value) | @@ -140,6 +153,20 @@ BaseHandle::replace(std::string const& key, QPDFObjectHandle value) | ||
| 140 | return false; | 153 | return false; |
| 141 | } | 154 | } |
| 142 | 155 | ||
| 156 | +/// @brief Replaces or removes the value associated with the given key in a dictionary. | ||
| 157 | +/// | ||
| 158 | +/// This method provides a stricter version of `BaseHandle::replace()` that throws an exception | ||
| 159 | +/// if the current object is not a dictionary, instead of silently returning false. It delegates | ||
| 160 | +/// to `BaseHandle::replace()` for the actual replacement logic. | ||
| 161 | +/// | ||
| 162 | +/// If the value is a direct null object, the key is removed from the dictionary (since the PDF | ||
| 163 | +/// specification doesn't distinguish between keys with null values and missing keys). Indirect | ||
| 164 | +/// null values are preserved as they represent dangling references. | ||
| 165 | +/// | ||
| 166 | +/// @param key The key for which the value should be replaced. | ||
| 167 | +/// @param value The new value to associate with the key. If this is a direct null, the key is | ||
| 168 | +/// removed instead. | ||
| 169 | +/// @throws std::runtime_error if the current object is not a dictionary. | ||
| 143 | void | 170 | void |
| 144 | BaseDictionary::replace(std::string const& key, QPDFObjectHandle value) | 171 | BaseDictionary::replace(std::string const& key, QPDFObjectHandle value) |
| 145 | { | 172 | { |
libqpdf/QPDF_objects.cc
| @@ -203,7 +203,7 @@ Objects::findHeader() | @@ -203,7 +203,7 @@ Objects::findHeader() | ||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | bool | 205 | bool |
| 206 | -Objects ::findStartxref() | 206 | +Objects::findStartxref() |
| 207 | { | 207 | { |
| 208 | if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) { | 208 | if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) { |
| 209 | // Position in front of offset token | 209 | // Position in front of offset token |
| @@ -1412,7 +1412,7 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | @@ -1412,7 +1412,7 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | ||
| 1412 | } | 1412 | } |
| 1413 | 1413 | ||
| 1414 | bool | 1414 | bool |
| 1415 | -Objects ::findEndstream() | 1415 | +Objects::findEndstream() |
| 1416 | { | 1416 | { |
| 1417 | // Find endstream or endobj. Position the input at that token. | 1417 | // Find endstream or endobj. Position the input at that token. |
| 1418 | auto t = readToken(*m->file, 20); | 1418 | auto t = readToken(*m->file, 20); |
libqpdf/qpdf/AcroForm.hh
| @@ -616,7 +616,7 @@ namespace qpdf::impl | @@ -616,7 +616,7 @@ namespace qpdf::impl | ||
| 616 | std::string default_appearance() const; | 616 | std::string default_appearance() const; |
| 617 | 617 | ||
| 618 | // Return the default resource dictionary for the field. This comes not from the field but | 618 | // Return the default resource dictionary for the field. This comes not from the field but |
| 619 | - // from the document-level /AcroForm dictionary. While several PDF generates put a /DR key | 619 | + // from the document-level /AcroForm dictionary. While several PDF generators put a /DR key |
| 620 | // in the form field's dictionary, experimentation suggests that many popular readers, | 620 | // in the form field's dictionary, experimentation suggests that many popular readers, |
| 621 | // including Adobe Acrobat and Acrobat Reader, ignore any /DR item on the field. | 621 | // including Adobe Acrobat and Acrobat Reader, ignore any /DR item on the field. |
| 622 | QPDFObjectHandle getDefaultResources(); | 622 | QPDFObjectHandle getDefaultResources(); |
| @@ -626,7 +626,7 @@ namespace qpdf::impl | @@ -626,7 +626,7 @@ namespace qpdf::impl | ||
| 626 | int getQuadding(); | 626 | int getQuadding(); |
| 627 | 627 | ||
| 628 | // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as | 628 | // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as |
| 629 | - // defined in qpdf/Constants.h// | 629 | + // defined in qpdf/Constants.h |
| 630 | int getFlags(); | 630 | int getFlags(); |
| 631 | 631 | ||
| 632 | // Methods for testing for particular types of form fields | 632 | // Methods for testing for particular types of form fields |
| @@ -646,7 +646,7 @@ namespace qpdf::impl | @@ -646,7 +646,7 @@ namespace qpdf::impl | ||
| 646 | // Returns true if field is of type /Btn and flags indicate that it is a pushbutton | 646 | // Returns true if field is of type /Btn and flags indicate that it is a pushbutton |
| 647 | bool isPushbutton(); | 647 | bool isPushbutton(); |
| 648 | 648 | ||
| 649 | - // Returns true if fields if of type /Ch | 649 | + // Returns true if field is of type /Ch |
| 650 | bool isChoice(); | 650 | bool isChoice(); |
| 651 | 651 | ||
| 652 | // Returns choices display values as UTF-8 strings | 652 | // Returns choices display values as UTF-8 strings |
libtests/objects.cc
| @@ -356,7 +356,7 @@ main(int argc, char* argv[]) | @@ -356,7 +356,7 @@ main(int argc, char* argv[]) | ||
| 356 | try { | 356 | try { |
| 357 | int n = QUtil::string_to_int(argv[1]); | 357 | int n = QUtil::string_to_int(argv[1]); |
| 358 | char const* filename1 = argv[2]; | 358 | char const* filename1 = argv[2]; |
| 359 | - char const* arg2 = argv[3]; | 359 | + char const* arg2 = (argc >= 4) ? argv[3] : ""; |
| 360 | runtest(n, filename1, arg2); | 360 | runtest(n, filename1, arg2); |
| 361 | } catch (std::exception& e) { | 361 | } catch (std::exception& e) { |
| 362 | std::cerr << e.what() << '\n'; | 362 | std::cerr << e.what() << '\n'; |
qpdf/qtest/qpdf/issue-150.out
| 1 | WARNING: issue-150.pdf: can't find PDF header | 1 | WARNING: issue-150.pdf: can't find PDF header |
| 2 | -WARNING: issue-150.pdf (xref stream: object 8 0, offset 56): treating object as null because of error during parsing : overflow/underflow converting 9900000000000000000 to 64-bit integer | 2 | +WARNING: issue-150.pdf (xref stream: object 8 0, offset 56): treating object as null because of error during parsing: overflow/underflow converting 9900000000000000000 to 64-bit integer |
| 3 | WARNING: issue-150.pdf: file is damaged | 3 | WARNING: issue-150.pdf: file is damaged |
| 4 | WARNING: issue-150.pdf (offset 4): xref not found | 4 | WARNING: issue-150.pdf (offset 4): xref not found |
| 5 | WARNING: issue-150.pdf: Attempting to reconstruct cross-reference table | 5 | WARNING: issue-150.pdf: Attempting to reconstruct cross-reference table |
qpdf/test_driver.cc
| @@ -17,7 +17,6 @@ | @@ -17,7 +17,6 @@ | ||
| 17 | #include <qpdf/QPDFJob.hh> | 17 | #include <qpdf/QPDFJob.hh> |
| 18 | #include <qpdf/QPDFNameTreeObjectHelper.hh> | 18 | #include <qpdf/QPDFNameTreeObjectHelper.hh> |
| 19 | #include <qpdf/QPDFNumberTreeObjectHelper.hh> | 19 | #include <qpdf/QPDFNumberTreeObjectHelper.hh> |
| 20 | -#include <qpdf/QPDFObjectHandle_private.hh> | ||
| 21 | #include <qpdf/QPDFOutlineDocumentHelper.hh> | 20 | #include <qpdf/QPDFOutlineDocumentHelper.hh> |
| 22 | #include <qpdf/QPDFPageDocumentHelper.hh> | 21 | #include <qpdf/QPDFPageDocumentHelper.hh> |
| 23 | #include <qpdf/QPDFPageLabelDocumentHelper.hh> | 22 | #include <qpdf/QPDFPageLabelDocumentHelper.hh> |
| @@ -27,6 +26,7 @@ | @@ -27,6 +26,7 @@ | ||
| 27 | #include <qpdf/QPDFWriter.hh> | 26 | #include <qpdf/QPDFWriter.hh> |
| 28 | #include <qpdf/QTC.hh> | 27 | #include <qpdf/QTC.hh> |
| 29 | #include <qpdf/QUtil.hh> | 28 | #include <qpdf/QUtil.hh> |
| 29 | +#include <qpdf/global.hh> | ||
| 30 | #include <climits> | 30 | #include <climits> |
| 31 | #include <cstdio> | 31 | #include <cstdio> |
| 32 | #include <cstdlib> | 32 | #include <cstdlib> |