[Libreoffice-commits] core.git: sw/qa sw/source writerfilter/source

Serge Krot Serge.Krot at cib.de
Fri Oct 6 06:07:27 UTC 2017


 sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport5.cxx               |   16 +
 sw/source/filter/ww8/docxexport.cxx                     |   42 ++-
 writerfilter/source/dmapper/DomainMapper.cxx            |   11 
 writerfilter/source/dmapper/SettingsTable.cxx           |  219 +++++++++++++++-
 writerfilter/source/dmapper/SettingsTable.hxx           |    2 
 6 files changed, 280 insertions(+), 10 deletions(-)

New commits:
commit 2694162969cf86ef366d3ce812fccd0630acc800
Author: Serge Krot <Serge.Krot at cib.de>
Date:   Fri Sep 29 18:01:54 2017 +0200

    tdf#66398 Import/export docx document protection properties
    
    Added:
    + import/export of all doc protection properties
    + unit test
    
    Change-Id: I7b65cf4f5c7add2a96fef407c243081fcc2b6d8d
    Reviewed-on: https://gerrit.libreoffice.org/43156
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docx b/sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docx
new file mode 100644
index 000000000000..d5c855994811
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
index 96868a3b6f66..418b0dc64019 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
@@ -945,6 +945,22 @@ DECLARE_OOXMLEXPORT_TEST(testSectionProtection, "sectionprot.odt")
     }
 }
 
+DECLARE_OOXMLEXPORT_TEST(tdf66398_permissions, "tdf66398_permissions.docx")
+{
+    if (xmlDocPtr pXmlSettings = parseExport("word/settings.xml"))
+    {
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "edit",               "readOnly");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "enforcement",        "1");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "cryptProviderType",  "rsaAES");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "cryptAlgorithmClass","hash");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "cryptAlgorithmType", "typeAny");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "cryptAlgorithmSid",  "14");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "cryptSpinCount",     "100000");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "hash",               "A0/Xy6KcXljJlZjP0TwJMPJuW2rc46UwXqn2ctxckc2nCECE5i89M85z2Noh3ZEA5NBQ9RJ5ycxiUH6nzmJaKw==");
+        assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "salt",               "B8k6wb1pkjUs4Nv/8QBk/w==");
+    }
+}
+
 DECLARE_OOXMLEXPORT_TEST(testSectionHeader, "sectionprot.odt")
 {
     if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 2b8d97fb43e6..b76c121bb0d2 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -21,6 +21,7 @@
 #include "docxexportfilter.hxx"
 #include "docxattributeoutput.hxx"
 #include "docxsdrexport.hxx"
+#include "docxhelper.hxx"
 
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XDocumentProperties.hpp>
@@ -935,6 +936,7 @@ void DocxExport::WriteSettings()
     {
         pFS->singleElementNS( XML_w, XML_documentProtection, FSNS(XML_w, XML_edit), "forms", FSNS(XML_w, XML_enforcement), "1",  FSEND );
     }
+
     // Do not justify lines with manual break
     if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK ))
     {
@@ -942,6 +944,7 @@ void DocxExport::WriteSettings()
         pFS->singleElementNS( XML_w, XML_doNotExpandShiftReturn, FSEND );
         pFS->endElementNS( XML_w, XML_compat );
     }
+
     // Automatic hyphenation: it's a global setting in Word, it's a paragraph setting in Writer.
     // Use the setting from the default style.
     SwTextFormatColl* pColl = m_pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, /*bRegardLanguage=*/false);
@@ -969,11 +972,12 @@ void DocxExport::WriteSettings()
     uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
 
     uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
-    OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
+    const OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
     if ( xPropSetInfo->hasPropertyByName( aGrabBagName ) )
     {
         uno::Sequence< beans::PropertyValue > propList;
         xPropSet->getPropertyValue( aGrabBagName ) >>= propList;
+
         for( sal_Int32 i=0; i < propList.getLength(); ++i )
         {
             if ( propList[i].Name == "ThemeFontLangProps" )
@@ -1002,6 +1006,7 @@ void DocxExport::WriteSettings()
 
                 uno::Sequence< beans::PropertyValue > aCompatSettingsSequence;
                 propList[i].Value >>= aCompatSettingsSequence;
+
                 for(sal_Int32 j=0; j < aCompatSettingsSequence.getLength(); ++j)
                 {
                     uno::Sequence< beans::PropertyValue > aCompatSetting;
@@ -1025,8 +1030,43 @@ void DocxExport::WriteSettings()
                         FSNS( XML_w, XML_val ),  OUStringToOString(aValue, RTL_TEXTENCODING_UTF8).getStr(),
                         FSEND);
                 }
+
                 pFS->endElementNS( XML_w, XML_compat );
             }
+            else if (propList[i].Name == "DocumentProtection")
+            {
+                sax_fastparser::FastAttributeList* pAttributeList = sax_fastparser::FastSerializerHelper::createAttrList();
+
+                uno::Sequence< beans::PropertyValue > rAttributeList;
+                propList[i].Value >>= rAttributeList;
+
+                for (sal_Int32 j = 0; j < rAttributeList.getLength(); ++j)
+                {
+                    static DocxStringTokenMap const aTokens[] =
+                    {
+                        { "edit",                XML_edit },
+                        { "enforcement",         XML_enforcement },
+                        { "formatting",          XML_formatting },
+                        { "cryptProviderType",   XML_cryptProviderType },
+                        { "cryptAlgorithmClass", XML_cryptAlgorithmClass },
+                        { "cryptAlgorithmType",  XML_cryptAlgorithmType },
+                        { "cryptAlgorithmSid",   XML_cryptAlgorithmSid },
+                        { "cryptSpinCount",      XML_cryptSpinCount },
+                        { "hash",                XML_hash },
+                        { "salt",                XML_salt },
+                        { nullptr, 0 }
+                    };
+
+                    if (sal_Int32 nToken = DocxStringGetToken(aTokens, rAttributeList[j].Name))
+                        pAttributeList->add(FSNS(XML_w, nToken), rAttributeList[j].Value.get<OUString>().toUtf8());
+                }
+
+                if (rAttributeList.getLength())
+                {
+                    sax_fastparser::XFastAttributeListRef xAttributeList(pAttributeList);
+                    pFS->singleElementNS(XML_w, XML_documentProtection, xAttributeList);
+                }
+            }
         }
     }
 
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index a158615c583e..f492c2c2d033 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -206,10 +206,16 @@ DomainMapper::~DomainMapper()
 
         // Grab-bag handling
         comphelper::SequenceAsHashMap aProperties;
+
         // Add the saved w:themeFontLang setting
         aProperties["ThemeFontLangProps"] <<= m_pImpl->GetSettingsTable()->GetThemeFontLangProperties();
+
         // Add the saved compat settings
         aProperties["CompatSettings"] <<= m_pImpl->GetSettingsTable()->GetCompatSettings();
+
+        // Add the saved DocumentProtection settings
+        aProperties["DocumentProtection"] <<= m_pImpl->GetSettingsTable()->GetDocumentProtectionSettings();
+
         uno::Reference<beans::XPropertySet> xDocProps(m_pImpl->GetTextDocument(), uno::UNO_QUERY);
         if (xDocProps.is())
         {
@@ -2810,6 +2816,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
             pProperties->resolve(*this);
     }
     break;
+    case NS_ooxml::LN_EG_RunLevelElts_permStart: // 93164
+    case NS_ooxml::LN_EG_RunLevelElts_permEnd: // 93165
+    {
+        break;
+    }
     default:
         {
 #ifdef DEBUG_WRITERFILTER
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index 9c5fed0ec78a..b747eb37abdb 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -39,6 +39,176 @@ namespace writerfilter {
 
 namespace 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.
+     */
+    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; };
+        // bool isReadOnly()       const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_readOnly; };
+        // bool isComments()       const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_comments; };
+        // bool isTrackChanges()   const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_trackedChanges; };
+        bool isForms()          const { return m_nEdit == NS_ooxml::LN_Value_doc_ST_DocProtect_forms; };
+    };
+
+    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 DEBUG_WRITERFILTER
+                    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
 {
@@ -71,6 +241,8 @@ struct SettingsTable_Impl
     std::vector<beans::PropertyValue> m_aCompatSettings;
     uno::Sequence<beans::PropertyValue> m_pCurrentCompatSetting;
 
+    DocumentProtection_Impl m_DocumentProtection;
+
     SettingsTable_Impl() :
       m_nDefaultTabStop( 720 ) //default is 1/2 in
     , m_bRecordChanges(false)
@@ -147,12 +319,40 @@ 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:
-        m_pImpl->m_bProtectForm = (nIntValue == NS_ooxml::LN_Value_doc_ST_DocProtect_forms);
+    case NS_ooxml::LN_CT_DocProtect_edit: // 92037
+        m_pImpl->m_DocumentProtection.m_nEdit = nIntValue;
+        m_pImpl->m_bProtectForm = m_pImpl->m_DocumentProtection.isForms();
         break;
-    case NS_ooxml::LN_CT_DocProtect_enforcement:
+    case NS_ooxml::LN_CT_DocProtect_enforcement: // 92039
+        m_pImpl->m_DocumentProtection.m_bEnforcement = (nIntValue != 0);
         m_pImpl->m_bProtectForm &= (bool)nIntValue;
         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;
     default:
     {
 #ifdef DEBUG_WRITERFILTER
@@ -184,9 +384,7 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
     case NS_ooxml::LN_CT_Settings_view:
     //PropertySetValues - need to be resolved
     {
-        writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
-        if( pProperties.get())
-            pProperties->resolve(*this);
+        resolveSprmProps(*this, rSprm);
     }
     break;
     case NS_ooxml::LN_CT_Settings_stylePaneFormatFilter: // 92493;
@@ -226,9 +424,7 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
     }
     break;
     case NS_ooxml::LN_CT_Settings_documentProtection:
-        {
-            resolveSprmProps(*this, rSprm);
-        }
+        resolveSprmProps(*this, rSprm);
         break;
     case NS_ooxml::LN_CT_Compat_usePrinterMetrics:
         m_pImpl->m_bUsePrinterMetrics = nIntValue;
@@ -376,6 +572,11 @@ uno::Sequence<beans::PropertyValue> SettingsTable::GetCompatSettings() const
     return comphelper::containerToSequence(m_pImpl->m_aCompatSettings);
 }
 
+css::uno::Sequence<css::beans::PropertyValue> SettingsTable::GetDocumentProtectionSettings() const
+{
+    return m_pImpl->m_DocumentProtection.toSequence();
+}
+
 static bool lcl_isDefault(const uno::Reference<beans::XPropertyState>& xPropertyState, const OUString& rPropertyName)
 {
     return xPropertyState->getPropertyState(rPropertyName) == beans::PropertyState_DEFAULT_VALUE;
diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx
index 28db5c26fb73..2a80bd186fc1 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -79,6 +79,8 @@ class SettingsTable : public LoggedProperties, public LoggedTable
 
     css::uno::Sequence<css::beans::PropertyValue> GetCompatSettings() const;
 
+    css::uno::Sequence<css::beans::PropertyValue> GetDocumentProtectionSettings() const;
+
     void ApplyProperties(css::uno::Reference<css::text::XTextDocument> const& xDoc);
 
  private:


More information about the Libreoffice-commits mailing list