diff options
author | Serge Krot <Serge.Krot@cib.de> | 2017-10-09 12:15:05 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2017-10-10 19:35:28 +0200 |
commit | f5c266695a4a88da7db971a21915e2bbf758d48e (patch) | |
tree | b11516ba17e51898a66152e4e75eb2ff34244ef3 /writerfilter | |
parent | 9c4d690b73b30aa144828935ad4e87eb13442d0c (diff) |
tdf#66398 Parse and output permissions for DOCX using bookmarks
Change-Id: Id08998ae775c5f383edc4bf0410d16f88c70dfd6
Reviewed-on: https://gerrit.libreoffice.org/43275
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'writerfilter')
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 25 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 117 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 53 | ||||
-rw-r--r-- | writerfilter/source/ooxml/model.xml | 70 |
4 files changed, 231 insertions, 34 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index f492c2c2d033..227f55935ee3 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1125,6 +1125,26 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) } 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); } @@ -2816,11 +2836,6 @@ 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/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index be16a2307eaf..8e1423cf1380 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -202,6 +202,7 @@ DomainMapper_Impl::DomainMapper_Impl( m_bStartBibliography(false), m_bStartGenericField(false), m_bTextInserted(false), + m_sCurrentPermId(0), m_pLastSectionContext( ), m_pLastCharacterContext(), m_sCurrentParaStyleId(), @@ -4791,6 +4792,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 ) { /* @@ -4869,6 +4871,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 208318c81c12..df22413a8cbd 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -258,6 +258,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 { @@ -334,6 +377,7 @@ class DomainMapper_Impl final { public: typedef std::map < OUString, BookmarkInsertPosition > BookmarkMap_t; + typedef std::map < sal_Int32, PermInsertPosition > PermMap_t; private: SourceDocumentType m_eDocumentType; @@ -375,6 +419,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; @@ -705,6 +754,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/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 81cdc3ff9c77..a9ffbdfa6c65 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -12126,6 +12126,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> @@ -12166,6 +12169,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"> @@ -12254,6 +12275,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> @@ -13279,29 +13306,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"> @@ -16291,12 +16295,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"/> @@ -17363,6 +17361,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> @@ -17425,6 +17435,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"/> |