summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Krot <Serge.Krot@cib.de>2017-09-29 18:01:54 +0200
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2017-10-06 08:06:59 +0200
commit2694162969cf86ef366d3ce812fccd0630acc800 (patch)
treed138fe58a69d5c048f31e5a571b52b86a36db558
parentb567cfb980435df131d776915bce9152135bdf0f (diff)
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@libreoffice.org> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docxbin0 -> 10420 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport5.cxx16
-rw-r--r--sw/source/filter/ww8/docxexport.cxx42
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx11
-rw-r--r--writerfilter/source/dmapper/SettingsTable.cxx219
-rw-r--r--writerfilter/source/dmapper/SettingsTable.hxx2
6 files changed, 280 insertions, 10 deletions
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf66398_permissions.docx
Binary files 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: