include/xmloff/xmlnamespace.hxx | 3 solenv/bin/hrcex | 13 solenv/bin/polib.py | 2 solenv/bin/uiex | 10 sw/qa/extras/uiwriter/data3/tdf140828.docx |binary sw/qa/extras/uiwriter/uiwriter3.cxx | 32 sw/qa/uitest/writer_dialogs/openDialogs.py | 3 sw/qa/uitest/writer_tests7/tdf140863.py | 75 + sw/source/core/doc/textboxhelper.cxx | 5 sw/source/core/docnode/section.cxx | 44 sw/source/core/text/porfly.cxx | 4 xmlsecurity/source/helper/ooxmlsecparser.cxx | 1473 +++++++++++++++++++++++---- xmlsecurity/source/helper/ooxmlsecparser.hxx | 74 - 13 files changed, 1460 insertions(+), 278 deletions(-)
New commits: commit 64b4af53d44243ff662a8b0cd404f134b589983e Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Wed Mar 31 15:05:09 2021 +0200 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Thu Apr 1 10:07:48 2021 +0200 tdf#140863: sw: Add UItest Change-Id: Ic1d3a56857dd68f436b870168ab394729a31d629 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113365 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/uitest/writer_dialogs/openDialogs.py b/sw/qa/uitest/writer_dialogs/openDialogs.py index 4dbacaa1215e..086904cc3712 100644 --- a/sw/qa/uitest/writer_dialogs/openDialogs.py +++ b/sw/qa/uitest/writer_dialogs/openDialogs.py @@ -37,7 +37,8 @@ dialogs = [ # {"command": ".uno:InsertBreak", "closeButton": "cancel"}, # tested in uitest/writer_tests/insertBreakDialog.py {"command": ".uno:InsertObject", "closeButton": "cancel"}, - {"command": ".uno:InsertSection", "closeButton": "cancel"}, + # {"command": ".uno:InsertSection", "closeButton": "cancel"}, + # tested in sw/qa/uitest/writer_tests7/tdf140863.py {"command": ".uno:InsertFrame", "closeButton": "cancel"}, {"command": ".uno:InsertObjectFloatingFrame", "closeButton": "cancel"}, {"command": ".uno:FontworkGalleryFloater", "closeButton": "cancel"}, diff --git a/sw/qa/uitest/writer_tests7/tdf140863.py b/sw/qa/uitest/writer_tests7/tdf140863.py new file mode 100644 index 000000000000..f0355e4684ed --- /dev/null +++ b/sw/qa/uitest/writer_tests7/tdf140863.py @@ -0,0 +1,75 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict + +class tdf140863(UITestCase): + + def test_tdf140863(self): + + self.ui_test.create_doc_in_start_center("writer") + + # Insert one section + self.ui_test.execute_dialog_through_command(".uno:InsertSection") + + xDialog = self.xUITest.getTopFocusWindow() + + xOkBtn = xDialog.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + # Insert a page break in the section + xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "UP"})) + self.xUITest.executeCommand(".uno:InsertPagebreak") + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "2") + + document = self.ui_test.get_component() + self.assertEqual(1, len(document.TextSections)) + self.assertTrue(document.TextSections.Section1.IsVisible) + + + self.ui_test.execute_dialog_through_command(".uno:EditRegion") + + xDialog = self.xUITest.getTopFocusWindow() + + xHide = xDialog.getChild('hide') + self.assertEqual('false', get_state_as_dict(xHide)['Selected']) + + xHide.executeAction('CLICK', tuple()) + + xOkBtn = xDialog.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.assertEqual(1, len(document.TextSections)) + self.assertFalse(document.TextSections.Section1.IsVisible) + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "1") + + self.ui_test.execute_dialog_through_command(".uno:EditRegion") + + xDialog = self.xUITest.getTopFocusWindow() + + xHide = xDialog.getChild('hide') + self.assertEqual('true', get_state_as_dict(xHide)['Selected']) + + xHide.executeAction('CLICK', tuple()) + + xOkBtn = xDialog.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.assertEqual(1, len(document.TextSections)) + self.assertTrue(document.TextSections.Section1.IsVisible) + + # Without the fix in place, this test would have failed with + # AssertionError: '1' != '2' + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "2") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: commit 60d3ed2874ecd556862aae26bc66e5a44fe14839 Author: Bjoern Michaelsen <bjoern.michael...@libreoffice.org> AuthorDate: Sun Nov 22 10:47:20 2020 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Thu Apr 1 10:07:37 2021 +0200 tdf#140863: section.cxx: Remove remaining SwClientNotifyCalls Change-Id: I569c5952a7491c37c677ad6b6d5f803a50b2e701 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106341 Tested-by: Jenkins Reviewed-by: Bjoern Michaelsen <bjoern.michael...@libreoffice.org> (cherry picked from commit 5fc6a601d7a1978db291fd0f7dcec638a7c25651) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113361 Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Tested-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/source/core/docnode/section.cxx b/sw/source/core/docnode/section.cxx index a3dad1262b23..00adf5a40f47 100644 --- a/sw/source/core/docnode/section.cxx +++ b/sw/source/core/docnode/section.cxx @@ -66,13 +66,6 @@ using namespace ::com::sun::star; namespace { - - void lcl_SwClientNotify(sw::BroadcastingModify& rModify, const SfxPoolItem* pOldNew) - { - const sw::LegacyModifyHint aHint(pOldNew, pOldNew); - rModify.SwClientNotifyCall(rModify, aHint); - } - class SwIntrnlSectRefLink : public SwBaseLink { SwSectionFormat& m_rSectFormat; @@ -318,8 +311,8 @@ void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition) // This should be shown by the bHiddenFlag. // Tell all Children that they are hidden - SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN ); - lcl_SwClientNotify(*pFormat, &aMsgItem); + const SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN ); + pFormat->CallSwClientNotify(sw::LegacyModifyHint(&aMsgItem, &aMsgItem)); // Delete all Frames pFormat->DelFrames(); @@ -333,8 +326,8 @@ void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition) if( !pParentSect || !pParentSect->IsHiddenFlag() ) { // Tell all Children that the Parent is not hidden anymore - SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN ); - lcl_SwClientNotify(*pFormat, &aMsgItem); + const SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN ); + pFormat->CallSwClientNotify(sw::LegacyModifyHint(&aMsgItem, &aMsgItem)); pFormat->MakeFrames(); } @@ -719,8 +712,8 @@ void SwSectionFormat::DelFrames() SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, true, false ); if( pCNd ) { - const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC ); - lcl_SwClientNotify(*pCNd, &rItem); + const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get(RES_PAGEDESC); + pCNd->CallSwClientNotify(sw::LegacyModifyHint(&rItem, &rItem)); } } @@ -945,22 +938,19 @@ void SwSectionFormat::UpdateParent() bIsHidden = pPS->IsHiddenFlag(); } SwIterator<SwSectionFormat,SwSectionFormat> aIter(*this); - for(SwSectionFormat* pLast = aIter.First(); pLast; pLast = aIter.Next()) - { - if(!pProtect->IsContentProtected() != !pSection->IsProtectFlag()) - lcl_SwClientNotify(*static_cast<sw::BroadcastingModify*>(pLast), static_cast<SfxPoolItem const *>(pProtect)); + if(!pProtect->IsContentProtected() != !pSection->IsProtectFlag()) + CallSwClientNotify(sw::LegacyModifyHint(pProtect, pProtect)); - // edit in readonly sections - if(!pEditInReadonly->GetValue() != !pSection->IsEditInReadonlyFlag()) - lcl_SwClientNotify(*static_cast<sw::BroadcastingModify*>(pLast), static_cast<SfxPoolItem const *>(pEditInReadonly)); + // edit in readonly sections + if(!pEditInReadonly->GetValue() != !pSection->IsEditInReadonlyFlag()) + CallSwClientNotify(sw::LegacyModifyHint(pEditInReadonly, pEditInReadonly)); - if(bIsHidden == pSection->IsHiddenFlag()) - { - SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden - ? RES_SECTION_HIDDEN - : RES_SECTION_NOT_HIDDEN ) ); - lcl_SwClientNotify(*static_cast<sw::BroadcastingModify*>(pLast), &aMsgItem); - } + if(bIsHidden == pSection->IsHiddenFlag()) + { + SwMsgPoolItem aMsgItem(static_cast<sal_uInt16>(bIsHidden + ? RES_SECTION_HIDDEN + : RES_SECTION_NOT_HIDDEN)); + CallSwClientNotify(sw::LegacyModifyHint(&aMsgItem, &aMsgItem)); } } commit 9661c7e48cef0f2e73aa024fcf5c0ecdbf0b037b Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Tue Mar 30 17:37:31 2021 +0200 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Thu Apr 1 10:07:31 2021 +0200 xmlsecurity: replace OOXMLSecParser implementation This is similar to 12b15be8f4f930a04d8056b9219ac969b42a9784 and following commits, but OOXMLSecParser has some differences to XSecParser, such as using a ds:Manifest, and requires a couple extra namespaces. Change-Id: I56e39d9609db8fcad50ca1632ff482c1f0a30ff5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113381 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit cc1d19f7bbaefa5fb22ebd1344112755068b93c9) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113359 diff --git a/include/xmloff/xmlnamespace.hxx b/include/xmloff/xmlnamespace.hxx index cabdcc7578e2..91ff2aae4cf3 100644 --- a/include/xmloff/xmlnamespace.hxx +++ b/include/xmloff/xmlnamespace.hxx @@ -76,6 +76,9 @@ constexpr sal_uInt16 XML_NAMESPACE_DSIG = 39; constexpr sal_uInt16 XML_NAMESPACE_DS = 40; constexpr sal_uInt16 XML_NAMESPACE_XADES132 = 41; constexpr sal_uInt16 XML_NAMESPACE_XADES141 = 42; +// OOXML digital signature extension namespaces, also based on xmldsig-core +constexpr sal_uInt16 XML_NAMESPACE_MDSSI = 43; +constexpr sal_uInt16 XML_NAMESPACE_MSODIGSIG = 44; // namespaces for ODF extended formats constexpr sal_uInt16 XML_NAMESPACE_EXT_BASE = 50; diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx index a25872fc057d..149e323eb8f6 100644 --- a/xmlsecurity/source/helper/ooxmlsecparser.cxx +++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx @@ -11,32 +11,1241 @@ #include "ooxmlsecparser.hxx" #include <xmlsignaturehelper.hxx> #include <xsecctl.hxx> + +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmlimp.hxx> + +#include <com/sun/star/xml/sax/SAXException.hpp> + #include <sal/log.hxx> -using namespace com::sun::star; +using namespace com::sun::star; + +class OOXMLSecParser::Context +{ + protected: + friend class OOXMLSecParser; + OOXMLSecParser & m_rParser; + private: + std::unique_ptr<SvXMLNamespaceMap> m_pOldNamespaceMap; + + public: + Context(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/); + + virtual void Characters(OUString const& /*rChars*/) + { + } +}; + +// it's possible that an unsupported element has an Id attribute and a +// ds:Reference digesting it - probably this means XSecController needs to know +// about it. (For known elements, the Id attribute is only processed according +// to the schema.) +class OOXMLSecParser::UnknownContext + : public OOXMLSecParser::Context +{ + public: + UnknownContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto OOXMLSecParser::Context::CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr<Context> +{ + // default: create new base context + return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap)); +} + +/** +note: anything in ds:Object should be trusted *only* if there is a ds:Reference + to it so it is signed (exception: the xades:EncapsulatedX509Certificate). + ds:SignedInfo precedes all ds:Object. + + There may be multiple ds:Signature for purpose of counter-signatures + but the way XAdES describes these, only the ds:SignatureValue element + would be referenced, so requiring a ds:Reference for anything in + ds:Object shouldn't cause issues. + */ +class OOXMLSecParser::ReferencedContextImpl + : public OOXMLSecParser::Context +{ + protected: + bool m_isReferenced; + + public: + ReferencedContextImpl(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) + { + OUString const id(m_rParser.HandleIdAttr(xAttrs)); + if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) + { + m_isReferenced = true; + } + return id; + } +}; + +class OOXMLSecParser::DsX509CertificateContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509CertificateContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509SerialNumberContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509SerialNumberContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerNameContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509IssuerNameContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerSerialContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rX509IssuerName; + OUString & m_rX509SerialNumber; + + public: + DsX509IssuerSerialContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rIssuerName, OUString & rSerialNumber) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +/// can't be sure what is supposed to happen here because the spec is clear as mud +class OOXMLSecParser::DsX509DataContext + : public OOXMLSecParser::Context +{ + private: + // sigh... "No ordering is implied by the above constraints." + // so store the ball of mud in vectors and try to figure it out later. + std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials; + std::vector<OUString> m_X509Certificates; + + public: + DsX509DataContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { + m_X509Certificates.emplace_back(); + return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsKeyInfoContext + : public OOXMLSecParser::Context +{ + public: + DsKeyInfoContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:PGPData + // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData + // (old code would read ds:Transform inside ds:RetrievalMethod but + // presumably that was a bug) + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + +}; + +class OOXMLSecParser::DsSignatureValueContext + : public OOXMLSecParser::Context +{ + private: + OUString m_Value; + + public: + DsSignatureValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setSignatureValue(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::DsDigestValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsDigestValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rValue.clear(); + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsDigestMethodContext + : public OOXMLSecParser::Context +{ + private: + sal_Int32 & m_rReferenceDigestID; + + public: + DsDigestMethodContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_Int32 & rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); + if (!ouAlgorithm.isEmpty()) + { + SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1 + && ouAlgorithm != ALGO_XMLDSIGSHA256 + && ouAlgorithm != ALGO_XMLDSIGSHA512, + "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512"); + if (ouAlgorithm == ALGO_XMLDSIGSHA1) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1; + else if (ouAlgorithm == ALGO_XMLDSIGSHA256) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256; + else if (ouAlgorithm == ALGO_XMLDSIGSHA512) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512; + else + m_rReferenceDigestID = 0; + } + } +}; + +class OOXMLSecParser::DsTransformContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString aAlgorithm = xAttrs->getValueByName("Algorithm"); + + if (aAlgorithm == ALGO_RELATIONSHIP) + { + m_rIsC14N = true; + } + } +}; + +class OOXMLSecParser::DsTransformsContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformsContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool & rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsReferenceContext + : public OOXMLSecParser::Context +{ + private: + OUString m_URI; + OUString m_Type; + OUString m_DigestValue; + bool m_IsC14N = false; + // Relevant for ODF. The digest algorithm selected by the DigestMethod + // element's Algorithm attribute. @see css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA256; + + public: + DsReferenceContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + + m_URI = xAttrs->getValueByName("URI"); + SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty"); + // Remember the type of this reference. + m_Type = xAttrs->getValueByName("Type"); + } + + virtual void EndElement() override + { + if (m_URI.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type); + } + else + { + if (m_IsC14N) // this is determined by nested ds:Transform + { + m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID); + } + else + /* + * it must be an octet stream + */ + { + m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID); + } + } + + m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureMethodContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureMethodContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + { + m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + } +}; + +class OOXMLSecParser::DsSignedInfoContext + : public OOXMLSecParser::Context +{ + public: + DsSignedInfoContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertDigestContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rDigestValue; + sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rDigestValue, sal_Int32 & rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + OUString m_CertDigest; + OUString m_X509IssuerName; + OUString m_X509SerialNumber; + + public: + XadesCertContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningCertificateContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSigningCertificateContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningTimeContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + XadesSigningTimeContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setDate("", m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::XadesSignedSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedSignaturePropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSignedPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedPropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesQualifyingPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesQualifyingPropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:UnsignedSignatureProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::MsodigsigSetupIDContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSetupIDContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureCommentsContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSignatureCommentsContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureInfoV1Context + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_SetupID; + OUString m_SignatureComments; + + public: + MsodigsigSignatureInfoV1Context(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID") + { + return std::make_unique<MsodigsigSetupIDContext>(m_rParser, std::move(pOldNamespaceMap), m_SetupID); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments") + { + return std::make_unique<MsodigsigSignatureCommentsContext>(m_rParser, std::move(pOldNamespaceMap), m_SignatureComments); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + if (!m_SetupID.isEmpty()) + { + m_rParser.m_pXSecController->setSignatureLineId(m_SetupID); + } + if (!m_SignatureComments.isEmpty()) + { + m_rParser.m_pXSecController->setDescription("", m_SignatureComments); + + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureInfoV1"); + } + } +}; + +class OOXMLSecParser::MdssiValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiValueContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MdssiSignatureTimeContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiSignatureTimeContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value") + { + return std::make_unique<MdssiValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +class OOXMLSecParser::DsSignaturePropertyContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + enum class SignatureProperty { Unknown, Date, Info }; + SignatureProperty m_Property = SignatureProperty::Unknown; + OUString m_Id; + OUString m_Value; + + public: + DsSignaturePropertyContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + switch (m_Property) + { + case SignatureProperty::Unknown: + SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); + break; + case SignatureProperty::Info: + break; // handled by child context + case SignatureProperty::Date: + m_rParser.m_pXSecController->setDate(m_Id, m_Value); + break; + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime") + { + m_Property = SignatureProperty::Date; + return std::make_unique<MdssiSignatureTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1") + { + return std::make_unique<MsodigsigSignatureInfoV1Context>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsSignaturePropertiesContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsManifestContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsManifestContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + +#if 0 + ??? + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } +#endif + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsObjectContext + : public OOXMLSecParser::ReferencedContextImpl +{ + enum class Mode { Default, ValidSignatureLineImage, InvalidSignatureLineImage }; + Mode m_Mode = Mode::Default; + OUString m_Value; + + public: + DsObjectContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + // init with "false" here - the Signature element can't be referenced by its child + : OOXMLSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const id(CheckIdAttrReferenced(xAttrs)); + if (id == "idValidSigLnImg") + { + m_Mode = Mode::ValidSignatureLineImage; + } + else if (id == "idInvalidSigLnImg") + { + m_Mode = Mode::InvalidSignatureLineImage; + } + } + + virtual void EndElement() override + { + switch (m_Mode) + { + case Mode::ValidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setValidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); + } + break; + case Mode::InvalidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); + } + break; + case Mode::Default: + break; + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest") + { + return std::make_unique<DsManifestContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureContext(OOXMLSecParser & rParser, + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); + m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_rParser.m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_rParser.m_pXSecController->setId( ouIdAttr ); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::unique_ptr<SvXMLNamespaceMap> pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + OOXMLSecParser::OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController) - : m_pXSecController(pXSecController) - ,m_bInDigestValue(false) - ,m_bInSignatureValue(false) - ,m_bInX509Certificate(false) - ,m_bInMdssiValue(false) - ,m_bInSignatureComments(false) - ,m_bInX509IssuerName(false) - ,m_bInX509SerialNumber(false) - ,m_bInCertDigest(false) - ,m_bInValidSignatureImage(false) - ,m_bInInvalidSignatureImage(false) - ,m_bInSignatureLineId(false) - ,m_bReferenceUnresolved(false) + : m_pNamespaceMap(new SvXMLNamespaceMap) + , m_pXSecController(pXSecController) ,m_rXMLSignatureHelper(rXMLSignatureHelper) { + using namespace xmloff::token; + m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS ); + m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132); + m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141); + m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + m_pNamespaceMap->Add( "_mdssi", NS_MDSSI, XML_NAMESPACE_MDSSI ); + m_pNamespaceMap->Add( "_msodigsig", "http://schemas.microsoft.com/office/2006/digsig", XML_NAMESPACE_MSODIGSIG ); + m_pNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); } OOXMLSecParser::~OOXMLSecParser() { } +OUString OOXMLSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) +{ + OUString const aId = xAttrs->getValueByName("Id"); + if (!aId.isEmpty()) + { + m_pXSecController->collectToVerify(aId); + } + return aId; +} + void SAL_CALL OOXMLSecParser::startDocument() { if (m_xNextHandler.is()) @@ -51,231 +1260,69 @@ void SAL_CALL OOXMLSecParser::endDocument() void SAL_CALL OOXMLSecParser::startElement(const OUString& rName, const uno::Reference<xml::sax::XAttributeList>& xAttribs) { - OUString aId = xAttribs->getValueByName("Id"); - if (!aId.isEmpty()) - m_pXSecController->collectToVerify(aId); + assert(m_pNamespaceMap); + std::unique_ptr<SvXMLNamespaceMap> pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); - if (rName == "Signature") - { - m_rXMLSignatureHelper.StartVerifySignatureElement(); - m_pXSecController->addSignature(); - if (!aId.isEmpty()) - m_pXSecController->setId(aId); - } - else if (rName == "SignatureMethod") - { - OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); - if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 - || ouAlgorithm == ALGO_ECDSASHA512) - m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); - } - else if (rName == "Reference") - { - OUString aURI = xAttribs->getValueByName("URI"); - if (aURI.startsWith("#")) - m_pXSecController->addReference(aURI.copy(1), xml::crypto::DigestID::SHA1, OUString()); - else - { - m_aReferenceURI = aURI; - m_bReferenceUnresolved = true; - } - } - else if (rName == "Transform") - { - if (m_bReferenceUnresolved) - { - OUString aAlgorithm = xAttribs->getValueByName("Algorithm"); - if (aAlgorithm == ALGO_RELATIONSHIP) - { - m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false, /*nDigestID=*/xml::crypto::DigestID::SHA256); - m_bReferenceUnresolved = false; - } - } - } - else if (rName == "DigestValue" && !m_bInCertDigest) - { - m_aDigestValue.clear(); - m_bInDigestValue = true; - } - else if (rName == "SignatureValue") - { - m_aSignatureValue.clear(); - m_bInSignatureValue = true; - } - else if (rName == "X509Certificate") - { - m_aX509Certificate.clear(); - m_bInX509Certificate = true; - } - else if (rName == "mdssi:Value") - { - m_aMdssiValue.clear(); - m_bInMdssiValue = true; - } - else if (rName == "SignatureComments") - { - m_aSignatureComments.clear(); - m_bInSignatureComments = true; - } - else if (rName == "X509IssuerName") - { - m_aX509IssuerName.clear(); - m_bInX509IssuerName = true; - } - else if (rName == "X509SerialNumber") - { - m_aX509SerialNumber.clear(); - m_bInX509SerialNumber = true; - } - else if (rName == "xd:CertDigest") - { - m_aCertDigest.clear(); - m_bInCertDigest = true; - } - else if (rName == "Object") + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr<Context> pContext; + + if (m_ContextStack.empty()) { - OUString sId = xAttribs->getValueByName("Id"); - if (sId == "idValidSigLnImg") - { - m_aValidSignatureImage.clear(); - m_bInValidSignatureImage = true; - } - else if (sId == "idInvalidSigLnImg") + if (nPrefix == XML_NAMESPACE_DS + && localName == "Signature") { - m_aInvalidSignatureImage.clear(); - m_bInInvalidSignatureImage = true; + pContext.reset(new DsSignatureContext(*this, std::move(pRewindMap))); } else { - SAL_INFO("xmlsecurity.ooxml", "Unknown 'Object' child element: " << rName); + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); } } - else if (rName == "SetupID") - { - m_aSignatureLineId.clear(); - m_bInSignatureLineId = true; - } else { - SAL_INFO("xmlsecurity.ooxml", "Unknown xml element: " << rName); + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); } + m_ContextStack.push(std::move(pContext)); + assert(!pRewindMap); + + m_ContextStack.top()->StartElement(xAttribs); + if (m_xNextHandler.is()) + { m_xNextHandler->startElement(rName, xAttribs); + } + } void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) { - if (rName == "SignedInfo") - m_pXSecController->setReferenceCount(); - else if (rName == "Reference") - { - if (m_bReferenceUnresolved) - { - // No transform algorithm found, assume binary. - m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true, /*nDigestID=*/xml::crypto::DigestID::SHA256); - m_bReferenceUnresolved = false; - } - m_pXSecController->setDigestValue(xml::crypto::DigestID::SHA256, m_aDigestValue); - } - else if (rName == "DigestValue" && !m_bInCertDigest) - m_bInDigestValue = false; - else if (rName == "SignatureValue") - { - m_pXSecController->setSignatureValue(m_aSignatureValue); - m_bInSignatureValue = false; - } - else if (rName == "X509Data") - { - std::vector<std::pair<OUString, OUString>> X509IssuerSerials; - std::vector<OUString> X509Certificates; - if (!m_aX509Certificate.isEmpty()) - { - X509Certificates.emplace_back(m_aX509Certificate); - } - if (!m_aX509IssuerName.isEmpty() && !m_aX509SerialNumber.isEmpty()) - { - X509IssuerSerials.emplace_back(m_aX509IssuerName, m_aX509SerialNumber); - } - m_pXSecController->setX509Data(X509IssuerSerials, X509Certificates); - } - else if (rName == "X509Certificate") - { - m_bInX509Certificate = false; - } - else if (rName == "mdssi:Value") - { - m_pXSecController->setDate("", m_aMdssiValue); - m_bInMdssiValue = false; - } - else if (rName == "SignatureComments") - { - m_pXSecController->setDescription("", m_aSignatureComments); - m_bInSignatureComments = false; - } - else if (rName == "X509IssuerName") - { - m_bInX509IssuerName = false; - } - else if (rName == "X509SerialNumber") - { - m_bInX509SerialNumber = false; - } - else if (rName == "xd:Cert") - { - m_pXSecController->setX509CertDigest(m_aCertDigest, css::xml::crypto::DigestID::SHA1, m_aX509IssuerName, m_aX509SerialNumber); - } - else if (rName == "xd:CertDigest") - { - m_bInCertDigest = false; - } - else if (rName == "Object") + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) { - if (m_bInValidSignatureImage) - { - m_pXSecController->setValidSignatureImage(m_aValidSignatureImage); - m_bInValidSignatureImage = false; - } - else if (m_bInInvalidSignatureImage) - { - m_pXSecController->setInvalidSignatureImage(m_aInvalidSignatureImage); - m_bInInvalidSignatureImage = false; - } + m_xNextHandler->endElement(rName); } - else if (rName == "SetupID") + + if (m_ContextStack.top()->m_pOldNamespaceMap) { - m_pXSecController->setSignatureLineId(m_aSignatureLineId); - m_bInSignatureLineId = false; + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); } - - if (m_xNextHandler.is()) - m_xNextHandler->endElement(rName); + m_ContextStack.pop(); } void SAL_CALL OOXMLSecParser::characters(const OUString& rChars) { - if (m_bInDigestValue && !m_bInCertDigest) - m_aDigestValue += rChars; - else if (m_bInSignatureValue) - m_aSignatureValue += rChars; - else if (m_bInX509Certificate) - m_aX509Certificate += rChars; - else if (m_bInMdssiValue) - m_aMdssiValue += rChars; - else if (m_bInSignatureComments) - m_aSignatureComments += rChars; - else if (m_bInX509IssuerName) - m_aX509IssuerName += rChars; - else if (m_bInX509SerialNumber) - m_aX509SerialNumber += rChars; - else if (m_bInCertDigest) - m_aCertDigest += rChars; - else if (m_bInValidSignatureImage) - m_aValidSignatureImage += rChars; - else if (m_bInInvalidSignatureImage) - m_aInvalidSignatureImage += rChars; - else if (m_bInSignatureLineId) - m_aSignatureLineId += rChars; + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); if (m_xNextHandler.is()) m_xNextHandler->characters(rChars); diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx index d3c199147255..ba0e274be6af 100644 --- a/xmlsecurity/source/helper/ooxmlsecparser.hxx +++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx @@ -15,6 +15,10 @@ #include <cppuhelper/implbase.hxx> +#include <xmloff/namespacemap.hxx> + +#include <stack> + class XSecController; class XMLSignatureHelper; @@ -25,38 +29,62 @@ class OOXMLSecParser: public cppu::WeakImplHelper css::lang::XInitialization > { +public: + class Context; +private: + class UnknownContext; + class ReferencedContextImpl; + class DsX509CertificateContext; + class DsX509SerialNumberContext; + class DsX509IssuerNameContext; + class DsX509IssuerSerialContext; + class DsX509DataContext; + class DsKeyInfoContext; + class DsSignatureValueContext; + class DsDigestValueContext; + class DsDigestMethodContext; + class DsTransformContext; + class DsTransformsContext; + class DsReferenceContext; + class DsSignatureMethodContext; + class DsSignedInfoContext; + class XadesEncapsulatedX509CertificateContext; + class XadesCertificateValuesContext; + class XadesUnsignedSignaturePropertiesContext; + class XadesUnsignedPropertiesContext; + class XadesCertDigestContext; + class XadesCertContext; + class XadesSigningCertificateContext; + class XadesSigningTimeContext; + class XadesSignedSignaturePropertiesContext; + class XadesSignedPropertiesContext; + class XadesQualifyingPropertiesContext; + class MdssiValueContext; + class MdssiSignatureTimeContext; + class MsodigsigSetupIDContext; + class MsodigsigSignatureCommentsContext; + class MsodigsigSignatureInfoV1Context; + class DsSignaturePropertyContext; + class DsSignaturePropertiesContext; + class DsManifestContext; + class DsObjectContext; + class DsSignatureContext; + class DsigSignaturesContext; + + std::stack<std::unique_ptr<Context>> m_ContextStack; + std::unique_ptr<SvXMLNamespaceMap> m_pNamespaceMap; + XSecController* m_pXSecController; css::uno::Reference<css::xml::sax::XDocumentHandler> m_xNextHandler; - bool m_bInDigestValue; - OUString m_aDigestValue; - bool m_bInSignatureValue; - OUString m_aSignatureValue; - bool m_bInX509Certificate; - OUString m_aX509Certificate; - bool m_bInMdssiValue; - OUString m_aMdssiValue; - bool m_bInSignatureComments; - OUString m_aSignatureComments; - bool m_bInX509IssuerName; - OUString m_aX509IssuerName; - bool m_bInX509SerialNumber; - OUString m_aX509SerialNumber; - bool m_bInCertDigest; - OUString m_aCertDigest; - bool m_bInValidSignatureImage; - OUString m_aValidSignatureImage; - bool m_bInInvalidSignatureImage; - OUString m_aInvalidSignatureImage; - bool m_bInSignatureLineId; - OUString m_aSignatureLineId; - /// Last seen <Reference URI="...">. OUString m_aReferenceURI; /// Already called addStreamReference() for this reference. bool m_bReferenceUnresolved; XMLSignatureHelper& m_rXMLSignatureHelper; + OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs); + public: explicit OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); virtual ~OOXMLSecParser() override; commit fcdda95bfff8c9f8cdfe3878e203ae48f6f93607 Author: Attila Bakos (NISZ) <bakos.attilakar...@nisz.hu> AuthorDate: Tue Mar 9 16:32:27 2021 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Thu Apr 1 10:07:25 2021 +0200 tdf#140828 sw textbox: fix AS_CHAR regression Textboxes anchored as characters don't lose their text frames after changing the anchor "To character". Regression from commit 493a916a3113e877835c9bc7c93faef0d29f9a33 (tdf#140158 tdf#138598 tdf#140598 sw: fix sync of AS_CHAR textboxes). Change-Id: I0e6d88c9dcdeff515744bc4c201a5640eb810d1b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112209 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113321 Tested-by: Jenkins Reviewed-by: Attila Bakos <bakos.attilakar...@nisz.hu> diff --git a/sw/qa/extras/uiwriter/data3/tdf140828.docx b/sw/qa/extras/uiwriter/data3/tdf140828.docx new file mode 100755 index 000000000000..bfdabc5d77ea Binary files /dev/null and b/sw/qa/extras/uiwriter/data3/tdf140828.docx differ diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 71d742bf4359..f0444d3f3c7a 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -14,6 +14,7 @@ #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <IDocumentDrawModelAccess.hxx> #include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/text/XTextFrame.hpp> #include <com/sun/star/text/XTextTablesSupplier.hpp> #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XTextViewCursorSupplier.hpp> @@ -854,6 +855,37 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf76636_2) CPPUNIT_ASSERT_EQUAL(sal_Int32(6), xTextTable->getColumns()->getCount()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf140828) +{ + load(DATA_DIRECTORY, "tdf140828.docx"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + + CPPUNIT_ASSERT_EQUAL(1, getShapes()); + uno::Reference<drawing::XShape> xShp = getShape(1); + CPPUNIT_ASSERT(xShp); + + uno::Reference<beans::XPropertySet> ShpProps(xShp, uno::UNO_QUERY_THROW); + dispatchCommand(mxComponent, ".uno:JumpToNextFrame", {}); + Scheduler::ProcessEventsToIdle(); + + dispatchCommand(mxComponent, ".uno:SetAnchorAtChar", {}); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(ShpProps->getPropertyValue("AnchorType").get<text::TextContentAnchorType>() + != text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER); + + uno::Reference<text::XTextFrame> xTxBx(SwTextBoxHelper::getUnoTextFrame(xShp)); + CPPUNIT_ASSERT(xTxBx); + + uno::Reference<beans::XPropertySet> TxBxProps(xTxBx, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(OUString("top left image"), xTxBx->getText()->getString()); + + CPPUNIT_ASSERT_MESSAGE("Bad Relative Orientation and Position!", + TxBxProps->getPropertyValue("HoriOrientRelation").get<sal_Int16>() + != text::RelOrientation::CHAR); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf132725) { load(DATA_DIRECTORY, "tdf132725.odt"); diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 5257d448bd55..6b9f87655d8d 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -165,8 +165,6 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, bool bCopyText) if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= eMode) syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode))); - // TODO: Text dialog attr setting to frame - const SwFormatAnchor& rAnch = pShape->GetAnchor(); if (!((rAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && rAnch.GetPageNum() != 0) || ((rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA @@ -723,6 +721,9 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u } else // Otherwise copy the anchor type of the shape { + // tdf#140828: Do not keep CHAR rel-orientation: + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, + uno::Any(text::RelOrientation::FRAME)); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); } // After anchoring the position must be set as well: diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index cafa70c48227..9426359156f1 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -351,9 +351,11 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, // Both rectangles are absolute, SwFormatHori/VertOrient's position // is relative to the print area of the anchor text frame. tools::Rectangle aTextRectangle = SwTextBoxHelper::getTextRectangle(pShape); + tools::Long nXoffs = SwTextBoxHelper::getTextRectangle(pShape, false).getX(); const auto aPos(pShape->GetAnchor().GetContentAnchor()); SwFormatVertOrient aVert(pTextBox->GetVertOrient()); + SwFormatHoriOrient aHori(pTextBox->GetHoriOrient()); // tdf#138598 Replace vertical alignment of As_char textboxes in footer // tdf#140158 Remove horizontal positioning of As_char textboxes, because @@ -373,10 +375,12 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, SwFormatAnchor aNewTxBxAnchor(pTextBox->GetAnchor()); aNewTxBxAnchor.SetAnchor(aPos); + aHori.SetPos(nXoffs); pTextBox->LockModify(); pTextBox->SetFormatAttr(aNewTxBxAnchor); pTextBox->SetFormatAttr(aVert); + pTextBox->SetFormatAttr(aHori); pTextBox->UnlockModify(); } } commit ec693c088dd51fcf86dcf48de66d4ead0f6dcdbc Author: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> AuthorDate: Mon Mar 29 15:55:45 2021 +0200 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Thu Apr 1 10:07:20 2021 +0200 python3-ify hrcex & uiex (creation of pot files) Change-Id: I824c9ed536a1e852d6bd157fbd7d4766327b7bcd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113319 Tested-by: Jenkins Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> (cherry picked from commit 9dfd55dffc4cca6617b4ee67be9a8bfe96601c00) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113353 Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> diff --git a/solenv/bin/hrcex b/solenv/bin/hrcex index 54cef2626a19..0645f79fcb37 100755 --- a/solenv/bin/hrcex +++ b/solenv/bin/hrcex @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import polib import binascii @@ -22,17 +22,18 @@ for o, a in myopts: ofile = a with open(ofile, "a") as output: - xgettext = Popen(["xgettext", "-C", "--add-comments", "--keyword=NC_:1c,2", "--keyword=NNC_:1c,2,3", "--from-code=UTF-8", "--no-wrap", ifile, "-o", "-"], stdout=PIPE) + xgettext = Popen(["xgettext", "-C", "--add-comments", "--keyword=NC_:1c,2", "--keyword=NNC_:1c,2,3", "--from-code=UTF-8", "--no-wrap", ifile, "-o", "-"], stdout=PIPE, encoding="UTF-8") # while overall format is c++, all of the strings use custom placeholders and don't follow c-format # esp. plain percent sign never is escaped explicitly - input = check_output(['sed', '-e', '/^#, c-format$/d'], stdin=xgettext.stdout) + input = check_output(['sed', '-e', '/^#, c-format$/d'], stdin=xgettext.stdout, encoding="UTF-8") xgettext.wait() + xgettext.stdout.close() po = polib.pofile(input) if len(po) != 0: - print >> output, "" + print("", file=output) for entry in po: keyid = entry.msgctxt + '|' + entry.msgid - print >> output, '#. ' + polib.genKeyId(keyid) + print('#. ' + polib.genKeyId(keyid), file=output) for i, occurrence in enumerate(entry.occurrences): entry.occurrences[i] = os.path.relpath(occurrence[0], os.environ['SRCDIR']), occurrence[1] - print >> output, entry + print(entry, file=output) diff --git a/solenv/bin/polib.py b/solenv/bin/polib.py index 5ab421365376..092e7dfdb8b3 100644 --- a/solenv/bin/polib.py +++ b/solenv/bin/polib.py @@ -1858,7 +1858,7 @@ def wrap(text, width=70, **kwargs): # }}} def genKeyId(inkey): - crc = binascii.crc32(bytes(inkey)) & 0xffffffff + crc = binascii.crc32(bytes(inkey, encoding="UTF-8")) & 0xffffffff # Use simple ASCII characters, exclude I, l, 1 and O, 0 to avoid confusing IDs symbols = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789"; outkey = "" diff --git a/solenv/bin/uiex b/solenv/bin/uiex index c9b00b2e062c..1f5faead4575 100755 --- a/solenv/bin/uiex +++ b/solenv/bin/uiex @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import polib import binascii @@ -22,13 +22,13 @@ for o, a in myopts: ofile = a with open(ofile, "a") as output: - input = check_output(["xgettext", "--add-comments", "--no-wrap", ifile, "-o", "-"]) + input = check_output(["xgettext", "--add-comments", "--no-wrap", ifile, "-o", "-"], encoding="UTF-8") po = polib.pofile(input) if len(po) != 0: - print >> output, "" + print("", file=output) for entry in po: keyid = entry.msgctxt + '|' + entry.msgid - print >> output, '#. ' + polib.genKeyId(keyid) + print('#. ' + polib.genKeyId(keyid), file=output) for i, occurrence in enumerate(entry.occurrences): entry.occurrences[i] = os.path.relpath(occurrence[0], os.environ['SRCDIR']), occurrence[1] - print >> output, entry + print(entry, file=output) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits