summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2016-02-15 11:38:23 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2016-02-15 17:24:47 +0100
commit565346a4fe0a074807381c2d8ea48242e9e69f4f (patch)
treed94b901ba04a794d5e97d76126e7061677f83c04
parent639aaa2fe5dfc2cb2739c6f833f3208ebf8dd710 (diff)
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
-rw-r--r--xmlsecurity/Library_xmlsecurity.mk1
-rw-r--r--xmlsecurity/inc/documentsignaturemanager.hxx62
-rw-r--r--xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx17
-rw-r--r--xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx336
-rw-r--r--xmlsecurity/source/helper/documentsignaturemanager.cxx296
5 files changed, 404 insertions, 308 deletions
diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index ecbade5f9bdf..c594ec9392a1 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 000000000000..6719c2613111
--- /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 4a97049038d5..eb99f3579887 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 c53b93d41978..77d058d0a7e2 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 000000000000..bb904b80f9a6
--- /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: */