diff --git a/PdfForQtLib/sources/pdfcatalog.cpp b/PdfForQtLib/sources/pdfcatalog.cpp index 9d4188a..6b5a7ce 100644 --- a/PdfForQtLib/sources/pdfcatalog.cpp +++ b/PdfForQtLib/sources/pdfcatalog.cpp @@ -211,6 +211,9 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume catalogObject.m_language = loader.readTextStringFromDictionary(catalogDictionary, "Lang", QString()); catalogObject.m_webCaptureInfo = PDFWebCaptureInfo::parse(catalogDictionary->get("SpiderInfo"), &document->getStorage()); catalogObject.m_outputIntents = loader.readObjectList(catalogDictionary->get("OutputIntents")); + catalogObject.m_pieceInfo = catalogDictionary->get("PieceInfo"); + catalogObject.m_perms = catalogDictionary->get("Perms"); + catalogObject.m_legalAttestation = PDFLegalAttestation::parse(&document->getStorage(), catalogDictionary->get("Legal")); return catalogObject; } @@ -824,4 +827,40 @@ PDFOutputIntentICCProfileInfo PDFOutputIntentICCProfileInfo::parse(const PDFObje return result; } +std::optional PDFLegalAttestation::parse(const PDFObjectStorage* storage, const PDFObject& object) +{ + std::optional result; + + if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object)) + { + PDFDocumentDataLoaderDecorator loader(storage); + + result = PDFLegalAttestation(); + + result->m_entries[JavaScriptActions] = loader.readIntegerFromDictionary(dictionary, "JavaScriptActions", 0); + result->m_entries[LaunchActions] = loader.readIntegerFromDictionary(dictionary, "LaunchActions", 0); + result->m_entries[URIActions] = loader.readIntegerFromDictionary(dictionary, "URIActions", 0); + result->m_entries[MovieActions] = loader.readIntegerFromDictionary(dictionary, "MovieActions", 0); + result->m_entries[SoundActions] = loader.readIntegerFromDictionary(dictionary, "SoundActions", 0); + result->m_entries[HideAnnotationActions] = loader.readIntegerFromDictionary(dictionary, "HideAnnotationActions", 0); + result->m_entries[GoToRemoteActions] = loader.readIntegerFromDictionary(dictionary, "GoToRemoteActions", 0); + result->m_entries[AlternateImages] = loader.readIntegerFromDictionary(dictionary, "AlternateImages", 0); + result->m_entries[ExternalStreams] = loader.readIntegerFromDictionary(dictionary, "ExternalStreams", 0); + result->m_entries[TrueTypeFonts] = loader.readIntegerFromDictionary(dictionary, "TrueTypeFonts", 0); + result->m_entries[ExternalRefXobjects] = loader.readIntegerFromDictionary(dictionary, "ExternalRefXobjects", 0); + result->m_entries[ExternalOPIdicts] = loader.readIntegerFromDictionary(dictionary, "ExternalOPIdicts", 0); + result->m_entries[NonEmbeddedFonts] = loader.readIntegerFromDictionary(dictionary, "NonEmbeddedFonts", 0); + result->m_entries[DevDepGS_OP] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_OP", 0); + result->m_entries[DevDepGS_HT] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_HT", 0); + result->m_entries[DevDepGS_TR] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_TR", 0); + result->m_entries[DevDepGS_UCR] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_UCR", 0); + result->m_entries[DevDepGS_BG] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_BG", 0); + result->m_entries[DevDepGS_FL] = loader.readIntegerFromDictionary(dictionary, "DevDepGS_FL", 0); + result->m_hasOptionalContent = loader.readBooleanFromDictionary(dictionary, "OptionalContent", false); + result->m_attestation = loader.readTextStringFromDictionary(dictionary, "Attestation", QString()); + } + + return result; +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfcatalog.h b/PdfForQtLib/sources/pdfcatalog.h index dba25c2..7fad208 100644 --- a/PdfForQtLib/sources/pdfcatalog.h +++ b/PdfForQtLib/sources/pdfcatalog.h @@ -403,6 +403,52 @@ private: PDFObject m_spectralData; }; +/// Legal attestations +class PDFFORQTLIBSHARED_EXPORT PDFLegalAttestation +{ +public: + explicit inline PDFLegalAttestation() = default; + + enum Entry + { + JavaScriptActions, + LaunchActions, + URIActions, + MovieActions, + SoundActions, + HideAnnotationActions, + GoToRemoteActions, + AlternateImages, + ExternalStreams, + TrueTypeFonts, + ExternalRefXobjects, + ExternalOPIdicts, + NonEmbeddedFonts, + DevDepGS_OP, + DevDepGS_HT, + DevDepGS_TR, + DevDepGS_UCR, + DevDepGS_BG, + DevDepGS_FL, + LastEntry + }; + + PDFInteger getEntry(Entry entry) const { return m_entries.at(entry); } + bool hasOptionalContent() const { return m_hasOptionalContent; } + const QString& getAttestationText() const { return m_attestation; } + + /// Parses legal attestation from object. If object cannot be parsed, or error occurs, + /// then no object is returned, no exception is thrown. + /// \param object Legal attestation dictionary + /// \param storage Storage + static std::optional parse(const PDFObjectStorage* storage, const PDFObject& object); + +private: + std::array m_entries = { }; + bool m_hasOptionalContent = false; + QString m_attestation; +}; + class PDFFORQTLIBSHARED_EXPORT PDFCatalog { public: @@ -464,6 +510,9 @@ public: const QString& getLanguage() const { return m_language; } const PDFWebCaptureInfo& getWebCaptureInfo() const { return m_webCaptureInfo; } const std::vector& getOutputIntents() const { return m_outputIntents; } + const PDFObject& getPieceInfo() const { return m_pieceInfo; } + const PDFObject& getPerms() const { return m_perms; } + const PDFLegalAttestation* getLegalAttestation() const { return m_legalAttestation.has_value() ? &m_legalAttestation.value() : nullptr; } /// Is document marked to have structure tree conforming to tagged document convention? bool isLogicalStructureMarked() const { return m_markInfoFlags.testFlag(MarkInfo_Marked); } @@ -516,6 +565,9 @@ private: QString m_language; PDFWebCaptureInfo m_webCaptureInfo; std::vector m_outputIntents; + PDFObject m_pieceInfo; + PDFObject m_perms; + std::optional m_legalAttestation; // Maps from Names dictionary std::map m_destinations;