27#include <com/sun/star/io/IOException.hpp>
28#include <com/sun/star/embed/XStorage.hpp>
29#include <com/sun/star/embed/StorageFormats.hpp>
30#include <com/sun/star/embed/ElementModes.hpp>
31#include <com/sun/star/beans/StringPair.hpp>
32#include <com/sun/star/beans/XPropertySet.hpp>
33#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
39#include <osl/diagnose.h>
51using namespace css::xml::sax;
55std::u16string_view getElement(std::u16string_view version,
size_t * index)
57 while (*index < version.size() && version[*index] ==
'0') {
67 std::u16string_view version1, std::u16string_view version2)
69 for (
size_t i1 = 0, i2 = 0; i1 != std::u16string_view::npos || i2 != std::u16string_view::npos;) {
70 std::u16string_view e1(getElement(version1, &i1));
71 std::u16string_view e2(getElement(version2, &i2));
72 if (e1.size() < e2.size()) {
74 }
else if (e1.size() > e2.size()) {
87 std::vector< OUString >& rList,
const Reference < css::embed::XStorage >& rxStore,
88 std::u16string_view rRootStorageName,
const bool bRecursive,
91 const Sequence< OUString > aElements = rxStore->getElementNames();
93 for (
const auto& rName : aElements )
95 if (rName ==
"[Content_Types].xml")
102 && (rName ==
"META-INF" || rName ==
"mimetype"))
108 OUString sEncName = ::rtl::Uri::encode(
109 rName, rtl_UriCharClassRelSegment,
110 rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8);
111 if (sEncName.isEmpty() && !rName.isEmpty())
112 throw css::uno::RuntimeException(
"Failed to encode element name of XStorage",
nullptr);
114 if ( rxStore->isStreamElement( rName ) )
120 OUString aFullName( rRootStorageName + sEncName );
121 rList.push_back(aFullName);
123 else if ( bRecursive && rxStore->isStorageElement( rName ) )
125 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ );
126 OUString aFullRootName( rRootStorageName + sEncName +
"/" );
153 OSL_ASSERT(!sODFVersion.empty());
180std::vector< OUString >
182 const Reference < css::embed::XStorage >& rxStore,
186 std::vector< OUString > aElements;
187 OUString aSep(
"/" );
199 OUString aSubStorageName(
"Pictures" );
202 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
204 aElements, xSubStore, Concat2View(aSubStorageName+aSep),
true, mode);
206 catch(css::io::IOException& )
211 aSubStorageName =
"ObjectReplacements";
214 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
216 aElements, xSubStore, Concat2View(aSubStorageName+aSep),
true, mode);
220 const Sequence< OUString > aElementNames = rxStore->getElementNames();
221 for (
const auto& rName : aElementNames )
223 if ( ( rName.match(
"Object " ) ) && rxStore->isStorageElement( rName ) )
225 Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ );
227 aElements, xTmpSubStore, Concat2View(rName+aSep),
true, mode);
231 catch( css::io::IOException& )
246 OUString aSubStorageName(
"Basic" );
249 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
251 aElements, xSubStore, Concat2View(aSubStorageName+aSep),
true, mode);
253 catch( css::io::IOException& )
259 aSubStorageName =
"Dialogs";
262 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
264 aElements, xSubStore, Concat2View(aSubStorageName+aSep),
true, mode);
266 catch( css::io::IOException& )
271 aSubStorageName =
"Scripts";
274 Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
276 aElements, xSubStore, Concat2View(aSubStorageName+aSep),
true, mode);
278 catch( css::io::IOException& )
297 if (!xStorage.is() || !xStorage->hasByName(
"[Content_Types].xml"))
301 uno::Reference<io::XInputStream> xRelStream(xStorage->openStreamElement(
"[Content_Types].xml", embed::ElementModes::READ), uno::UNO_QUERY);
303 if (aContentTypeInfo.getLength() < 2)
305 SAL_WARN(
"xmlsecurity.helper",
"no defaults or overrides in aContentTypeInfo");
308 const uno::Sequence<beans::StringPair>& rDefaults = aContentTypeInfo[0];
309 const uno::Sequence<beans::StringPair>& rOverrides = aContentTypeInfo[1];
311 for (OUString& rElement : rElements)
313 auto it = std::find_if(rOverrides.begin(), rOverrides.end(), [&](
const beans::StringPair& rPair)
315 return rPair.First == Concat2View(
"/" + rElement);
318 if (it != rOverrides.end())
320 rElement =
"/" + rElement +
"?ContentType=" + it->Second;
324 it = std::find_if(rDefaults.begin(), rDefaults.end(), [&](
const beans::StringPair& rPair)
326 return rElement.endsWith(Concat2View(
"." + rPair.First));
329 if (it != rDefaults.end())
331 rElement =
"/" + rElement +
"?ContentType=" + it->Second;
334 SAL_WARN(
"xmlsecurity.helper",
"found no content type for " << rElement);
337 std::sort(rElements.begin(), rElements.end());
341 const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode,
DocumentSignatureMode eDocSigMode )
343 sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ;
344 if ( nOpenMode & css::embed::ElementModes::WRITE )
345 nSubStorageOpenMode = css::embed::ElementModes::WRITE;
352 if (rxStore->hasByName(
"META-INF"))
356 aHelper.xSignatureStorage = rxStore->openStorageElement(
"META-INF", nSubStorageOpenMode );
357 if (
aHelper.xSignatureStorage.is() )
359 OUString aSIGStreamName;
369 =
aHelper.xSignatureStorage->openStreamElement(aSIGStreamName, nOpenMode);
371 "DocumentSignatureHelper::OpenSignatureStream: stream name is '"
372 << aSIGStreamName <<
"'");
373 if (
aHelper.xSignatureStream.is())
375 uno::Reference<io::XInputStream> xInputStream(
aHelper.xSignatureStream,
378 uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY);
379 xPropertySet->getPropertyValue(
"Size") >>= nSize;
380 if (nSize >= 0 || nSize < SAL_MAX_INT32)
382 uno::Sequence<sal_Int8>
aData;
383 xInputStream->readBytes(aData, nSize);
385 "DocumentSignatureHelper::OpenSignatureStream: stream content is '"
386 << OString(
reinterpret_cast<const char*
>(
aData.getArray()),
391 aHelper.xSignatureStream.clear();
394 aHelper.xSignatureStream =
aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode );
397 catch(css::io::IOException& )
400 SAL_WARN_IF( nOpenMode != css::embed::ElementModes::READ,
"xmlsecurity.helper",
"Error creating signature stream..." );
403 else if(rxStore->hasByName(
"[Content_Types].xml"))
407 if (rxStore->hasByName(
"_xmlsignatures") && (nOpenMode & embed::ElementModes::TRUNCATE))
409 rxStore->removeElement(
"_xmlsignatures");
411 aHelper.xSignatureStorage = rxStore->openStorageElement(
"_xmlsignatures", nSubStorageOpenMode);
412 aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
414 catch (
const io::IOException&)
416 TOOLS_WARN_EXCEPTION_IF(nOpenMode != css::embed::ElementModes::READ,
"xmlsecurity.helper",
"DocumentSignatureHelper::OpenSignatureStream:");
425 const Reference < css::embed::XStorage >& rxStore,
426 std::u16string_view sOdfVersion)
431 if (rxStore->hasByName(
"META-INF"))
447 const ::std::vector< OUString > & sElementList,
452 unsigned int nRealCount = 0;
453 std::function<OUString(
const OUString&)> fEncode = [](
const OUString& rStr) {
return rStr; };
458 fEncode = [](
const OUString& rStr) {
459 return rtl::Uri::encode(rStr, rtl_UriCharClassPchar, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8);
466 if ( ( rInf.
nType == SignatureReferenceType::BINARYSTREAM ) || ( rInf.
nType == SignatureReferenceType::XMLSTREAM ) )
469 if (std::any_of(sElementList.cbegin(), sElementList.cend(),
470 [&fEncode, &rInf](
const OUString& rElement) { return fEncode(rElement) == fEncode(rInf.ouURI); }))
474 return sElementList.size() == nRealCount;
482 std::u16string_view rUri, std::u16string_view rPath)
485 std::vector<OUString> vUriSegments;
489 std::vector<OUString> vPathSegments;
493 if (vUriSegments.size() != vPathSegments.size())
498 vUriSegments.cbegin(), vUriSegments.cend(), vPathSegments.cbegin(),
499 [](
const OUString& rUriSegment,
const OUString& rPathSegment) {
501 OUString sDecUri = rtl::Uri::decode(rUriSegment, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
502 return sDecUri == rPathSegment;
508 return "documentsignatures.xml";
513 return "macrosignatures.xml";
518 return "packagesignatures.xml";
522 const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
526 xDocumentHandler->startElement(
"DigestMethod", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
527 xDocumentHandler->endElement(
"DigestMethod");
531 uno::Reference<xml::sax::XDocumentHandler>
const& xDocumentHandler,
535 xDocumentHandler->startElement(
"xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
537 xDocumentHandler->startElement(
"DigestValue", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
539 xDocumentHandler->characters(rCertInfo.
CertDigest);
540 xDocumentHandler->endElement(
"DigestValue");
541 xDocumentHandler->endElement(
"xd:CertDigest");
542 xDocumentHandler->startElement(
"xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
543 xDocumentHandler->startElement(
"X509IssuerName", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
545 xDocumentHandler->endElement(
"X509IssuerName");
546 xDocumentHandler->startElement(
"X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
548 xDocumentHandler->endElement(
"X509SerialNumber");
549 xDocumentHandler->endElement(
"xd:IssuerSerial");
550 xDocumentHandler->endElement(
"xd:Cert");
554 const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler,
556 const OUString& sDate,
const bool bWriteSignatureLineData)
560 pAttributeList->AddAttribute(
"Id",
"idSignedProperties_" + signatureInfo.
ouSignatureId);
561 xDocumentHandler->startElement(
"xd:SignedProperties", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
564 xDocumentHandler->startElement(
"xd:SignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
565 xDocumentHandler->startElement(
"xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
566 xDocumentHandler->characters(sDate);
567 xDocumentHandler->endElement(
"xd:SigningTime");
568 xDocumentHandler->startElement(
"xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
574 for (
auto const& rData : signatureInfo.
X509Datas)
576 for (
auto const& it : rData)
589 xDocumentHandler->endElement(
"xd:SigningCertificate");
590 xDocumentHandler->startElement(
"xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
591 xDocumentHandler->startElement(
"xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(
new comphelper::AttributeList()));
592 xDocumentHandler->endElement(
"xd:SignaturePolicyImplied");
593 xDocumentHandler->endElement(
"xd:SignaturePolicyIdentifier");
599 pAttributeList->AddAttribute(
600 "xmlns:loext",
"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0");
601 xDocumentHandler->startElement(
602 "loext:SignatureLine",
603 Reference<XAttributeList>(pAttributeList));
607 xDocumentHandler->startElement(
608 "loext:SignatureLineId",
611 xDocumentHandler->endElement(
"loext:SignatureLineId");
616 xDocumentHandler->startElement(
617 "loext:SignatureLineValidImage",
620 OUString aGraphicInBase64;
623 SAL_WARN(
"xmlsecurity.helper",
"could not convert graphic to base64");
625 xDocumentHandler->characters(aGraphicInBase64);
626 xDocumentHandler->endElement(
"loext:SignatureLineValidImage");
631 xDocumentHandler->startElement(
632 "loext:SignatureLineInvalidImage",
634 OUString aGraphicInBase64;
637 SAL_WARN(
"xmlsecurity.helper",
"could not convert graphic to base64");
638 xDocumentHandler->characters(aGraphicInBase64);
639 xDocumentHandler->endElement(
"loext:SignatureLineInvalidImage");
642 xDocumentHandler->endElement(
"loext:SignatureLine");
645 xDocumentHandler->endElement(
"xd:SignedSignatureProperties");
647 xDocumentHandler->endElement(
"xd:SignedProperties");
static bool GraphicToBase64(const Graphic &rGraphic, OUString &rOUString, bool bAddPrefix=true, ConvertDataFormat aTargetFormat=ConvertDataFormat::Unknown)
#define TOOLS_WARN_EXCEPTION_IF(cond, area, stream)
constexpr OUStringLiteral ODFVER_012_TEXT
static void WriteXadesCert(uno::Reference< xml::sax::XDocumentHandler > const &xDocumentHandler, SignatureInformation::X509CertInfo const &rCertInfo)
static void ImplFillElementList(std::vector< OUString > &rList, const Reference< css::embed::XStorage > &rxStore, std::u16string_view rRootStorageName, const bool bRecursive, const DocumentSignatureAlgorithm mode)
DocumentSignatureAlgorithm
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
void writeDigestMethod(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocumentHandler)
OUString GetPackageSignatureDefaultStreamName()
void AppendContentTypes(const css::uno::Reference< css::embed::XStorage > &xStorage, std::vector< OUString > &rElements)
In case the storage is OOXML, prepend a leading '/' and append content type to the element URIs.
SignatureStreamHelper OpenSignatureStream(const css::uno::Reference< css::embed::XStorage > &rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode)
bool checkIfAllFilesAreSigned(const ::std::vector< OUString > &sElementList, const SignatureInformation &sigInfo, const DocumentSignatureAlgorithm alg)
void writeSignedProperties(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocumentHandler, const SignatureInformation &signatureInfo, const OUString &sDate, const bool bWriteSignatureLineData)
bool CanSignWithGPG(const css::uno::Reference< css::embed::XStorage > &rxStore, std::u16string_view sOdfVersion)
OUString GetDocumentContentSignatureDefaultStreamName()
bool equalsReferenceUriManifestPath(std::u16string_view rUri, std::u16string_view rPath)
DocumentSignatureAlgorithm getDocumentAlgorithm(std::u16string_view sODFVersion, const SignatureInformation &sigInfo)
bool isOOo3_2_Signature(const SignatureInformation &sigInfo)
std::vector< OUString > CreateElementList(const css::uno::Reference< css::embed::XStorage > &rxStore, DocumentSignatureMode eMode, const DocumentSignatureAlgorithm mode)
bool isODFPre_1_2(std::u16string_view sODFVersion)
OUString GetScriptingContentSignatureDefaultStreamName()
constexpr OUStringLiteral aData
uno::Sequence< uno::Sequence< beans::StringPair > > ReadContentTypeSequence(const uno::Reference< io::XInputStream > &xInStream, const uno::Reference< uno::XComponentContext > &rContext)
Reference< XComponentContext > getProcessComponentContext()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(std::u16string_view version1, std::u16string_view version2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
constexpr OUStringLiteral ALGO_XMLDSIGSHA256