1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <documentsignaturemanager.hxx>
21 #include <config_gpgme.h>
23 #include <gpg/SEInitializer.hxx>
25 #include <com/sun/star/embed/StorageFormats.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/embed/XStorage.hpp>
28 #include <com/sun/star/io/XTempFile.hpp>
29 #include <com/sun/star/io/XTruncate.hpp>
30 #include <com/sun/star/embed/XTransactedObject.hpp>
31 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/packages/manifest/ManifestReader.hpp>
35 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
36 #include <com/sun/star/xml/sax/XWriter.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
39 #include <comphelper/base64.hxx>
40 #include <comphelper/storagehelper.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <sal/log.hxx>
43 #include <tools/datetime.hxx>
44 #include <o3tl/string_view.hxx>
45 #include <svl/cryptosign.hxx>
47 #include <certificate.hxx>
48 #include <biginteger.hxx>
50 #include <xmlsec/xmlsec_init.hxx>
52 #include <pdfsignaturehelper.hxx>
57 using namespace css::graphic
;
58 using namespace css::uno
;
60 /// RAII class to init / shut down libxmlsec.
68 Xmlsec::Xmlsec() { initXmlSec(); }
70 Xmlsec::~Xmlsec() { deInitXmlSec(); }
74 /// Shared access to libxmlsec, to avoid double init.
77 static std::shared_ptr
<Xmlsec
>& get();
80 std::shared_ptr
<Xmlsec
>& XmlsecLibrary::get()
82 static std::shared_ptr
<Xmlsec
> pInstance
= std::make_shared
<Xmlsec
>();
87 DocumentSignatureManager::DocumentSignatureManager(
88 const uno::Reference
<uno::XComponentContext
>& xContext
, DocumentSignatureMode eMode
)
90 , maSignatureHelper(xContext
)
91 , meSignatureMode(eMode
)
95 DocumentSignatureManager::~DocumentSignatureManager() { mpXmlsecLibrary
.reset(); }
97 bool DocumentSignatureManager::init()
99 SAL_WARN_IF(mxSEInitializer
.is(), "xmlsecurity.helper",
100 "DocumentSignatureManager::Init - mxSEInitializer already set!");
101 SAL_WARN_IF(mxSecurityContext
.is(), "xmlsecurity.helper",
102 "DocumentSignatureManager::Init - mxSecurityContext already set!");
103 SAL_WARN_IF(mxGpgSEInitializer
.is(), "xmlsecurity.helper",
104 "DocumentSignatureManager::Init - mxGpgSEInitializer already set!");
106 // xmlsec is needed by both services, so init before those
107 mpXmlsecLibrary
= XmlsecLibrary::get();
109 mxSEInitializer
= xml::crypto::SEInitializer::create(mxContext
);
110 #if HAVE_FEATURE_GPGME
111 mxGpgSEInitializer
.set(new SEInitializerGpg());
114 if (mxSEInitializer
.is())
115 mxSecurityContext
= mxSEInitializer
->createSecurityContext(OUString());
117 #if HAVE_FEATURE_GPGME
118 if (mxGpgSEInitializer
.is())
119 mxGpgSecurityContext
= mxGpgSEInitializer
->createSecurityContext(OUString());
121 return mxSecurityContext
.is() || mxGpgSecurityContext
.is();
123 return mxSecurityContext
.is();
127 PDFSignatureHelper
& DocumentSignatureManager::getPDFSignatureHelper()
130 if (!mxSecurityContext
.is())
133 SAL_WARN_IF(!bInit
, "xmlsecurity.comp", "Error initializing security context!");
135 if (!mpPDFSignatureHelper
)
136 mpPDFSignatureHelper
= std::make_unique
<PDFSignatureHelper
>();
138 return *mpPDFSignatureHelper
;
141 #if 0 // For some reason does not work
142 bool DocumentSignatureManager::IsXAdESRelevant()
146 // ZIP-based: ODF or OOXML.
147 maSignatureHelper
.StartMission();
149 SignatureStreamHelper aStreamHelper
= ImplOpenSignatureStream(embed::ElementModes::READ
, /*bUseTempStream=*/true);
150 if (aStreamHelper
.nStorageFormat
== embed::StorageFormats::OFOPXML
)
152 maSignatureHelper
.EndMission();
155 // FIXME: How to figure out if it is ODF 1.2?
156 maSignatureHelper
.EndMission();
163 bool DocumentSignatureManager::readManifest()
165 // Check if manifest was already read
166 if (m_manifest
.hasElements())
175 uno::Reference
<packages::manifest::XManifestReader
> xReader
176 = packages::manifest::ManifestReader::create(mxContext
);
178 if (mxStore
->hasByName(u
"META-INF"_ustr
))
180 //Get the manifest.xml
181 uno::Reference
<embed::XStorage
> xSubStore(
182 mxStore
->openStorageElement(u
"META-INF"_ustr
, embed::ElementModes::READ
),
185 uno::Reference
<io::XInputStream
> xStream(
186 xSubStore
->openStreamElement(u
"manifest.xml"_ustr
, css::embed::ElementModes::READ
),
189 m_manifest
= xReader
->readManifestSequence(xStream
);
194 /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
195 We use the manifest to find out if a file is xml and if it is encrypted.
196 The parameter is an encoded uri. However, the manifest contains paths. Therefore
197 the path is encoded as uri, so they can be compared.
199 bool DocumentSignatureManager::isXML(std::u16string_view rURI
)
201 SAL_WARN_IF(!mxStore
.is(), "xmlsecurity.helper", "empty storage reference");
204 bool bPropsAvailable
= false;
205 static constexpr OUStringLiteral
sPropFullPath(u
"FullPath");
206 static constexpr OUStringLiteral
sPropMediaType(u
"MediaType");
207 static constexpr OUStringLiteral
sPropDigest(u
"Digest");
211 for (const uno::Sequence
<beans::PropertyValue
>& entry
: m_manifest
)
215 bool bEncrypted
= false;
216 for (const beans::PropertyValue
& prop
: entry
)
218 if (prop
.Name
== sPropFullPath
)
219 prop
.Value
>>= sPath
;
220 else if (prop
.Name
== sPropMediaType
)
221 prop
.Value
>>= sMediaType
;
222 else if (prop
.Name
== sPropDigest
)
225 if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI
, sPath
))
227 bIsXML
= sMediaType
== "text/xml" && !bEncrypted
;
228 bPropsAvailable
= true;
233 if (!bPropsAvailable
)
235 //This would be the case for at least mimetype, META-INF/manifest.xml
236 //META-INF/macrosignatures.xml.
237 //Files can only be encrypted if they are in the manifest.xml.
238 //That is, the current file cannot be encrypted, otherwise bPropsAvailable
240 size_t nSep
= rURI
.rfind('.');
241 if (nSep
!= std::u16string_view::npos
)
243 std::u16string_view aExt
= rURI
.substr(nSep
+ 1);
244 if (o3tl::equalsIgnoreAsciiCase(aExt
, u
"XML"))
251 //If bTempStream is true, then a temporary stream is return. If it is false then, the actual
252 //signature stream is used.
253 //Every time the user presses Add a new temporary stream is created.
254 //We keep the temporary stream as member because ImplGetSignatureInformations
255 //will later access the stream to create DocumentSignatureInformation objects
256 //which are stored in maCurrentSignatureInformations.
257 SignatureStreamHelper
DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode
,
260 SignatureStreamHelper aHelper
;
261 if (mxStore
.is() && mxStore
->hasByName(u
"[Content_Types].xml"_ustr
))
262 aHelper
.nStorageFormat
= embed::StorageFormats::OFOPXML
;
266 if (nStreamOpenMode
& embed::ElementModes::TRUNCATE
)
268 //We write always into a new temporary stream.
269 mxTempSignatureStream
= new utl::TempFileFastService
;
270 if (aHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
)
271 aHelper
.xSignatureStream
= mxTempSignatureStream
;
274 mxTempSignatureStorage
= comphelper::OStorageHelper::GetStorageOfFormatFromStream(
275 ZIP_STORAGE_FORMAT_STRING
, mxTempSignatureStream
);
276 aHelper
.xSignatureStorage
= mxTempSignatureStorage
;
281 //When we read from the temp stream, then we must have previously
283 SAL_WARN_IF(!mxTempSignatureStream
.is(), "xmlsecurity.helper",
284 "empty temp. signature stream reference");
286 aHelper
.xSignatureStream
= mxTempSignatureStream
;
287 if (aHelper
.nStorageFormat
== embed::StorageFormats::OFOPXML
)
288 aHelper
.xSignatureStorage
= mxTempSignatureStorage
;
292 //No temporary stream
293 if (!mxSignatureStream
.is())
295 //We may not have a dedicated stream for writing the signature
296 //So we take one directly from the storage
297 //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
298 //in which case Add/Remove is not allowed. This is done, for example, if the
299 //document is readonly
300 aHelper
= DocumentSignatureHelper::OpenSignatureStream(mxStore
, nStreamOpenMode
,
305 aHelper
.xSignatureStream
= mxSignatureStream
;
309 if (nStreamOpenMode
& embed::ElementModes::TRUNCATE
)
311 if (aHelper
.xSignatureStream
.is()
312 && aHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
)
314 uno::Reference
<io::XTruncate
> xTruncate(aHelper
.xSignatureStream
, uno::UNO_QUERY_THROW
);
315 xTruncate
->truncate();
318 else if (bTempStream
|| mxSignatureStream
.is())
320 //In case we read the signature stream from the storage directly,
321 //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
322 //then XSeakable is not supported
323 uno::Reference
<io::XSeekable
> xSeek(aHelper
.xSignatureStream
, uno::UNO_QUERY_THROW
);
330 bool DocumentSignatureManager::add(
331 svl::crypto::SigningContext
& rSigningContext
,
332 const uno::Reference
<xml::crypto::XXMLSecurityContext
>& xSecurityContext
,
333 const OUString
& rDescription
, sal_Int32
& nSecurityId
, bool bAdESCompliant
,
334 const OUString
& rSignatureLineId
, const Reference
<XGraphic
>& xValidGraphic
,
335 const Reference
<XGraphic
>& xInvalidGraphic
)
337 uno::Reference
<security::XCertificate
> xCert
= rSigningContext
.m_xCertificate
;
338 uno::Reference
<lang::XServiceInfo
> xServiceInfo(xSecurityContext
, uno::UNO_QUERY
);
340 && xServiceInfo
->getImplementationName()
341 == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
343 SAL_WARN("xmlsecurity.helper", "no certificate selected");
348 if (xServiceInfo
->getImplementationName()
349 == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
351 // GPG keys only really have PGPKeyId and PGPKeyPacket
354 SAL_WARN("xmlsecurity.helper", "cannot sign pdfs with GPG keys");
358 maSignatureHelper
.StartMission(xSecurityContext
);
360 nSecurityId
= maSignatureHelper
.GetNewSecurityId();
362 OUStringBuffer aStrBuffer
;
363 comphelper::Base64::encode(aStrBuffer
, xCert
->getEncoded());
366 if (auto pCertificate
= dynamic_cast<xmlsecurity::Certificate
*>(xCert
.get()))
368 OUStringBuffer aBuffer
;
369 comphelper::Base64::encode(aBuffer
, pCertificate
->getSHA256Thumbprint());
370 aKeyId
= aBuffer
.makeStringAndClear();
373 SAL_WARN("xmlsecurity.helper",
374 "XCertificate implementation without an xmlsecurity::Certificate one");
376 maSignatureHelper
.SetGpgCertificate(nSecurityId
, aKeyId
, aStrBuffer
.makeStringAndClear(),
377 xCert
->getIssuerName());
383 // Something not ZIP based, try PDF.
384 nSecurityId
= getPDFSignatureHelper().GetNewSecurityId();
385 getPDFSignatureHelper().SetX509Certificate(rSigningContext
);
386 getPDFSignatureHelper().SetDescription(rDescription
);
387 uno::Reference
<io::XInputStream
> xInputStream(mxSignatureStream
, uno::UNO_QUERY
);
388 if (!getPDFSignatureHelper().Sign(mxModel
, xInputStream
, bAdESCompliant
))
390 if (rSigningContext
.m_xCertificate
.is())
392 SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
399 OUString aCertSerial
= xmlsecurity::bigIntegerToNumericString(xCert
->getSerialNumber());
400 if (aCertSerial
.isEmpty())
402 SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
406 maSignatureHelper
.StartMission(xSecurityContext
);
408 nSecurityId
= maSignatureHelper
.GetNewSecurityId();
410 OUStringBuffer aStrBuffer
;
411 comphelper::Base64::encode(aStrBuffer
, xCert
->getEncoded());
413 OUString aCertDigest
;
414 svl::crypto::SignatureMethodAlgorithm eAlgorithmID
415 = svl::crypto::SignatureMethodAlgorithm::RSA
;
416 if (auto pCertificate
= dynamic_cast<xmlsecurity::Certificate
*>(xCert
.get()))
418 OUStringBuffer aBuffer
;
419 comphelper::Base64::encode(aBuffer
, pCertificate
->getSHA256Thumbprint());
420 aCertDigest
= aBuffer
.makeStringAndClear();
422 eAlgorithmID
= pCertificate
->getSignatureMethodAlgorithm();
425 SAL_WARN("xmlsecurity.helper",
426 "XCertificate implementation without an xmlsecurity::Certificate one");
428 maSignatureHelper
.SetX509Certificate(nSecurityId
, xCert
->getIssuerName(), aCertSerial
,
429 aStrBuffer
.makeStringAndClear(), aCertDigest
,
433 const uno::Sequence
<uno::Reference
<security::XCertificate
>> aCertPath
434 = xSecurityContext
->getSecurityEnvironment()->buildCertificatePath(xCert
);
436 OUStringBuffer aStrBuffer
;
437 for (uno::Reference
<security::XCertificate
> const& rxCertificate
: aCertPath
)
439 comphelper::Base64::encode(aStrBuffer
, rxCertificate
->getEncoded());
440 OUString aString
= aStrBuffer
.makeStringAndClear();
441 maSignatureHelper
.AddEncapsulatedX509Certificate(aString
);
444 std::vector
<OUString
> aElements
= DocumentSignatureHelper::CreateElementList(
445 mxStore
, meSignatureMode
, DocumentSignatureAlgorithm::OOo3_2
);
447 if (mxScriptingSignatureStream
.is())
449 aElements
.emplace_back(
451 + DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName());
452 std::sort(aElements
.begin(), aElements
.end());
455 DocumentSignatureHelper::AppendContentTypes(mxStore
, aElements
);
457 for (OUString
const& rUri
: aElements
)
459 bool bBinaryMode
= !isXML(rUri
);
460 maSignatureHelper
.AddForSigning(nSecurityId
, rUri
, bBinaryMode
, bAdESCompliant
);
463 maSignatureHelper
.SetDateTime(nSecurityId
, DateTime(DateTime::SYSTEM
));
464 maSignatureHelper
.SetDescription(nSecurityId
, rDescription
);
466 if (!rSignatureLineId
.isEmpty())
467 maSignatureHelper
.SetSignatureLineId(nSecurityId
, rSignatureLineId
);
469 if (xValidGraphic
.is())
470 maSignatureHelper
.SetSignatureLineValidGraphic(nSecurityId
, xValidGraphic
);
472 if (xInvalidGraphic
.is())
473 maSignatureHelper
.SetSignatureLineInvalidGraphic(nSecurityId
, xInvalidGraphic
);
475 // We open a signature stream in which the existing and the new
476 //signature is written. ImplGetSignatureInformation (later in this function) will
477 //then read the stream and fill maCurrentSignatureInformations. The final signature
478 //is written when the user presses OK. Then only maCurrentSignatureInformation and
479 //a sax writer are used to write the information.
480 SignatureStreamHelper aStreamHelper
481 = ImplOpenSignatureStream(embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
, true);
483 if (aStreamHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
)
485 uno::Reference
<io::XOutputStream
> xOutputStream(aStreamHelper
.xSignatureStream
,
486 uno::UNO_QUERY_THROW
);
487 uno::Reference
<xml::sax::XWriter
> xSaxWriter
488 = maSignatureHelper
.CreateDocumentHandlerWithHeader(xOutputStream
);
490 // Export old signatures...
491 uno::Reference
<xml::sax::XDocumentHandler
> xDocumentHandler(xSaxWriter
,
492 uno::UNO_QUERY_THROW
);
493 std::size_t nInfos
= maCurrentSignatureInformations
.size();
494 for (std::size_t n
= 0; n
< nInfos
; n
++)
495 XMLSignatureHelper::ExportSignature(xDocumentHandler
, maCurrentSignatureInformations
[n
],
498 // Create a new one...
499 maSignatureHelper
.CreateAndWriteSignature(xDocumentHandler
, bAdESCompliant
);
502 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler
);
509 maSignatureHelper
.EnsureSignaturesRelation(mxStore
, /*bAdd=*/true);
510 // Old signatures + the new one.
511 int nSignatureCount
= maCurrentSignatureInformations
.size() + 1;
512 maSignatureHelper
.ExportSignatureRelations(aStreamHelper
.xSignatureStorage
,
515 // Export old signatures.
516 for (std::size_t i
= 0; i
< maCurrentSignatureInformations
.size(); ++i
)
517 maSignatureHelper
.ExportOOXMLSignature(mxStore
, aStreamHelper
.xSignatureStorage
,
518 maCurrentSignatureInformations
[i
], i
+ 1);
520 // Create a new signature.
521 maSignatureHelper
.CreateAndWriteOOXMLSignature(mxStore
, aStreamHelper
.xSignatureStorage
,
525 uno::Reference
<embed::XTransactedObject
> xTransact(aStreamHelper
.xSignatureStorage
,
528 uno::Reference
<io::XOutputStream
> xOutputStream(aStreamHelper
.xSignatureStream
,
530 xOutputStream
->closeOutput();
532 uno::Reference
<io::XTempFile
> xTempFile(aStreamHelper
.xSignatureStream
, uno::UNO_QUERY
);
533 SAL_INFO("xmlsecurity.helper",
534 "DocumentSignatureManager::add temporary storage at " << xTempFile
->getUri());
537 maSignatureHelper
.EndMission();
541 void DocumentSignatureManager::remove(sal_uInt16 nPosition
)
545 // Something not ZIP based, try PDF.
546 uno::Reference
<io::XInputStream
> xInputStream(mxSignatureStream
, uno::UNO_QUERY
);
547 if (!PDFSignatureHelper::RemoveSignature(xInputStream
, nPosition
))
549 SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed");
553 // Only erase when the removal was successful, it may fail for PDF.
554 // Also, erase the requested and all following signatures, as PDF signatures are always chained.
555 maCurrentSignatureInformations
.erase(maCurrentSignatureInformations
.begin() + nPosition
,
556 maCurrentSignatureInformations
.end());
560 maCurrentSignatureInformations
.erase(maCurrentSignatureInformations
.begin() + nPosition
);
562 // Export all other signatures...
563 SignatureStreamHelper aStreamHelper
= ImplOpenSignatureStream(
564 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
, /*bTempStream=*/true);
566 if (aStreamHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
)
568 uno::Reference
<io::XOutputStream
> xOutputStream(aStreamHelper
.xSignatureStream
,
569 uno::UNO_QUERY_THROW
);
570 uno::Reference
<xml::sax::XWriter
> xSaxWriter
571 = maSignatureHelper
.CreateDocumentHandlerWithHeader(xOutputStream
);
573 uno::Reference
<xml::sax::XDocumentHandler
> xDocumentHandler(xSaxWriter
,
574 uno::UNO_QUERY_THROW
);
575 std::size_t nInfos
= maCurrentSignatureInformations
.size();
576 for (std::size_t n
= 0; n
< nInfos
; ++n
)
577 XMLSignatureHelper::ExportSignature(xDocumentHandler
, maCurrentSignatureInformations
[n
],
580 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler
);
587 int nSignatureCount
= maCurrentSignatureInformations
.size();
588 maSignatureHelper
.ExportSignatureRelations(aStreamHelper
.xSignatureStorage
,
591 // Export old signatures.
592 for (std::size_t i
= 0; i
< maCurrentSignatureInformations
.size(); ++i
)
593 maSignatureHelper
.ExportOOXMLSignature(mxStore
, aStreamHelper
.xSignatureStorage
,
594 maCurrentSignatureInformations
[i
], i
+ 1);
597 uno::Reference
<embed::XTransactedObject
> xTransact(aStreamHelper
.xSignatureStorage
,
600 uno::Reference
<io::XOutputStream
> xOutputStream(aStreamHelper
.xSignatureStream
,
602 xOutputStream
->closeOutput();
604 uno::Reference
<io::XTempFile
> xTempFile(aStreamHelper
.xSignatureStream
, uno::UNO_QUERY
);
605 SAL_INFO("xmlsecurity.helper", "DocumentSignatureManager::remove: temporary storage is at "
606 << xTempFile
->getUri());
610 void DocumentSignatureManager::read(bool bUseTempStream
, bool bCacheLastSignature
)
612 maCurrentSignatureInformations
.clear();
616 // ZIP-based: ODF or OOXML.
617 maSignatureHelper
.StartMission(mxSecurityContext
);
619 SignatureStreamHelper aStreamHelper
620 = ImplOpenSignatureStream(embed::ElementModes::READ
, bUseTempStream
);
621 if (aStreamHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
622 && aStreamHelper
.xSignatureStream
.is())
624 uno::Reference
<io::XInputStream
> xInputStream(aStreamHelper
.xSignatureStream
,
626 maSignatureHelper
.ReadAndVerifySignature(xInputStream
);
628 else if (aStreamHelper
.nStorageFormat
== embed::StorageFormats::OFOPXML
629 && aStreamHelper
.xSignatureStorage
.is())
630 maSignatureHelper
.ReadAndVerifySignatureStorage(aStreamHelper
.xSignatureStorage
,
631 bCacheLastSignature
);
632 maSignatureHelper
.EndMission();
634 // this parses the XML independently from ImplVerifySignatures() - check
635 // certificates here too ...
636 for (auto const& it
: maSignatureHelper
.GetSignatureInformations())
638 if (!it
.X509Datas
.empty())
640 uno::Reference
<xml::crypto::XSecurityEnvironment
> const xSecEnv(
641 getSecurityEnvironment());
642 getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv
, it
);
646 maCurrentSignatureInformations
= maSignatureHelper
.GetSignatureInformations();
650 // Something not ZIP based, try PDF.
651 uno::Reference
<io::XInputStream
> xInputStream(mxSignatureStream
, uno::UNO_QUERY
);
652 if (getPDFSignatureHelper().ReadAndVerifySignature(xInputStream
))
653 maCurrentSignatureInformations
= getPDFSignatureHelper().GetSignatureInformations();
657 void DocumentSignatureManager::write(bool bXAdESCompliantIfODF
)
661 // Something not ZIP based, assume PDF, which is written directly in add() already.
665 // Export all other signatures...
666 SignatureStreamHelper aStreamHelper
= ImplOpenSignatureStream(
667 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
, false);
669 if (aStreamHelper
.xSignatureStream
.is()
670 && aStreamHelper
.nStorageFormat
!= embed::StorageFormats::OFOPXML
)
673 uno::Reference
<io::XOutputStream
> xOutputStream(aStreamHelper
.xSignatureStream
,
675 uno::Reference
<xml::sax::XWriter
> xSaxWriter
676 = maSignatureHelper
.CreateDocumentHandlerWithHeader(xOutputStream
);
678 uno::Reference
<xml::sax::XDocumentHandler
> xDocumentHandler(xSaxWriter
,
679 uno::UNO_QUERY_THROW
);
680 std::size_t nInfos
= maCurrentSignatureInformations
.size();
681 for (std::size_t n
= 0; n
< nInfos
; ++n
)
682 XMLSignatureHelper::ExportSignature(xDocumentHandler
, maCurrentSignatureInformations
[n
],
683 bXAdESCompliantIfODF
);
685 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler
);
687 else if (aStreamHelper
.xSignatureStorage
.is()
688 && aStreamHelper
.nStorageFormat
== embed::StorageFormats::OFOPXML
)
691 std::size_t nSignatureCount
= maCurrentSignatureInformations
.size();
692 maSignatureHelper
.ExportSignatureContentTypes(mxStore
, nSignatureCount
);
693 if (nSignatureCount
> 0)
694 maSignatureHelper
.ExportSignatureRelations(aStreamHelper
.xSignatureStorage
,
698 // Removing all signatures: then need to remove the signature relation as well.
699 maSignatureHelper
.EnsureSignaturesRelation(mxStore
, /*bAdd=*/false);
700 // Also remove the whole signature sub-storage: release our read-write reference + remove the element.
701 aStreamHelper
= SignatureStreamHelper();
702 mxStore
->removeElement(u
"_xmlsignatures"_ustr
);
705 for (std::size_t i
= 0; i
< nSignatureCount
; ++i
)
706 maSignatureHelper
.ExportOOXMLSignature(mxStore
, aStreamHelper
.xSignatureStorage
,
707 maCurrentSignatureInformations
[i
], i
+ 1);
710 // If stream was not provided, we are responsible for committing it...
711 if (!mxSignatureStream
.is() && aStreamHelper
.xSignatureStorage
.is())
713 uno::Reference
<embed::XTransactedObject
> xTrans(aStreamHelper
.xSignatureStorage
,
719 uno::Reference
<xml::crypto::XSecurityEnvironment
> DocumentSignatureManager::getSecurityEnvironment()
721 return mxSecurityContext
.is() ? mxSecurityContext
->getSecurityEnvironment()
722 : uno::Reference
<xml::crypto::XSecurityEnvironment
>();
725 uno::Reference
<xml::crypto::XSecurityEnvironment
>
726 DocumentSignatureManager::getGpgSecurityEnvironment()
728 return mxGpgSecurityContext
.is() ? mxGpgSecurityContext
->getSecurityEnvironment()
729 : uno::Reference
<xml::crypto::XSecurityEnvironment
>();
732 uno::Reference
<xml::crypto::XXMLSecurityContext
> const&
733 DocumentSignatureManager::getSecurityContext() const
735 return mxSecurityContext
;
738 uno::Reference
<xml::crypto::XXMLSecurityContext
> const&
739 DocumentSignatureManager::getGpgSecurityContext() const
741 return mxGpgSecurityContext
;
744 void DocumentSignatureManager::setModel(const uno::Reference
<frame::XModel
>& xModel
)
749 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */