[Libreoffice-commits] core.git: 2 commits - xmlsecurity/inc xmlsecurity/Library_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Feb 15 16:25:46 UTC 2016


 xmlsecurity/Library_xmlsecurity.mk                      |    1 
 xmlsecurity/inc/documentsignaturemanager.hxx            |   62 ++
 xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx |   17 
 xmlsecurity/qa/unit/signing/signing.cxx                 |   84 ----
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx  |  336 ++--------------
 xmlsecurity/source/helper/documentsignaturemanager.cxx  |  296 ++++++++++++++
 6 files changed, 424 insertions(+), 372 deletions(-)

New commits:
commit 0d6328164e32dc8b5cd47e27bfcc2e2f6f906799
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Feb 15 17:05:00 2016 +0100

    CppunitTest_xmlsecurity_signing: use DocumentSignatureManager
    
    Change-Id: I97acb4a2e9aedb15671d65f6995faeab4ff5716f

diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index 7d85750..6f2249c 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -18,6 +18,7 @@
 #include <com/sun/star/security/SerialNumberAdapter.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
 #include <com/sun/star/io/TempFile.hpp>
+#include <com/sun/star/packages/manifest/ManifestReader.hpp>
 
 #include <comphelper/processfactory.hxx>
 #include <sax/tools/converter.hxx>
@@ -33,6 +34,7 @@
 
 #include <xmlsecurity/documentsignaturehelper.hxx>
 #include <xmlsecurity/xmlsignaturehelper.hxx>
+#include <documentsignaturemanager.hxx>
 
 using namespace com::sun::star;
 
@@ -67,8 +69,6 @@ public:
 private:
     void createDoc(const OUString& rURL = OUString());
     uno::Reference<security::XCertificate> getCertificate(XMLSignatureHelper& rSignatureHelper);
-    void sign(utl::TempFile& rTempFile, XMLSignatureHelper& rSignatureHelper, const uno::Reference<io::XOutputStream>& xOutputStream);
-    std::vector<SignatureInformation> verify(XMLSignatureHelper& rSignatureHelper, const uno::Reference<io::XInputStream>& xInputStream);
 };
 
 SigningTest::SigningTest()
@@ -119,58 +119,11 @@ uno::Reference<security::XCertificate> SigningTest::getCertificate(XMLSignatureH
     return xSecurityEnvironment->createCertificateFromAscii(aCertificate);
 }
 
-void SigningTest::sign(utl::TempFile& rTempFile, XMLSignatureHelper& rSignatureHelper, const uno::Reference<io::XOutputStream>& xOutputStream)
-{
-    CPPUNIT_ASSERT(rSignatureHelper.Init());
-
-    SvStream* pStream = utl::UcbStreamHelper::CreateStream(rTempFile.GetURL(), StreamMode::READ);
-    uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream));
-    uno::Reference<embed::XStorage> xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(ZIP_STORAGE_FORMAT_STRING, xStream);
-    CPPUNIT_ASSERT(xStorage.is());
-
-    rSignatureHelper.SetStorage(xStorage, "1.2");
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(rSignatureHelper);
-    CPPUNIT_ASSERT(xCertificate.is());
-
-    uno::Reference<security::XSerialNumberAdapter> xSerialNumberAdapter = security::SerialNumberAdapter::create(mxComponentContext);
-    OUString aCertSerial = xSerialNumberAdapter->toString(xCertificate->getSerialNumber());
-    CPPUNIT_ASSERT(!aCertSerial.isEmpty());
-
-    rSignatureHelper.StartMission();
-    sal_Int32 nSecurityId = rSignatureHelper.GetNewSecurityId();
-    OUStringBuffer aStrBuffer;
-    sax::Converter::encodeBase64(aStrBuffer, xCertificate->getEncoded());
-    rSignatureHelper.SetX509Certificate(nSecurityId, xCertificate->getIssuerName(), aCertSerial, aStrBuffer.makeStringAndClear());
-    DocumentSignatureMode eSignatureMode = SignatureModeDocumentContent;
-    std::vector<OUString> aElements = DocumentSignatureHelper::CreateElementList(xStorage, eSignatureMode, OOo3_2Document);
-    for (size_t i = 0; i < aElements.size(); ++i)
-    {
-        bool bBinaryMode = aElements[i].startsWith("Thumbnails/");
-        rSignatureHelper.AddForSigning(nSecurityId, aElements[i], aElements[i], bBinaryMode);
-    }
-    rSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
-    rSignatureHelper.SetDescription(nSecurityId, "SigningTest::sign");
-
-    uno::Reference<xml::sax::XWriter> xWriter = rSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
-    uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xWriter, uno::UNO_QUERY);
-    CPPUNIT_ASSERT(rSignatureHelper.CreateAndWriteSignature(xDocumentHandler));
-    XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
-
-    rSignatureHelper.EndMission();
-}
-
-std::vector<SignatureInformation> SigningTest::verify(XMLSignatureHelper& rSignatureHelper, const uno::Reference<io::XInputStream>& xInputStream)
-{
-    rSignatureHelper.StartMission();
-    rSignatureHelper.ReadAndVerifySignature(xInputStream);
-    rSignatureHelper.EndMission();
-    return rSignatureHelper.GetSignatureInformations();
-}
-
 void SigningTest::testDescription()
 {
-    // Create an empty document and store it to a tempfile.
+    // Create an empty document and store it to a tempfile, finally load it as a storage.
     createDoc();
+
     utl::TempFile aTempFile;
     aTempFile.EnableKillingFile();
     uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
@@ -178,22 +131,25 @@ void SigningTest::testDescription()
     aMediaDescriptor["FilterName"] <<= OUString("writer8");
     xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
 
-    // Then sign the document, and store the signature it a second tempfile, so we don't write to the original storage when we read it as well.
-    XMLSignatureHelper aSignatureHelper(mxComponentContext);
-    uno::Reference<io::XStream> xSignatureStream(io::TempFile::create(mxComponentContext), uno::UNO_QUERY);
-    uno::Reference<io::XOutputStream> xOutputStream(xSignatureStream, uno::UNO_QUERY);
-    sign(aTempFile, aSignatureHelper, xOutputStream);
+    DocumentSignatureManager aManager(mxComponentContext, SignatureModeDocumentContent);
+    CPPUNIT_ASSERT(aManager.maSignatureHelper.Init());
+    uno::Reference <embed::XStorage> xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+    CPPUNIT_ASSERT(xStorage.is());
+    aManager.mxStore = xStorage;
+    aManager.maSignatureHelper.SetStorage(xStorage, "1.2");
 
-    // Go back to the start of the signature.
-    uno::Reference<io::XSeekable> xSeekable(xSignatureStream, uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xSeekable->getPosition() != 0);
-    xSeekable->seek(0);
+    // Then add a signature document.
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager.maSignatureHelper);
+    CPPUNIT_ASSERT(xCertificate.is());
+    OUString aDescription("SigningTest::testDescription");
+    sal_Int32 nSecurityId;
+    aManager.add(xCertificate, aDescription, nSecurityId);
 
     // Read back the signature and make sure that the description survives the roundtrip.
-    uno::Reference<io::XInputStream> xInputStream(xSignatureStream, uno::UNO_QUERY);
-    std::vector<SignatureInformation> aSignatureInformations = verify(aSignatureHelper, xInputStream);
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aSignatureInformations.size());
-    CPPUNIT_ASSERT_EQUAL(OUString("SigningTest::sign"), aSignatureInformations[0].ouDescription);
+    aManager.read(/*bUseTempStream=*/true);
+    std::vector<SignatureInformation>& rInformations = aManager.maCurrentSignatureInformations;
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rInformations.size());
+    CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription);
 }
 
 void SigningTest::testOOXMLPartial()
commit 565346a4fe0a074807381c2d8ea48242e9e69f4f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Feb 15 11:38:23 2016 +0100

    xmlsecurity: factor out DocumentSignatureManager from DigitalSignaturesDialog
    
    It's hard to unit test signing when the logic is implemented in the Add
    and OK button handlers.
    
    Change-Id: I5e07df69cd808cf170e21dfd55f2f44bc79c58a8

diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index ecbade5..c594ec9 100644
--- a/xmlsecurity/Library_xmlsecurity.mk
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -54,6 +54,7 @@ $(eval $(call gb_Library_add_exception_objects,xmlsecurity,\
 	xmlsecurity/source/dialogs/macrosecurity \
 	xmlsecurity/source/dialogs/resourcemanager \
 	xmlsecurity/source/helper/documentsignaturehelper \
+	xmlsecurity/source/helper/documentsignaturemanager \
 	xmlsecurity/source/helper/ooxmlsecparser \
 	xmlsecurity/source/helper/xmlsignaturehelper2 \
 	xmlsecurity/source/helper/xmlsignaturehelper \
diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx
new file mode 100644
index 0000000..6719c26
--- /dev/null
+++ b/xmlsecurity/inc/documentsignaturemanager.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX
+#define INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX
+
+#include "xmlsecuritydllapi.h"
+#include <xmlsecurity/sigstruct.hxx>
+#include <xmlsecurity/xmlsignaturehelper.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <xmlsecurity/documentsignaturehelper.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+/// Manages signatures (addition, removal), used by DigitalSignaturesDialog.
+class XMLSECURITY_DLLPUBLIC DocumentSignatureManager
+{
+public:
+    css::uno::Reference<css::uno::XComponentContext> mxContext;
+    css::uno::Reference<css::embed::XStorage> mxStore;
+    XMLSignatureHelper maSignatureHelper;
+    SignatureInformations maCurrentSignatureInformations;
+    DocumentSignatureMode meSignatureMode;
+    css::uno::Sequence< css::uno::Sequence<css::beans::PropertyValue> > m_manifest;
+    css::uno::Reference<css::io::XStream> mxSignatureStream;
+    css::uno::Reference<css::io::XStream> mxTempSignatureStream;
+    /// Storage containing all OOXML signatures, unused for ODF.
+    css::uno::Reference<css::embed::XStorage> mxTempSignatureStorage;
+
+    DocumentSignatureManager(const css::uno::Reference<css::uno::XComponentContext>& xContext, DocumentSignatureMode eMode);
+    ~DocumentSignatureManager();
+    /**
+     * Checks if a particular stream is a valid xml stream. Those are treated
+     * differently when they are signed (c14n transformation)
+     */
+    bool isXML(const OUString& rURI);
+    SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
+    /// Add a new signature, using xCert as a signing certificate, and rDescription as description.
+    bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId);
+    /// Read signatures from either a temp stream or the real storage.
+    void read(bool bUseTempStream);
+};
+
+#endif // INCLUDED_XMLSECURITY_INC_XMLSECURITY_DOCUMENTSIGNATUREMANAGER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx
index 4a97049..eb99f35 100644
--- a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx
+++ b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx
@@ -29,6 +29,7 @@
 
 #include <xmlsecurity/documentsignaturehelper.hxx>
 #include <xmlsecurity/xmlsignaturehelper.hxx>
+#include <documentsignaturemanager.hxx>
 
 #include <vector>
 
@@ -52,18 +53,10 @@ class DigitalSignaturesDialog : public ModalDialog
 {
 private:
     css::uno::Reference< css::uno::XComponentContext >& mxCtx;
-    XMLSignatureHelper      maSignatureHelper;
-
-    css::uno::Reference < css::embed::XStorage > mxStore;
-    css::uno::Reference < css::io::XStream > mxSignatureStream;
-    css::uno::Reference < css::io::XStream > mxTempSignatureStream;
-    /// Storage containing all OOXML signatures, unused for ODF.
-    css::uno::Reference<css::embed::XStorage> mxTempSignatureStorage;
-    SignatureInformations   maCurrentSignatureInformations;
+
+    DocumentSignatureManager maSignatureManager;
     bool                    mbVerifySignatures;
     bool                    mbSignaturesChanged;
-    DocumentSignatureMode   meSignatureMode;
-    css::uno::Sequence < css::uno::Sequence < css::beans::PropertyValue > > m_manifest;
 
     VclPtr<FixedText>          m_pHintDocFT;
     VclPtr<FixedText>          m_pHintBasicFT;
@@ -101,7 +94,6 @@ private:
     void                ImplGetSignatureInformations(bool bUseTempStream);
     void                ImplFillSignaturesBox();
     void                ImplShowSignaturesDetails();
-    SignatureStreamHelper ImplOpenSignatureStream( sal_Int32 eStreamMode, bool bTempStream );
 
     //Checks if adding is allowed.
     //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
@@ -109,9 +101,6 @@ private:
     bool canAdd();
     bool canRemove();
 
-    //Checks if a particular stream is a valid xml stream. Those are treated differently
-    //when they are signed (c14n transformation)
-    bool isXML(const OUString& rURI );
     bool canAddRemove();
 
 public:
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index c53b93d..77d058d 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -108,71 +108,13 @@ void SaveODFItem::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {
     }
 }
 
-/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
-    We use the manifest to find out if a file is xml and if it is encrypted.
-    The parameter is an encoded uri. However, the manifest contains paths. Therefore
-    the path is encoded as uri, so they can be compared.
-*/
-bool DigitalSignaturesDialog::isXML(const OUString& rURI )
-{
-    OSL_ASSERT(mxStore.is());
-
-    bool bIsXML = false;
-    bool bPropsAvailable = false;
-    const OUString sPropFullPath("FullPath");
-    const OUString sPropMediaType("MediaType");
-    const OUString sPropDigest("Digest");
-
-    for (int i = 0; i < m_manifest.getLength(); i++)
-    {
-        const Sequence< css::beans::PropertyValue >& entry = m_manifest[i];
-        OUString sPath, sMediaType;
-        bool bEncrypted = false;
-        for (int j = 0; j < entry.getLength(); j++)
-        {
-            const css::beans::PropertyValue & prop = entry[j];
-
-            if (prop.Name.equals( sPropFullPath ) )
-                prop.Value >>= sPath;
-            else if (prop.Name.equals( sPropMediaType ) )
-                prop.Value >>= sMediaType;
-            else if (prop.Name.equals( sPropDigest ) )
-                bEncrypted = true;
-        }
-        if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
-        {
-            bIsXML = sMediaType == "text/xml" && ! bEncrypted;
-            bPropsAvailable = true;
-            break;
-        }
-    }
-    if (!bPropsAvailable)
-    {
-        //This would be the case for at least mimetype, META-INF/manifest.xml
-        //META-INF/macrosignatures.xml.
-        //Files can only be encrypted if they are in the manifest.xml.
-        //That is, the current file cannot be encrypted, otherwise bPropsAvailable
-        //would be true.
-        OUString aXMLExt( "XML" );
-        sal_Int32 nSep = rURI.lastIndexOf( '.' );
-        if ( nSep != (-1) )
-        {
-            OUString aExt = rURI.copy( nSep+1 );
-            if (aExt.equalsIgnoreAsciiCase(aXMLExt ))
-                bIsXML = true;
-        }
-     }
-    return bIsXML;
-}
-
 DigitalSignaturesDialog::DigitalSignaturesDialog(
     vcl::Window* pParent,
     uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
     bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
     : ModalDialog(pParent, "DigitalSignaturesDialog", "xmlsec/ui/digitalsignaturesdialog.ui")
     , mxCtx(rxCtx)
-    , maSignatureHelper(rxCtx)
-    , meSignatureMode(eMode)
+    , maSignatureManager(rxCtx, eMode)
     , m_sODFVersion (sODFVersion)
     , m_bHasDocumentSignature(bHasDocumentSignature)
     , m_bWarningShowSignMacro(false)
@@ -229,7 +171,7 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
 
     m_pCloseBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
 
-    switch( meSignatureMode )
+    switch( maSignatureManager.meSignatureMode )
     {
         case SignatureModeDocumentContent:  m_pHintDocFT->Show();     break;
         case SignatureModeMacros:           m_pHintBasicFT->Show();   break;
@@ -265,13 +207,13 @@ void DigitalSignaturesDialog::dispose()
 
 bool DigitalSignaturesDialog::Init()
 {
-    bool bInit = maSignatureHelper.Init();
+    bool bInit = maSignatureManager.maSignatureHelper.Init();
 
     DBG_ASSERT( bInit, "Error initializing security context!" );
 
     if ( bInit )
     {
-        maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
+        maSignatureManager.maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
     }
 
     return bInit;
@@ -279,8 +221,8 @@ bool DigitalSignaturesDialog::Init()
 
 void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore )
 {
-    mxStore = rxStore;
-    maSignatureHelper.SetStorage( mxStore, m_sODFVersion);
+    maSignatureManager.mxStore = rxStore;
+    maSignatureManager.maSignatureHelper.SetStorage( maSignatureManager.mxStore, m_sODFVersion);
 
     Reference < css::packages::manifest::XManifestReader > xReader =
         css::packages::manifest::ManifestReader::create(mxCtx);
@@ -299,20 +241,20 @@ void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference <
             xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
             UNO_QUERY_THROW);
 
-        m_manifest = xReader->readManifestSequence(xStream);
+        maSignatureManager.m_manifest = xReader->readManifestSequence(xStream);
     }
 }
 
 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
 {
-    mxSignatureStream = rxStream;
+    maSignatureManager.mxSignatureStream = rxStream;
 }
 
 bool DigitalSignaturesDialog::canAddRemove()
 {
     //m56
     bool ret = true;
-    OSL_ASSERT(mxStore.is());
+    OSL_ASSERT(maSignatureManager.mxStore.is());
     bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
     SaveODFItem item;
     bool bSave1_1 = item.isLessODF1_2();
@@ -332,7 +274,7 @@ bool DigitalSignaturesDialog::canAddRemove()
     //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
     //adding a macro signature will break an existing document signature.
     //The sfx2 will remove the documentsignature when the user adds a macro signature
-    if (meSignatureMode == SignatureModeMacros
+    if (maSignatureManager.meSignatureMode == SignatureModeMacros
         && ret)
     {
         if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
@@ -392,8 +334,7 @@ IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, SignatureHighlightHdl, SvTreeList
 IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, OKButtonHdl, Button*, void)
 {
     // Export all other signatures...
-    SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
-        embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false );
+    SignatureStreamHelper aStreamHelper = maSignatureManager.ImplOpenSignatureStream(embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false);
 
     if (aStreamHelper.xSignatureStream.is() && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
     {
@@ -401,13 +342,13 @@ IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, OKButtonHdl, Button*, void)
         uno::Reference< io::XOutputStream > xOutputStream(
             aStreamHelper.xSignatureStream, uno::UNO_QUERY );
         uno::Reference< com::sun::star::xml::sax::XWriter> xSaxWriter =
-            maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
+            maSignatureManager.maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
 
         uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
-        size_t nInfos = maCurrentSignatureInformations.size();
+        size_t nInfos = maSignatureManager.maCurrentSignatureInformations.size();
         for( size_t n = 0 ; n < nInfos ; ++n )
             XMLSignatureHelper::ExportSignature(
-            xDocumentHandler, maCurrentSignatureInformations[ n ] );
+            xDocumentHandler, maSignatureManager.maCurrentSignatureInformations[ n ] );
 
         XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
 
@@ -415,16 +356,16 @@ IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, OKButtonHdl, Button*, void)
     else if (aStreamHelper.xSignatureStorage.is() && aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
     {
         // OOXML
-        size_t nSignatureCount = maCurrentSignatureInformations.size();
-        maSignatureHelper.ExportSignatureContentTypes(mxStore, nSignatureCount);
-        maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, nSignatureCount);
+        size_t nSignatureCount = maSignatureManager.maCurrentSignatureInformations.size();
+        maSignatureManager.maSignatureHelper.ExportSignatureContentTypes(maSignatureManager.mxStore, nSignatureCount);
+        maSignatureManager.maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, nSignatureCount);
 
         for (size_t i = 0; i < nSignatureCount; ++i)
-            maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, maCurrentSignatureInformations[i], i + 1);
+            maSignatureManager.maSignatureHelper.ExportOOXMLSignature(maSignatureManager.mxStore, aStreamHelper.xSignatureStorage, maSignatureManager.maCurrentSignatureInformations[i], i + 1);
     }
 
     // If stream was not provided, we are responsible for committing it....
-    if ( !mxSignatureStream.is() )
+    if ( !maSignatureManager.mxSignatureStream.is() )
     {
         uno::Reference< embed::XTransactedObject > xTrans(
             aStreamHelper.xSignatureStorage, uno::UNO_QUERY );
@@ -451,109 +392,17 @@ IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
         return;
     try
     {
-        uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureHelper.GetSecurityEnvironment();
+        uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.maSignatureHelper.GetSecurityEnvironment();
 
-        uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
-            ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
         ScopedVclPtrInstance< CertificateChooser > aChooser( this, mxCtx, xSecEnv );
         if ( aChooser->Execute() == RET_OK )
         {
-            uno::Reference< ::com::sun::star::security::XCertificate > xCert = aChooser->GetSelectedCertificate();
-            if ( !xCert.is() )
-            {
-                SAL_WARN( "xmlsecurity.dialogs", "no certificate selected" );
+            sal_Int32 nSecurityId;
+            if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetDescription(), nSecurityId))
                 return;
-            }
-            OUString aCertSerial = xSerialNumberAdapter->toString( xCert->getSerialNumber() );
-            if ( aCertSerial.isEmpty() )
-            {
-                OSL_FAIL( "Error in Certificate, problem with serial number!" );
-                return;
-            }
-
-            maSignatureHelper.StartMission();
-
-            sal_Int32 nSecurityId = maSignatureHelper.GetNewSecurityId();
-
-            OUStringBuffer aStrBuffer;
-            ::sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
-
-            maSignatureHelper.SetX509Certificate( nSecurityId,
-                xCert->getIssuerName(), aCertSerial,
-                aStrBuffer.makeStringAndClear());
-
-            std::vector< OUString > aElements =
-                DocumentSignatureHelper::CreateElementList(
-                    mxStore, meSignatureMode, OOo3_2Document);
-            DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
-
-            sal_Int32 nElements = aElements.size();
-            for ( sal_Int32 n = 0; n < nElements; n++ )
-            {
-                bool bBinaryMode = !isXML(aElements[n]);
-                maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode );
-            }
-
-            maSignatureHelper.SetDateTime( nSecurityId, Date( Date::SYSTEM ), tools::Time( tools::Time::SYSTEM ) );
-            maSignatureHelper.SetDescription(nSecurityId, aChooser->GetDescription());
-
-            // We open a signature stream in which the existing and the new
-            //signature is written. ImplGetSignatureInformation (later in this function) will
-            //then read the stream an will fill  maCurrentSignatureInformations. The final signature
-            //is written when the user presses OK. Then only maCurrentSignatureInformation and
-            //a sax writer are used to write the information.
-            SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
-                css::embed::ElementModes::WRITE|css::embed::ElementModes::TRUNCATE, true);
-
-            if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
-            {
-                Reference< css::io::XOutputStream > xOutputStream(
-                    aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
-                Reference< css::xml::sax::XWriter> xSaxWriter =
-                    maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
-
-                // Export old signatures...
-                uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
-                size_t nInfos = maCurrentSignatureInformations.size();
-                for ( size_t n = 0; n < nInfos; n++ )
-                    XMLSignatureHelper::ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]);
-
-                // Create a new one...
-                maSignatureHelper.CreateAndWriteSignature( xDocumentHandler );
-
-                // That's it...
-                XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
-            }
-            else
-            {
-                // OOXML
-
-                // Handle relations.
-                maSignatureHelper.EnsureSignaturesRelation(mxStore);
-                // Old signatures + the new one.
-                int nSignatureCount = maCurrentSignatureInformations.size() + 1;
-                maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, nSignatureCount);
-
-                // Create a new signature.
-                maSignatureHelper.CreateAndWriteOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, nSignatureCount);
-
-                // Flush objects.
-                uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage, uno::UNO_QUERY);
-                xTransact->commit();
-                uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
-                xOutputStream->closeOutput();
-
-                uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
-                SAL_INFO("xmlsecurity.dialogs", "AddButtonHdl: temporary storage is at " << xTempFile->getUri());
-            }
-
-            maSignatureHelper.EndMission();
-
-            aStreamHelper = SignatureStreamHelper();    // release objects...
-
             mbSignaturesChanged = true;
 
-            sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
+            sal_Int32 nStatus = maSignatureManager.maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
 
             if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
             {
@@ -587,20 +436,19 @@ IMPL_LINK_NOARG_TYPED(DigitalSignaturesDialog, RemoveButtonHdl, Button*, void)
         try
         {
             sal_uInt16 nSelected = (sal_uInt16) reinterpret_cast<sal_uIntPtr>( m_pSignaturesLB->FirstSelected()->GetUserData() );
-            maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected );
+            maSignatureManager.maCurrentSignatureInformations.erase( maSignatureManager.maCurrentSignatureInformations.begin()+nSelected );
 
             // Export all other signatures...
-            SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
-                css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true);
+            SignatureStreamHelper aStreamHelper = maSignatureManager.ImplOpenSignatureStream(css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true);
             Reference< css::io::XOutputStream > xOutputStream(
                 aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
             Reference< css::xml::sax::XWriter> xSaxWriter =
-                maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
+                maSignatureManager.maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
 
             uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
-            size_t nInfos = maCurrentSignatureInformations.size();
+            size_t nInfos = maSignatureManager.maCurrentSignatureInformations.size();
             for( size_t n = 0 ; n < nInfos ; ++n )
-                XMLSignatureHelper::ExportSignature( xDocumentHandler, maCurrentSignatureInformations[ n ] );
+                XMLSignatureHelper::ExportSignature( xDocumentHandler, maSignatureManager.maCurrentSignatureInformations[ n ] );
 
             XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
 
@@ -629,13 +477,13 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
 {
     m_pSignaturesLB->Clear();
 
-    uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = maSignatureHelper.GetSecurityEnvironment();
+    uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = maSignatureManager.maSignatureHelper.GetSecurityEnvironment();
     uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
         ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
 
     uno::Reference< ::com::sun::star::security::XCertificate > xCert;
 
-    size_t nInfos = maCurrentSignatureInformations.size();
+    size_t nInfos = maSignatureManager.maCurrentSignatureInformations.size();
     size_t nValidSigs = 0, nValidCerts = 0;
     bool bAllNewSignatures = true;
 
@@ -644,12 +492,12 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
         for( size_t n = 0; n < nInfos; ++n )
         {
             DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
-                m_sODFVersion, maCurrentSignatureInformations[n]);
+                m_sODFVersion, maSignatureManager.maCurrentSignatureInformations[n]);
             std::vector< OUString > aElementsToBeVerified =
                 DocumentSignatureHelper::CreateElementList(
-                mxStore, meSignatureMode, mode);
+                maSignatureManager.mxStore, maSignatureManager.meSignatureMode, mode);
 
-            const SignatureInformation& rInfo = maCurrentSignatureInformations[n];
+            const SignatureInformation& rInfo = maSignatureManager.maCurrentSignatureInformations[n];
             //First we try to get the certificate which is embedded in the XML Signature
             if (!rInfo.ouX509Certificate.isEmpty())
                 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
@@ -721,20 +569,20 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
             }
             //Check if the signature is a "old" document signature, that is, which was created
             //by an version of OOo previous to 3.2
-            else if (meSignatureMode == SignatureModeDocumentContent
+            else if (maSignatureManager.meSignatureMode == SignatureModeDocumentContent
                 && bSigValid && bCertValid && !DocumentSignatureHelper::isOOo3_2_Signature(
-                maCurrentSignatureInformations[n]))
+                maSignatureManager.maCurrentSignatureInformations[n]))
             {
                 aImage = m_pSigsNotvalidatedImg->GetImage();
                 bAllNewSignatures &= false;
             }
-            else if (meSignatureMode == SignatureModeDocumentContent
+            else if (maSignatureManager.meSignatureMode == SignatureModeDocumentContent
                 && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature(
-                maCurrentSignatureInformations[n]))
+                maSignatureManager.maCurrentSignatureInformations[n]))
             {
                 aImage = m_pSigsValidImg->GetImage();
             }
-            else if (meSignatureMode == SignatureModeMacros
+            else if (maSignatureManager.meSignatureMode == SignatureModeMacros
                 && bSigValid && bCertValid)
             {
                 aImage = m_pSigsValidImg->GetImage();
@@ -778,23 +626,7 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
 //Otherwise the real signature stream is used.
 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream)
 {
-    maCurrentSignatureInformations.clear();
-
-    maSignatureHelper.StartMission();
-
-    SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
-        css::embed::ElementModes::READ, bUseTempStream);
-    if ( aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML && aStreamHelper.xSignatureStream.is() )
-    {
-        uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY );
-        maSignatureHelper.ReadAndVerifySignature( xInputStream );
-    }
-    else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML && aStreamHelper.xSignatureStorage.is())
-        maSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage);
-    maSignatureHelper.EndMission();
-
-    maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
-
+    maSignatureManager.read(bUseTempStream);
     mbVerifySignatures = false;
 }
 
@@ -803,9 +635,9 @@ void DigitalSignaturesDialog::ImplShowSignaturesDetails()
     if( m_pSignaturesLB->FirstSelected() )
     {
         sal_uInt16 nSelected = (sal_uInt16) reinterpret_cast<sal_uIntPtr>( m_pSignaturesLB->FirstSelected()->GetUserData() );
-        const SignatureInformation& rInfo = maCurrentSignatureInformations[ nSelected ];
+        const SignatureInformation& rInfo = maSignatureManager.maCurrentSignatureInformations[ nSelected ];
         css::uno::Reference<css::xml::crypto::XSecurityEnvironment > xSecEnv =
-            maSignatureHelper.GetSecurityEnvironment();
+            maSignatureManager.maSignatureHelper.GetSecurityEnvironment();
         css::uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
             ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
         // Use Certificate from doc, not from key store
@@ -819,94 +651,10 @@ void DigitalSignaturesDialog::ImplShowSignaturesDetails()
         DBG_ASSERT( xCert.is(), "Error getting Certificate!" );
         if ( xCert.is() )
         {
-            ScopedVclPtrInstance< CertificateViewer > aViewer( this, maSignatureHelper.GetSecurityEnvironment(), xCert, false );
+            ScopedVclPtrInstance< CertificateViewer > aViewer( this, maSignatureManager.maSignatureHelper.GetSecurityEnvironment(), xCert, false );
             aViewer->Execute();
         }
     }
 }
 
-//If bTempStream is true, then a temporary stream is return. If it is false then, the actual
-//signature stream is used.
-//Every time the user presses Add a new temporary stream is created.
-//We keep the temporary stream as member because ImplGetSignatureInformations
-//will later access the stream to create DocumentSignatureInformation objects
-//which are stored in maCurrentSignatureInformations.
-SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream(
-    sal_Int32 nStreamOpenMode, bool bTempStream)
-{
-    SignatureStreamHelper aHelper;
-    if (mxStore.is())
-    {
-        uno::Reference<container::XNameAccess> xNameAccess(mxStore, uno::UNO_QUERY);
-        if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
-            aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
-    }
-
-    if (bTempStream)
-    {
-        if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
-        {
-            //We write always into a new temporary stream.
-            mxTempSignatureStream.set(css::io::TempFile::create(mxCtx), UNO_QUERY_THROW);
-            if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
-                aHelper.xSignatureStream = mxTempSignatureStream;
-            else
-            {
-                mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream);
-                aHelper.xSignatureStorage = mxTempSignatureStorage;
-            }
-        }
-        else
-        {
-            //When we read from the temp stream, then we must have previously
-            //created one.
-            OSL_ASSERT(mxTempSignatureStream.is());
-        }
-        aHelper.xSignatureStream = mxTempSignatureStream;
-        if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
-            aHelper.xSignatureStorage = mxTempSignatureStorage;
-    }
-    else
-    {
-        //No temporary stream
-        if (!mxSignatureStream.is())
-        {
-            //We may not have a dedicated stream for writing the signature
-            //So we take one directly from the storage
-            //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
-            //in which case Add/Remove is not allowed. This is done, for example, if the
-            //document is readonly
-            aHelper = DocumentSignatureHelper::OpenSignatureStream(
-                mxStore, nStreamOpenMode, meSignatureMode );
-        }
-        else
-        {
-            aHelper.xSignatureStream = mxSignatureStream;
-        }
-    }
-
-    if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
-    {
-        if (aHelper.xSignatureStream.is() && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
-        {
-            css::uno::Reference < css::io::XTruncate > xTruncate(
-                aHelper.xSignatureStream, UNO_QUERY_THROW);
-            DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" );
-            xTruncate->truncate();
-        }
-    }
-    else if ( bTempStream || mxSignatureStream.is())
-    {
-        //In case we read the signature stream from the storage directly,
-        //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
-        //then XSeakable is not supported
-        css::uno::Reference < css::io::XSeekable > xSeek(
-            aHelper.xSignatureStream, UNO_QUERY_THROW);
-        DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" );
-        xSeek->seek( 0 );
-    }
-
-    return aHelper;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
new file mode 100644
index 0000000..bb904b8
--- /dev/null
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -0,0 +1,296 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <documentsignaturemanager.hxx>
+
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/TempFile.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/security/SerialNumberAdapter.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+
+#include <comphelper/storagehelper.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sax/tools/converter.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+
+using namespace com::sun::star;
+
+DocumentSignatureManager::DocumentSignatureManager(const uno::Reference<uno::XComponentContext>& xContext, DocumentSignatureMode eMode)
+    : mxContext(xContext),
+      maSignatureHelper(xContext),
+      meSignatureMode(eMode)
+{
+}
+
+DocumentSignatureManager::~DocumentSignatureManager()
+{
+}
+
+/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
+    We use the manifest to find out if a file is xml and if it is encrypted.
+    The parameter is an encoded uri. However, the manifest contains paths. Therefore
+    the path is encoded as uri, so they can be compared.
+*/
+bool DocumentSignatureManager::isXML(const OUString& rURI)
+{
+    SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference");
+
+    // FIXME figure out why this is necessary.
+    static bool bTest = getenv("LO_TESTNAME");
+    if (bTest)
+        return true;
+
+    bool bIsXML = false;
+    bool bPropsAvailable = false;
+    const OUString sPropFullPath("FullPath");
+    const OUString sPropMediaType("MediaType");
+    const OUString sPropDigest("Digest");
+
+    for (int i = 0; i < m_manifest.getLength(); i++)
+    {
+        const uno::Sequence<css::beans::PropertyValue>& entry = m_manifest[i];
+        OUString sPath, sMediaType;
+        bool bEncrypted = false;
+        for (int j = 0; j < entry.getLength(); j++)
+        {
+            const css::beans::PropertyValue& prop = entry[j];
+
+            if (prop.Name.equals(sPropFullPath))
+                prop.Value >>= sPath;
+            else if (prop.Name.equals(sPropMediaType))
+                prop.Value >>= sMediaType;
+            else if (prop.Name.equals(sPropDigest))
+                bEncrypted = true;
+        }
+        if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
+        {
+            bIsXML = sMediaType == "text/xml" && ! bEncrypted;
+            bPropsAvailable = true;
+            break;
+        }
+    }
+    if (!bPropsAvailable)
+    {
+        //This would be the case for at least mimetype, META-INF/manifest.xml
+        //META-INF/macrosignatures.xml.
+        //Files can only be encrypted if they are in the manifest.xml.
+        //That is, the current file cannot be encrypted, otherwise bPropsAvailable
+        //would be true.
+        OUString aXMLExt("XML");
+        sal_Int32 nSep = rURI.lastIndexOf('.');
+        if (nSep != (-1))
+        {
+            OUString aExt = rURI.copy(nSep+1);
+            if (aExt.equalsIgnoreAsciiCase(aXMLExt))
+                bIsXML = true;
+        }
+    }
+    return bIsXML;
+}
+
+//If bTempStream is true, then a temporary stream is return. If it is false then, the actual
+//signature stream is used.
+//Every time the user presses Add a new temporary stream is created.
+//We keep the temporary stream as member because ImplGetSignatureInformations
+//will later access the stream to create DocumentSignatureInformation objects
+//which are stored in maCurrentSignatureInformations.
+SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream)
+{
+    SignatureStreamHelper aHelper;
+    if (mxStore.is())
+    {
+        uno::Reference<container::XNameAccess> xNameAccess(mxStore, uno::UNO_QUERY);
+        if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
+            aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
+    }
+
+    if (bTempStream)
+    {
+        if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
+        {
+            //We write always into a new temporary stream.
+            mxTempSignatureStream.set(css::io::TempFile::create(mxContext), uno::UNO_QUERY_THROW);
+            if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+                aHelper.xSignatureStream = mxTempSignatureStream;
+            else
+            {
+                mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream);
+                aHelper.xSignatureStorage = mxTempSignatureStorage;
+            }
+        }
+        else
+        {
+            //When we read from the temp stream, then we must have previously
+            //created one.
+            SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper", "empty temp. signature stream reference");
+        }
+        aHelper.xSignatureStream = mxTempSignatureStream;
+        if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+            aHelper.xSignatureStorage = mxTempSignatureStorage;
+    }
+    else
+    {
+        //No temporary stream
+        if (!mxSignatureStream.is())
+        {
+            //We may not have a dedicated stream for writing the signature
+            //So we take one directly from the storage
+            //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
+            //in which case Add/Remove is not allowed. This is done, for example, if the
+            //document is readonly
+            aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode, meSignatureMode);
+        }
+        else
+        {
+            aHelper.xSignatureStream = mxSignatureStream;
+        }
+    }
+
+    if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
+    {
+        if (aHelper.xSignatureStream.is() && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+        {
+            css::uno::Reference<css::io::XTruncate> xTruncate(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
+            xTruncate->truncate();
+        }
+    }
+    else if (bTempStream || mxSignatureStream.is())
+    {
+        //In case we read the signature stream from the storage directly,
+        //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
+        //then XSeakable is not supported
+        uno::Reference<io::XSeekable> xSeek(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
+        xSeek->seek(0);
+    }
+
+    return aHelper;
+}
+
+bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId)
+{
+    if (!xCert.is())
+    {
+        SAL_WARN("xmlsecurity.helper", "no certificate selected");
+        return false;
+    }
+
+    uno::Reference<security::XSerialNumberAdapter> xSerialNumberAdapter = security::SerialNumberAdapter::create(mxContext);
+    OUString aCertSerial = xSerialNumberAdapter->toString(xCert->getSerialNumber());
+    if (aCertSerial.isEmpty())
+    {
+        SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
+        return false;
+    }
+
+    maSignatureHelper.StartMission();
+
+    nSecurityId = maSignatureHelper.GetNewSecurityId();
+
+    OUStringBuffer aStrBuffer;
+    sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
+
+    maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial, aStrBuffer.makeStringAndClear());
+
+    std::vector< OUString > aElements = DocumentSignatureHelper::CreateElementList(mxStore, meSignatureMode, OOo3_2Document);
+    DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
+
+    sal_Int32 nElements = aElements.size();
+    for (sal_Int32 n = 0; n < nElements; n++)
+    {
+        bool bBinaryMode = !isXML(aElements[n]);
+        maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode);
+    }
+
+    maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
+    maSignatureHelper.SetDescription(nSecurityId, rDescription);
+
+    // We open a signature stream in which the existing and the new
+    //signature is written. ImplGetSignatureInformation (later in this function) will
+    //then read the stream an will fill  maCurrentSignatureInformations. The final signature
+    //is written when the user presses OK. Then only maCurrentSignatureInformation and
+    //a sax writer are used to write the information.
+    SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, true);
+
+    if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+    {
+        uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, uno::UNO_QUERY_THROW);
+        uno::Reference<xml::sax::XWriter> xSaxWriter = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
+
+        // Export old signatures...
+        uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW);
+        size_t nInfos = maCurrentSignatureInformations.size();
+        for (size_t n = 0; n < nInfos; n++)
+            XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n]);
+
+        // Create a new one...
+        maSignatureHelper.CreateAndWriteSignature(xDocumentHandler);
+
+        // That's it...
+        XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
+    }
+    else
+    {
+        // OOXML
+
+        // Handle relations.
+        maSignatureHelper.EnsureSignaturesRelation(mxStore);
+        // Old signatures + the new one.
+        int nSignatureCount = maCurrentSignatureInformations.size() + 1;
+        maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, nSignatureCount);
+
+        // Create a new signature.
+        maSignatureHelper.CreateAndWriteOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, nSignatureCount);
+
+        // Flush objects.
+        uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage, uno::UNO_QUERY);
+        xTransact->commit();
+        uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
+        xOutputStream->closeOutput();
+
+        uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
+        SAL_INFO("xmlsecurity.dialogs", "AddButtonHdl: temporary storage is at " << xTempFile->getUri());
+    }
+
+    maSignatureHelper.EndMission();
+    return true;
+}
+
+void DocumentSignatureManager::read(bool bUseTempStream)
+{
+    maCurrentSignatureInformations.clear();
+
+    maSignatureHelper.StartMission();
+
+    SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(css::embed::ElementModes::READ, bUseTempStream);
+    if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML && aStreamHelper.xSignatureStream.is())
+    {
+        uno::Reference< io::XInputStream > xInputStream(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
+        maSignatureHelper.ReadAndVerifySignature(xInputStream);
+    }
+    else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML && aStreamHelper.xSignatureStorage.is())
+        maSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage);
+    maSignatureHelper.EndMission();
+
+    maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list