diff --git a/libqpdf/QPDFAnnotationObjectHelper.cc b/libqpdf/QPDFAnnotationObjectHelper.cc index 573273c..ce2b12d 100644 --- a/libqpdf/QPDFAnnotationObjectHelper.cc +++ b/libqpdf/QPDFAnnotationObjectHelper.cc @@ -1,10 +1,12 @@ #include -#include #include +#include #include #include +using namespace qpdf; + QPDFAnnotationObjectHelper::QPDFAnnotationObjectHelper(QPDFObjectHandle oh) : QPDFObjectHelper(oh) { @@ -31,19 +33,15 @@ QPDFAnnotationObjectHelper::getAppearanceDictionary() std::string QPDFAnnotationObjectHelper::getAppearanceState() { - if (oh().getKey("/AS").isName()) { - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AS present"); - return oh().getKey("/AS").getName(); - } - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AS absent"); - return ""; + Name AS = (*this)["/AS"]; + return AS ? AS.value() : ""; } int QPDFAnnotationObjectHelper::getFlags() { - QPDFObjectHandle flags_obj = oh().getKey("/F"); - return flags_obj.isInteger() ? flags_obj.getIntValueAsInt() : 0; + Integer flags_obj = (*this)["/F"]; + return flags_obj ? flags_obj : 0; } QPDFObjectHandle diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index fe9ff1c..85a426a 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -10,6 +10,8 @@ #include #include +using namespace qpdf; + QPDFFormFieldObjectHelper::QPDFFormFieldObjectHelper(QPDFObjectHandle oh) : QPDFObjectHelper(oh), m(new Members()) @@ -98,9 +100,8 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const& n std::string QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const& name) { - auto fv = getInheritableFieldValue(name); - if (fv.isName()) { - return fv.getName(); + if (Name fv = getInheritableFieldValue(name)) { + return fv; } return {}; } @@ -245,7 +246,7 @@ QPDFFormFieldObjectHelper::isCheckbox() bool QPDFFormFieldObjectHelper::isChecked() { - return isCheckbox() && getValue().isName() && getValue().getName() != "/Off"; + return isCheckbox() && Name(getValue()) != "/Off"; } bool @@ -301,25 +302,25 @@ QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, std::string void QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) { + Name name = value; if (getFieldType() == "/Btn") { if (isCheckbox()) { - if (!value.isName()) { + if (!name) { warn("ignoring attempt to set a checkbox field to a value whose type is not name"); return; } - std::string name = value.getName(); // Accept any value other than /Off to mean checked. Files have been seen that use // /1 or other values. setCheckBoxValue(name != "/Off"); return; } if (isRadioButton()) { - if (!value.isName()) { + if (!name) { warn( "ignoring attempt to set a radio button field to an object that is not a name"); return; } - setRadioButtonValue(value); + setRadioButtonValue(name); return; } if (isPushbutton()) { @@ -743,17 +744,18 @@ QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& ao { QPDFObjectHandle AS = aoh.getAppearanceStream("/N"); if (AS.null()) { - QTC::TC("qpdf", "QPDFFormFieldObjectHelper create AS from scratch"); QPDFObjectHandle::Rectangle rect = aoh.getRect(); QPDFObjectHandle::Rectangle bbox(0, 0, rect.urx - rect.llx, rect.ury - rect.lly); - QPDFObjectHandle dict = QPDFObjectHandle::parse( - "<< /Resources << /ProcSet [ /PDF /Text ] >> /Type /XObject /Subtype /Form >>"); - dict.replaceKey("/BBox", QPDFObjectHandle::newFromRectangle(bbox)); + auto dict = Dictionary( + {{"/BBox", QPDFObjectHandle::newFromRectangle(bbox)}, + {"/Resources", Dictionary({{"/ProcSet", Array({Name("/PDF"), Name("/Text")})}})}, + {"/Type", Name("/XObject")}, + {"/Subtype", Name("/Form")}}); AS = QPDFObjectHandle::newStream(oh().getOwningQPDF(), "/Tx BMC\nEMC\n"); AS.replaceDict(dict); - QPDFObjectHandle AP = aoh.getAppearanceDictionary(); - if (AP.null()) { - aoh.getObjectHandle().replaceKey("/AP", QPDFObjectHandle::newDictionary()); + Dictionary AP = aoh.getAppearanceDictionary(); + if (!AP) { + aoh.getObjectHandle().replaceKey("/AP", Dictionary::empty()); AP = aoh.getAppearanceDictionary(); } AP.replaceKey("/N", AS); @@ -776,7 +778,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& ao std::string DA = getDefaultAppearance(); std::string V = getValueAsString(); std::vector opt; - if (isChoice() && ((getFlags() & ff_ch_combo) == 0)) { + if (isChoice() && (getFlags() & ff_ch_combo) == 0) { opt = getChoices(); } @@ -791,29 +793,26 @@ QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& ao std::string font_name = tff.getFontName(); if (!font_name.empty()) { // See if the font is encoded with something we know about. - QPDFObjectHandle resources = AS.getDict().getKey("/Resources"); - QPDFObjectHandle font = getFontFromResource(resources, font_name); - bool found_font_in_dr = false; + Dictionary resources = AS.getDict()["/Resources"]; + Dictionary font = getFontFromResource(resources, font_name); if (!font) { - QPDFObjectHandle dr = getDefaultResources(); - font = getFontFromResource(dr, font_name); - found_font_in_dr = font.isDictionary(); - } - if (found_font_in_dr && resources.isDictionary()) { - if (resources.isIndirect()) { - resources = resources.getQPDF().makeIndirectObject(resources.shallowCopy()); - AS.getDict().replaceKey("/Resources", resources); + font = getFontFromResource(getDefaultResources(), font_name); + if (resources) { + if (resources.indirect()) { + resources = resources.qpdf()->makeIndirectObject(resources.copy()); + AS.getDict().replaceKey("/Resources", resources); + } + // Use mergeResources to force /Font to be local + QPDFObjectHandle res = resources; + res.mergeResources(Dictionary({{"/Font", Dictionary::empty()}})); + res.getKey("/Font").replaceKey(font_name, font); } - // Use mergeResources to force /Font to be local - resources.mergeResources("<< /Font << >> >>"_qpdf); - resources.getKey("/Font").replaceKey(font_name, font); } - if (font.isDictionary() && font.getKey("/Encoding").isName()) { - std::string encoding = font.getKey("/Encoding").getName(); - if (encoding == "/WinAnsiEncoding") { + if (Name Encoding = font["/Encoding"]) { + if (Encoding == "/WinAnsiEncoding") { encoder = &QUtil::utf8_to_win_ansi; - } else if (encoding == "/MacRomanEncoding") { + } else if (Encoding == "/MacRomanEncoding") { encoder = &QUtil::utf8_to_mac_roman; } } diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 3dd04da..f3d909d 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -766,14 +766,14 @@ QPDFObjectHandle::isScalar() const bool QPDFObjectHandle::isNameAndEquals(std::string const& name) const { - return isName() && (getName() == name); + return Name(*this) == name; } bool QPDFObjectHandle::isDictionaryOfType(std::string const& type, std::string const& subtype) const { - return isDictionary() && (type.empty() || getKey("/Type").isNameAndEquals(type)) && - (subtype.empty() || getKey("/Subtype").isNameAndEquals(subtype)); + return isDictionary() && (type.empty() || Name((*this)["/Type"]) == type) && + (subtype.empty() || Name((*this)["/Subtype"]) == subtype); } bool @@ -952,7 +952,33 @@ QPDFObjectHandle::getValueAsReal(std::string& value) const return true; } -// Name accessors +// Name methods + +QPDFObjectHandle +QPDFObjectHandle::newName(std::string const& name) +{ + return {QPDFObject::create(name)}; +} + +Name::Name(std::string const& name) : + BaseHandle(QPDFObject::create(name)) +{ +} + +Name::Name(std::string&& name) : + BaseHandle(QPDFObject::create(std::move(name))) +{ +} + +std::string const& +Name::value() const +{ + auto* n = as(); + if (!n) { + throw invalid_error("Name"); + } + return n->name; +} std::string QPDFObjectHandle::getName() const @@ -961,7 +987,6 @@ QPDFObjectHandle::getName() const return obj->getStringValue(); } else { typeWarning("name", "returning dummy name"); - QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); return "/QPDFFakeName"; } } @@ -1695,12 +1720,6 @@ QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_z } QPDFObjectHandle -QPDFObjectHandle::newName(std::string const& name) -{ - return {QPDFObject::create(name)}; -} - -QPDFObjectHandle QPDFObjectHandle::newString(std::string const& str) { return {QPDFObject::create(str)}; diff --git a/libqpdf/QPDFOutlineObjectHelper.cc b/libqpdf/QPDFOutlineObjectHelper.cc index 4c3a2bf..0ae818e 100644 --- a/libqpdf/QPDFOutlineObjectHelper.cc +++ b/libqpdf/QPDFOutlineObjectHelper.cc @@ -48,26 +48,19 @@ QPDFOutlineObjectHelper::getKids() QPDFObjectHandle QPDFOutlineObjectHelper::getDest() { - QPDFObjectHandle dest; - QPDFObjectHandle A; - if (oh().hasKey("/Dest")) { - QTC::TC("qpdf", "QPDFOutlineObjectHelper direct dest"); - dest = oh().getKey("/Dest"); - } else if ( - (A = oh().getKey("/A")).isDictionary() && A.getKey("/S").isName() && - (A.getKey("/S").getName() == "/GoTo") && A.hasKey("/D")) { - QTC::TC("qpdf", "QPDFOutlineObjectHelper action dest"); - dest = A.getKey("/D"); + auto dest = (*this)["/Dest"]; + if (dest.null()) { + auto const& A = (*this)["/A"]; + if (Name(A["/S"]) == "/GoTo") { + dest = A["/D"]; + } } - if (!dest) { + if (dest.null()) { return QPDFObjectHandle::newNull(); } - if (dest.isName() || dest.isString()) { - QTC::TC("qpdf", "QPDFOutlineObjectHelper named dest"); - dest = m->dh.resolveNamedDest(dest); + return m->dh.resolveNamedDest(dest); } - return dest; } diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 73a9b38..558b542 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -38,11 +38,10 @@ namespace setDecodeParms(QPDFObjectHandle decode_parms) final { // we only validate here - processing happens in decryptStream - if (auto dict = decode_parms.as_dictionary(optional)) { + if (Dictionary dict = decode_parms) { for (auto const& [key, value]: dict) { if (key == "/Type" && - (value.null() || - (value.isName() && value.getName() == "/CryptFilterDecodeParms"))) { + (value.null() || Name(value) == "/CryptFilterDecodeParms")) { continue; } if (key == "/Name") { @@ -54,7 +53,7 @@ namespace } return true; } - return false; + return decode_parms.null(); } Pipeline* @@ -374,7 +373,7 @@ Stream::filterable( auto s = stream(); // Check filters - auto filter_obj = s->stream_dict.getKey("/Filter"); + auto const& filter_obj = s->stream_dict["/Filter"]; if (filter_obj.null()) { // No filters @@ -387,14 +386,14 @@ Stream::filterable( return false; } filters.emplace_back(ff()); - } else if (auto array = filter_obj.as_array(strict)) { + } else if (Array array = filter_obj) { // Potentially multiple filters - for (auto const& item: array) { - if (!item.isName()) { + for (Name item: array) { + if (!item) { warn("stream filter type is not name or array"); return false; } - auto ff = s->filter_factory(item.getName()); + auto ff = s->filter_factory(item); if (!ff) { filters.clear(); return false; diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 8be325a..5a7839d 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -600,18 +600,17 @@ QPDF::EncryptionData::recover_encryption_key_with_password( } QPDF::encryption_method_e -QPDF::EncryptionParameters::interpretCF(QPDFObjectHandle const& cf) const +QPDF::EncryptionParameters::interpretCF(Name const& cf) const { - if (!cf.isName()) { + if (!cf) { // Default: /Identity return e_none; } - std::string filter = cf.getName(); - auto it = crypt_filters.find(filter); + auto it = crypt_filters.find(cf); if (it != crypt_filters.end()) { return it->second; } - if (filter == "/Identity") { + if (cf == "/Identity") { return e_none; } return e_unknown; @@ -677,8 +676,7 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) throw qpdf.damagedPDF("/Encrypt in trailer dictionary is not a dictionary"); } - if (!(encryption_dict.getKey("/Filter").isName() && - (encryption_dict.getKey("/Filter").getName() == "/Standard"))) { + if (Name(encryption_dict["/Filter"]) != "/Standard") { throw unsupported("unsupported encryption filter"); } if (!encryption_dict.getKey("/SubFilter").null()) { @@ -766,16 +764,12 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) for (auto const& [filter, cdict]: CF.as_dictionary()) { if (cdict.isDictionary()) { encryption_method_e method = e_none; - if (cdict.getKey("/CFM").isName()) { - std::string method_name = cdict.getKey("/CFM").getName(); - if (method_name == "/V2") { - QTC::TC("qpdf", "QPDF_encryption CFM V2"); + if (Name const& CFM = cdict["/CFM"]) { + if (CFM == "/V2") { method = e_rc4; - } else if (method_name == "/AESV2") { - QTC::TC("qpdf", "QPDF_encryption CFM AESV2"); + } else if (CFM == "/AESV2") { method = e_aes; - } else if (method_name == "/AESV3") { - QTC::TC("qpdf", "QPDF_encryption CFM AESV3"); + } else if (CFM == "/AESV3") { method = e_aesv3; } else { // Don't complain now -- maybe we won't need to reference this type. @@ -786,9 +780,9 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) } } - cf_stream = interpretCF(encryption_dict.getKey("/StmF")); - cf_string = interpretCF(encryption_dict.getKey("/StrF")); - if (auto EFF = encryption_dict.getKey("/EFF"); EFF.isName()) { + cf_stream = interpretCF(encryption_dict["/StmF"]); + cf_string = interpretCF(encryption_dict["/StrF"]); + if (Name const& EFF = encryption_dict["/EFF"]) { // qpdf does not use this for anything other than informational purposes. This is // intended to instruct conforming writers on which crypt filter should be used when new // file attachments are added to a PDF file, but qpdf never generates encrypted files @@ -937,12 +931,7 @@ QPDF::decryptStream( bool is_root_metadata, std::unique_ptr& decrypt_pipeline) { - std::string type; - if (stream_dict.getKey("/Type").isName()) { - type = stream_dict.getKey("/Type").getName(); - } - if (type == "/XRef") { - QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file"); + if (Name(stream_dict["/Type"]) == "/XRef") { return; } bool use_aes = false; @@ -951,26 +940,20 @@ QPDF::decryptStream( std::string method_source = "/StmF from /Encrypt dictionary"; if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) { - if (stream_dict.getKey("/DecodeParms").isDictionary()) { - QPDFObjectHandle decode_parms = stream_dict.getKey("/DecodeParms"); - if (decode_parms.isDictionaryOfType("/CryptFilterDecodeParms")) { - QTC::TC("qpdf", "QPDF_encryption stream crypt filter"); - method = encp->interpretCF(decode_parms.getKey("/Name")); + if (Dictionary decode_parms = stream_dict["/DecodeParms"]) { + if (Name(decode_parms["/Type"]) == "/CryptFilterDecodeParms") { + method = encp->interpretCF(decode_parms["/Name"]); method_source = "stream's Crypt decode parameters"; } - } else if ( - stream_dict.getKey("/DecodeParms").isArray() && - stream_dict.getKey("/Filter").isArray()) { - auto filter = stream_dict.getKey("/Filter"); - auto decode = stream_dict.getKey("/DecodeParms"); + } else { + Array filter = stream_dict["/Filter"]; + Array decode = stream_dict.getKey("/DecodeParms"); if (filter.size() == decode.size()) { - int i = 0; - for (auto const& item: filter.as_array()) { - if (item.isNameAndEquals("/Crypt")) { - auto crypt_params = decode.getArrayItem(i); - if (crypt_params.isDictionary() && - crypt_params.getKey("/Name").isName()) { - method = encp->interpretCF(crypt_params.getKey("/Name")); + size_t i = 0; + for (Name item: filter) { + if (item == "/Crypt") { + if (Name name = decode[i]["/Name"]) { + method = encp->interpretCF(name); method_source = "stream's Crypt decode parameters (array)"; } break; @@ -982,8 +965,7 @@ QPDF::decryptStream( } if (method == e_unknown) { - if ((!encp->encrypt_metadata) && is_root_metadata) { - QTC::TC("qpdf", "QPDF_encryption cleartext metadata"); + if (!encp->encrypt_metadata && is_root_metadata) { method = e_none; } else { method = encp->cf_stream; @@ -1008,13 +990,13 @@ QPDF::decryptStream( default: // filter local to this stream. - qpdf_for_warning.warn(QPDFExc( - qpdf_e_damaged_pdf, - file->getName(), - "", - file->getLastOffset(), - "unknown encryption filter for streams (check " + method_source + - "); streams may be decrypted improperly")); + qpdf_for_warning.warn( + {qpdf_e_damaged_pdf, + file->getName(), + "", + file->getLastOffset(), + "unknown encryption filter for streams (check " + method_source + + "); streams may be decrypted improperly"}); // To avoid repeated warnings, reset cf_stream. Assume we'd want to use AES if V == 4. encp->cf_stream = e_aes; use_aes = true; @@ -1023,11 +1005,9 @@ QPDF::decryptStream( } std::string key = getKeyForObject(encp, og, use_aes); if (use_aes) { - QTC::TC("qpdf", "QPDF_encryption aes decode stream"); decrypt_pipeline = std::make_unique("AES stream decryption", pipeline, false, key); } else { - QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); decrypt_pipeline = std::make_unique("RC4 stream decryption", pipeline, key); } pipeline = decrypt_pipeline.get(); diff --git a/libqpdf/qpdf/QPDFObjectHandle_private.hh b/libqpdf/qpdf/QPDFObjectHandle_private.hh index c213f1b..cca454d 100644 --- a/libqpdf/qpdf/QPDFObjectHandle_private.hh +++ b/libqpdf/qpdf/QPDFObjectHandle_private.hh @@ -324,7 +324,7 @@ namespace qpdf { } - // Return the integer value. If the object is not a valid integer, throw a + // Return the integer value. If the object is not a valid Integer, throw a // std::invalid_argument exception. If the object is out of range for the target type, // throw a std::overflow_error or std::underflow_error exception. template @@ -391,6 +391,45 @@ namespace qpdf // escaping. Return {false, false} if the name is not valid utf-8, otherwise return {true, // true} if no characters require or {true, false} if escaping is required. static std::pair analyzeJSONEncoding(std::string const& name); + + Name() = default; + Name(Name const&) = default; + Name(Name&&) = default; + Name& operator=(Name const&) = default; + Name& operator=(Name&&) = default; + ~Name() = default; + + explicit Name(std::string const&); + explicit Name(std::string&&); + + Name(QPDFObjectHandle const& oh) : + BaseHandle(oh.type_code() == ::ot_name ? oh : QPDFObjectHandle()) + { + } + + Name(QPDFObjectHandle&& oh) : + BaseHandle(oh.type_code() == ::ot_name ? std::move(oh) : QPDFObjectHandle()) + { + } + + // Return the name value. If the object is not a valid Name, throw a + // std::invalid_argument exception. + operator std::string() const& + { + return value(); + } + + // Return the integer value. If the object is not a valid integer, throw a + // std::invalid_argument exception. + std::string const& value() const; + + // Return true if object value is equal to the 'rhs' value. Return false if the object is + // not a valid Name. + friend bool + operator==(Name const& lhs, std::string_view rhs) + { + return lhs && lhs.value() == rhs; + } }; class Stream final: public BaseHandle diff --git a/libqpdf/qpdf/QPDFObject_private.hh b/libqpdf/qpdf/QPDFObject_private.hh index 9dd4b92..03ccad9 100644 --- a/libqpdf/qpdf/QPDFObject_private.hh +++ b/libqpdf/qpdf/QPDFObject_private.hh @@ -28,6 +28,7 @@ namespace qpdf class BaseDictionary; class Dictionary; class Integer; + class Name; class Stream; } // namespace qpdf @@ -138,6 +139,7 @@ class QPDF_Name final { friend class QPDFObject; friend class qpdf::BaseHandle; + friend class qpdf::Name; explicit QPDF_Name(std::string name) : name(std::move(name)) diff --git a/libqpdf/qpdf/QPDF_private.hh b/libqpdf/qpdf/QPDF_private.hh index cd51ec2..19d9e3c 100644 --- a/libqpdf/qpdf/QPDF_private.hh +++ b/libqpdf/qpdf/QPDF_private.hh @@ -7,6 +7,8 @@ #include #include +using namespace qpdf; + // Writer class is restricted to QPDFWriter so that only it can call certain methods. class QPDF::Writer { @@ -204,7 +206,7 @@ class QPDF::EncryptionParameters } void initialize(QPDF& qpdf); - encryption_method_e interpretCF(QPDFObjectHandle const& cf) const; + encryption_method_e interpretCF(Name const& cf) const; private: bool encrypted{false}; diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 4fff849..db7c792 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -96,7 +96,6 @@ QPDF recovered stream length 0 QPDF found wrong endstream in recovery 0 QPDF_Stream pipeStreamData with null pipeline 0 QPDFWriter not recompressing /FlateDecode 0 -QPDF_encryption xref stream from encrypted file 0 QPDFJob unable to filter 0 QUtil non-trivial UTF-16 0 QPDF xref overwrite invalid objgen 0 @@ -141,18 +140,12 @@ qpdf-c called qpdf_set_minimum_pdf_version 0 qpdf-c called qpdf_force_pdf_version 0 qpdf-c called qpdf_init_write multiple times 0 QPDF_encryption rc4 decode string 0 -QPDF_encryption rc4 decode stream 0 QPDFWriter not compressing metadata 0 -QPDF_encryption CFM V2 0 -QPDF_encryption CFM AESV2 0 QPDF_encryption aes decode string 0 -QPDF_encryption cleartext metadata 0 -QPDF_encryption aes decode stream 0 QPDFWriter forcing object stream disable 0 QPDFWriter forced version disabled encryption 0 qpdf-c called qpdf_set_r4_encryption_parameters_insecure 0 qpdf-c called qpdf_set_static_aes_IV 0 -QPDF_encryption stream crypt filter 0 QPDF ERR object stream with wrong type 0 QPDF object gone after xref reconstruction 0 qpdf-c called qpdf_has_error 0 @@ -222,7 +215,6 @@ QPDFWriter remove ADBE 0 QPDFWriter remove existing Extensions 0 QPDFWriter preserve ADBE 0 QPDF_encryption skip 0x28 0 -QPDF_encryption CFM AESV3 0 qpdf-c called qpdf_get_pdf_extension_level 0 qpdf-c called qpdf_set_r5_encryption_parameters 0 qpdf-c called qpdf_set_r6_encryption_parameters 0 @@ -275,7 +267,6 @@ QPDFParser eof in parse 0 QPDFParser eof in parseRemainder 0 QPDFObjectHandle boolean returning false 0 QPDFObjectHandle real returning 0.0 0 -QPDFObjectHandle name returning dummy name 0 QPDFObjectHandle string returning empty string 0 QPDFObjectHandle string returning empty utf8 0 QPDFObjectHandle operator returning fake value 0 @@ -301,8 +292,6 @@ QPDFFormFieldObjectHelper TU absent 0 QPDFFormFieldObjectHelper TM absent 0 QPDFFormFieldObjectHelper Q present 1 QPDFFormFieldObjectHelper DA present 1 -QPDFAnnotationObjectHelper AS present 0 -QPDFAnnotationObjectHelper AS absent 0 QPDFAnnotationObjectHelper AP stream 0 QPDFAnnotationObjectHelper AP dictionary 0 QPDFAnnotationObjectHelper AP sub stream 0 @@ -317,9 +306,6 @@ QPDFAcroFormDocumentHelper annotation found 1 QPDFJob keep files open n 0 QPDFJob keep files open y 0 QPDFJob automatically set keep files open 1 -QPDFOutlineObjectHelper direct dest 0 -QPDFOutlineObjectHelper action dest 0 -QPDFOutlineObjectHelper named dest 0 QPDFOutlineDocumentHelper string named dest 0 QPDFObjectHandle merge top type mismatch 0 QPDFObjectHandle merge shallow copy 0 @@ -366,7 +352,6 @@ QPDFJob bytes fallback warning 0 QPDFJob invalid utf-8 in auto 0 QPDFJob input password hex-bytes 0 QPDFPageDocumentHelper ignore annotation with no appearance 0 -QPDFFormFieldObjectHelper create AS from scratch 0 QPDFFormFieldObjectHelper replaced BMC at EOF 0 QPDFFormFieldObjectHelper fallback Tf 0 QPDFPageObjectHelper copy shared attribute 1