/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ #include #include #include #include namespace vcl::pdf { namespace { constexpr const char* constPadding = " " " " " " " " " " "\n"; } XmpMetadata::XmpMetadata() : mbWritten(false) , mnPDF_A(0) , mbPDF_UA(false) { } void XmpMetadata::write() { mpMemoryStream = std::make_unique(4096 /*Initial*/, 64 /*Resize*/); // Header mpMemoryStream->WriteOString(std::string_view(reinterpret_cast( u8"\n"))); { tools::XmlWriter aXmlWriter(mpMemoryStream.get()); aXmlWriter.startDocument(2, false); aXmlWriter.startElement("x"_ostr, "xmpmeta"_ostr, "adobe:ns:meta/"_ostr); aXmlWriter.startElement("rdf"_ostr, "RDF"_ostr, "http://www.w3.org/1999/02/22-rdf-syntax-ns#"_ostr); // PDF/A part ( ISO 19005-1:2005 - 6.7.11 ) if (mnPDF_A > 0) { OString sPdfVersion = OString::number(mnPDF_A); aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:pdfaid", "http://www.aiim.org/pdfa/ns/id/"_ostr); aXmlWriter.startElement("pdfaid:part"); aXmlWriter.content(sPdfVersion); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaid:conformance"); aXmlWriter.content("B"_ostr); aXmlWriter.endElement(); aXmlWriter.endElement(); } // Dublin Core properties if (!msTitle.isEmpty() || !msAuthor.isEmpty() || !msSubject.isEmpty() || !maContributor.empty() || !msCoverage.isEmpty() || !msIdentifier.isEmpty() || !maPublisher.empty() || !maRelation.empty() || !msRights.isEmpty() || !msSource.isEmpty() || !msType.isEmpty()) { aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"_ostr); aXmlWriter.startElement("dc:format"); aXmlWriter.content("application/pdf"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("dc:date"); aXmlWriter.startElement("rdf:Seq"); aXmlWriter.startElement("rdf:li"); aXmlWriter.content(m_sCreateDate); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); if (!msTitle.isEmpty()) { // this is according to PDF/A-1, technical corrigendum 1 (2007-04-01) aXmlWriter.startElement("dc:title"); aXmlWriter.startElement("rdf:Alt"); aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("xml:lang", "x-default"_ostr); aXmlWriter.content(msTitle); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!msAuthor.isEmpty()) { aXmlWriter.startElement("dc:creator"); aXmlWriter.startElement("rdf:Seq"); aXmlWriter.startElement("rdf:li"); aXmlWriter.content(msAuthor); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!msSubject.isEmpty()) { aXmlWriter.startElement("dc:description"); aXmlWriter.startElement("rdf:Alt"); aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("xml:lang", "x-default"_ostr); aXmlWriter.content(msSubject); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!maContributor.empty()) { aXmlWriter.startElement("dc:contributor"); aXmlWriter.startElement("rdf:Bag"); for (const OString& rContributor : maContributor) { aXmlWriter.startElement("rdf:li"); aXmlWriter.content(rContributor); aXmlWriter.endElement(); } aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!msCoverage.isEmpty()) { aXmlWriter.startElement("dc:coverage"); aXmlWriter.content(msCoverage); aXmlWriter.endElement(); } if (!msIdentifier.isEmpty()) { aXmlWriter.startElement("dc:identifier"); aXmlWriter.content(msIdentifier); aXmlWriter.endElement(); } if (!maPublisher.empty()) { aXmlWriter.startElement("dc:publisher"); aXmlWriter.startElement("rdf:Bag"); for (const OString& rPublisher : maPublisher) { aXmlWriter.startElement("rdf:li"); aXmlWriter.content(rPublisher); aXmlWriter.endElement(); } aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!maRelation.empty()) { aXmlWriter.startElement("dc:relation"); aXmlWriter.startElement("rdf:Bag"); for (const OString& rRelation : maRelation) { aXmlWriter.startElement("rdf:li"); aXmlWriter.content(rRelation); aXmlWriter.endElement(); } aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!msRights.isEmpty()) { aXmlWriter.startElement("dc:rights"); aXmlWriter.startElement("rdf:Alt"); aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("xml:lang", "x-default"_ostr); aXmlWriter.content(msRights); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); } if (!msSource.isEmpty()) { aXmlWriter.startElement("dc:source"); aXmlWriter.content(msSource); aXmlWriter.endElement(); } if (!msType.isEmpty()) { aXmlWriter.startElement("dc:type"); aXmlWriter.content(msType); aXmlWriter.endElement(); } aXmlWriter.endElement(); } // PDF/UA if (mbPDF_UA) { if (mnPDF_A != 0) { // tdf#157517 PDF/A extension schema is required aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:pdfaExtension", "http://www.aiim.org/pdfa/ns/extension/"_ostr); aXmlWriter.attribute("xmlns:pdfaSchema", "http://www.aiim.org/pdfa/ns/schema#"_ostr); aXmlWriter.attribute("xmlns:pdfaProperty", "http://www.aiim.org/pdfa/ns/property#"_ostr); aXmlWriter.startElement("pdfaExtension:schemas"); aXmlWriter.startElement("rdf:Bag"); aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("rdf:parseType", "Resource"_ostr); aXmlWriter.startElement("pdfaSchema:namespaceURI"); aXmlWriter.content("http://www.aiim.org/pdfua/ns/id/"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaSchema:prefix"); aXmlWriter.content("pdfuaid"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaSchema:schema"); aXmlWriter.content("PDF/UA identification schema"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaSchema:property"); aXmlWriter.startElement("rdf:Seq"); aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("rdf:parseType", "Resource"_ostr); aXmlWriter.startElement("pdfaProperty:category"); aXmlWriter.content("internal"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:description"); aXmlWriter.content("PDF/UA version identifier"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:name"); aXmlWriter.content("part"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:valueType"); aXmlWriter.content("Integer"_ostr); aXmlWriter.endElement(); aXmlWriter.endElement(); // rdf:li aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("rdf:parseType", "Resource"_ostr); aXmlWriter.startElement("pdfaProperty:category"); aXmlWriter.content("internal"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:description"); aXmlWriter.content("PDF/UA amendment identifier"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:name"); aXmlWriter.content("amd"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:valueType"); aXmlWriter.content("Text"_ostr); aXmlWriter.endElement(); aXmlWriter.endElement(); // rdf:li aXmlWriter.startElement("rdf:li"); aXmlWriter.attribute("rdf:parseType", "Resource"_ostr); aXmlWriter.startElement("pdfaProperty:category"); aXmlWriter.content("internal"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:description"); aXmlWriter.content("PDF/UA corrigenda identifier"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:name"); aXmlWriter.content("corr"_ostr); aXmlWriter.endElement(); aXmlWriter.startElement("pdfaProperty:valueType"); aXmlWriter.content("Text"_ostr); aXmlWriter.endElement(); aXmlWriter.endElement(); // rdf:li aXmlWriter.endElement(); // rdf:Seq aXmlWriter.endElement(); // pdfaSchema:property aXmlWriter.endElement(); // rdf:li aXmlWriter.endElement(); // rdf:Bag aXmlWriter.endElement(); // pdfaExtension:schemas aXmlWriter.endElement(); // rdf:Description } OString sPdfUaVersion = OString::number(1); aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:pdfuaid", "http://www.aiim.org/pdfua/ns/id/"_ostr); aXmlWriter.startElement("pdfuaid:part"); aXmlWriter.content(sPdfUaVersion); aXmlWriter.endElement(); aXmlWriter.endElement(); } // PDF properties if (!msProducer.isEmpty() || !msKeywords.isEmpty() || !msPDFVersion.isEmpty()) { aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:pdf", "http://ns.adobe.com/pdf/1.3/"_ostr); if (!msProducer.isEmpty()) { aXmlWriter.startElement("pdf:Producer"); aXmlWriter.content(msProducer); aXmlWriter.endElement(); } if (!msKeywords.isEmpty()) { aXmlWriter.startElement("pdf:Keywords"); aXmlWriter.content(msKeywords); aXmlWriter.endElement(); } if (!msPDFVersion.isEmpty()) { aXmlWriter.startElement("pdf:PDFVersion"); aXmlWriter.content(msPDFVersion); aXmlWriter.endElement(); } aXmlWriter.endElement(); } // XMP Basic schema aXmlWriter.startElement("rdf:Description"); aXmlWriter.attribute("rdf:about", ""_ostr); aXmlWriter.attribute("xmlns:xmp", "http://ns.adobe.com/xap/1.0/"_ostr); if (!m_sCreatorTool.isEmpty()) { aXmlWriter.startElement("xmp:CreatorTool"); aXmlWriter.content(m_sCreatorTool); aXmlWriter.endElement(); } aXmlWriter.startElement("xmp:CreateDate"); aXmlWriter.content(m_sCreateDate); aXmlWriter.endElement(); aXmlWriter.startElement("xmp:ModifyDate"); aXmlWriter.content(m_sCreateDate); aXmlWriter.endElement(); aXmlWriter.startElement("xmp:MetadataDate"); aXmlWriter.content(m_sCreateDate); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endElement(); aXmlWriter.endDocument(); } // add padding (needed so the metadata can be changed in-place" for (sal_Int32 nSpaces = 1; nSpaces <= 21; nSpaces++) mpMemoryStream->WriteOString(constPadding); mpMemoryStream->WriteOString("\n"); mbWritten = true; } sal_uInt64 XmpMetadata::getSize() { if (!mbWritten) write(); return mpMemoryStream->GetSize(); } const void* XmpMetadata::getData() { if (!mbWritten) write(); return mpMemoryStream->GetData(); } } // end vcl::pdf /* vim:set shiftwidth=4 softtabstop=4 expandtab: */