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@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/compilerplugins/clang/unusedfields.writeonly.results b/compilerplugins/clang/unusedfields.writeonly.results
index 7bf4af9..c97ce0c 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 0000000..f0fab46
--- /dev/null
+++ b/sw/qa/uitest/data/writeprotection.docx
Binary files differ
diff --git a/sw/qa/uitest/writer_tests6/tdf89383.py b/sw/qa/uitest/writer_tests6/tdf89383.py
new file mode 100644
index 0000000..26f5594
--- /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 add7c20..2b974536 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 0000000..dddf964
--- /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 0000000..2ec0f3f
--- /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 616b097..f11add3 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 a780635..f97d0a0 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_DocumentProtection.toSequence();
return m_pImpl->m_pDocumentProtection->toSequence();
}
uno::Sequence<beans::PropertyValue> SettingsTable::GetWriteProtectionSettings() const
{
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 431bb5d..a0af31b 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 0000000..724dbb7
--- /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 0000000..21b420b
--- /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: */