[Libreoffice-commits] core.git: compilerplugins/clang sw/qa writerfilter/Library_writerfilter.mk writerfilter/source

Tünde Tóth (via logerrit) logerrit at kemper.freedesktop.org
Mon Sep 27 14:35:43 UTC 2021


 compilerplugins/clang/unusedfields.writeonly.results |    4 
 sw/qa/uitest/data/writeprotection.docx               |binary
 sw/qa/uitest/writer_tests6/tdf89383.py               |   28 ++
 writerfilter/Library_writerfilter.mk                 |    2 
 writerfilter/source/dmapper/DocumentProtection.cxx   |  239 +++++++++++++++++
 writerfilter/source/dmapper/DocumentProtection.hxx   |   88 ++++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx    |    4 
 writerfilter/source/dmapper/SettingsTable.cxx        |  260 +------------------
 writerfilter/source/dmapper/SettingsTable.hxx        |    2 
 writerfilter/source/dmapper/WriteProtection.cxx      |  143 ++++++++++
 writerfilter/source/dmapper/WriteProtection.hxx      |   58 ++++
 11 files changed, 590 insertions(+), 238 deletions(-)

New commits:
commit bfd7730f4cf002a79dc9c02c23286850fee3f12a
Author:     Tünde Tóth <toth.tunde at nisz.hu>
AuthorDate: Tue Sep 21 11:41:04 2021 +0200
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Mon Sep 27 16:35:07 2021 +0200

    tdf#89383 DOCX import: fix permission for editing
    
    w:writeProtection passwords in DOCX documents created
    with Word weren't asked and verified to permit editing.
    
    Change-Id: I53d73e3acaf0c0fd398ded2de52e1d8ef00cfd56
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122384
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: László Németh <nemeth at numbertext.org>

diff --git a/compilerplugins/clang/unusedfields.writeonly.results b/compilerplugins/clang/unusedfields.writeonly.results
index 7bf4af94dc79..c97ce0cb37fc 100644
--- a/compilerplugins/clang/unusedfields.writeonly.results
+++ b/compilerplugins/clang/unusedfields.writeonly.results
@@ -1060,8 +1060,8 @@ writerfilter/source/dmapper/DomainMapperTableHandler.cxx:240
     writerfilter::dmapper::TableInfo aTablePropertyIds std::vector<PropertyIds>
 writerfilter/source/dmapper/PropertyMap.hxx:219
     writerfilter::dmapper::SectionPropertyMap m_nDebugSectionNumber sal_Int32
-writerfilter/source/dmapper/SettingsTable.cxx:264
-    writerfilter::dmapper::SettingsTable_Impl m_sRedlineProtectionKey class rtl::OUString
+writerfilter/source/dmapper/DocumentProtection.hxx:50
+    writerfilter::dmapper::DocumentProtection m_sRedlineProtectionKey class rtl::OUString
 xmlhelp/source/cxxhelp/provider/databases.hxx:249
     chelp::Databases m_aDatabases chelp::Databases::DatabasesTable
 xmlhelp/source/cxxhelp/provider/databases.hxx:255
diff --git a/sw/qa/uitest/data/writeprotection.docx b/sw/qa/uitest/data/writeprotection.docx
new file mode 100644
index 000000000000..f0fab46a9d8f
Binary files /dev/null and b/sw/qa/uitest/data/writeprotection.docx differ
diff --git a/sw/qa/uitest/writer_tests6/tdf89383.py b/sw/qa/uitest/writer_tests6/tdf89383.py
new file mode 100644
index 000000000000..26f559460100
--- /dev/null
+++ b/sw/qa/uitest/writer_tests6/tdf89383.py
@@ -0,0 +1,28 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# 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/.
+#
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_url_for_data_file
+from libreoffice.uno.propertyvalue import mkPropertyValues
+
+#Bug 89383 - Read-only passwords on OOXML files are not working
+
+class tdf89383(UITestCase):
+   def test_tdf89383_DOCX(self):
+        with self.ui_test.load_file(get_url_for_data_file("writeprotection.docx")):
+            document = self.ui_test.get_component()
+
+            # Without the fix in place, this test would have failed with
+            # AssertionError: False is not true
+            self.assertTrue(document.isReadonly())
+
+            with self.ui_test.execute_dialog_through_command(".uno:EditDoc") as xDialog:
+                xPassword = xDialog.getChild("newpassEntry")
+                xPassword.executeAction("TYPE", mkPropertyValues({"TEXT": "a"}))
+
+            self.assertFalse(document.isReadonly())
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk
index add7c20bb2ea..2b974536557b 100644
--- a/writerfilter/Library_writerfilter.mk
+++ b/writerfilter/Library_writerfilter.mk
@@ -78,6 +78,7 @@ $(eval $(call gb_Library_add_exception_objects,writerfilter,\
     writerfilter/source/dmapper/CellColorHandler \
     writerfilter/source/dmapper/CellMarginHandler \
     writerfilter/source/dmapper/ConversionHelper \
+	writerfilter/source/dmapper/DocumentProtection \
     writerfilter/source/dmapper/DomainMapper \
     writerfilter/source/dmapper/DomainMapperTableHandler \
     writerfilter/source/dmapper/DomainMapperTableManager \
@@ -113,6 +114,7 @@ $(eval $(call gb_Library_add_exception_objects,writerfilter,\
     writerfilter/source/dmapper/TblStylePrHandler \
     writerfilter/source/dmapper/ThemeTable \
     writerfilter/source/dmapper/WrapPolygonHandler \
+	writerfilter/source/dmapper/WriteProtection \
     writerfilter/source/dmapper/util \
     writerfilter/source/filter/RtfFilter \
     writerfilter/source/filter/WriterFilter \
diff --git a/writerfilter/source/dmapper/DocumentProtection.cxx b/writerfilter/source/dmapper/DocumentProtection.cxx
new file mode 100644
index 000000000000..dddf964c4022
--- /dev/null
+++ b/writerfilter/source/dmapper/DocumentProtection.cxx
@@ -0,0 +1,239 @@
+/* -*- 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 "DocumentProtection.hxx"
+#include "TagLogger.hxx"
+#include <vector>
+#include <comphelper/sequence.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter::dmapper
+{
+DocumentProtection::DocumentProtection()
+    : LoggedProperties("DocumentProtection")
+    , m_nEdit(
+          NS_ooxml::
+              LN_Value_doc_ST_DocProtect_none) // Specifies that no editing restrictions have been applied to the document
+    , m_bProtectForm(false)
+    , m_bRedlineProtection(false)
+    , m_bReadOnly(false)
+    , m_bEnforcement(false)
+    , m_bFormatting(false)
+    , m_nCryptProviderType(NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES)
+    , m_sCryptAlgorithmClass("hash")
+    , m_sCryptAlgorithmType("typeAny")
+    , m_CryptSpinCount(0)
+{
+}
+
+DocumentProtection::~DocumentProtection() {}
+
+void DocumentProtection::lcl_attribute(Id nName, Value& val)
+{
+    int nIntValue = val.getInt();
+    OUString sStringValue = val.getString();
+
+    switch (nName)
+    {
+        case NS_ooxml::LN_CT_DocProtect_edit: // 92037
+            m_nEdit = nIntValue;
+            // multiple DocProtect_edits should not exist. If they do, last one wins
+            m_bRedlineProtection = false;
+            m_bProtectForm = false;
+            m_bReadOnly = false;
+            switch (nIntValue)
+            {
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges:
+                {
+                    m_bRedlineProtection = true;
+                    m_sRedlineProtectionKey = m_sHash;
+                    break;
+                }
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_forms:
+                    m_bProtectForm = true;
+                    break;
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly:
+                    m_bReadOnly = true;
+                    break;
+            }
+            break;
+        case NS_ooxml::LN_CT_DocProtect_enforcement: // 92039
+            m_bEnforcement = (nIntValue != 0);
+            break;
+        case NS_ooxml::LN_CT_DocProtect_formatting: // 92038
+            m_bFormatting = (nIntValue != 0);
+            break;
+        case NS_ooxml::LN_AG_Password_cryptProviderType: // 92025
+            m_nCryptProviderType = nIntValue;
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmClass: // 92026
+            if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgClass_hash) // 92023
+                m_sCryptAlgorithmClass = "hash";
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmType: // 92027
+            if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgType_typeAny) // 92024
+                m_sCryptAlgorithmType = "typeAny";
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmSid: // 92028
+            m_sCryptAlgorithmSid = sStringValue;
+            break;
+        case NS_ooxml::LN_AG_Password_cryptSpinCount: // 92029
+            m_CryptSpinCount = nIntValue;
+            break;
+        case NS_ooxml::LN_AG_Password_hash: // 92035
+            m_sHash = sStringValue;
+            break;
+        case NS_ooxml::LN_AG_Password_salt: // 92036
+            m_sSalt = sStringValue;
+            break;
+        default:
+        {
+#ifdef DBG_UTIL
+            TagLogger::getInstance().element("unhandled");
+#endif
+        }
+    }
+}
+
+void DocumentProtection::lcl_sprm(Sprm& /*rSprm*/) {}
+
+uno::Sequence<beans::PropertyValue> DocumentProtection::toSequence() const
+{
+    std::vector<beans::PropertyValue> documentProtection;
+
+    if (enabled())
+    {
+        // w:edit
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "edit";
+
+            switch (m_nEdit)
+            {
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_none:
+                    aValue.Value <<= OUString("none");
+                    break;
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly:
+                    aValue.Value <<= OUString("readOnly");
+                    break;
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_comments:
+                    aValue.Value <<= OUString("comments");
+                    break;
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges:
+                    aValue.Value <<= OUString("trackedChanges");
+                    break;
+                case NS_ooxml::LN_Value_doc_ST_DocProtect_forms:
+                    aValue.Value <<= OUString("forms");
+                    break;
+                default:
+                {
+#ifdef DBG_UTIL
+                    TagLogger::getInstance().element("unhandled");
+#endif
+                }
+            }
+
+            documentProtection.push_back(aValue);
+        }
+
+        // w:enforcement
+        if (m_bEnforcement)
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "enforcement";
+            aValue.Value <<= OUString("1");
+            documentProtection.push_back(aValue);
+        }
+
+        // w:formatting
+        if (m_bFormatting)
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "formatting";
+            aValue.Value <<= OUString("1");
+            documentProtection.push_back(aValue);
+        }
+
+        // w:cryptProviderType
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "cryptProviderType";
+            if (m_nCryptProviderType == NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES)
+                aValue.Value <<= OUString("rsaAES");
+            else if (m_nCryptProviderType == NS_ooxml::LN_Value_doc_ST_CryptProv_rsaFull)
+                aValue.Value <<= OUString("rsaFull");
+            documentProtection.push_back(aValue);
+        }
+
+        // w:cryptAlgorithmClass
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "cryptAlgorithmClass";
+            aValue.Value <<= m_sCryptAlgorithmClass;
+            documentProtection.push_back(aValue);
+        }
+
+        // w:cryptAlgorithmType
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "cryptAlgorithmType";
+            aValue.Value <<= m_sCryptAlgorithmType;
+            documentProtection.push_back(aValue);
+        }
+
+        // w:cryptAlgorithmSid
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "cryptAlgorithmSid";
+            aValue.Value <<= m_sCryptAlgorithmSid;
+            documentProtection.push_back(aValue);
+        }
+
+        // w:cryptSpinCount
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "cryptSpinCount";
+            aValue.Value <<= OUString::number(m_CryptSpinCount);
+            documentProtection.push_back(aValue);
+        }
+
+        // w:hash
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "hash";
+            aValue.Value <<= m_sHash;
+            documentProtection.push_back(aValue);
+        }
+
+        // w:salt
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = "salt";
+            aValue.Value <<= m_sSalt;
+            documentProtection.push_back(aValue);
+        }
+    }
+
+    return comphelper::containerToSequence(documentProtection);
+}
+
+} //namespace writerfilter::dmapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DocumentProtection.hxx b/writerfilter/source/dmapper/DocumentProtection.hxx
new file mode 100644
index 000000000000..2ec0f3f21c41
--- /dev/null
+++ b/writerfilter/source/dmapper/DocumentProtection.hxx
@@ -0,0 +1,88 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "LoggedResources.hxx"
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <ooxml/resourceids.hxx>
+
+namespace writerfilter::dmapper
+{
+/** Document protection restrictions
+     *
+     * This element specifies the set of document protection restrictions which have been applied to the contents of a
+     * WordprocessingML document.These restrictions should be enforced by applications editing this document
+     * when the enforcement attribute is turned on, and ignored(but persisted) otherwise.Document protection is a
+     * set of restrictions used to prevent unintentional changes to all or part of a WordprocessingML document.
+     */
+class DocumentProtection : public LoggedProperties
+{
+private:
+    /** Document Editing Restrictions
+         *
+         * Possible values:
+         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_none
+         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly
+         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_comments
+         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges
+         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_forms
+         */
+    sal_Int32 m_nEdit;
+    bool m_bProtectForm;
+    bool m_bRedlineProtection;
+    OUString m_sRedlineProtectionKey;
+    bool m_bReadOnly;
+    bool m_bEnforcement;
+    bool m_bFormatting;
+
+    /** Provider type
+         *
+         * Possible values:
+         *  "rsaAES"  - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES
+         *  "rsaFull" - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaFull
+         */
+    sal_Int32 m_nCryptProviderType;
+    OUString m_sCryptAlgorithmClass;
+    OUString m_sCryptAlgorithmType;
+    OUString m_sCryptAlgorithmSid;
+    sal_Int32 m_CryptSpinCount;
+    OUString m_sHash;
+    OUString m_sSalt;
+
+    virtual void lcl_attribute(Id Name, Value& val) override;
+    virtual void lcl_sprm(Sprm& sprm) override;
+
+    bool enabled() const { return !isNone(); }
+    bool isNone() const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_none; };
+
+public:
+    DocumentProtection();
+    virtual ~DocumentProtection() override;
+
+    css::uno::Sequence<css::beans::PropertyValue> toSequence() const;
+
+    bool getProtectForm() const { return m_bProtectForm; }
+    bool getRedlineProtection() const { return m_bRedlineProtection; }
+    bool getReadOnly() const { return m_bReadOnly; }
+    bool getEnforcement() const { return m_bEnforcement; }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 616b09755a81..f11add33d7ca 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -7710,6 +7710,10 @@ void DomainMapper_Impl::ApplySettingsTable()
         {
             xSettings->setPropertyValue("GutterAtTop", uno::makeAny(true));
         }
+        uno::Sequence<beans::PropertyValue> aWriteProtection
+                = m_pSettingsTable->GetWriteProtectionSettings();
+        if (aWriteProtection.hasElements())
+                xSettings->setPropertyValue("ModifyPasswordInfo", uno::makeAny(aWriteProtection));
     }
     catch(const uno::Exception&)
     {
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index a780635b5997..f97d0a00d893 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -18,7 +18,9 @@
  */
 
 #include "SettingsTable.hxx"
+#include "DocumentProtection.hxx"
 #include "TagLogger.hxx"
+#include "WriteProtection.hxx"
 
 #include <vector>
 
@@ -32,7 +34,6 @@
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/sequence.hxx>
-#include <ooxml/resourceids.hxx>
 #include "ConversionHelper.hxx"
 #include "DomainMapper.hxx"
 #include "util.hxx"
@@ -61,176 +62,6 @@ sal_Int16 lcl_GetZoomType(Id nType)
 
 namespace dmapper
 {
-    namespace {
-
-    /** Document protection restrictions
-     *
-     * This element specifies the set of document protection restrictions which have been applied to the contents of a
-     * WordprocessingML document.These restrictions should be enforced by applications editing this document
-     * when the enforcement attribute is turned on, and ignored(but persisted) otherwise.Document protection is a
-     * set of restrictions used to prevent unintentional changes to all or part of a WordprocessingML document.
-     */
-    struct DocumentProtection_Impl
-    {
-        /** Document Editing Restrictions
-         *
-         * Possible values:
-         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_none
-         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly
-         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_comments
-         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges
-         *  - NS_ooxml::LN_Value_doc_ST_DocProtect_forms
-         */
-        sal_Int32       m_nEdit;
-        bool            m_bEnforcement;
-        bool            m_bFormatting;
-
-        /** Provider type
-         *
-         * Possible values:
-         *  "rsaAES"  - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES
-         *  "rsaFull" - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaFull
-         */
-        sal_Int32       m_nCryptProviderType;
-        OUString        m_sCryptAlgorithmClass;
-        OUString        m_sCryptAlgorithmType;
-        OUString        m_sCryptAlgorithmSid;
-        sal_Int32       m_CryptSpinCount;
-        OUString        m_sHash;
-        OUString        m_sSalt;
-
-        DocumentProtection_Impl()
-            : m_nEdit(NS_ooxml::LN_Value_doc_ST_DocProtect_none) // Specifies that no editing restrictions have been applied to the document
-            , m_bEnforcement(false)
-            , m_bFormatting(false)
-            , m_nCryptProviderType(NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES)
-            , m_sCryptAlgorithmClass("hash")
-            , m_sCryptAlgorithmType("typeAny")
-            , m_CryptSpinCount(0)
-        {
-        }
-
-        css::uno::Sequence<css::beans::PropertyValue> toSequence() const;
-
-        bool enabled() const
-        {
-            return ! isNone();
-        }
-
-        bool isNone()           const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_none; };
-    };
-
-    }
-
-    css::uno::Sequence<css::beans::PropertyValue> DocumentProtection_Impl::toSequence() const
-    {
-        std::vector<beans::PropertyValue> documentProtection;
-
-        if (enabled())
-        {
-            // w:edit
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "edit";
-
-                switch (m_nEdit)
-                {
-                case NS_ooxml::LN_Value_doc_ST_DocProtect_none:             aValue.Value <<= OUString("none"); break;
-                case NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly:         aValue.Value <<= OUString("readOnly"); break;
-                case NS_ooxml::LN_Value_doc_ST_DocProtect_comments:         aValue.Value <<= OUString("comments"); break;
-                case NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges:   aValue.Value <<= OUString("trackedChanges"); break;
-                case NS_ooxml::LN_Value_doc_ST_DocProtect_forms:            aValue.Value <<= OUString("forms"); break;
-                default:
-                {
-#ifdef DBG_UTIL
-                    TagLogger::getInstance().element("unhandled");
-#endif
-                }
-                }
-
-                documentProtection.push_back(aValue);
-            }
-
-            // w:enforcement
-            if (m_bEnforcement)
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "enforcement";
-                aValue.Value <<= OUString("1");
-                documentProtection.push_back(aValue);
-            }
-
-            // w:formatting
-            if (m_bFormatting)
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "formatting";
-                aValue.Value <<= OUString("1");
-                documentProtection.push_back(aValue);
-            }
-
-            // w:cryptProviderType
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "cryptProviderType";
-                if (m_nCryptProviderType == NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES)
-                    aValue.Value <<= OUString("rsaAES");
-                else if (m_nCryptProviderType == NS_ooxml::LN_Value_doc_ST_CryptProv_rsaFull)
-                    aValue.Value <<= OUString("rsaFull");
-                documentProtection.push_back(aValue);
-            }
-
-            // w:cryptAlgorithmClass
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "cryptAlgorithmClass";
-                aValue.Value <<= m_sCryptAlgorithmClass;
-                documentProtection.push_back(aValue);
-            }
-
-            // w:cryptAlgorithmType
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "cryptAlgorithmType";
-                aValue.Value <<= m_sCryptAlgorithmType;
-                documentProtection.push_back(aValue);
-            }
-
-            // w:cryptAlgorithmSid
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "cryptAlgorithmSid";
-                aValue.Value <<= m_sCryptAlgorithmSid;
-                documentProtection.push_back(aValue);
-            }
-
-            // w:cryptSpinCount
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "cryptSpinCount";
-                aValue.Value <<= OUString::number(m_CryptSpinCount);
-                documentProtection.push_back(aValue);
-            }
-
-            // w:hash
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "hash";
-                aValue.Value <<= m_sHash;
-                documentProtection.push_back(aValue);
-            }
-
-            // w:salt
-            {
-                beans::PropertyValue aValue;
-                aValue.Name = "salt";
-                aValue.Value <<= m_sSalt;
-                documentProtection.push_back(aValue);
-            }
-        }
-
-        return comphelper::containerToSequence(documentProtection);
-    }
 
 struct SettingsTable_Impl
 {
@@ -259,10 +90,6 @@ struct SettingsTable_Impl
     bool                m_bSplitPgBreakAndParaMark;
     bool                m_bMirrorMargin;
     bool                m_bDoNotExpandShiftReturn;
-    bool                m_bProtectForm;
-    bool                m_bRedlineProtection;
-    OUString            m_sRedlineProtectionKey;
-    bool                m_bReadOnly;
     bool                m_bDisplayBackgroundShape;
     bool                m_bNoLeading = false;
     OUString            m_sDecimalSymbol;
@@ -274,7 +101,8 @@ struct SettingsTable_Impl
     uno::Sequence<beans::PropertyValue> m_pCurrentCompatSetting;
     OUString            m_sCurrentDatabaseDataSource;
 
-    DocumentProtection_Impl m_DocumentProtection;
+    std::shared_ptr<DocumentProtection> m_pDocumentProtection;
+    std::shared_ptr<WriteProtection> m_pWriteProtection;
     bool m_bGutterAtTop = false;
 
     SettingsTable_Impl() :
@@ -301,9 +129,6 @@ struct SettingsTable_Impl
     , m_bSplitPgBreakAndParaMark(false)
     , m_bMirrorMargin(false)
     , m_bDoNotExpandShiftReturn(false)
-    , m_bProtectForm(false)
-    , m_bRedlineProtection(false)
-    , m_bReadOnly(false)
     , m_bDisplayBackgroundShape(false)
     , m_sDecimalSymbol(".")
     , m_sListSeparator(",")
@@ -325,6 +150,8 @@ SettingsTable::SettingsTable(const DomainMapper& rDomainMapper)
         // Longer space sequence is opt-in for RTF, and not in OOXML.
         m_pImpl->m_bLongerSpaceSequence = true;
     }
+    m_pImpl->m_pDocumentProtection = std::make_shared<DocumentProtection>();
+    m_pImpl->m_pWriteProtection = std::make_shared<WriteProtection>();
 }
 
 SettingsTable::~SettingsTable()
@@ -371,57 +198,6 @@ void SettingsTable::lcl_attribute(Id nName, Value & val)
         m_pImpl->m_pCurrentCompatSetting[2].Name = "val";
         m_pImpl->m_pCurrentCompatSetting[2].Value <<= sStringValue;
         break;
-    case NS_ooxml::LN_CT_DocProtect_edit: // 92037
-        m_pImpl->m_DocumentProtection.m_nEdit = nIntValue;
-        // multiple DocProtect_edits should not exist. If they do, last one wins
-        m_pImpl->m_bRedlineProtection = false;
-        m_pImpl->m_bProtectForm = false;
-        m_pImpl->m_bReadOnly = false;
-        switch (nIntValue)
-        {
-        case NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges:
-        {
-            m_pImpl->m_bRedlineProtection = true;
-            m_pImpl->m_sRedlineProtectionKey = m_pImpl->m_DocumentProtection.m_sHash;
-            break;
-        }
-        case NS_ooxml::LN_Value_doc_ST_DocProtect_forms:
-            m_pImpl->m_bProtectForm = true;
-            break;
-        case NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly:
-            m_pImpl->m_bReadOnly = true;
-            break;
-        }
-        break;
-    case NS_ooxml::LN_CT_DocProtect_enforcement: // 92039
-        m_pImpl->m_DocumentProtection.m_bEnforcement = (nIntValue != 0);
-        break;
-    case NS_ooxml::LN_CT_DocProtect_formatting: // 92038
-        m_pImpl->m_DocumentProtection.m_bFormatting = (nIntValue != 0);
-        break;
-    case NS_ooxml::LN_AG_Password_cryptProviderType: // 92025
-        m_pImpl->m_DocumentProtection.m_nCryptProviderType = nIntValue;
-        break;
-    case NS_ooxml::LN_AG_Password_cryptAlgorithmClass: // 92026
-        if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgClass_hash) // 92023
-            m_pImpl->m_DocumentProtection.m_sCryptAlgorithmClass = "hash";
-        break;
-    case NS_ooxml::LN_AG_Password_cryptAlgorithmType: // 92027
-        if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgType_typeAny) // 92024
-            m_pImpl->m_DocumentProtection.m_sCryptAlgorithmType = "typeAny";
-        break;
-    case NS_ooxml::LN_AG_Password_cryptAlgorithmSid: // 92028
-        m_pImpl->m_DocumentProtection.m_sCryptAlgorithmSid = sStringValue;
-        break;
-    case NS_ooxml::LN_AG_Password_cryptSpinCount: // 92029
-        m_pImpl->m_DocumentProtection.m_CryptSpinCount = nIntValue;
-        break;
-    case NS_ooxml::LN_AG_Password_hash: // 92035
-        m_pImpl->m_DocumentProtection.m_sHash = sStringValue;
-        break;
-    case NS_ooxml::LN_AG_Password_salt: // 92036
-        m_pImpl->m_DocumentProtection.m_sSalt = sStringValue;
-        break;
     case NS_ooxml::LN_CT_TrackChangesView_insDel:
         m_pImpl->m_bShowInsDelChanges = (nIntValue != 0);
         break;
@@ -505,7 +281,10 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
         resolveSprmProps(*this, rSprm);
         break;
     case NS_ooxml::LN_CT_Settings_documentProtection:
-        resolveSprmProps(*this, rSprm);
+        resolveSprmProps(*(m_pImpl->m_pDocumentProtection), rSprm);
+        break;
+    case NS_ooxml::LN_CT_Settings_writeProtection:
+        resolveSprmProps(*(m_pImpl->m_pWriteProtection), rSprm);
         break;
     case NS_ooxml::LN_CT_Compat_usePrinterMetrics:
         m_pImpl->m_bUsePrinterMetrics = nIntValue;
@@ -678,12 +457,15 @@ bool SettingsTable::GetDoNotExpandShiftReturn() const
 
 bool SettingsTable::GetProtectForm() const
 {
-    return m_pImpl->m_bProtectForm && m_pImpl->m_DocumentProtection.m_bEnforcement;
+    return m_pImpl->m_pDocumentProtection->getProtectForm()
+           && m_pImpl->m_pDocumentProtection->getEnforcement();
 }
 
 bool SettingsTable::GetReadOnly() const
 {
-    return m_pImpl->m_bReadOnly && m_pImpl->m_DocumentProtection.m_bEnforcement;
+    return m_pImpl->m_pWriteProtection->getRecommended()
+           || (m_pImpl->m_pDocumentProtection->getReadOnly()
+               && m_pImpl->m_pDocumentProtection->getEnforcement());
 }
 
 bool SettingsTable::GetNoHyphenateCaps() const
@@ -733,9 +515,14 @@ uno::Sequence<beans::PropertyValue> SettingsTable::GetCompatSettings() const
     return comphelper::containerToSequence(m_pImpl->m_aCompatSettings);
 }
 
-css::uno::Sequence<css::beans::PropertyValue> SettingsTable::GetDocumentProtectionSettings() const
+uno::Sequence<beans::PropertyValue> SettingsTable::GetDocumentProtectionSettings() const
+{
+    return m_pImpl->m_pDocumentProtection->toSequence();
+}
+
+uno::Sequence<beans::PropertyValue> SettingsTable::GetWriteProtectionSettings() const
 {
-    return m_pImpl->m_DocumentProtection.toSequence();
+    return m_pImpl->m_pWriteProtection->toSequence();
 }
 
 const OUString & SettingsTable::GetCurrentDatabaseDataSource() const
@@ -772,7 +559,8 @@ void SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& x
     {
         xDocProps->setPropertyValue("RecordChanges", uno::makeAny( m_pImpl->m_bRecordChanges ) );
         // Password protected Record changes
-        if ( m_pImpl->m_bRecordChanges && m_pImpl->m_bRedlineProtection && m_pImpl->m_DocumentProtection.m_bEnforcement )
+        if (m_pImpl->m_bRecordChanges && m_pImpl->m_pDocumentProtection->getRedlineProtection()
+            && m_pImpl->m_pDocumentProtection->getEnforcement())
         {
             // use dummy protection key to forbid disabling of Record changes without a notice
             // (extending the recent GrabBag support)    TODO support password verification...
diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx
index 431bb5d7c671..a0af31bed6bb 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -87,6 +87,8 @@ public:
 
     css::uno::Sequence<css::beans::PropertyValue> GetDocumentProtectionSettings() const;
 
+    css::uno::Sequence<css::beans::PropertyValue> GetWriteProtectionSettings() const;
+
     void ApplyProperties(css::uno::Reference<css::text::XTextDocument> const& xDoc);
 
     bool GetCompatSettingValue(std::u16string_view sCompatName) const;
diff --git a/writerfilter/source/dmapper/WriteProtection.cxx b/writerfilter/source/dmapper/WriteProtection.cxx
new file mode 100644
index 000000000000..724dbb77e783
--- /dev/null
+++ b/writerfilter/source/dmapper/WriteProtection.cxx
@@ -0,0 +1,143 @@
+/* -*- 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 "WriteProtection.hxx"
+#include "TagLogger.hxx"
+#include <ooxml/resourceids.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter::dmapper
+{
+WriteProtection::WriteProtection()
+    : LoggedProperties("WriteProtection")
+    , m_nCryptProviderType(NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES)
+    , m_CryptSpinCount(0)
+    , m_bRecommended(false)
+{
+}
+
+WriteProtection::~WriteProtection() {}
+
+void WriteProtection::lcl_attribute(Id nName, Value& val)
+{
+    int nIntValue = val.getInt();
+    OUString sStringValue = val.getString();
+
+    switch (nName)
+    {
+        case NS_ooxml::LN_AG_Password_cryptProviderType: // 92025
+            m_nCryptProviderType = nIntValue;
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmClass: // 92026
+            if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgClass_hash) // 92023
+                m_sCryptAlgorithmClass = "hash";
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmType: // 92027
+            if (nIntValue == NS_ooxml::LN_Value_doc_ST_AlgType_typeAny) // 92024
+                m_sCryptAlgorithmType = "typeAny";
+            break;
+        case NS_ooxml::LN_AG_Password_cryptAlgorithmSid: // 92028
+        {
+            sal_Int32 nCryptAlgorithmSid = sStringValue.toInt32();
+            switch (nCryptAlgorithmSid)
+            {
+                case 1:
+                    m_sAlgorithmName = "MD2";
+                    break;
+                case 2:
+                    m_sAlgorithmName = "MD4";
+                    break;
+                case 3:
+                    m_sAlgorithmName = "MD5";
+                    break;
+                case 4:
+                    m_sAlgorithmName = "SHA-1";
+                    break;
+                case 5:
+                    m_sAlgorithmName = "MAC";
+                    break;
+                case 6:
+                    m_sAlgorithmName = "RIPEMD";
+                    break;
+                case 7:
+                    m_sAlgorithmName = "RIPEMD-160";
+                    break;
+                case 9:
+                    m_sAlgorithmName = "HMAC";
+                    break;
+                case 12:
+                    m_sAlgorithmName = "SHA-256";
+                    break;
+                case 13:
+                    m_sAlgorithmName = "SHA-384";
+                    break;
+                case 14:
+                    m_sAlgorithmName = "SHA-512";
+                    break;
+                default:; // 8, 10, 11, any other value: Undefined.
+            }
+        }
+        break;
+        case NS_ooxml::LN_AG_Password_cryptSpinCount: // 92029
+            m_CryptSpinCount = nIntValue;
+            break;
+        case NS_ooxml::LN_AG_Password_hash: // 92035
+            m_sHash = sStringValue;
+            break;
+        case NS_ooxml::LN_AG_Password_salt: // 92036
+            m_sSalt = sStringValue;
+            break;
+        case NS_ooxml::LN_CT_WriteProtection_recommended:
+            m_bRecommended = nIntValue;
+            break;
+        default:
+        {
+#ifdef DBG_UTIL
+            TagLogger::getInstance().element("unhandled");
+#endif
+        }
+    }
+}
+
+void WriteProtection::lcl_sprm(Sprm& /*rSprm*/) {}
+
+uno::Sequence<beans::PropertyValue> WriteProtection::toSequence() const
+{
+    uno::Sequence<beans::PropertyValue> aResult;
+    if (!m_sAlgorithmName.isEmpty() && !m_sSalt.isEmpty() && !m_sHash.isEmpty()
+        && m_sCryptAlgorithmClass == "hash" && m_sCryptAlgorithmType == "typeAny")
+    {
+        aResult.realloc(4);
+        aResult[0].Name = "algorithm-name";
+        aResult[0].Value <<= m_sAlgorithmName;
+        aResult[1].Name = "salt";
+        aResult[1].Value <<= m_sSalt;
+        aResult[2].Name = "iteration-count";
+        aResult[2].Value <<= m_CryptSpinCount;
+        aResult[3].Name = "hash";
+        aResult[3].Value <<= m_sHash;
+    }
+
+    return aResult;
+}
+
+} //namespace writerfilter::dmapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/WriteProtection.hxx b/writerfilter/source/dmapper/WriteProtection.hxx
new file mode 100644
index 000000000000..21b420b4bcd9
--- /dev/null
+++ b/writerfilter/source/dmapper/WriteProtection.hxx
@@ -0,0 +1,58 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "LoggedResources.hxx"
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+namespace writerfilter::dmapper
+{
+class WriteProtection : public LoggedProperties
+{
+private:
+    /** Provider type
+         *
+         * Possible values:
+         *  "rsaAES"  - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaAES
+         *  "rsaFull" - NS_ooxml::LN_Value_doc_ST_CryptProv_rsaFull
+         */
+    sal_Int32 m_nCryptProviderType;
+    OUString m_sCryptAlgorithmClass;
+    OUString m_sCryptAlgorithmType;
+    sal_Int32 m_CryptSpinCount;
+    OUString m_sAlgorithmName;
+    OUString m_sHash;
+    OUString m_sSalt;
+    bool m_bRecommended;
+
+    virtual void lcl_attribute(Id Name, Value& val) override;
+    virtual void lcl_sprm(Sprm& sprm) override;
+
+public:
+    WriteProtection();
+    virtual ~WriteProtection() override;
+
+    css::uno::Sequence<css::beans::PropertyValue> toSequence() const;
+
+    bool getRecommended() const { return m_bRecommended; }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list