include/sfx2/objsh.hxx                                     |   10 +
 include/sfx2/strings.hrc                                   |    1 
 sfx2/source/doc/guisaveas.cxx                              |    7 -
 sfx2/source/doc/objserv.cxx                                |   81 ++++++++++---
 xmlsecurity/source/component/documentdigitalsignatures.cxx |    8 +
 5 files changed, 86 insertions(+), 21 deletions(-)

New commits:
commit 46722dbaa7795074e3c5043a76ae3f3a7782491e
Author:     TokieSan <elto...@aucegypt.edu>
AuthorDate: Tue Jun 6 21:51:42 2023 +0300
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Sun Jun 18 22:03:43 2023 +0200

    tdf#155665 Adding option to remember signatures for each save
    
    Added the option in digital signatures dialog to remember used
    signature.
    
    Implemented ResignDocument function in objserv.cxx to resign after
    every save in case the option to remember signature is on.
    Added a new dialog box that checks whether there is a need to
    remember the signature.
    
    Change-Id: Ia7dbcc952044e9542e3fe6cd84b5d6633fcd1461
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152687
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index b29fb43d77e4..15533c2954ca 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -190,6 +190,7 @@ private:
                                                   // sal_False := new object
     bool                        bIsInGenerateThumbnail; //optimize thumbnail 
generate and store procedure to improve odt saving performance, i120030
     bool                        mbAvoidRecentDocs; ///< Avoid adding to the 
recent documents list, if not necessary.
+    bool                        bRememberSignature; // Do we want to remember 
the signature.
 
     enum TriState               {undefined, yes, no};
     TriState                    mbContinueImportOnFilterExceptions = 
undefined; // try to import as much as possible
@@ -199,6 +200,8 @@ private:
     SAL_DLLPRIVATE void UpdateTime_Impl(const css::uno::Reference<
         css::document::XDocumentProperties> & i_xDocProps);
 
+    css::uno::Sequence< css::security::DocumentSignatureInformation > 
rSignatureInfosRemembered;
+
     SAL_DLLPRIVATE bool SaveTo_Impl(SfxMedium &rMedium, const SfxItemSet* pSet 
);
 
 protected:
@@ -350,13 +353,14 @@ public:
     void AfterSigning(bool bSignSuccess, bool bSignScriptingContent);
     bool HasValidSignatures() const;
     SignatureState              GetDocumentSignatureState();
-    void                        SignDocumentContent(weld::Window* 
pDialogParent);
+    bool                        SignDocumentContent(weld::Window* 
pDialogParent);
     css::uno::Sequence<css::security::DocumentSignatureInformation> 
GetDocumentSignatureInformation(
         bool bScriptingContent,
         const css::uno::Reference<css::security::XDocumentDigitalSignatures>& 
xSigner
         = css::uno::Reference<css::security::XDocumentDigitalSignatures>());
 
     bool SignDocumentContentUsingCertificate(const 
css::uno::Reference<css::security::XCertificate>& xCertificate);
+    bool ResignDocument(css::uno::Sequence< 
css::security::DocumentSignatureInformation >& rSignaturesInfo);
 
     void SignSignatureLine(weld::Window* pDialogParent, const OUString& 
aSignatureLineId,
                            const 
css::uno::Reference<css::security::XCertificate>& xCert,
@@ -364,7 +368,7 @@ public:
                            const css::uno::Reference<css::graphic::XGraphic>& 
xInvalidGraphic,
                            const OUString& aComment);
     SignatureState              GetScriptingSignatureState();
-    void                        SignScriptingContent(weld::Window* 
pDialogParent);
+    bool                        SignScriptingContent(weld::Window* 
pDialogParent);
     DECL_DLLPRIVATE_LINK(SignDocumentHandler, weld::Button&, void);
 
     virtual std::shared_ptr<SfxDocumentInfoDialog> 
CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet& rItemSet);
@@ -458,6 +462,8 @@ public:
     /// Don't add to the recent documents - it's an expensive operation, 
sometimes it is not wanted.
     bool                        IsAvoidRecentDocs() const { return 
mbAvoidRecentDocs; }
 
+    bool                        IsRememberingSignature() const { return 
bRememberSignature; }
+
     /// Don't add to the recent documents - it's an expensive operation, 
sometimes it is not wanted.
     void                        AvoidRecentDocs(bool bAvoid) { 
mbAvoidRecentDocs = bAvoid; }
 
diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc
index bd2c0b5d5630..3ccc50cb0947 100644
--- a/include/sfx2/strings.hrc
+++ b/include/sfx2/strings.hrc
@@ -149,6 +149,7 @@
 #define RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE 
NC_("RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE", "Saving will remove all existing 
signatures.\nDo you want to continue saving the document?")
 #define RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN  
NC_("RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN", "The document has to be saved 
before it can be signed.\nDo you want to save the document?")
 #define STR_QUERY_CANCELCHECKOUT                
NC_("STR_QUERY_CANCELCHECKOUT", "This will discard all changes on the server 
since check-out.\nDo you want to proceed?")
+#define STR_QUERY_REMEMBERSIGNATURE             
NC_("STR_QUERY_REMEMBERSIGNATURE", "Do you want to remember that signature for 
each save?")
 #define STR_INFO_WRONGDOCFORMAT                 NC_("STR_INFO_WRONGDOCFORMAT", 
"This document must be saved in OpenDocument file format before it can be 
digitally signed.")
 #define RID_XMLSEC_DOCUMENTSIGNED               
NC_("RID_XMLSEC_DOCUMENTSIGNED", " (Signed)")
 #define STR_EMBEDDED_TITLE                      NC_("STR_EMBEDDED_TITLE", " 
(Embedded document)")
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index b6d4ce61d8a6..272d68fedac6 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -1487,11 +1487,14 @@ bool SfxStoringHelper::GUIStoreModel( const 
uno::Reference< frame::XModel >& xMo
 
     if (!comphelper::LibreOfficeKit::isActive() && !( m_nStoreMode & 
EXPORT_REQUESTED ) )
     {
+        SfxObjectShell* pDocShell = SfxViewShell::Current()->GetObjectShell();
+
         // if it is no export, warn user that the signature will be removed
-        if (  SignatureState::OK == nDocumentSignatureState
+        if (  !pDocShell->IsRememberingSignature()
+           && (SignatureState::OK == nDocumentSignatureState
            || SignatureState::INVALID == nDocumentSignatureState
            || SignatureState::NOTVALIDATED == nDocumentSignatureState
-           || SignatureState::PARTIAL_OK == nDocumentSignatureState)
+           || SignatureState::PARTIAL_OK == nDocumentSignatureState) )
         {
             std::unique_ptr<weld::MessageDialog> 
xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(xModel),
                                                              
VclMessageType::Question, VclButtonsType::YesNo, 
SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE)));
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 78c4fd01f667..f321cbfc74a7 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -532,6 +532,8 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
 
     sal_uInt16 nId = rReq.GetSlot();
 
+    bool bHaveWeSigned = false;
+
     if( SID_SIGNATURE == nId || SID_MACRO_SIGNATURE == nId )
     {
         if ( QueryHiddenInformation( HiddenWarningFact::WhenSigning, nullptr ) 
== RET_YES )
@@ -541,7 +543,8 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 uno::Reference<security::XCertificate> xCertificate = 
GetSignPDFCertificate();
                 if (xCertificate.is())
                 {
-                    SignDocumentContentUsingCertificate(xCertificate);
+
+                    bHaveWeSigned |= 
SignDocumentContentUsingCertificate(xCertificate);
 
                     // Reload to show how the PDF actually looks like after 
signing. This also
                     // changes "finish signing" on the infobar back to "sign 
document" as a side
@@ -568,14 +571,31 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 }
                 else
                 {
-                    SignDocumentContent(pDialogParent);
+                    bHaveWeSigned |= SignDocumentContent(pDialogParent);
                 }
             }
             else
             {
-                SignScriptingContent(pDialogParent);
+                bHaveWeSigned |= SignScriptingContent(pDialogParent);
             }
         }
+
+        if ( bHaveWeSigned && HasValidSignatures() )
+        {
+            std::unique_ptr<weld::MessageDialog> 
xBox(Application::CreateMessageDialog( pDialogParent,
+                                                      
VclMessageType::Question, VclButtonsType::YesNo, 
SfxResId(STR_QUERY_REMEMBERSIGNATURE)));
+            if (xBox->run() == RET_YES)
+            {
+                rSignatureInfosRemembered = 
GetDocumentSignatureInformation(false);
+                bRememberSignature = true;
+            }
+            else
+            {
+                rSignatureInfosRemembered = uno::Sequence< 
security::DocumentSignatureInformation >();
+                bRememberSignature = false;
+            }
+        }
+
         return;
     }
 
@@ -1207,6 +1227,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 }
             }
 
+            if (nId == SID_SAVEDOC && bRememberSignature && 
rSignatureInfosRemembered.hasElements())
+                ResignDocument(rSignatureInfosRemembered);
+
             rReq.SetReturnValue( SfxBoolItem(0, nErrorCode == ERRCODE_NONE ) );
 
             ResetError();
@@ -1527,9 +1550,10 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
                         aInfobarType = InfobarType::DANGER;
                         break;
                     case SignatureState::INVALID:
-                        sMessage = SfxResId(STR_SIGNATURE_INVALID);
+                        // If we are remembering the certificates, it should 
be kept as valid
+                        sMessage = SfxResId(bRememberSignature ? 
STR_SIGNATURE_OK : STR_SIGNATURE_INVALID);
                         // Warning only, I've tried Danger and it looked too 
scary
-                        aInfobarType = InfobarType::WARNING;
+                        aInfobarType = ( bRememberSignature ? 
InfobarType::INFO : InfobarType::WARNING );
                         break;
                     case SignatureState::NOTVALIDATED:
                         sMessage = SfxResId(STR_SIGNATURE_NOTVALIDATED);
@@ -1880,11 +1904,15 @@ bool SfxObjectShell::PrepareForSigning(weld::Window* 
pDialogParent)
         if (nVersion >= SvtSaveOptions::ODFSVER_012)
         {
             OUString sQuestion(bHasSign ? 
SfxResId(STR_XMLSEC_QUERY_SAVESIGNEDBEFORESIGN) : 
SfxResId(RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN));
-            std::unique_ptr<weld::MessageDialog> 
xQuestion(Application::CreateMessageDialog(pDialogParent,
-                                                           
VclMessageType::Question, VclButtonsType::YesNo, sQuestion));
+            std::unique_ptr<weld::MessageDialog> xQuestion;
 
+            if (!bRememberSignature)
+            {
+                xQuestion = 
std::unique_ptr<weld::MessageDialog>(Application::CreateMessageDialog(pDialogParent,
+                                                           
VclMessageType::Question, VclButtonsType::YesNo, sQuestion));
+            }
 
-            if (xQuestion->run() == RET_YES)
+            if ( bRememberSignature || ( xQuestion != nullptr && 
xQuestion->run() == RET_YES ) )
             {
                 sal_uInt16 nId = SID_SAVEDOC;
                 if ( !GetMedium() || GetMedium()->GetName().isEmpty() )
@@ -1932,7 +1960,7 @@ bool SfxObjectShell::PrepareForSigning(weld::Window* 
pDialogParent)
 
     // the document is not modified currently, so it can not become modified 
after signing
     pImpl->m_bAllowModifiedBackAfterSigning = false;
-    if ( IsEnableSetModified() )
+    if ( IsEnableSetModified() || /*bRememberSignature == */true )
     {
         EnableSetModified( false );
         pImpl->m_bAllowModifiedBackAfterSigning = true;
@@ -1968,7 +1996,7 @@ void SfxObjectShell::AfterSigning(bool bSignSuccess, bool 
bSignScriptingContent)
     if ( bSignSuccess )
         RecheckSignature(bSignScriptingContent);
 
-    if ( pImpl->m_bAllowModifiedBackAfterSigning )
+    if ( pImpl->m_bAllowModifiedBackAfterSigning || /* bRememberSignature ==*/ 
true )
         EnableSetModified();
 }
 
@@ -2041,17 +2069,36 @@ SignatureState 
SfxObjectShell::GetDocumentSignatureState()
     return ImplGetSignatureState();
 }
 
-void SfxObjectShell::SignDocumentContent(weld::Window* pDialogParent)
+bool SfxObjectShell::SignDocumentContent(weld::Window* pDialogParent)
 {
     if (!PrepareForSigning(pDialogParent))
-        return;
+        return false;
 
     if (CheckIsReadonly(false, pDialogParent))
-        return;
+        return false;
 
     bool bSignSuccess = GetMedium()->SignContents_Impl(pDialogParent, false, 
HasValidSignatures());
 
     AfterSigning(bSignSuccess, false);
+
+    return bSignSuccess;
+}
+
+bool SfxObjectShell::ResignDocument(uno::Sequence< 
security::DocumentSignatureInformation >& rSignaturesInfo)
+{
+    bool bSignSuccess = true;
+
+    // This should be at most one element, automatic iteration to avoid 
pointing issues in case no signs
+    for (auto & rInfo : rSignaturesInfo)
+    {
+        auto xCert = rInfo.Signer;
+        if (xCert.is())
+        {
+            bSignSuccess &= SignDocumentContentUsingCertificate(xCert);
+        }
+    }
+
+    return bSignSuccess;
 }
 
 bool SfxObjectShell::SignDocumentContentUsingCertificate(const 
Reference<XCertificate>& xCertificate)
@@ -2162,17 +2209,19 @@ SignatureState 
SfxObjectShell::GetScriptingSignatureState()
     return ImplGetSignatureState( true );
 }
 
-void SfxObjectShell::SignScriptingContent(weld::Window* pDialogParent)
+bool SfxObjectShell::SignScriptingContent(weld::Window* pDialogParent)
 {
     if (!PrepareForSigning(pDialogParent))
-        return;
+        return false;
 
     if (CheckIsReadonly(true, pDialogParent))
-        return;
+        return false;
 
     bool bSignSuccess = GetMedium()->SignContents_Impl(pDialogParent, true, 
HasValidSignatures());
 
     AfterSigning(bSignSuccess, true);
+
+    return bSignSuccess;
 }
 
 const uno::Sequence<sal_Int8>& SfxObjectShell::getUnoTunnelId()
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx 
b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 990fa5dea739..0fd029fc2d81 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -869,7 +869,13 @@ bool DocumentDigitalSignatures::signWithCertificateImpl(
     aSignatureManager.setSignatureStream(xStream);
     aSignatureManager.setModel(xModel);
 
-    Reference<XXMLSecurityContext> xSecurityContext = 
aSignatureManager.getSecurityContext();
+    Reference<XXMLSecurityContext> xSecurityContext;
+    Reference<XServiceInfo> xServiceInfo(xCertificate, UNO_QUERY);
+    if (xServiceInfo->getImplementationName()
+        == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl")
+        xSecurityContext = aSignatureManager.getGpgSecurityContext();
+    else
+        xSecurityContext = aSignatureManager.getSecurityContext();
 
     sal_Int32 nSecurityId;
 

Reply via email to