[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - sw/qa sw/source writerfilter/source
Serge Krot
Serge.Krot at cib.de
Wed Oct 18 08:45:58 UTC 2017
Rebased ref, commits from common ancestor:
commit faa71d493a8c9ceab3a67ab7d5197d3b8ec020e2
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
This includes:
- original fix, import/export of all doc protection properties
- unit test
- remove double initialization of the form protection
- do not output document protection in docx twice
- remove useless breaks
- fix cid#1418980: Resource leak
- parse and output permissions for DOCX using bookmarks
- enhance unit test: check permissions at content level
- fix copy-paste: call start() bookmark instead of end()
Conflicts:
sw/source/filter/ww8/docxexport.cxx
writerfilter/source/dmapper/DomainMapper.cxx
sw/source/filter/ww8/docxexport.cxx
Change-Id: I63bde881507dc3c5d123bbcf96b63027522ea569
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 d4c99766b730..45f1aea29b82 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
@@ -963,6 +963,33 @@ DECLARE_OOXMLEXPORT_TEST(testSectionProtection, "sectionprot.odt")
}
}
+DECLARE_OOXMLEXPORT_TEST(tdf66398_permissions, "tdf66398_permissions.docx")
+{
+ // check document permission settings for the whole document
+ 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==");
+ }
+
+ // get bookmark interface
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xBookmarksByName(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+
+ // check: we have 2 bookmarks
+ CPPUNIT_ASSERT_EQUAL(xBookmarksByIdx->getCount(), static_cast<sal_Int32>(2));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("_GoBack"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("permission-for-group:267014232:everyone"));
+}
+
DECLARE_OOXMLEXPORT_TEST(testSectionHeader, "sectionprot.odt")
{
if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index d37e9989a0e0..2b245545583c 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1224,8 +1224,13 @@ void DocxAttributeOutput::EndRun()
// if there is some redlining in the document, output it
StartRedline( m_pRedlineData );
- DoWriteBookmarks( );
- DoWriteAnnotationMarks( );
+ // XML_r node should be surrounded with bookmark-begin and bookmark-end nodes if it has bookmarks.
+ // The same is applied for permission ranges.
+ // But due to unit test "testFdo85542" let's output bookmark-begin with bookmark-end.
+ DoWriteBookmarksStart();
+ DoWriteBookmarksEnd();
+ DoWritePermissionsStart();
+ DoWriteAnnotationMarks();
if( m_closeHyperlinkInThisRun && m_startedHyperlink && !m_hyperLinkAnchor.isEmpty() && m_hyperLinkAnchor.startsWith("_Toc"))
{
@@ -1301,6 +1306,9 @@ void DocxAttributeOutput::EndRun()
m_pSerializer->mergeTopMarks(Tag_StartRun_1);
+ // XML_r node should be surrounded with permission-begin and permission-end nodes if it has permission.
+ DoWritePermissionsEnd();
+
for (std::vector<const SwOLENode*>::iterator it = m_aPostponedMaths.begin(); it != m_aPostponedMaths.end(); ++it)
WritePostponedMath(*it);
m_aPostponedMaths.clear();
@@ -1358,41 +1366,159 @@ void DocxAttributeOutput::EndRun()
}
}
-void DocxAttributeOutput::DoWriteBookmarks()
+void DocxAttributeOutput::DoWriteBookmarkTagStart(const OUString & bookmarkName)
+{
+ const OString rId = OString::number(m_nNextBookmarkId);
+ const OString rName = OUStringToOString(BookmarkToWord(bookmarkName), RTL_TEXTENCODING_UTF8).getStr();
+
+ m_pSerializer->singleElementNS(XML_w, XML_bookmarkStart,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSNS(XML_w, XML_name), rName.getStr(),
+ FSEND);
+}
+
+void DocxAttributeOutput::DoWriteBookmarkTagEnd(const OUString & bookmarkName)
{
- // Write the start bookmarks
- for ( const auto & it : m_rBookmarksStart )
+ const auto nameToIdIter = m_rOpenedBookmarksIds.find(bookmarkName);
+ if (nameToIdIter != m_rOpenedBookmarksIds.end())
{
- OString rName = OUStringToOString( BookmarkToWord( it ), RTL_TEXTENCODING_UTF8 ).getStr();
+ const sal_Int32 nId = nameToIdIter->second;
+ const OString rId = OString::number(nId);
+
+ m_pSerializer->singleElementNS(XML_w, XML_bookmarkEnd,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSEND);
+ }
+}
+/// Write the start bookmarks
+void DocxAttributeOutput::DoWriteBookmarksStart()
+{
+ for (const OUString & bookmarkName : m_rBookmarksStart)
+ {
// Output the bookmark
- const sal_Int32 nId = m_nNextBookmarkId++;
- m_rOpenedBookmarksIds[it] = nId;
- m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
- FSNS( XML_w, XML_id ), OString::number( nId ).getStr( ),
- FSNS( XML_w, XML_name ), rName.getStr(),
- FSEND );
- m_sLastOpenedBookmark = rName;
+ DoWriteBookmarkTagStart(bookmarkName);
+
+ m_rOpenedBookmarksIds[bookmarkName] = m_nNextBookmarkId;
+ m_sLastOpenedBookmark = OUStringToOString(BookmarkToWord(bookmarkName), RTL_TEXTENCODING_UTF8).getStr();
+ m_nNextBookmarkId++;
}
m_rBookmarksStart.clear();
+}
- // export the end bookmarks
- for ( const auto & it : m_rBookmarksEnd )
+/// export the end bookmarks
+void DocxAttributeOutput::DoWriteBookmarksEnd()
+{
+ for (const OUString & bookmarkName : m_rBookmarksEnd)
{
// Get the id of the bookmark
- auto pPos = m_rOpenedBookmarksIds.find(it);
- if ( pPos != m_rOpenedBookmarksIds.end() )
+ auto pPos = m_rOpenedBookmarksIds.find(bookmarkName);
+ if (pPos != m_rOpenedBookmarksIds.end())
{
- const sal_Int32 nId = ( *pPos ).second;
- m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
- FSNS( XML_w, XML_id ), OString::number( nId ).getStr(),
- FSEND );
- m_rOpenedBookmarksIds.erase( it );
+ // Output the bookmark
+ DoWriteBookmarkTagEnd(bookmarkName);
+
+ m_rOpenedBookmarksIds.erase(bookmarkName);
}
}
m_rBookmarksEnd.clear();
}
+// For construction of the special bookmark name template for permissions:
+// see, PermInsertPosition::createBookmarkName()
+//
+// Syntax:
+// - "permission-for-user:<permission-id>:<permission-user-name>"
+// - "permission-for-group:<permission-id>:<permission-group-name>"
+//
+void DocxAttributeOutput::DoWritePermissionTagStart(const OUString & permission)
+{
+ OUString permissionIdAndName;
+
+ if (permission.startsWith("permission-for-group:", &permissionIdAndName))
+ {
+ const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+ const OUString permissionId = permissionIdAndName.copy(0, sparatorIndex);
+ const OUString permissionName = permissionIdAndName.copy(sparatorIndex + 1);
+
+ const OString rId = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+ const OString rName = OUStringToOString(BookmarkToWord(permissionName), RTL_TEXTENCODING_UTF8).getStr();
+
+ m_pSerializer->singleElementNS(XML_w, XML_permStart,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSNS(XML_w, XML_edGrp), rName.getStr(),
+ FSEND);
+ }
+ else // if (permission.startsWith("permission-for-user:", &permissionIdAndName))
+ {
+ const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+ const OUString permissionId = permissionIdAndName.copy(0, sparatorIndex);
+ const OUString permissionName = permissionIdAndName.copy(sparatorIndex + 1);
+
+ const OString rId = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+ const OString rName = OUStringToOString(BookmarkToWord(permissionName), RTL_TEXTENCODING_UTF8).getStr();
+
+ m_pSerializer->singleElementNS(XML_w, XML_permStart,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSNS(XML_w, XML_ed), rName.getStr(),
+ FSEND);
+ }
+}
+
+
+// For construction of the special bookmark name template for permissions:
+// see, PermInsertPosition::createBookmarkName()
+//
+// Syntax:
+// - "permission-for-user:<permission-id>:<permission-user-name>"
+// - "permission-for-group:<permission-id>:<permission-group-name>"
+//
+void DocxAttributeOutput::DoWritePermissionTagEnd(const OUString & permission)
+{
+ OUString permissionIdAndName;
+
+ if (permission.startsWith("permission-for-group:", &permissionIdAndName))
+ {
+ const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+ const OUString permissionId = permissionIdAndName.copy(0, sparatorIndex);
+ const OString rId = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+
+ m_pSerializer->singleElementNS(XML_w, XML_permEnd,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSEND);
+ }
+ else // if (permission.startsWith("permission-for-user:", &permissionIdAndName))
+ {
+ const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+ const OUString permissionId = permissionIdAndName.copy(0, sparatorIndex);
+ const OString rId = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+
+ m_pSerializer->singleElementNS(XML_w, XML_permEnd,
+ FSNS(XML_w, XML_id), rId.getStr(),
+ FSEND);
+ }
+}
+
+/// Write the start permissions
+void DocxAttributeOutput::DoWritePermissionsStart()
+{
+ for (const OUString & permission : m_rPermissionsStart)
+ {
+ DoWritePermissionTagStart(permission);
+ }
+ m_rPermissionsStart.clear();
+}
+
+/// export the end permissions
+void DocxAttributeOutput::DoWritePermissionsEnd()
+{
+ for (const OUString & permission : m_rPermissionsEnd)
+ {
+ DoWritePermissionTagEnd(permission);
+ }
+ m_rPermissionsEnd.clear();
+}
+
void DocxAttributeOutput::DoWriteAnnotationMarks()
{
// Write the start annotation marks
@@ -1619,13 +1745,9 @@ void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
}
// Write the bookmark start if any
- OUString aBkmName( m_sFieldBkm );
- if ( !aBkmName.isEmpty() )
+ if ( !m_sFieldBkm.isEmpty() )
{
- m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
- FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
- FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
- FSEND );
+ DoWriteBookmarkTagStart(m_sFieldBkm);
}
if (rInfos.pField ) // For hyperlinks and TOX
@@ -1649,11 +1771,9 @@ void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
}
// Write the bookmark end if any
- if ( !aBkmName.isEmpty() )
+ if ( !m_sFieldBkm.isEmpty() )
{
- m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
- FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
- FSEND );
+ DoWriteBookmarkTagEnd(m_sFieldBkm);
m_nNextBookmarkId++;
}
@@ -6772,18 +6892,33 @@ void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFie
m_Fields.begin()->pFieldmark = &rFieldmark;
}
-void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
- std::vector< OUString >& rEnds )
+void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds )
{
- for ( const auto & it : rStarts )
+ for ( const OUString & name : rStarts )
{
- m_rBookmarksStart.push_back( it );
+ if (name.startsWith("permission-for-group:") ||
+ name.startsWith("permission-for-user:"))
+ {
+ m_rPermissionsStart.push_back(name);
+ }
+ else
+ {
+ m_rBookmarksStart.push_back(name);
+ }
}
rStarts.clear();
- for ( const auto & it : rEnds )
+ for ( const OUString & name : rEnds )
{
- m_rBookmarksEnd.push_back( it );
+ if (name.startsWith("permission-for-group:") ||
+ name.startsWith("permission-for-user:"))
+ {
+ m_rPermissionsEnd.push_back(name);
+ }
+ else
+ {
+ m_rBookmarksEnd.push_back(name);
+ }
}
rEnds.clear();
}
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index fd4143081c0f..8413b487d0b4 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -692,7 +692,16 @@ protected:
private:
- void DoWriteBookmarks( );
+ void DoWriteBookmarkTagStart(const OUString & bookmarkName);
+ void DoWriteBookmarkTagEnd(const OUString & bookmarkName);
+ void DoWriteBookmarksStart();
+ void DoWriteBookmarksEnd();
+
+ void DoWritePermissionTagStart(const OUString & permission);
+ void DoWritePermissionTagEnd(const OUString & permission);
+ void DoWritePermissionsStart();
+ void DoWritePermissionsEnd();
+
void DoWriteAnnotationMarks( );
void WritePostponedGraphic();
void WritePostponedMath(const SwOLENode* pObject);
@@ -773,6 +782,10 @@ private:
std::vector<OUString> m_rBookmarksStart;
std::vector<OUString> m_rBookmarksEnd;
+ /// Permissions to output
+ std::vector<OUString> m_rPermissionsStart;
+ std::vector<OUString> m_rPermissionsEnd;
+
/// Annotation marks to output
std::vector<OString> m_rAnnotationMarksStart;
std::vector<OString> m_rAnnotationMarksEnd;
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 42900986c57c..e8e738377f25 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>
@@ -855,12 +856,6 @@ void DocxExport::WriteSettings()
pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
OString::number( m_aSettings.defaultTabStop).getStr(), FSEND );
- // Protect form
- if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::PROTECT_FORM ))
- {
- pFS->singleElementNS( XML_w, XML_documentProtection, FSNS(XML_w, XML_edit), "forms", FSNS(XML_w, XML_enforcement), "1", FSEND );
- }
-
// 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);
@@ -887,12 +882,14 @@ void DocxExport::WriteSettings()
// Has themeFontLang information
uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
+ bool hasProtectionProperties = false;
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" )
@@ -921,6 +918,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;
@@ -947,18 +945,64 @@ void DocxExport::WriteSettings()
pFS->endElementNS( XML_w, XML_compat );
}
+ else if (propList[i].Name == "DocumentProtection")
+ {
+
+ uno::Sequence< beans::PropertyValue > rAttributeList;
+ propList[i].Value >>= rAttributeList;
+
+ if (rAttributeList.getLength())
+ {
+ sax_fastparser::FastAttributeList* pAttributeList = sax_fastparser::FastSerializerHelper::createAttrList();
+ 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());
+ }
+
+ // we have document protection from from input DOCX file
+
+ sax_fastparser::XFastAttributeListRef xAttributeList(pAttributeList);
+ pFS->singleElementNS(XML_w, XML_documentProtection, xAttributeList);
+
+ hasProtectionProperties = true;
+ }
+ }
}
}
+ // Protect form
// Section-specific write protection
- if ( m_pSections->DocumentIsProtected() )
+ if (! hasProtectionProperties)
{
- pFS->singleElementNS( XML_w, XML_documentProtection,
- FSNS( XML_w, XML_enforcement ), "true",
- FSNS( XML_w, XML_edit ), "forms",
- FSEND );
+ if (m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM) ||
+ m_pSections->DocumentIsProtected())
+ {
+ // we have form protection from Writer or from input ODT file
+
+ pFS->singleElementNS(XML_w, XML_documentProtection,
+ FSNS(XML_w, XML_edit), "forms",
+ FSNS(XML_w, XML_enforcement), "true",
+ FSEND);
+ }
}
+ // finish settings.xml
pFS->endElementNS( XML_w, XML_settings );
}
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 789aebea2cf8..138fca3f7863 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -190,10 +190,14 @@ DomainMapper::~DomainMapper()
// Grab-bag handling
comphelper::SequenceAsHashMap aProperties;
+
// Add the saved w:themeFontLang setting
aProperties["ThemeFontLangProps"] = uno::makeAny(GetThemeFontLangProperties());
// Add the saved compat settings
aProperties["CompatSettings"] = uno::makeAny(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())
{
@@ -1077,6 +1081,26 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
case NS_ooxml::LN_CT_Cnf_val:
m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "val", sStringValue);
break;
+ case NS_ooxml::LN_CT_PermStart_ed:
+ {
+ m_pImpl->setPermissionRangeEd(sStringValue);
+ break;
+ }
+ case NS_ooxml::LN_CT_PermStart_edGrp:
+ {
+ m_pImpl->setPermissionRangeEdGrp(sStringValue);
+ break;
+ }
+ case NS_ooxml::LN_CT_PermStart_id:
+ {
+ m_pImpl->startOrEndPermissionRange(nIntValue);
+ break;
+ }
+ case NS_ooxml::LN_CT_PermEnd_id:
+ {
+ m_pImpl->startOrEndPermissionRange(nIntValue);
+ break;
+ }
default:
SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled token: " << nName);
}
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index bd532b87cc19..19d6f1a82985 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -199,6 +199,7 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bTOCPageRef(false),
m_bStartGenericField(false),
m_bTextInserted(false),
+ m_sCurrentPermId(0),
m_pLastSectionContext( ),
m_pLastCharacterContext(),
m_nCurrentTabStopIndex( 0 ),
@@ -4586,6 +4587,7 @@ void DomainMapper_Impl::SetBookmarkName( const OUString& rBookmarkName )
m_sCurrentBkmkName = rBookmarkName;
}
+// This method was used as-is for DomainMapper_Impl::startOrEndPermissionRange() implementation.
void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
{
/*
@@ -4665,6 +4667,121 @@ void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
}
}
+void DomainMapper_Impl::setPermissionRangeEd(const OUString& user)
+{
+ PermMap_t::iterator aPremIter = m_aPermMap.find(m_sCurrentPermId);
+ if (aPremIter != m_aPermMap.end())
+ aPremIter->second.m_Ed = user;
+ else
+ m_sCurrentPermEd = user;
+}
+
+void DomainMapper_Impl::setPermissionRangeEdGrp(const OUString& group)
+{
+ PermMap_t::iterator aPremIter = m_aPermMap.find(m_sCurrentPermId);
+ if (aPremIter != m_aPermMap.end())
+ aPremIter->second.m_EdGrp = group;
+ else
+ m_sCurrentPermEdGrp = group;
+}
+
+// This method is based on implementation from DomainMapper_Impl::StartOrEndBookmark()
+void DomainMapper_Impl::startOrEndPermissionRange(sal_Int32 permissinId)
+{
+ /*
+ * Add the dummy paragraph to handle section properties
+ * if the first element in the section is a table. If the dummy para is not added yet, then add it;
+ * So permission is not attached to the wrong paragraph.
+ */
+ if (getTableManager().isInCell() && m_nTableDepth == 0 && GetIsFirstParagraphInSection()
+ && !GetIsDummyParaAddedForTableInSection() && !GetIsTextFrameInserted())
+ {
+ AddDummyParaForTableInSection();
+ }
+
+ if (m_aTextAppendStack.empty())
+ return;
+
+ const bool bIsAfterDummyPara = GetIsDummyParaAddedForTableInSection() && GetIsFirstParagraphInSection();
+
+ uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
+ PermMap_t::iterator aPermIter = m_aPermMap.find(permissinId);
+
+ //is the bookmark name already registered?
+ try
+ {
+ if (aPermIter == m_aPermMap.end())
+ {
+ //otherwise insert a text range as marker
+ bool bIsStart = true;
+ uno::Reference< text::XTextRange > xCurrent;
+ if (xTextAppend.is())
+ {
+ uno::Reference< text::XTextCursor > xCursor = xTextAppend->createTextCursorByRange(xTextAppend->getEnd());
+
+ if (!bIsAfterDummyPara)
+ bIsStart = !xCursor->goLeft(1, false);
+ xCurrent = xCursor->getStart();
+ }
+
+ // register the start of the new permission
+ m_sCurrentPermId = permissinId;
+ m_aPermMap.emplace(permissinId, PermInsertPosition(bIsStart, permissinId, m_sCurrentPermEd, m_sCurrentPermEdGrp, xCurrent));
+
+ // clean up
+ m_sCurrentPermEd.clear();
+ m_sCurrentPermEdGrp.clear();
+ }
+ else
+ {
+ if (m_xTextFactory.is())
+ {
+ uno::Reference< text::XTextCursor > xCursor;
+ uno::Reference< text::XText > xText = aPermIter->second.m_xTextRange->getText();
+ if (aPermIter->second.m_bIsStartOfText && !bIsAfterDummyPara)
+ {
+ xCursor = xText->createTextCursorByRange(xText->getStart());
+ }
+ else
+ {
+ xCursor = xText->createTextCursorByRange(aPermIter->second.m_xTextRange);
+ xCursor->goRight(1, false);
+ }
+
+ xCursor->gotoRange(xTextAppend->getEnd(), true);
+ // A Paragraph was recently finished, and a new Paragraph has not been started as yet
+ // then move the bookmark-End to the earlier paragraph
+ if (IsOutsideAParagraph())
+ {
+ xCursor->goLeft(1, false);
+ }
+
+ // create a new bookmark using specific bookmark name pattern for permissions
+ uno::Reference< text::XTextContent > xPerm(m_xTextFactory->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY_THROW);
+ uno::Reference< container::XNamed > xPermNamed(xPerm, uno::UNO_QUERY_THROW);
+ xPermNamed->setName(aPermIter->second.createBookmarkName());
+
+ // add new bookmark
+ const bool bAbsorb = !xCursor->isCollapsed();
+ uno::Reference< text::XTextRange > xCurrent = uno::Reference< text::XTextRange >(xCursor, uno::UNO_QUERY_THROW);
+ xTextAppend->insertTextContent(xCurrent, xPerm, bAbsorb);
+ }
+
+ // remove proccessed permission
+ m_aPermMap.erase(aPermIter);
+
+ // clean up
+ m_sCurrentPermId = 0;
+ m_sCurrentPermEd.clear();
+ m_sCurrentPermEdGrp.clear();
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ //TODO: What happens to bookmarks where start and end are at different XText objects?
+ }
+}
+
void DomainMapper_Impl::AddAnnotationPosition(
const bool bStart,
const sal_Int32 nAnnotationId)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 37bea0a84605..ad96d4c77ef9 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -261,6 +261,49 @@ struct BookmarkInsertPosition
{}
};
+struct PermInsertPosition
+{
+ bool m_bIsStartOfText;
+ sal_Int32 m_Id;
+ OUString m_Ed;
+ OUString m_EdGrp;
+
+ css::uno::Reference<css::text::XTextRange> m_xTextRange;
+
+ PermInsertPosition(bool bIsStartOfText, sal_Int32 id, const OUString& ed, const OUString& edGrp, css::uno::Reference<css::text::XTextRange> const& xTextRange)
+ : m_bIsStartOfText(bIsStartOfText)
+ , m_Id(id)
+ , m_Ed(ed)
+ , m_EdGrp(edGrp)
+ , m_xTextRange(xTextRange)
+ {}
+
+ OUString createBookmarkName() const
+ {
+ OUString bookmarkName;
+
+ assert((!m_Ed.isEmpty()) || (!m_EdGrp.isEmpty()));
+
+ if (m_Ed.isEmpty())
+ {
+ bookmarkName += "permission-for-group:";
+ bookmarkName += OUString::number(m_Id);
+ bookmarkName += ":";
+ bookmarkName += m_EdGrp;
+ }
+ else
+ {
+ bookmarkName += "permission-for-user:";
+ bookmarkName += OUString::number(m_Id);
+ bookmarkName += ":";
+ bookmarkName += m_Ed;
+ }
+
+ //todo: make sure the name is not used already!
+ return bookmarkName;
+ }
+};
+
/// Stores the start/end positions of an annotation before its insertion.
struct AnnotationPosition
{
@@ -339,6 +382,7 @@ class DomainMapper_Impl
{
public:
typedef std::map < OUString, BookmarkInsertPosition > BookmarkMap_t;
+ typedef std::map < sal_Int32, PermInsertPosition > PermMap_t;
private:
SourceDocumentType m_eDocumentType;
@@ -380,6 +424,11 @@ private:
OUString m_sCurrentBkmkId;
OUString m_sCurrentBkmkName;
+ PermMap_t m_aPermMap;
+ sal_Int32 m_sCurrentPermId;
+ OUString m_sCurrentPermEd;
+ OUString m_sCurrentPermEdGrp;
+
PageMar m_aPageMargins;
SymbolData m_aSymbolData;
@@ -696,6 +745,10 @@ public:
void SetBookmarkName( const OUString& rBookmarkName );
void StartOrEndBookmark( const OUString& rId );
+ void setPermissionRangeEd(const OUString& user);
+ void setPermissionRangeEdGrp(const OUString& group);
+ void startOrEndPermissionRange(sal_Int32 permissinId);
+
void AddAnnotationPosition(
const bool bStart,
const sal_Int32 nAnnotationId );
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index 10791f065f5e..56c1c247e7df 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -38,6 +38,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_nHyphenationZone(0)
@@ -146,12 +318,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;
@@ -229,9 +427,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;
@@ -363,6 +559,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 648bf6d41b93..347de39c2cdf 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -77,6 +77,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:
diff --git a/writerfilter/source/ooxml/factoryimpl.py b/writerfilter/source/ooxml/factoryimpl.py
index 8584e196cb38..519936b7b42e 100644
--- a/writerfilter/source/ooxml/factoryimpl.py
+++ b/writerfilter/source/ooxml/factoryimpl.py
@@ -25,7 +25,7 @@ def createFastChildContextFromFactory(model):
(OOXMLFastContextHandler* pHandler, OOXMLFactory_ns::Pointer_t pFactory, Token_t Element)
{
uno::Reference <xml::sax::XFastContextHandler> aResult;
- Id nDefine = pHandler->getDefine();
+ const Id nDefine = pHandler->getDefine();
if (pFactory.get() != NULL)
{
@@ -33,7 +33,7 @@ def createFastChildContextFromFactory(model):
Id nElementId;
if (pFactory->getElementId(nDefine, Element, nResource, nElementId))
{
- Id nId = pFactory->getResourceId(nDefine, Element);
+ const Id nId = pFactory->getResourceId(nDefine, Element);
switch (nResource)
{""")
@@ -118,7 +118,6 @@ public:
std::string fastTokenToId(sal_uInt32 nToken)
{
-
std::string sResult;
#ifdef DEBUG_WRITERFILTER
diff --git a/writerfilter/source/ooxml/factoryimpl_ns.py b/writerfilter/source/ooxml/factoryimpl_ns.py
index d9baaa1c3613..a222af8e8fb0 100644
--- a/writerfilter/source/ooxml/factoryimpl_ns.py
+++ b/writerfilter/source/ooxml/factoryimpl_ns.py
@@ -235,7 +235,6 @@ def printValueData(values):
output_else = "else "
print(" else { return false; }")
print(" return true;")
- print(" break;")
print(" }")
@@ -258,7 +257,6 @@ def factoryGetListValue(nsNode):
appendValueData(values, valueData, idToLabel(valueNode.getAttribute("tokenid")))
printValueData(values)
print(" return false;")
- print(" break;")
print(""" default:
break;
@@ -376,7 +374,6 @@ def factoryCreateElementMap(files, nsNode):
print(" default: return false;")
print(" }")
print(" return true;")
- print(" break;")
print(" default:")
print(" switch (nId)")
print(" {")
@@ -384,10 +381,7 @@ def factoryCreateElementMap(files, nsNode):
print(""" default: return false;
}
return true;
- break;
}
-
- return false;
}
""")
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 1f5aa8285ecc..a96acdc05627 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -12117,6 +12117,9 @@
</attribute>
<ref name="CT_MarkupRange"/>
</define>
+ <define name="CT_MarkupRangePerm">
+ <ref name="CT_MarkupRange"/>
+ </define>
<define name="CT_MarkupRangeCommentStart">
<ref name="CT_Markup"/>
</define>
@@ -12157,6 +12160,24 @@
<ref name="ST_String"/>
</attribute>
</define>
+ <define name="CT_PermStart">
+ <ref name="CT_MarkupRangePerm"/>
+ <attribute name="ed">
+ <data type="string"/>
+ </attribute>
+ <attribute name="edGrp">
+ <data type="string"/>
+ </attribute>
+ <attribute name="colFirst">
+ <data type="ST_DecimalNumber"/>
+ </attribute>
+ <attribute name="colLast">
+ <data type="ST_DecimalNumber"/>
+ </attribute>
+ </define>
+ <define name="CT_PermEnd">
+ <ref name="CT_MarkupRangePerm"/>
+ </define>
<define name="CT_TrackChangeNumbering">
<ref name="CT_TrackChange"/>
<attribute name="original">
@@ -12245,6 +12266,12 @@
<element name="bookmarkEnd">
<ref name="CT_MarkupRangeBookmark"/>
</element>
+ <element name="permStart">
+ <ref name="CT_PermStart"/>
+ </element>
+ <element name="permEnd">
+ <ref name="CT_PermEnd"/>
+ </element>
<element name="moveFromRangeStart">
<ref name="CT_MoveBookmark"/>
</element>
@@ -13271,29 +13298,6 @@
<data type="string"/>
</attribute>
</define>
- <define name="CT_Perm">
- <attribute name="id">
- <data type="string"/>
- </attribute>
- <attribute name="displacedByCustomXml">
- <data type="string"/>
- </attribute>
- </define>
- <define name="CT_PermStart">
- <ref name="CT_Perm"/>
- <attribute name="edGrp">
- <data type="string"/>
- </attribute>
- <attribute name="ed">
- <data type="string"/>
- </attribute>
- <attribute name="colFirst">
- <data type="string"/>
- </attribute>
- <attribute name="colLast">
- <data type="string"/>
- </attribute>
- </define>
<define name="CT_Text">
<ref name="ST_String"/>
<attribute name="xml:space">
@@ -16255,12 +16259,6 @@
<element name="proofErr">
<ref name="CT_ProofErr"/>
</element>
- <element name="permStart">
- <ref name="CT_PermStart"/>
- </element>
- <element name="permEnd">
- <ref name="CT_Perm"/>
- </element>
<ref name="EG_RangeMarkupElements"/>
<element name="ins">
<ref name="CT_RunTrackChange"/>
@@ -17326,6 +17324,18 @@
<resource name="CT_MarkupRangeBookmark" resource="Properties">
<attribute name="id" tokenid="ooxml:CT_MarkupRangeBookmark_id"/>
</resource>
+ <resource name="CT_PermStart" resource="Properties">
+ <attribute name="id" tokenid="ooxml:CT_PermStart_id"/>
+ <attribute name="colFirst" tokenid="ooxml:CT_PermStart_colFirst"/>
+ <attribute name="colLast" tokenid="ooxml:CT_PermStart_colLast"/>
+ <attribute name="ed" tokenid="ooxml:CT_PermStart_ed"/>
+ <attribute name="edGrp" tokenid="ooxml:CT_PermStart_edGrp"/>
+ <attribute name="displacedByCustomXml" tokenid="ooxml:CT_PermStart_displacedByCustomXml"/>
+ </resource>
+ <resource name="CT_PermEnd" resource="Properties">
+ <attribute name="id" tokenid="ooxml:CT_PermEnd_id"/>
+ <attribute name="displacedByCustomXml" tokenid="ooxml:CT_PermEnd_displacedByCustomXml"/>
+ </resource>
<resource name="CT_MarkupRangeCommentStart" resource="Properties">
<attribute name="id" tokenid="ooxml:EG_RangeMarkupElements_commentRangeStart"/>
</resource>
@@ -17388,6 +17398,8 @@
<resource name="EG_RangeMarkupElements" resource="Properties">
<element name="bookmarkStart" tokenid="ooxml:EG_RangeMarkupElements_bookmarkStart"/>
<element name="bookmarkEnd" tokenid="ooxml:EG_RangeMarkupElements_bookmarkEnd"/>
+ <element name="permStart" tokenid="ooxml:EG_RangeMarkupElements_PermStart"/>
+ <element name="permEnd" tokenid="ooxml:EG_RangeMarkupElements_PermEnd"/>
<element name="moveFromRangeStart" tokenid="ooxml:EG_RangeMarkupElements_moveFromRangeStart"/>
<element name="moveFromRangeEnd" tokenid="ooxml:EG_RangeMarkupElements_moveFromRangeEnd"/>
<element name="moveToRangeStart" tokenid="ooxml:EG_RangeMarkupElements_moveToRangeStart"/>
More information about the Libreoffice-commits
mailing list