commit b9ee6f9f9b6d8003e20e7b0d2da635f3d763449a Author: CentOS Sources Date: Tue May 16 06:09:56 2023 +0000 import libreoffice-6.4.7.2-13.el8 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07521f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +SOURCES/17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip +SOURCES/185d60944ea767075d27247c3162b3bc-unowinreg.dll +SOURCES/884ed41809687c3e168fc7c19b16585149ff058eca79acbf3ee784f6630704cc-opens___.ttf +SOURCES/a7983f859eafb2677d7ff386a023bc40-xsltml_2.1.2.zip +SOURCES/gpgkey-C2839ECAD9408FBE9531C3E9F434A1EFAFEEAEA3.gpg.asc +SOURCES/libreoffice-6.4.7.2.tar.xz +SOURCES/libreoffice-base-symbolic.svg +SOURCES/libreoffice-calc-symbolic.svg +SOURCES/libreoffice-draw-symbolic.svg +SOURCES/libreoffice-help-6.4.7.2.tar.xz +SOURCES/libreoffice-impress-symbolic.svg +SOURCES/libreoffice-main-symbolic.svg +SOURCES/libreoffice-math-symbolic.svg +SOURCES/libreoffice-translations-6.4.7.2.tar.xz +SOURCES/libreoffice-writer-symbolic.svg diff --git a/.libreoffice.metadata b/.libreoffice.metadata new file mode 100644 index 0000000..21d524c --- /dev/null +++ b/.libreoffice.metadata @@ -0,0 +1,15 @@ +7168b0f40aa5c72267899601c116d2348d2f56ec SOURCES/17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip +0619ed3a89644bef318df67db12045b2b590585b SOURCES/185d60944ea767075d27247c3162b3bc-unowinreg.dll +d336802a36ed2c87dd243e7c2f1d0542dace5cca SOURCES/884ed41809687c3e168fc7c19b16585149ff058eca79acbf3ee784f6630704cc-opens___.ttf +2d49e11b0b711970f494294dc3698f05eb294853 SOURCES/a7983f859eafb2677d7ff386a023bc40-xsltml_2.1.2.zip +7b5fd93d787fbc6d9c2d4025d543730ee8dc4559 SOURCES/gpgkey-C2839ECAD9408FBE9531C3E9F434A1EFAFEEAEA3.gpg.asc +b29d8cdb3db8d6b317e1cb9117b020d7e676e601 SOURCES/libreoffice-6.4.7.2.tar.xz +54fc749ba924f9ca4e0391caaf579ab344302038 SOURCES/libreoffice-base-symbolic.svg +9de544172d736d59589767000c1f657034a5d53d SOURCES/libreoffice-calc-symbolic.svg +0f6dc4726da0920869354fbe4b2924f9ac569b4a SOURCES/libreoffice-draw-symbolic.svg +ca7e087ef62f30c033db84ceb0f6a4021f53653e SOURCES/libreoffice-help-6.4.7.2.tar.xz +8c74dd667c660cc643c4d715dd50491ba92146d5 SOURCES/libreoffice-impress-symbolic.svg +c77acd04a7647b09745f9424ab0f65d52dfcd397 SOURCES/libreoffice-main-symbolic.svg +3857a55644148eb25ed1a594bd00d1262761fb39 SOURCES/libreoffice-math-symbolic.svg +0f74fd6286e71ff2b7c7bc01f41c8972e354d81c SOURCES/libreoffice-translations-6.4.7.2.tar.xz +d4f0674ad46a832120db956cc01a27fdc2060458 SOURCES/libreoffice-writer-symbolic.svg diff --git a/SOURCES/0001-0.5.1-is-sufficient.patch b/SOURCES/0001-0.5.1-is-sufficient.patch new file mode 100644 index 0000000..af39158 --- /dev/null +++ b/SOURCES/0001-0.5.1-is-sufficient.patch @@ -0,0 +1,46 @@ +From ceac69bff953ebd9b54a1f3a032079523c4414d0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Sun, 25 Oct 2020 20:23:39 +0000 +Subject: [PATCH] 0.5.1 is sufficient + +Change-Id: I710a83de8f261d6164eb760d3290c963a5bbe5e1 +--- + configure.ac | 15 +-------------- + 1 file changed, 1 insertion(+), 14 deletions(-) + +diff --git a/configure.ac b/configure.ac +index a6696df15f06..c17fdf5b0d22 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -7050,7 +7050,7 @@ dnl Check for system libcmis + dnl =================================================================== + # libcmis requires curl and we can't build curl for iOS + if test $_os != iOS; then +- libo_CHECK_SYSTEM_MODULE([libcmis],[LIBCMIS],[libcmis-0.5 >= 0.5.2]) ++ libo_CHECK_SYSTEM_MODULE([libcmis],[LIBCMIS],[libcmis-0.5 >= 0.5.0]) + ENABLE_LIBCMIS=TRUE + else + ENABLE_LIBCMIS= +@@ -7090,19 +7090,6 @@ elif test "$GCC" = "yes" -o "$COM_IS_CLANG" = TRUE; then + #include + #include + +- #if defined SYSTEM_LIBCMIS +- // See ucb/source/ucp/cmis/auth_provider.hxx: +- #if !defined __clang__ +- #pragma GCC diagnostic push +- #pragma GCC diagnostic ignored "-Wdeprecated" +- #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +- #endif +- #include +- #if !defined __clang__ +- #pragma GCC diagnostic pop +- #endif +- #endif +- + void f(std::vector & v, std::function fn) { + std::sort(v.begin(), v.end(), fn); + } +-- +2.26.2 + diff --git a/SOURCES/0001-1.2.25-is-sufficient.patch b/SOURCES/0001-1.2.25-is-sufficient.patch new file mode 100644 index 0000000..5c643af --- /dev/null +++ b/SOURCES/0001-1.2.25-is-sufficient.patch @@ -0,0 +1,26 @@ +From 92c95c8c3724f267e57827f69f93ef4e6387f793 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Sun, 25 Oct 2020 21:14:10 +0000 +Subject: [PATCH] 1.2.25 is sufficient + +Change-Id: Ie184fbaaf6eea0ae1a39bf142d3391768be9607d +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index a62c131a6d0e..c815ea2c3f8b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -8364,7 +8364,7 @@ libo_CHECK_SYSTEM_MODULE([expat], [EXPAT], [expat]) + dnl =================================================================== + dnl Check for system xmlsec + dnl =================================================================== +-libo_CHECK_SYSTEM_MODULE([xmlsec], [XMLSEC], [xmlsec1-nss >= 1.2.28]) ++libo_CHECK_SYSTEM_MODULE([xmlsec], [XMLSEC], [xmlsec1-nss >= 1.2.25]) + + AC_MSG_CHECKING([whether to enable Embedded OpenType support]) + if test "$_os" != "WINNT" -a "$_os" != "Darwin" -a "$enable_eot" = "yes"; then +-- +2.26.2 + diff --git a/SOURCES/0001-CVE-2021-25636.patch b/SOURCES/0001-CVE-2021-25636.patch new file mode 100644 index 0000000..61bfe18 --- /dev/null +++ b/SOURCES/0001-CVE-2021-25636.patch @@ -0,0 +1,69 @@ +From ae1bd20a2d4d7b7d64edc3b06d7f901c05175b7d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 20 Dec 2021 17:05:44 +0000 +Subject: [PATCH] only use X509Data + +Change-Id: I52e6588f5fac04bb26d77c1f3af470db73e41f72 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127193 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +(cherry picked from commit be446d81e07b5499152efeca6ca23034e51ea5ff) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127178 +Reviewed-by: Adolfo Jayme Barrientos +(cherry picked from commit b0404f80577de9ff69e58390c6f6ef949fdb0139) +--- + .../source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx | 6 ++++++ + xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx | 6 ++++++ + 2 files changed, 12 insertions(+) + +diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx +index db400e6..39f9d7f 100644 +--- a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx ++++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx +@@ -21,6 +21,8 @@ + #include + #include + ++#include ++ + #include + #include + +@@ -229,6 +231,10 @@ SAL_CALL XMLSignature_MSCryptImpl::validate( + // We do certificate verification ourselves. + pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + ++ // limit possible key data to valid X509 certificates only, no KeyValues ++ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0) ++ throw RuntimeException("failed to limit allowed key data"); ++ + //Verify signature + //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) + //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if +diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx +index 827580b..8f4d6f8 100644 +--- a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx ++++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx +@@ -19,6 +19,8 @@ + + #include + ++#include ++ + #include + #include + #include +@@ -243,6 +245,10 @@ SAL_CALL XMLSignature_NssImpl::validate( + // We do certificate verification ourselves. + pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + ++ // limit possible key data to valid X509 certificates only, no KeyValues ++ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0) ++ throw RuntimeException("failed to limit allowed key data"); ++ + //Verify signature + int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode ); + +-- +2.33.1 + diff --git a/SOURCES/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch b/SOURCES/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch new file mode 100644 index 0000000..e02b110 --- /dev/null +++ b/SOURCES/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch @@ -0,0 +1,63 @@ +From 77f30ada1156ca1e1357776fea8e9dc113f6898d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Thu, 3 Mar 2022 14:22:37 +0000 +Subject: [PATCH 1/4] CVE-2022-26305 compare authors using Thumbprint + +Change-Id: I338f58eb07cbf0a3d13a7dafdaddac09252a8546 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130929 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +(cherry picked from commit 65442205b5b274ad309308162f150f8d41648f72) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130866 +Reviewed-by: Michael Stahl +(cherry picked from commit a7aaa78acea4c1d51283c2fce54ff9f5339026f8) +--- + .../component/documentdigitalsignatures.cxx | 23 +++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx +index b9066ea92cac..5a21c8421bec 100644 +--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx ++++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx +@@ -19,9 +19,10 @@ + + #include + +-#include ++#include + #include + #include ++#include + #include + #include + #include +@@ -666,9 +667,23 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted( + Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors(); + + return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(), +- [&xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { +- return xmlsecurity::EqualDistinguishedNames(rAuthor[0], xAuthor->getIssuerName()) +- && ( rAuthor[1] == sSerialNum ); ++ [this, &xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { ++ if (!xmlsecurity::EqualDistinguishedNames(rAuthor[0], xAuthor->getIssuerName())) ++ return false; ++ if (rAuthor[1] != sSerialNum) ++ return false; ++ ++ DocumentSignatureManager aSignatureManager(mxCtx, {}); ++ if (!aSignatureManager.init()) ++ return false; ++ uno::Reference xCert = aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(rAuthor[2]); ++ ++ auto pAuthor = dynamic_cast(xAuthor.get()); ++ auto pCert = dynamic_cast(xCert.get()); ++ if (pAuthor && pCert) ++ return pCert->getSHA256Thumbprint() == pAuthor->getSHA256Thumbprint(); ++ ++ return xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint(); + }); + } + +-- +2.37.1 + diff --git a/SOURCES/0001-CVE-2022-3140.patch b/SOURCES/0001-CVE-2022-3140.patch new file mode 100644 index 0000000..4bb1976 --- /dev/null +++ b/SOURCES/0001-CVE-2022-3140.patch @@ -0,0 +1,279 @@ +From 3831e68bffc233f581e3eb1cb3c7ed925daab86f Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Tue, 30 Aug 2022 14:04:52 +0200 +Subject: [PATCH] Filter out unwanted command URIs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139225 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit 27d29f7df428885865a8e2313283839b20f2a34b) +Conflicts: + desktop/source/app/cmdlineargs.cxx + +Change-Id: I0b7e5329af8cc053d14d5c60ec14fe7f364ef993 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139182 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +(cherry picked from commit da291e2960b75153f41d440a1b41961567432e8c) + +These commands are always URLs already + +Change-Id: I5083765c879689d7f933bbe00ad70bb68e635a21 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139042 +Tested-by: Jean-Pierre Ledure +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit e61701e1ee6763de72b397e6ade1124eca9400f3) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138980 +Reviewed-by: Caolán McNamara +(cherry picked from commit 5b4025bb56999f5c895c6f7e0b52f521800d65b0) + +check IFrame "FrameURL" target + +similiar to + +commit b3edf85e0fe6ca03dc26e1bf531be82193bc9627 +Date: Wed Aug 7 17:37:11 2019 +0100 + + warn on load when a document binds an event to a macro + +Change-Id: Iea888b1c083d2dc69ec322309ac9ae8c5e5eb315 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139059 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit c7450d0b9d02c64ae3da467d329040787039767e) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139117 +Reviewed-by: Christian Lohmaier +(cherry picked from commit f5e3b0a7966d7d28817292adbb58fb43f28b7c6d) + +check impress/calc IFrame "FrameURL" target + +similar to + +commit c7450d0b9d02c64ae3da467d329040787039767e +Date: Tue Aug 30 17:01:08 2022 +0100 + + check IFrame "FrameURL" target + +Change-Id: Ibf28c29acb4476830431d02772f3ecd4b23a6a27 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139495 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit d0312786571221c2dd4f63fa69f6f0489d7d39ec) +--- + desktop/source/app/cmdlineargs.cxx | 10 +++++++++- + sfx2/source/appl/macroloader.cxx | 9 +++++++-- + sfx2/source/doc/iframe.cxx | 21 ++++++++++++++++----- + sfx2/source/inc/macroloader.hxx | 2 ++ + sw/source/filter/html/htmlplug.cxx | 7 ++++++- + sw/source/filter/xml/xmltexti.cxx | 9 +++++++-- + wizards/source/access2base/DoCmd.xba | 2 +- + xmloff/source/draw/ximpshap.cxx | 4 ++++ + 8 files changed, 52 insertions(+), 12 deletions(-) + +diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx +index 381147c..5babfbe 100644 +--- a/desktop/source/app/cmdlineargs.cxx ++++ b/desktop/source/app/cmdlineargs.cxx +@@ -27,6 +27,7 @@ + + #include "cmdlineargs.hxx" + #include ++#include + #include + #include + #include +@@ -169,7 +170,14 @@ CommandLineEvent CheckOfficeURI(/* in,out */ OUString& arg, CommandLineEvent cur + } + if (nURIlen < 0) + nURIlen = rest2.getLength(); +- arg = rest2.copy(0, nURIlen); ++ auto const uri = rest2.copy(0, nURIlen); ++ if (INetURLObject(uri).GetProtocol() == INetProtocol::Macro) { ++ // Let the "Open" machinery process the full command URI (leading to failure, by intention, ++ // as the "Open" machinery does not know about those command URI schemes): ++ curEvt = CommandLineEvent::Open; ++ } else { ++ arg = uri; ++ } + return curEvt; + } + +diff --git a/sfx2/source/appl/macroloader.cxx b/sfx2/source/appl/macroloader.cxx +index 98e036e..b50d1e6 100644 +--- a/sfx2/source/appl/macroloader.cxx ++++ b/sfx2/source/appl/macroloader.cxx +@@ -76,10 +76,10 @@ css::uno::Sequence SAL_CALL SfxMacroLoader::getSupportedServiceNames() + return aSeq; + } + +-SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() ++SfxObjectShell* SfxMacroLoader::GetObjectShell(const Reference & xFrame) + { + SfxObjectShell* pDocShell = nullptr; +- Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); ++ + if ( xFrame.is() ) + { + SfxFrame* pFrame=nullptr; +@@ -96,6 +96,11 @@ SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() + return pDocShell; + } + ++SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() ++{ ++ Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); ++ return SfxMacroLoader::GetObjectShell(xFrame); ++} + + uno::Reference SAL_CALL SfxMacroLoader::queryDispatch( + const util::URL& aURL , +diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx +index 8b12715..b5291b2 100644 +--- a/sfx2/source/doc/iframe.cxx ++++ b/sfx2/source/doc/iframe.cxx +@@ -39,11 +39,13 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + + using namespace ::com::sun::star; + +@@ -159,6 +161,19 @@ sal_Bool SAL_CALL IFrameObject::load( + { + if ( SvtMiscOptions().IsPluginsEnabled() ) + { ++ util::URL aTargetURL; ++ aTargetURL.Complete = maFrmDescr.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); ++ uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) ); ++ xTrans->parseStrict( aTargetURL ); ++ ++ if (INetURLObject(aTargetURL.Complete).GetProtocol() == INetProtocol::Macro) ++ { ++ uno::Reference xParentFrame = xFrame->getCreator(); ++ SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame); ++ if (pDoc && !pDoc->AdjustMacroMode()) ++ return false; ++ } ++ + DBG_ASSERT( !mxFrame.is(), "Frame already existing!" ); + VclPtr pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); + VclPtr pWin = VclPtr::Create( pParent, maFrmDescr.IsFrameBorderOn() ); +@@ -181,16 +196,12 @@ sal_Bool SAL_CALL IFrameObject::load( + if ( xFramesSupplier.is() ) + mxFrame->setCreator( xFramesSupplier ); + +- util::URL aTargetURL; +- aTargetURL.Complete = maFrmDescr.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); +- uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) ); +- xTrans->parseStrict( aTargetURL ); +- + uno::Sequence < beans::PropertyValue > aProps(2); + aProps[0].Name = "PluginMode"; + aProps[0].Value <<= sal_Int16(2); + aProps[1].Name = "ReadOnly"; + aProps[1].Value <<= true; ++ + uno::Reference < frame::XDispatch > xDisp = mxFrame->queryDispatch( aTargetURL, "_self", 0 ); + if ( xDisp.is() ) + xDisp->dispatch( aTargetURL, aProps ); +diff --git a/sfx2/source/inc/macroloader.hxx b/sfx2/source/inc/macroloader.hxx +index 9e1dfba..b3e7a5e 100644 +--- a/sfx2/source/inc/macroloader.hxx ++++ b/sfx2/source/inc/macroloader.hxx +@@ -82,6 +82,8 @@ public: + virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override; + + virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) override; ++ ++ static SfxObjectShell* GetObjectShell(const css::uno::Reference& xFrame); + }; + + #endif +diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx +index a0da671..eb70704 100644 +--- a/sw/source/filter/html/htmlplug.cxx ++++ b/sw/source/filter/html/htmlplug.cxx +@@ -1087,7 +1087,12 @@ void SwHTMLParser::InsertFloatingFrame() + bool bHasBorder = aFrameDesc.HasFrameBorder(); + Size aMargin = aFrameDesc.GetMargin(); + +- xSet->setPropertyValue("FrameURL", uno::makeAny( aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); ++ OUString sHRef = aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); ++ ++ if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro) ++ NotifyMacroEventRead(); ++ ++ xSet->setPropertyValue("FrameURL", uno::makeAny( sHRef ) ); + xSet->setPropertyValue("FrameName", uno::makeAny( aName ) ); + + if ( eScroll == ScrollingMode::Auto ) +diff --git a/sw/source/filter/xml/xmltexti.cxx b/sw/source/filter/xml/xmltexti.cxx +index 788bec5..72a14b9 100644 +--- a/sw/source/filter/xml/xmltexti.cxx ++++ b/sw/source/filter/xml/xmltexti.cxx +@@ -853,9 +853,14 @@ uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertFloatingFra + uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); + if ( xSet.is() ) + { ++ OUString sHRef = URIHelper::SmartRel2Abs( ++ INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ); ++ ++ if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro) ++ GetXMLImport().NotifyMacroEventRead(); ++ + xSet->setPropertyValue("FrameURL", +- makeAny( URIHelper::SmartRel2Abs( +- INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ) ); ++ makeAny( rHRef ) ); + + xSet->setPropertyValue("FrameName", + makeAny( rName ) ); +diff --git a/wizards/source/access2base/DoCmd.xba b/wizards/source/access2base/DoCmd.xba +index 27b0d74..26755a8 100644 +--- a/wizards/source/access2base/DoCmd.xba ++++ b/wizards/source/access2base/DoCmd.xba +@@ -2655,7 +2655,7 @@ Private Sub _ShellExecute(sCommand As String) + + Dim oShell As Object + Set oShell = createUnoService("com.sun.star.system.SystemShellExecute") +- oShell.execute(sCommand, "" , com.sun.star.system.SystemShellExecuteFlags.DEFAULTS) ++ oShell.execute(sCommand, "" , com.sun.star.system.SystemShellExecuteFlags.URIS_ONLY) + + End Sub ' _ShellExecute V0.8.5 + +diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx +index 2e509f8..ae35f1e 100644 +--- a/xmloff/source/draw/ximpshap.cxx ++++ b/xmloff/source/draw/ximpshap.cxx +@@ -87,6 +87,7 @@ + #include + #include + #include ++#include + #include + + using namespace ::com::sun::star; +@@ -3243,6 +3244,9 @@ void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< cs + + if( !maHref.isEmpty() ) + { ++ if (INetURLObject(maHref).GetProtocol() == INetProtocol::Macro) ++ GetImport().NotifyMacroEventRead(); ++ + xProps->setPropertyValue("FrameURL", Any(maHref) ); + } + } +-- +2.37.3 + diff --git a/SOURCES/0001-Convert-attribute-value-to-UTF-8-when-passing-it-to-.patch b/SOURCES/0001-Convert-attribute-value-to-UTF-8-when-passing-it-to-.patch new file mode 100644 index 0000000..964aea4 --- /dev/null +++ b/SOURCES/0001-Convert-attribute-value-to-UTF-8-when-passing-it-to-.patch @@ -0,0 +1,50 @@ +From 78fd31b17931e1217d3b11fcbd13a41d79d99055 Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Wed, 23 Sep 2020 11:41:05 +0200 +Subject: [PATCH] Convert attribute value to UTF-8 when passing it to libxml2 + +Using toUtf8, requiring the OUString to actually contain well-formed data, but +which is likely OK for this test-code--only function, and is also what similar +dumpAsXml functions e.g. in editeng/source/items/textitem.cxx already use. + +This appears to have been broken ever since the code's introduction in +553f10c71a2cc92f5f5890e24948f5277e3d2758 "add dumpAsXml() to more pool items", +and it would typically only have written the leading zero or one +(depending on the architecture's endianness) characters. (I ran across it on +big-endian s390x, where CppunitTest_sd_tiledrendering +SdTiledRenderingTest::testTdf104405 failed because of + +> Entity: line 2: parser error : Input is not proper UTF-8, indicate encoding ! +> Bytes: 0xCF 0x22 0x2F 0x3E +> ation=""/> +Date: Wed, 23 Sep 2020 12:01:35 +0200 +Subject: [PATCH] Correctly read PNG into bitmaps N32BitTcA... formats (where + alpha comes first) + +This appears to be a regression introduced with +86ea64f216819696cd86d1926aff0a138ace2baf "Support for native 32bit Bitmap in VCL +and SVP (cairo) backend". It caused CppunitTest_vcl_png_test to fail on +(big-endian) Linux s390x with + +> vcl/qa/cppunit/png/PngFilterTest.cxx:176:PngFilterTest::testPng +> equality assertion failed +> - Expected: c[ff000040] +> - Actual : c[0000ff40] + +where eFormat happens to be ScanlineFormat::N32BitTcArgb, vs. +ScanlineFormat::N32BitTcBgra on e.g. Linux x86-64 (and which thus didn't notice +the lack of support for N32BitTcA... formats where alpha goes first instead of +last). + +Change-Id: Id6030468718f6ef831b42f2b5ad7ba2c4c46a805 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103240 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit 0387077e6647d7a30fd36d4ec41dfc559afe45c3) +--- + vcl/source/filter/png/PngImageReader.cxx | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx +index 958cae34eb46..6e9f3825face 100644 +--- a/vcl/source/filter/png/PngImageReader.cxx ++++ b/vcl/source/filter/png/PngImageReader.cxx +@@ -188,6 +188,8 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32) + for (auto& rRow : aRows) + rRow.resize(aRowSizeBytes, 0); + ++ auto const alphaFirst = (eFormat == ScanlineFormat::N32BitTcAbgr ++ || eFormat == ScanlineFormat::N32BitTcArgb); + for (int pass = 0; pass < nNumberOfPasses; pass++) + { + for (png_uint_32 y = 0; y < height; y++) +@@ -199,10 +201,17 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32) + for (size_t i = 0; i < aRowSizeBytes; i += 4) + { + sal_Int8 alpha = pRow[i + 3]; ++ if (alphaFirst) ++ { ++ pScanline[iColor++] = alpha; ++ } + pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 0], alpha); + pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 1], alpha); + pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 2], alpha); +- pScanline[iColor++] = alpha; ++ if (!alphaFirst) ++ { ++ pScanline[iColor++] = alpha; ++ } + } + } + } +-- +2.33.1 + diff --git a/SOURCES/0001-Fix-endianness-issues-in-OOX-crypto-routines.patch b/SOURCES/0001-Fix-endianness-issues-in-OOX-crypto-routines.patch new file mode 100644 index 0000000..bae5223 --- /dev/null +++ b/SOURCES/0001-Fix-endianness-issues-in-OOX-crypto-routines.patch @@ -0,0 +1,116 @@ +From 96b088a62174a70441ebe959495756e9d86203a2 Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Thu, 24 Sep 2020 14:51:16 +0200 +Subject: [PATCH] Fix endianness issues in OOX crypto routines + +...without which CppunitTest_sw_ooxmlencryption failed on (big-endian) s390x: + +* The 32-bit segment counter in AgileEngine::de-/encrypt apparently needs to be + stored in LSB format (at least, if it is, CppunitTest_sw_ooxmlencryption + ultimately succeeded, whereas otherwise it failed). + +* The UTF-16 string in Standard2007Engine::calculateEncryptionKey apparently + needs to be in LSB format (at least, if it is, CppunitTest_sw_ooxmlencryption + ultimately succeeded, whereas otherwise it failed). + +* The various 32-bit values in the EncryptionStandardHeader and + EncryptionVerifierAES data structures apparently need to be written out in LSB + format in Standard2007Engine::writeEncryptionInfo, given that they are always + read in LSB format in Standard2007Engine::readEncryptionInfo. + +Change-Id: I3a1efbfe324b1bbd539b88dc5d40bb44f9676ffa +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103315 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit 646a69757b928aeaf6e0d0d41c4b30c02803a3a3) +--- + oox/source/crypto/AgileEngine.cxx | 16 +++++++++----- + oox/source/crypto/Standard2007Engine.cxx | 28 +++++++++++++++++------- + 2 files changed, 30 insertions(+), 14 deletions(-) + +diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx +index 7c2a0e9c93d2..0fc972bf2ca5 100644 +--- a/oox/source/crypto/AgileEngine.cxx ++++ b/oox/source/crypto/AgileEngine.cxx +@@ -457,9 +457,11 @@ bool AgileEngine::decrypt(BinaryXInputStream& aInputStream, + + while ((inputLength = aInputStream.readMemory(inputBuffer.data(), inputBuffer.size())) > 0) + { +- sal_uInt8* segmentBegin = reinterpret_cast(&segment); +- sal_uInt8* segmentEnd = segmentBegin + sizeof(segment); +- std::copy(segmentBegin, segmentEnd, saltWithBlockKey.begin() + saltSize); ++ auto p = saltWithBlockKey.begin() + saltSize; ++ p[0] = segment & 0xFF; ++ p[1] = (segment >> 8) & 0xFF; ++ p[2] = (segment >> 16) & 0xFF; ++ p[3] = segment >> 24; + + hashCalc(hash, saltWithBlockKey, mInfo.hashAlgorithm); + +@@ -800,9 +802,11 @@ void AgileEngine::encrypt(css::uno::Reference & rxInputS + inputLength : oox::core::roundUp(inputLength, sal_uInt32(mInfo.blockSize)); + + // Update Key +- sal_uInt8* segmentBegin = reinterpret_cast(&nSegment); +- sal_uInt8* segmentEnd = segmentBegin + nSegmentByteSize; +- std::copy(segmentBegin, segmentEnd, saltWithBlockKey.begin() + saltSize); ++ auto p = saltWithBlockKey.begin() + saltSize; ++ p[0] = nSegment & 0xFF; ++ p[1] = (nSegment >> 8) & 0xFF; ++ p[2] = (nSegment >> 16) & 0xFF; ++ p[3] = nSegment >> 24; + + hashCalc(hash, saltWithBlockKey, mInfo.hashAlgorithm); + +diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx +index 38c4e03baf15..e96fc8f841f2 100644 +--- a/oox/source/crypto/Standard2007Engine.cxx ++++ b/oox/source/crypto/Standard2007Engine.cxx +@@ -79,12 +79,12 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) + std::vector initialData(saltSize + passwordByteLength); + std::copy(saltArray, saltArray + saltSize, initialData.begin()); + +- const sal_uInt8* passwordByteArray = reinterpret_cast(rPassword.getStr()); +- +- std::copy( +- passwordByteArray, +- passwordByteArray + passwordByteLength, +- initialData.begin() + saltSize); ++ auto p = initialData.begin() + saltSize; ++ for (sal_Int32 i = 0; i != rPassword.getLength(); ++i) { ++ auto c = rPassword[i]; ++ *p++ = c & 0xFF; ++ *p++ = c >> 8; ++ } + + // use "hash" vector for result of sha1 hashing + // calculate SHA1 hash of initialData +@@ -223,11 +223,23 @@ void Standard2007Engine::writeEncryptionInfo(BinaryXOutputStream& rStream) + sal_uInt32 headerSize = encryptionHeaderSize + cspNameSize; + rStream.WriteUInt32(headerSize); + +- rStream.writeMemory(&mInfo.header, encryptionHeaderSize); ++ rStream.WriteUInt32(mInfo.header.flags); ++ rStream.WriteUInt32(mInfo.header.sizeExtra); ++ rStream.WriteUInt32(mInfo.header.algId); ++ rStream.WriteUInt32(mInfo.header.algIdHash); ++ rStream.WriteUInt32(mInfo.header.keyBits); ++ rStream.WriteUInt32(mInfo.header.providedType); ++ rStream.WriteUInt32(mInfo.header.reserved1); ++ rStream.WriteUInt32(mInfo.header.reserved2); + rStream.writeUnicodeArray(lclCspName); + rStream.WriteUInt16(0); + +- rStream.writeMemory(&mInfo.verifier, sizeof(msfilter::EncryptionVerifierAES)); ++ rStream.WriteUInt32(mInfo.verifier.saltSize); ++ rStream.writeMemory(&mInfo.verifier.salt, sizeof mInfo.verifier.salt); ++ rStream.writeMemory(&mInfo.verifier.encryptedVerifier, sizeof mInfo.verifier.encryptedVerifier); ++ rStream.WriteUInt32(mInfo.verifier.encryptedVerifierHashSize); ++ rStream.writeMemory( ++ &mInfo.verifier.encryptedVerifierHash, sizeof mInfo.verifier.encryptedVerifierHash); + } + + void Standard2007Engine::encrypt(css::uno::Reference & rxInputStream, +-- +2.33.1 + diff --git a/SOURCES/0001-Flatpak-Add-app-bin-libreoffice-app-libreoffice-prog.patch b/SOURCES/0001-Flatpak-Add-app-bin-libreoffice-app-libreoffice-prog.patch new file mode 100644 index 0000000..d25d154 --- /dev/null +++ b/SOURCES/0001-Flatpak-Add-app-bin-libreoffice-app-libreoffice-prog.patch @@ -0,0 +1,64 @@ +From acca5c87e73255db350a02d13bf34a62efaf9c93 Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Tue, 21 Apr 2020 14:07:24 +0200 +Subject: [PATCH] Flatpak: Add /app/bin/libreoffice -> + /app/libreoffice/program/soffice symlink + +Which removes the need to rewrite the + + Exec=${UNIXBASISROOTNAME} + +lines from sysui/desktop/menus/*.desktop, and helps to harmonize the plain +Flatpak build with the one done from Fedora RPMs (see +). + +(Also change the manifest command from an absolute path to a filename relative +to PATH. It is not clear to me which one would be better or more conventional, +but at least also uses just +a filename in its example.) + +Change-Id: I69c380b84503bf3d85801093fb92567852ceb00b +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92837 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +--- + solenv/bin/assemble-flatpak.sh | 4 ++-- + solenv/flatpak-manifest.in | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/solenv/bin/assemble-flatpak.sh b/solenv/bin/assemble-flatpak.sh +index b4bce2d4d172..0738fcd59ad2 100755 +--- a/solenv/bin/assemble-flatpak.sh ++++ b/solenv/bin/assemble-flatpak.sh +@@ -14,13 +14,13 @@ + set -e + + cp -r "${PREFIXDIR?}"/lib/libreoffice /app/ ++ln -s /app/libreoffice/program/soffice /app/bin/libreoffice + + ## libreoffice-*.desktop -> org.libreoffice.LibreOffice.*.desktop: + mkdir -p /app/share/applications + for i in "${PREFIXDIR?}"/share/applications/libreoffice-*.desktop + do +- sed -e 's,^Exec=libreoffice,Exec=/app/libreoffice/program/soffice,' \ +- -e 's/^Icon=libreoffice-/Icon=org.libreoffice.LibreOffice./' "$i" \ ++ sed -e 's/^Icon=libreoffice-/Icon=org.libreoffice.LibreOffice./' "$i" \ + >/app/share/applications/org.libreoffice.LibreOffice."${i#"${PREFIXDIR?}"/share/applications/libreoffice-}" + done + mv /app/share/applications/org.libreoffice.LibreOffice.startcenter.desktop \ +diff --git a/solenv/flatpak-manifest.in b/solenv/flatpak-manifest.in +index 9f64a142dd68..754b6b6dbbe1 100644 +--- a/solenv/flatpak-manifest.in ++++ b/solenv/flatpak-manifest.in +@@ -6,7 +6,7 @@ + "sdk-extensions": [ + "org.freedesktop.Sdk.Extension.openjdk11" + ], +- "command": "/app/libreoffice/program/soffice", ++ "command": "libreoffice", + "modules": [ + { + "name": "openjdk", +-- +2.26.0 + diff --git a/SOURCES/0001-Read-MOSDocumentLockFile-UTF-16-string-data-with-sam.patch b/SOURCES/0001-Read-MOSDocumentLockFile-UTF-16-string-data-with-sam.patch new file mode 100644 index 0000000..17afff6 --- /dev/null +++ b/SOURCES/0001-Read-MOSDocumentLockFile-UTF-16-string-data-with-sam.patch @@ -0,0 +1,59 @@ +From 9f393ee10ae198063bbe3b71c2c87262e7880a34 Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Wed, 23 Sep 2020 11:53:11 +0200 +Subject: [PATCH] Read MOSDocumentLockFile UTF-16 string data with same + endianness +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +...as MSODocumentLockFile::WriteEntryToStream has written it to (i.e., +always as UTF-16LE, assuming that is actually the right format to use). The +discrepancy between writing and reading the string data appears to be present +ever since the code's introduction in 5db1e20b8b0942dac2d50f3cd34532bb61147020 +"Introduce new lockfile handler for MSO like lockfiles". + +This caused CppunitTest_svl_lockfiles to fail on (big-endian) s390x Linux with + +> svl/qa/unit/lockfiles/test_lockfiles.cxx:578:(anonymous namespace)::LockfileTest::testWordLockFileRT +> equality assertion failed +> - Expected: LockFile Test +> - Actual : 䰀漀挀欀䘀椀氀攀 吀攀猀琀 + +etc. + +Change-Id: I97267aa14a3a926e7fd7bb1d2ce7d2de05d52a64 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103238 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit 1b9fa11a0869246fe0433b79aab30dd216cf92b6) +--- + svl/source/misc/msodocumentlockfile.cxx | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/svl/source/misc/msodocumentlockfile.cxx b/svl/source/misc/msodocumentlockfile.cxx +index 9650db03999f..0c857ffb53ec 100644 +--- a/svl/source/misc/msodocumentlockfile.cxx ++++ b/svl/source/misc/msodocumentlockfile.cxx +@@ -228,8 +228,16 @@ LockFileEntry MSODocumentLockFile::GetLockData() + nUTF16Len = *++pBuf; // use Excel/PowerPoint position + + if (nUTF16Len > 0 && nUTF16Len <= 52) // skip wrong format +- aResult[LockFileComponent::OOOUSERNAME] +- = OUString(reinterpret_cast(pBuf + 2), nUTF16Len); ++ { ++ OUStringBuffer str(nUTF16Len); ++ sal_uInt8 const* p = reinterpret_cast(pBuf + 2); ++ for (int i = 0; i != nUTF16Len; ++i) ++ { ++ str.append(sal_Unicode(p[0] | (sal_uInt32(p[1]) << 8))); ++ p += 2; ++ } ++ aResult[LockFileComponent::OOOUSERNAME] = str.makeStringAndClear(); ++ } + } + } + return aResult; +-- +2.33.1 + diff --git a/SOURCES/0001-Related-tdf-127782-resize-the-print-dialog-to-its-op.patch b/SOURCES/0001-Related-tdf-127782-resize-the-print-dialog-to-its-op.patch new file mode 100644 index 0000000..0a0b1aa --- /dev/null +++ b/SOURCES/0001-Related-tdf-127782-resize-the-print-dialog-to-its-op.patch @@ -0,0 +1,2186 @@ +From d613261e913f96cb088fa97c7f4a85b0e57e32c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 10 Jan 2020 17:27:04 +0000 +Subject: [PATCH] Related: tdf#127782 resize the print dialog to its optimum + size... +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +after expander is activated + +Change-Id: I3f87243f0502829e048173987c8998898d351adf +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86575 +Tested-by: Jenkins +Reviewed-by: Heiko Tietze +(cherry picked from commit fa412876add97cab38d404723c49d35775f8efea) + +Related: tdf#127782 use size groups to avoid changing widths on using expanders + +Change-Id: I07335d466cf8f9fa1692372eeecbb484a2f4386d +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86923 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit 0874fa237b3b6be3890915a744c5d34ba2bef8f7) + +change label in print dialog from "OK" to "Print" + +Change-Id: I1d6b04678ab039138908bc9555763bea057fa996 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88212 +Tested-by: Jenkins +Reviewed-by: Heiko Tietze +(cherry picked from commit aec3cce9e4aa12e6cfe229e11d6548f0c3a7cbb5) + +tdf#130517 improve accelerators on Print dialog page + +- add accelerator for Print +- change accelerators for other "p" items + - All Pages to A + - Preview to v + - Order (not needed, because _r on checkbox is enough) + +Change-Id: I7db4153829132dcbbb7c7356591f43df809583ca +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89127 +Tested-by: Jenkins +Reviewed-by: Seth Chaiklin +Reviewed-by: Heiko Tietze +(cherry picked from commit 5c3604542191b3c69da2d9d912c5c5a20c7143e9) + +missing use_underlines + +Change-Id: I2953069ee266c2a7850181826b299f0037a936ea +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90662 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit 80b4419d94e74b79330945aa76f06b0e62fe0d88) + +tdf#127782 - New Print dialog is too high + +ScrollWindow behind the tab control + +Change-Id: I5560f4368f94a45eeb1e3af3bf18df0f305ab3da +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92758 +Tested-by: Jenkins +Reviewed-by: Heiko Tietze +(cherry picked from commit 26ada4335a5804735ae37cf9a89f8145e0931fd7) +--- + sw/inc/strings.hrc | 2 +- + vcl/inc/printdlg.hxx | 4 + + vcl/source/window/printdlg.cxx | 9 + + vcl/uiconfig/ui/printdialog.ui | 1721 ++++++++++++++++---------------- + 4 files changed, 887 insertions(+), 849 deletions(-) + +diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc +index 8c771426ef00..074681b65fae 100644 +--- a/sw/inc/strings.hrc ++++ b/sw/inc/strings.hrc +@@ -621,7 +621,7 @@ + #define STR_PRINTOPTUI_BROCHURE NC_("STR_PRINTOPTUI_BROCHURE", "Broch~ure") + #define STR_PRINTOPTUI_LEFT_SCRIPT NC_("STR_PRINTOPTUI_LEFT_SCRIPT", "Left-to-right script") + #define STR_PRINTOPTUI_RIGHT_SCRIPT NC_("STR_PRINTOPTUI_RIGHT_SCRIPT", "Right-to-left script") +-#define STR_PRINTOPTUI_PRINTALLPAGES NC_("STR_PRINTOPTUI_PRINTALLPAGES", "All ~Pages") ++#define STR_PRINTOPTUI_PRINTALLPAGES NC_("STR_PRINTOPTUI_PRINTALLPAGES", "~All Pages") + #define STR_PRINTOPTUI_PRINTPAGES NC_("STR_PRINTOPTUI_PRINTPAGES", "Pa~ges:") + #define STR_PRINTOPTUI_PRINTEVENPAGES NC_("STR_PRINTOPTUI_PRINTEVENPAGES", "~Even pages") + #define STR_PRINTOPTUI_PRINTODDPAGES NC_("STR_PRINTOPTUI_PRINTODDPAGES", "~Odd pages") +diff --git a/vcl/inc/printdlg.hxx b/vcl/inc/printdlg.hxx +index 5e8289d6b4d1..9db2e07ca698 100644 +--- a/vcl/inc/printdlg.hxx ++++ b/vcl/inc/printdlg.hxx +@@ -186,6 +186,8 @@ namespace vcl + std::unique_ptr mxNupOrderWin; + /// border around each page + std::unique_ptr mxBorderCB; ++ std::unique_ptr mxRangeExpander; ++ std::unique_ptr mxLayoutExpander; + std::unique_ptr mxCustom; + + OUString const maPrintToFileText; +@@ -234,6 +236,8 @@ namespace vcl + DECL_LINK( UIOption_SpinModifyHdl, weld::SpinButton&, void ); + DECL_LINK( UIOption_EntryModifyHdl, weld::Entry&, void ); + ++ DECL_LINK( ExpandHdl, weld::Expander&, void ); ++ + css::beans::PropertyValue* getValueForWindow(weld::Widget*) const; + + void preparePreview( bool i_bMayUseCache ); +diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx +index 7d340559806a..ceb25a7e8609 100644 +--- a/vcl/source/window/printdlg.cxx ++++ b/vcl/source/window/printdlg.cxx +@@ -566,6 +566,8 @@ PrintDialog::PrintDialog(weld::Window* i_pWindow, const std::shared_ptrweld_check_button("bordercb")) ++ , mxRangeExpander(m_xBuilder->weld_expander("exRangeExpander")) ++ , mxLayoutExpander(m_xBuilder->weld_expander("exLayoutExpander")) + , mxCustom(m_xBuilder->weld_widget("customcontents")) + , maPrintToFileText( VclResId( SV_PRINT_TOFILE_TXT ) ) + , maDefPrtText( VclResId( SV_PRINT_DEFPRT_TXT ) ) +@@ -695,9 +697,16 @@ PrintDialog::PrintDialog(weld::Window* i_pWindow, const std::shared_ptrconnect_value_changed( LINK( this, PrintDialog, MetricSpinModifyHdl ) ); + mxSheetMarginEdt->connect_value_changed( LINK( this, PrintDialog, MetricSpinModifyHdl ) ); + ++ mxRangeExpander->connect_expanded(LINK( this, PrintDialog, ExpandHdl)); ++ mxLayoutExpander->connect_expanded(LINK( this, PrintDialog, ExpandHdl)); ++ + updateNupFromPages(); + } + ++IMPL_LINK_NOARG(PrintDialog, ExpandHdl, weld::Expander&, void) ++{ ++ m_xDialog->resize_to_request(); ++} + + PrintDialog::~PrintDialog() + { +diff --git a/vcl/uiconfig/ui/printdialog.ui b/vcl/uiconfig/ui/printdialog.ui +index fc98a18a89a9..d0ebb7abe103 100644 +--- a/vcl/uiconfig/ui/printdialog.ui ++++ b/vcl/uiconfig/ui/printdialog.ui +@@ -1,5 +1,5 @@ + +- ++ + + + +@@ -66,7 +66,7 @@ + 0 + 0 + dialog +- ++ + + + +@@ -100,6 +100,7 @@ + True + True + 10 ++ True + + + False +@@ -109,13 +110,13 @@ + + + +- gtk-ok ++ _Print + True + True + True + True + True +- True ++ True + + + False +@@ -145,38 +146,30 @@ + + + +- ++ + True + False +- 6 ++ True ++ True + +- ++ + True + False ++ 6 ++ vertical ++ 12 + +- ++ + True +- True ++ False + vertical +- 6 + +- ++ + True + False +- vertical +- +- +- True +- False +- GDK_STRUCTURE_MASK | GDK_SCROLL_MASK +- Print preview +- +- +- True +- True +- 0 +- +- ++ GDK_STRUCTURE_MASK | GDK_SCROLL_MASK ++ Print preview ++ 6 + + + True +@@ -184,103 +177,29 @@ + 0 + + ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False + +- ++ + True + False ++ 6 + +- ++ + True +- False +- 10 +- 6 +- +- +- True +- True +- True +- Last page +- imgLast +- +- +- False +- True +- end +- 0 +- +- +- +- +- True +- True +- True +- Next page +- imgForward +- +- +- False +- False +- end +- 1 +- +- +- +- +- True +- False +- / %n +- +- +- False +- True +- end +- 2 +- +- +- +- +- True +- True +- 3 +- 1 +- +- +- False +- True +- end +- 3 +- +- +- +- +- True +- True +- True +- Previous page +- imgBack +- +- +- False +- False +- end +- 4 +- +- +- +- +- True +- True +- True +- First page +- imgFirst +- +- +- False +- False +- end +- 5 +- +- ++ True ++ True ++ Last page ++ imgLast + + + False +@@ -290,49 +209,121 @@ + + + +- ++ ++ True ++ True ++ True ++ Next page ++ imgForward ++ ++ ++ False ++ False ++ end ++ 1 ++ ++ ++ ++ + True + False +- 10 +- 3 +- +- +- Preview +- True +- True +- False +- center +- True +- True +- True +- +- +- False +- True +- end +- 0 +- +- ++ / %n ++ ++ ++ False ++ True ++ end ++ 2 ++ ++ ++ ++ ++ True ++ True ++ 3 ++ 1 + + + False + True ++ end ++ 3 ++ ++ ++ ++ ++ True ++ True ++ True ++ Previous page ++ imgBack ++ ++ ++ False ++ False ++ end + 4 + + ++ ++ ++ True ++ True ++ True ++ First page ++ imgFirst ++ ++ ++ False ++ False ++ end ++ 5 ++ ++ + + + False + True + end +- 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 3 ++ ++ ++ Pre_view ++ True ++ True ++ False ++ center ++ True ++ True ++ True ++ ++ ++ False ++ True ++ end ++ 0 ++ ++ ++ ++ ++ False ++ True ++ 4 + + + + +- True ++ False + True +- 0 ++ end ++ 1 + + + +@@ -343,65 +334,52 @@ + + + +- ++ + True +- False +- vertical ++ True ++ 6 ++ True ++ True + +- ++ + True + True +- True +- True ++ in ++ 500 ++ 450 + +- ++ + True + False +- 6 +- vertical +- 12 + +- ++ + True + False +- 0 +- none ++ 6 ++ vertical ++ 12 + +- ++ + True + False +- 6 +- 12 ++ 0 ++ none + +- ++ + True + False +- vertical +- 6 +- +- +- True +- False +- +- +- False +- True +- 0 +- +- ++ 6 ++ 12 + +- ++ + True + False ++ vertical + 6 + +- ++ + True + False +- Status: +- +- +- + + + False +@@ -410,13 +388,55 @@ + + + +- ++ + True + False +- Default Printer +- +- +- ++ 6 ++ ++ ++ True ++ False ++ Status: ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Default Printer ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Properties... ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ end ++ 2 ++ ++ + + + False +@@ -424,217 +444,82 @@ + 1 + + +- +- +- Properties... +- True +- True +- True +- end +- +- +- False +- True +- end +- 2 +- +- + +- +- False +- True +- 1 +- + + + ++ ++ ++ True ++ False ++ Printer ++ True ++ printersbox ++ ++ ++ ++ ++ + ++ ++ False ++ True ++ 0 ++ + +- +- +- True +- False +- Printer +- True +- printersbox +- +- +- +- +- +- +- +- False +- True +- 0 +- +- +- +- +- True +- False +- 0 +- none + +- ++ + True + False +- 6 +- 12 ++ 0 ++ none + +- ++ + True + False +- 2 +- 6 +- +- +- _All pages +- True +- True +- False +- start +- 2 +- True +- True +- True +- +- +- 0 +- 0 +- 2 +- +- +- +- +- _Pages: +- True +- True +- False +- start +- 2 +- 2 +- True +- True +- rbAllPages +- +- +- 0 +- 1 +- +- +- +- +- True +- True +- True +- True +- e.g.: 1, 3-5, 7, 9 +- +- +- 1 +- 1 +- +- +- +- +- _Even pages +- True +- True +- False +- start +- 2 +- 2 +- True +- True +- rbAllPages +- +- +- 0 +- 2 +- 2 +- +- +- +- +- _Odd pages +- True +- True +- False +- start +- 2 +- 2 +- True +- True +- rbAllPages +- +- +- 0 +- 3 +- 2 +- +- ++ 6 ++ 12 + +- +- _Selection +- True +- False +- start +- 2 +- True +- True +- rbAllPages +- +- +- 0 +- 4 +- 2 +- +- +- +- ++ + True +- True +- True +- True ++ False ++ 6 + +- ++ + True + False + 2 + 6 + +- +- False ++ ++ _All pages ++ True ++ True ++ False + start +- _From which print: ++ 2 + True +- printextrabox ++ True ++ True + + + 0 + 0 +- +- +- +- +- False +- True +- +- +- 1 +- 0 + 2 + + + +- ++ ++ _Pages: + True +- False ++ True ++ False + start +- Paper _sides: ++ 2 ++ 2 + True +- sidesbox ++ True ++ rbAllPages + + + 0 +@@ -642,635 +527,763 @@ + + + +- ++ + True +- False ++ True + True +- +- Print on one side (simplex) +- Print on both sides (duplex long edge) +- Print on both sides (duplex short edge) +- ++ True ++ e.g.: 1, 3-5, 7, 9 + + + 1 + 1 +- 2 + + + +- ++ ++ _Even pages + True +- False ++ True ++ False + start +- _Number of copies: ++ 2 ++ 2 + True +- copycount ++ True ++ rbAllPages + + + 0 + 2 ++ 2 + + + +- ++ ++ _Odd pages + True + True +- center +- True +- True +- 1 +- adjustment2 +- 1 ++ False ++ start ++ 2 ++ 2 ++ True ++ True ++ rbAllPages + + +- 1 +- 2 ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ _Selection ++ True ++ False ++ start ++ 2 ++ True ++ True ++ rbAllPages ++ ++ ++ 0 ++ 4 ++ 2 + + ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True + +- ++ + True + False +- end +- 4 ++ 2 ++ 6 ++ ++ ++ False ++ start ++ _From which print: ++ True ++ printextrabox ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ False ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ start ++ Paper _sides: ++ True ++ sidesbox ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ ++ Print on one side (simplex) ++ Print on both sides (duplex long edge) ++ Print on both sides (duplex short edge) ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ start ++ _Number of copies: ++ True ++ copycount ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ center ++ True ++ True ++ 1 ++ adjustment2 ++ 1 ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ start ++ Order: ++ True ++ reverseorder ++ ++ ++ 0 ++ 4 ++ 2 ++ ++ + +- +- _Collate ++ ++ Print in _reverse order + True + True + False ++ start + True + True + + +- False +- True +- 0 ++ 1 ++ 4 + + + +- ++ + True + False +- gtk-missing-image ++ start ++ 4 ++ ++ ++ _Collate ++ True ++ True ++ False ++ True ++ True ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ gtk-missing-image ++ ++ ++ False ++ True ++ 1 ++ ++ + + +- False +- True +- 1 ++ 1 ++ 3 + + ++ ++ ++ + +- +- 2 +- 2 +- + +- +- ++ ++ + True + False +- start +- _Order: +- True +- reverseorder +- +- +- 0 +- 3 +- +- +- +- +- Print in _reverse order +- True +- True +- False +- start ++ _more + True +- True + +- +- 1 +- 3 +- 2 +- + + +- +- +- +- True +- False +- _more +- True +- ++ ++ 0 ++ 1 ++ + + +- +- 0 +- 5 +- 2 +- + + + ++ ++ ++ True ++ False ++ Range and Copies ++ ++ ++ ++ ++ + ++ ++ False ++ True ++ 1 ++ + +- +- +- True +- False +- Range and Copies +- grid1 +- +- +- +- +- +- +- +- False +- True +- 1 +- +- +- +- +- True +- False +- 0 +- none + +- ++ + True + False +- 6 +- 12 ++ 0 ++ none + +- ++ + True + False +- 6 +- 6 ++ 6 ++ 12 + +- ++ + True + False +- start +- Orientation: +- True +- pageorientationbox +- +- +- 0 +- 1 +- +- +- +- +- True +- False +- start +- Paper size: +- True +- papersizebox +- +- +- 0 +- 0 +- +- +- +- +- True +- False +- True +- 0 +- +- Automatic +- Portrait +- Landscape +- +- +- +- 1 +- 1 +- +- +- +- +- True +- False +- True +- +- +- 1 +- 0 +- +- +- +- +- True +- True +- True +- True ++ 6 + +- ++ + True + False + 6 + 6 + +- ++ + True + False +- 3 +- +- +- Pages per sheet: +- True +- True +- False +- start +- True +- True +- True +- +- +- +- +- +- False +- True +- 0 +- +- +- +- +- True +- False +- +- +- False +- True +- 1 +- +- ++ start ++ Orientation: ++ True ++ pageorientationbox + + + 0 +- 0 ++ 1 + + + +- ++ + True +- False +- True +- 0 +- +- 1 +- 2 +- 4 +- 6 +- 9 +- 16 +- Custom +- +- +- +- +- +- +- 1 +- 0 +- 3 +- +- +- +- + False + start +- Pages: ++ Paper size: + True +- pagerows ++ papersizebox + + + 0 +- 1 +- +- +- +- +- True +- True +- 1 +- adjustment3 +- 1 +- +- +- 1 +- 1 ++ 0 + + + +- ++ ++ True + False +- by +- True +- pagecols +- +- +- 2 +- 1 +- +- +- +- +- True +- True +- 1 +- adjustment4 +- 1 ++ True ++ 0 ++ ++ Automatic ++ Portrait ++ Landscape ++ + + +- 3 ++ 1 + 1 + + + +- ++ ++ True + False +- start +- Margin: +- True +- pagemarginsb +- +- +- 0 +- 2 +- +- +- +- +- True +- True +- 0 +- adjustment5 ++ True + + + 1 +- 2 ++ 0 + + ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True + +- ++ ++ True + False +- start +- between pages +- +- +- 2 +- 2 +- 2 +- +- +- +- +- False +- start +- Distance: +- True +- sheetmarginsb +- +- +- 0 +- 3 +- +- +- +- +- True +- True +- 0 +- adjustment6 +- +- +- 1 +- 3 +- +- +- +- +- False +- start +- to sheet border +- +- +- 2 +- 3 +- 2 +- +- +- +- +- True +- False +- start +- Order: +- True +- orderbox ++ 6 ++ 6 ++ ++ ++ True ++ False ++ 3 ++ ++ ++ Pages per sheet: ++ True ++ True ++ False ++ start ++ True ++ True ++ True ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ 0 ++ ++ 1 ++ 2 ++ 4 ++ 6 ++ 9 ++ 16 ++ Custom ++ ++ ++ ++ ++ ++ ++ 1 ++ 0 ++ 3 ++ ++ ++ ++ ++ False ++ start ++ Pages: ++ True ++ pagerows ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ 1 ++ adjustment3 ++ 1 ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ False ++ by ++ True ++ pagecols ++ ++ ++ 2 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ 1 ++ adjustment4 ++ 1 ++ ++ ++ 3 ++ 1 ++ ++ ++ ++ ++ False ++ start ++ Margin: ++ True ++ pagemarginsb ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ 0 ++ adjustment5 ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ False ++ start ++ between pages ++ ++ ++ 2 ++ 2 ++ 2 ++ ++ ++ ++ ++ False ++ start ++ Distance: ++ True ++ sheetmarginsb ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ 0 ++ adjustment6 ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ False ++ start ++ to sheet border ++ ++ ++ 2 ++ 3 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ start ++ Order: ++ True ++ orderbox ++ ++ ++ 0 ++ 4 ++ ++ ++ ++ ++ True ++ False ++ True ++ ++ Left to right, then down ++ Top to bottom, then right ++ Top to bottom, then left ++ Right to left, then down ++ ++ ++ ++ 1 ++ 4 ++ 3 ++ ++ ++ ++ ++ Draw a border around each page ++ True ++ True ++ False ++ start ++ True ++ True ++ ++ ++ 0 ++ 5 ++ 4 ++ ++ ++ ++ ++ Brochure ++ True ++ True ++ False ++ start ++ True ++ True ++ pagespersheetbtn ++ ++ ++ 0 ++ 6 ++ ++ ++ ++ ++ False ++ ++ ++ 1 ++ 6 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ Collation preview ++ center ++ start ++ ++ ++ 4 ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +- +- 0 +- 4 +- + +- +- ++ ++ + True + False +- True +- +- Left to right, then down +- Top to bottom, then right +- Top to bottom, then left +- Right to left, then down +- +- +- +- 1 +- 4 +- 3 +- +- +- +- +- Draw a border around each page +- True +- True +- False +- start ++ m_ore + True +- True + +- +- 0 +- 5 +- 4 +- + +- +- +- Brochure +- True +- True +- False +- start +- True +- True +- pagespersheetbtn +- +- +- 0 +- 6 +- +- +- +- +- False +- +- +- 1 +- 6 +- 3 +- +- +- +- +- True +- False +- Collation preview +- center +- start +- +- +- 4 +- 4 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- True +- False +- m_ore +- True + ++ ++ 0 ++ 1 ++ + + +- +- 0 +- 2 +- 2 +- + + + ++ ++ ++ True ++ False ++ Page Layout ++ ++ ++ ++ ++ + +- +- +- +- True +- False +- Page Layout +- +- +- +- ++ ++ False ++ True ++ 2 ++ + + +- +- False +- True +- 2 +- + + + +- +- +- True +- False +- General +- +- +- False +- +- ++ ++ ++ ++ ++ True ++ False ++ General ++ ++ ++ False ++ ++ ++ ++ ++ True ++ False ++ 6 ++ vertical + +- +- True +- False +- 6 +- vertical +- +- +- +- +- +- 1 +- +- +- +- +- True +- False +- custom +- +- +- 1 +- False +- ++ + + + +- True +- True +- 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ custom ++ ++ ++ 1 ++ False + + + + +- True ++ False + True + 1 + + + + +- True ++ False + True + 0 + +@@ -1278,6 +1291,18 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +-- +2.25.3 + diff --git a/SOURCES/0001-Resolves-rhbz-1432468-disable-opencl-by-default.patch b/SOURCES/0001-Resolves-rhbz-1432468-disable-opencl-by-default.patch new file mode 100644 index 0000000..d17e9c0 --- /dev/null +++ b/SOURCES/0001-Resolves-rhbz-1432468-disable-opencl-by-default.patch @@ -0,0 +1,26 @@ +From b54cfe9d3d22fdd40f7015bd343df8620c983779 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 27 Mar 2017 11:47:01 +0100 +Subject: [PATCH] Resolves: rhbz#1432468 disable opencl by default + +Change-Id: Ie037fcabdd219f195425979dd721501fb5527573 +--- + officecfg/registry/schema/org/openoffice/Office/Common.xcs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index 946bd32..284d694 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -5670,7 +5670,7 @@ + Determines whether OpenCL can be used, when available, to speed up + some operations. + +- true ++ false + + + +-- +2.9.3 + diff --git a/SOURCES/0001-Resolves-rhbz-1893846-if-last-close-had-insert-index.patch b/SOURCES/0001-Resolves-rhbz-1893846-if-last-close-had-insert-index.patch new file mode 100644 index 0000000..62e19ae --- /dev/null +++ b/SOURCES/0001-Resolves-rhbz-1893846-if-last-close-had-insert-index.patch @@ -0,0 +1,30 @@ +From d59960d5de3f07726594d980152a3bfeb58bace9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 2 Nov 2020 19:27:04 +0000 +Subject: [PATCH 1/8] Resolves: rhbz#1893846 if last close had insert, index + dialog open + +when starting a new writer document + +Change-Id: I83131c01aa53208a321abade48d48a6f7965d0ff +--- + sw/source/ui/index/swuiidxmrk.cxx | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sw/source/ui/index/swuiidxmrk.cxx b/sw/source/ui/index/swuiidxmrk.cxx +index 33a0eab8cd69..5eca069b963b 100644 +--- a/sw/source/ui/index/swuiidxmrk.cxx ++++ b/sw/source/ui/index/swuiidxmrk.cxx +@@ -955,7 +955,8 @@ SwIndexMarkFloatDlg::SwIndexMarkFloatDlg(SfxBindings* _pBindings, + "modules/swriter/ui/indexentry.ui", "IndexEntryDialog") + , m_aContent(m_xDialog, *m_xBuilder, bNew, *::GetActiveWrtShell()) + { +- m_aContent.ReInitDlg(*::GetActiveWrtShell()); ++ if (SwWrtShell* pSh = ::GetActiveWrtShell()) ++ m_aContent.ReInitDlg(*pSh); + Initialize(pInfo); + } + +-- +2.28.0 + diff --git a/SOURCES/0001-Resolves-tdf-132739-two-style-tags-where-there-shoul.patch b/SOURCES/0001-Resolves-tdf-132739-two-style-tags-where-there-shoul.patch new file mode 100644 index 0000000..eb0b7ab --- /dev/null +++ b/SOURCES/0001-Resolves-tdf-132739-two-style-tags-where-there-shoul.patch @@ -0,0 +1,72 @@ +From 5c705fbd9e4d231fed87b7e8ac06d8b7d4c6891f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Thu, 12 Aug 2021 12:55:30 +0100 +Subject: [PATCH] Resolves: tdf#132739 two style tags where there should be + just one + +Change-Id: Id9c8c8cc8c5ffdd21ba79ff39a6279cf2ddc8025 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120360 +Tested-by: Jenkins +Reviewed-by: Adolfo Jayme Barrientos +--- + sw/source/filter/html/css1atr.cxx | 4 +++- + sw/source/filter/html/htmltabw.cxx | 9 ++++++--- + sw/source/filter/html/wrthtml.hxx | 2 +- + 3 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx +index 7b1a5cc19be3..c401d95a788f 100644 +--- a/sw/source/filter/html/css1atr.cxx ++++ b/sw/source/filter/html/css1atr.cxx +@@ -2113,10 +2113,12 @@ void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameF + Strm().WriteChar( '\"' ); + } + +-void SwHTMLWriter::OutCSS1_TableCellBorderHack(SwFrameFormat const& rFrameFormat) ++void SwHTMLWriter::OutCSS1_TableCellBordersAndBG(SwFrameFormat const& rFrameFormat, const SvxBrushItem *pBrushItem) + { + SwCSS1OutMode const aMode( *this, + CSS1_OUTMODE_STYLE_OPT_ON|CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_TABLEBOX, nullptr ); ++ if (pBrushItem) ++ OutCSS1_SvxBrush(*this, *pBrushItem, Css1Background::Table, nullptr); + OutCSS1_SvxBox(*this, rFrameFormat.GetBox()); + if (!m_bFirstCSS1Property) + { +diff --git a/sw/source/filter/html/htmltabw.cxx b/sw/source/filter/html/htmltabw.cxx +index 4c83319747b7..63812a9b3ef6 100644 +--- a/sw/source/filter/html/htmltabw.cxx ++++ b/sw/source/filter/html/htmltabw.cxx +@@ -424,11 +424,14 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, + // Avoid non-CSS version in the ReqIF case. + rWrt.OutBackground( pBrushItem, false ); + +- if( rWrt.m_bCfgOutStyles ) +- OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem ); ++ if (!rWrt.m_bCfgOutStyles) ++ pBrushItem = nullptr; + } + +- rWrt.OutCSS1_TableCellBorderHack(*pBox->GetFrameFormat()); ++ // tdf#132739 with rWrt.m_bCfgOutStyles of true bundle the brush item css ++ // properties into the same "style" tag as the borders so there is only one ++ // style tag ++ rWrt.OutCSS1_TableCellBordersAndBG(*pBox->GetFrameFormat(), pBrushItem); + + sal_uInt32 nNumFormat = 0; + double nValue = 0.0; +diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx +index ab282ba652ff..f82325ee50ae 100644 +--- a/sw/source/filter/html/wrthtml.hxx ++++ b/sw/source/filter/html/wrthtml.hxx +@@ -484,7 +484,7 @@ public: + void writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameFormat& rFrameFormat, const OUString& rAltText, HtmlFrmOpts nFrameOpts); + + void OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameFormat ); +- void OutCSS1_TableCellBorderHack(const SwFrameFormat& rFrameFormat); ++ void OutCSS1_TableCellBordersAndBG(const SwFrameFormat& rFrameFormat, const SvxBrushItem *pBrushItem); + void OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol ); + void OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat, HtmlFrmOpts nFrameOpts, + const SdrObject *pSdrObj=nullptr, +-- +2.31.1 + diff --git a/SOURCES/0001-Restructure-solenv-bin-assemble-flatpak.sh.patch b/SOURCES/0001-Restructure-solenv-bin-assemble-flatpak.sh.patch new file mode 100644 index 0000000..5ccb2e9 --- /dev/null +++ b/SOURCES/0001-Restructure-solenv-bin-assemble-flatpak.sh.patch @@ -0,0 +1,340 @@ +From 54f42e1b75dd795f9d53dce181397f114eeae21b Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Tue, 28 Apr 2020 16:43:31 +0200 +Subject: [PATCH] Restructure solenv/bin/assemble-flatpak.sh + +...so that parts of it can be reused by the Flatpak build done from Fedora RPMs +(see ). The reused parts +are split out into solenv/bin/assemble-flatpak-*.sh files. + +(I can't remember any specific reason why I added the section to the +Flathub org.libreoffice.LibreOffice.appdata.xml; maybe just because the file +format allows for it and it appeared easy to generate the section when writing +the file. For the Fedora LO RPMs, none of the existing appdata.xml files +contained such a section, and generating one for the Fedora Flatpak case would +require obtaining values for those LIBO_VERSION_* variables, so I just added a +switch to solenv/bin/assemble-flatpak-appdata-step1.sh allowing not to write +that section at all. Splitting solenv/bin/assemble-flatpak-appdata.sh in two +steps is necessary because the Fedora Flatpak case wants to replace the +screenshots in the first part of the generated +org.libreoffice.LibreOffice.appdata.xml, but not in the appended original +appdata.xml files, so needs to hook in between those two steps.) + +Change-Id: Ic527f3d88ccbee85e86dad3569b8e73776adf273 +--- + solenv/bin/assemble-flatpak-appdata-step1.sh | 96 +++++++++++++++++ + solenv/bin/assemble-flatpak-appdata-step2.sh | 26 +++++ + solenv/bin/assemble-flatpak-desktop.sh | 42 ++++++++ + solenv/bin/assemble-flatpak.sh | 102 +------------------ + 4 files changed, 169 insertions(+), 97 deletions(-) + create mode 100755 solenv/bin/assemble-flatpak-appdata-step1.sh + create mode 100755 solenv/bin/assemble-flatpak-appdata-step2.sh + create mode 100755 solenv/bin/assemble-flatpak-desktop.sh + +diff --git a/solenv/bin/assemble-flatpak-appdata-step1.sh b/solenv/bin/assemble-flatpak-appdata-step1.sh +new file mode 100755 +index 000000000000..4658dd45d018 +--- /dev/null ++++ b/solenv/bin/assemble-flatpak-appdata-step1.sh +@@ -0,0 +1,96 @@ ++#! /bin/bash ++# ++# This file is part of the LibreOffice project. ++# ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++# ++ ++# Part of solenv/bin/assemble-flatpak.sh that is shared with a downstream mechanism of building a ++# Flatpak from a Fedora libreoffice.spec file. ++# ++# Arguments: ++# $1 pathname, ending in a slash, of the directory into which to put the target ++# org.libreoffice.LibreOffice.appdata.xml file ++# $2 "1" if a section shall be included in the target ++# org.libreoffice.LibreOffice.appdata.xml file, "0" if not ++ ++set -e ++ ++## org.libreoffice.LibreOffice.appdata.xml is manually derived from the various ++## inst/share/appdata/libreoffice-*.appdata.xml (at least recent GNOME Software ++## doesn't show more than five screenshots anyway, so restrict to one each from ++## the five libreoffice-*.appdata.xml: Writer, Calc, Impress, Draw, Base): ++cat <<\EOF >"${1?}"org.libreoffice.LibreOffice.appdata.xml ++ ++ ++ org.libreoffice.LibreOffice.desktop ++ CC0-1.0 ++ MPL-2.0 ++ LibreOffice ++ The LibreOffice productivity suite ++ ++

LibreOffice is a powerful office suite. Its clean interface and ++ feature-rich tools help you unleash your creativity and enhance your ++ productivity. LibreOffice includes several applications that make it the most ++ powerful Free and Open Source office suite on the market: Writer (word ++ processing), Calc (spreadsheets), Impress (presentations), Draw (vector ++ graphics and flowcharts), Base (databases), and Math (formula editing).

++

LibreOffice supports opening and saving into a wide variety of formats, so ++ you can easily share documents with users of other popular office suites ++ without worrying about compatibility.

++
++ http://www.libreoffice.org/discover/libreoffice/ ++ https://bugs.documentfoundation.org/ ++ https://donate.libreoffice.org/ ++ https://wiki.documentfoundation.org/Faq ++ http://www.libreoffice.org/get-help/documentation/ ++ https://wiki.documentfoundation.org/Translating_LibreOffice ++ ++ ++ https://hub.libreoffice.org/screenshots/writer-01.png ++ ++ ++ ++ https://hub.libreoffice.org/screenshots/calc-02.png ++ ++ ++ ++ https://hub.libreoffice.org/screenshots/impress-01.png ++ ++ ++ ++ https://hub.libreoffice.org/screenshots/draw-02.png ++ ++ ++ ++ https://hub.libreoffice.org/screenshots/base-02.png ++ ++ ++ ++ The Document Foundation ++ libreoffice_at_lists.freedesktop.org ++ ++ HiDpiIcon ++ HighContrast ++ ModernToolkit ++ UserDocs ++ ++ ++EOF ++ ++if [ "${2?}" = 1 ] ++then ++ cat <>"${1?}"org.libreoffice.LibreOffice.appdata.xml ++ ++ ++ ++EOF ++fi ++ ++cat <<\EOF >>"${1?}"org.libreoffice.LibreOffice.appdata.xml ++
++EOF +diff --git a/solenv/bin/assemble-flatpak-appdata-step2.sh b/solenv/bin/assemble-flatpak-appdata-step2.sh +new file mode 100755 +index 000000000000..4f06e6b19148 +--- /dev/null ++++ b/solenv/bin/assemble-flatpak-appdata-step2.sh +@@ -0,0 +1,26 @@ ++#! /bin/bash ++# ++# This file is part of the LibreOffice project. ++# ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++# ++ ++# Part of solenv/bin/assemble-flatpak.sh that is shared with a downstream mechanism of building a ++# Flatpak from a Fedora libreoffice.spec file. ++# ++# Arguments: ++# $1 pathname, ending in a slash, of the directory containing the source libreoffice-*.appdata.xml ++# files ++# $2 pathname, ending in a slash, of the directory containing the target ++# org.libreoffice.LibreOffice.appdata.xml file ++ ++set -e ++ ++# append the appdata for the different components ++for i in "${1?}"libreoffice-*.appdata.xml ++do ++ sed "1 d; s/libreoffice-/org.libreoffice.LibreOffice./" "$i" \ ++ >>"${2?}"org.libreoffice.LibreOffice.appdata.xml ++done +diff --git a/solenv/bin/assemble-flatpak-desktop.sh b/solenv/bin/assemble-flatpak-desktop.sh +new file mode 100755 +index 000000000000..6d06de4fbbbe +--- /dev/null ++++ b/solenv/bin/assemble-flatpak-desktop.sh +@@ -0,0 +1,42 @@ ++#! /bin/bash ++# ++# This file is part of the LibreOffice project. ++# ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++# ++ ++# Part of solenv/bin/assemble-flatpak.sh that is shared with a downstream mechanism of building a ++# Flatpak from a Fedora libreoffice.spec file. ++# ++# Arguments: ++# $1 pathname, ending in a slash, of the directory containing the source libreoffice-*.desktop ++# files ++# $2 pathname, ending in a slash, of the directory into which to put the target ++# org.libreoffice.LibreOffice.*.desktop files ++ ++set -e ++ ++## libreoffice-*.desktop -> org.libreoffice.LibreOffice.*.desktop: ++for i in "${1?}"libreoffice-*.desktop ++do ++ sed -e 's/^Icon=libreoffice-/Icon=org.libreoffice.LibreOffice./' "$i" \ ++ >"${2?}"org.libreoffice.LibreOffice."${i#"${1?}"libreoffice-}" ++done ++mv "${2?}"org.libreoffice.LibreOffice.startcenter.desktop "${2?}"org.libreoffice.LibreOffice.desktop ++ ++# Flatpak .desktop exports take precedence over system ones due to ++# the order of XDG_DATA_DIRS - re-associating text/plain seems a bit much ++sed -i "s/text\/plain;//" "${2?}"org.libreoffice.LibreOffice.writer.desktop ++ ++desktop-file-edit --set-key=X-Endless-Alias --set-value=libreoffice-startcenter \ ++ --set-key=X-Flatpak-RenamedFrom --set-value='libreoffice-startcenter.desktop;' \ ++ "${2?}"org.libreoffice.LibreOffice.desktop ++for i in base calc draw impress math writer xsltfilter ++do ++ desktop-file-edit --set-key=X-Endless-Alias --set-value=libreoffice-"$i" \ ++ --set-key=X-Flatpak-RenamedFrom \ ++ --set-value="libreoffice-$i.desktop;org.libreoffice.LibreOffice-$i.desktop;" \ ++ "${2?}"org.libreoffice.LibreOffice."$i".desktop ++done +diff --git a/solenv/bin/assemble-flatpak.sh b/solenv/bin/assemble-flatpak.sh +index 0738fcd59ad2..8ca5bcf08c41 100755 +--- a/solenv/bin/assemble-flatpak.sh ++++ b/solenv/bin/assemble-flatpak.sh +@@ -16,30 +16,9 @@ set -e + cp -r "${PREFIXDIR?}"/lib/libreoffice /app/ + ln -s /app/libreoffice/program/soffice /app/bin/libreoffice + +-## libreoffice-*.desktop -> org.libreoffice.LibreOffice.*.desktop: + mkdir -p /app/share/applications +-for i in "${PREFIXDIR?}"/share/applications/libreoffice-*.desktop +-do +- sed -e 's/^Icon=libreoffice-/Icon=org.libreoffice.LibreOffice./' "$i" \ +- >/app/share/applications/org.libreoffice.LibreOffice."${i#"${PREFIXDIR?}"/share/applications/libreoffice-}" +-done +-mv /app/share/applications/org.libreoffice.LibreOffice.startcenter.desktop \ +- /app/share/applications/org.libreoffice.LibreOffice.desktop +- +-# Flatpak .desktop exports take precedence over system ones due to +-# the order of XDG_DATA_DIRS - re-associating text/plain seems a bit much +-sed -i "s/text\/plain;//" /app/share/applications/org.libreoffice.LibreOffice.writer.desktop +- +-desktop-file-edit --set-key=X-Endless-Alias --set-value=libreoffice-startcenter \ +- --set-key=X-Flatpak-RenamedFrom --set-value='libreoffice-startcenter.desktop;' \ +- /app/share/applications/org.libreoffice.LibreOffice.desktop +-for i in base calc draw impress math writer xsltfilter +-do +- desktop-file-edit --set-key=X-Endless-Alias --set-value=libreoffice-"$i" \ +- --set-key=X-Flatpak-RenamedFrom \ +- --set-value="libreoffice-$i.desktop;org.libreoffice.LibreOffice-$i.desktop;" \ +- /app/share/applications/org.libreoffice.LibreOffice."$i".desktop +-done ++"${SRCDIR?}"/solenv/bin/assemble-flatpak-desktop.sh "${PREFIXDIR?}"/share/applications/ \ ++ /app/share/applications/ + + ## icons/hicolor/*/apps/libreoffice-* -> + ## icons/hicolor/*/apps/org.libreoffice.LibreOffice-*: +@@ -82,81 +61,10 @@ do + ln -rs /app/share/runtime/locale/"${lang}"/registry/"${basename}".xcd "${i}" + done + +-## org.libreoffice.LibreOffice.appdata.xml is manually derived from the various +-## inst/share/appdata/libreoffice-*.appdata.xml (at least recent GNOME Software +-## doesn't show more than five screenshots anyway, so restrict to one each from +-## the five libreoffice-*.appdata.xml: Writer, Calc, Impress, Draw, Base): + mkdir -p /app/share/appdata +-cat </app/share/appdata/org.libreoffice.LibreOffice.appdata.xml +- +- +- org.libreoffice.LibreOffice.desktop +- CC0-1.0 +- MPL-2.0 +- LibreOffice +- The LibreOffice productivity suite +- +-

LibreOffice is a powerful office suite. Its clean interface and +- feature-rich tools help you unleash your creativity and enhance your +- productivity. LibreOffice includes several applications that make it the most +- powerful Free and Open Source office suite on the market: Writer (word +- processing), Calc (spreadsheets), Impress (presentations), Draw (vector +- graphics and flowcharts), Base (databases), and Math (formula editing).

+-

LibreOffice supports opening and saving into a wide variety of formats, so +- you can easily share documents with users of other popular office suites +- without worrying about compatibility.

+-
+- http://www.libreoffice.org/discover/libreoffice/ +- https://bugs.documentfoundation.org/ +- https://donate.libreoffice.org/ +- https://wiki.documentfoundation.org/Faq +- http://www.libreoffice.org/get-help/documentation/ +- https://wiki.documentfoundation.org/Translating_LibreOffice +- +- +- https://hub.libreoffice.org/screenshots/writer-01.png +- +- +- +- https://hub.libreoffice.org/screenshots/calc-02.png +- +- +- +- https://hub.libreoffice.org/screenshots/impress-01.png +- +- +- +- https://hub.libreoffice.org/screenshots/draw-02.png +- +- +- +- https://hub.libreoffice.org/screenshots/base-02.png +- +- +- +- The Document Foundation +- libreoffice_at_lists.freedesktop.org +- +- HiDpiIcon +- HighContrast +- ModernToolkit +- UserDocs +- +- +- +- +- +-
+-EOF +- +-# append the appdata for the different components +-for i in "${PREFIXDIR?}"/share/appdata/libreoffice-*.appdata.xml +-do +- sed "1 d; s/libreoffice-/org.libreoffice.LibreOffice./" "$i" \ +- >>/app/share/appdata/org.libreoffice.LibreOffice.appdata.xml +-done ++"${SRCDIR?}"/solenv/bin/assemble-flatpak-appdata-step1.sh /app/share/appdata/ 1 ++"${SRCDIR?}"/solenv/bin/assemble-flatpak-appdata-step2.sh "${PREFIXDIR?}"/share/appdata/ \ ++ /app/share/appdata/ + + ## see for further places where build-finish would +-- +2.26.2 + diff --git a/SOURCES/0001-Revert-tdf-69060-lock-refreshing-font-data-when-load.patch b/SOURCES/0001-Revert-tdf-69060-lock-refreshing-font-data-when-load.patch new file mode 100644 index 0000000..f398fd1 --- /dev/null +++ b/SOURCES/0001-Revert-tdf-69060-lock-refreshing-font-data-when-load.patch @@ -0,0 +1,150 @@ +From d7ed56975a828eac321959e4510ee14560847b1f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 28 Oct 2020 14:25:11 +0000 +Subject: [PATCH] Revert "tdf#69060: lock refreshing font data when loading a + document" + +This reverts commit 98d71c4e0847797a4ba9229a8e6d832a8a3d5e0f. +--- + include/vcl/outdev.hxx | 3 --- + include/vcl/svapp.hxx | 11 ----------- + sfx2/source/doc/objstor.cxx | 4 ---- + vcl/inc/svdata.hxx | 3 --- + vcl/source/app/svapp.cxx | 5 ----- + vcl/source/outdev/font.cxx | 32 +------------------------------- + 6 files changed, 1 insertion(+), 57 deletions(-) + +diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx +index cd3c84d13305..55b466b42464 100644 +--- a/include/vcl/outdev.hxx ++++ b/include/vcl/outdev.hxx +@@ -1278,9 +1278,6 @@ public: + //If bNewFontLists is true then drop and refetch lists of system fonts + SAL_DLLPRIVATE static void ImplUpdateAllFontData( bool bNewFontLists ); + +- // Lock font updates for all output devices +- static void LockFontUpdates(bool bLock); +- + protected: + SAL_DLLPRIVATE const LogicalFontInstance* GetFontInstance() const; + SAL_DLLPRIVATE long GetEmphasisAscent() const { return mnEmphasisAscent; } +diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx +index 16b8015b923a..4f7b9d6def31 100644 +--- a/include/vcl/svapp.hxx ++++ b/include/vcl/svapp.hxx +@@ -1326,17 +1326,6 @@ public: + + ///@} + +- /** Lock font updates for all output devices +- +- @remark When performing operations that might involve multiple registration of fonts, such as +- opening/closing documents with multiple embedded fonts, then each font addition/removal +- might cause an event that initiates a rebuild of each OutputDevice's font lists. +- +- Locking font updates disables processing such events, and unlocking causes a single such +- processing for all OutputDevices. +- */ +- static void LockFontUpdates(bool bLock); +- + // For vclbootstrapprotector: + static void setDeInitHook(Link const & hook); + +diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx +index 6d7b3f99ee69..ac9f4242a1bc 100644 +--- a/sfx2/source/doc/objstor.cxx ++++ b/sfx2/source/doc/objstor.cxx +@@ -582,10 +582,6 @@ bool SfxObjectShell::ImportFromGeneratedStream_Impl( + bool SfxObjectShell::DoLoad( SfxMedium *pMed ) + { + ModifyBlocker_Impl aBlock( this ); +- struct FontLockGuard { +- FontLockGuard() { Application::LockFontUpdates(true); } +- ~FontLockGuard() { Application::LockFontUpdates(false); } +- } aFontLockGuard; + + pMedium = pMed; + pMedium->CanDisposeStorage_Impl( true ); +diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx +index e41ec23488b3..dc10f3102ede 100644 +--- a/vcl/inc/svdata.hxx ++++ b/vcl/inc/svdata.hxx +@@ -338,9 +338,6 @@ struct ImplSVData + VclPtr mpDefaultWin; // Default-Window + bool mbDeInit = false; // Is VCL deinitializing + std::unique_ptr mpSalSystem; // SalSystem interface +- int mnFontUpdatesLockCount = 0; // avoid repeated font updates +- bool mbFontUpdatesPending = false; // need to update font data after unlock +- bool mbFontUpdatesNewLists = false; // generate new font lists + bool mbResLocaleSet = false; // SV-Resource-Manager + std::locale maResLocale; // Resource locale + ImplSchedulerContext maSchedCtx; // indepen data for class Scheduler +diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx +index c4c3be9699e3..de4eac9687fc 100644 +--- a/vcl/source/app/svapp.cxx ++++ b/vcl/source/app/svapp.cxx +@@ -1036,11 +1036,6 @@ void Application::RemoveUserEvent( ImplSVEvent * nUserEvent ) + } + } + +-void Application::LockFontUpdates(bool bLock) +-{ +- OutputDevice::LockFontUpdates(bLock); +-} +- + WorkWindow* Application::GetAppWindow() + { + return ImplGetSVData()->maWinData.mpAppWin; +diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx +index 22c61063bd21..e1fd7d107e63 100644 +--- a/vcl/source/outdev/font.cxx ++++ b/vcl/source/outdev/font.cxx +@@ -559,16 +559,7 @@ void OutputDevice::ImplClearAllFontData(bool bNewFontLists) + + void OutputDevice::ImplRefreshAllFontData(bool bNewFontLists) + { +- auto svdata = ImplGetSVData(); +- DBG_TESTSOLARMUTEX(); +- if (!svdata->mnFontUpdatesLockCount) +- ImplUpdateFontDataForAllFrames(&OutputDevice::ImplRefreshFontData, bNewFontLists); +- else +- { +- svdata->mbFontUpdatesPending = true; +- if (bNewFontLists) +- svdata->mbFontUpdatesNewLists = true; +- } ++ ImplUpdateFontDataForAllFrames( &OutputDevice::ImplRefreshFontData, bNewFontLists ); + } + + void OutputDevice::ImplUpdateAllFontData(bool bNewFontLists) +@@ -614,27 +605,6 @@ void OutputDevice::ImplUpdateFontDataForAllFrames( const FontUpdateHandler_t pHd + } + } + +-void OutputDevice::LockFontUpdates(bool bLock) +-{ +- auto svdata = ImplGetSVData(); +- DBG_TESTSOLARMUTEX(); +- if (bLock) +- { +- ++svdata->mnFontUpdatesLockCount; +- } +- else if (svdata->mnFontUpdatesLockCount > 0) +- { +- --svdata->mnFontUpdatesLockCount; +- if (!svdata->mnFontUpdatesLockCount && svdata->mbFontUpdatesPending) +- { +- ImplRefreshAllFontData(svdata->mbFontUpdatesNewLists); +- +- svdata->mbFontUpdatesPending = false; +- svdata->mbFontUpdatesNewLists = false; +- } +- } +-} +- + void OutputDevice::BeginFontSubstitution() + { + ImplSVData* pSVData = ImplGetSVData(); +-- +2.26.2 + diff --git a/SOURCES/0001-backports-to-ease-CVE-backporting.patch b/SOURCES/0001-backports-to-ease-CVE-backporting.patch new file mode 100644 index 0000000..56ac48e --- /dev/null +++ b/SOURCES/0001-backports-to-ease-CVE-backporting.patch @@ -0,0 +1,259 @@ +From c2cf13da3bbf756ef3f78251c40d45fc23c27f36 Mon Sep 17 00:00:00 2001 +From: Samuel Mehrbrodt +Date: Wed, 29 Apr 2020 07:42:24 +0200 +Subject: [PATCH 1/6] backports to ease CVE backporting + +Remove unnecessary if block + +And format code inside + +Change-Id: Ied0d98935134bf6f7bc8c929645ad5faac9affa3 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93116 +Tested-by: Jenkins +Reviewed-by: Samuel Mehrbrodt +(cherry picked from commit cf36fe5eb41910c26d58fb25e54ccf2e0ee01365) + +space out the namespace constant values + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88938 +(cherry picked from commit 5352d45dd4a04f8f02cf7f6ad4169126d3b3586a) + +Change-Id: I30f54bfc1389e91b18e4fee8b83e1b297419899b +--- + include/xmloff/xmlnmspe.hxx | 16 +-- + .../component/documentdigitalsignatures.cxx | 130 +++++++++--------- + .../source/helper/xmlsignaturehelper.cxx | 1 + + 3 files changed, 75 insertions(+), 72 deletions(-) + +diff --git a/include/xmloff/xmlnmspe.hxx b/include/xmloff/xmlnmspe.hxx +index a00628b6b999..b079053c38d3 100644 +--- a/include/xmloff/xmlnmspe.hxx ++++ b/include/xmloff/xmlnmspe.hxx +@@ -69,7 +69,7 @@ XML_NAMESPACE( XML_NAMESPACE_VERSIONS_LIST, 37U ) + + // namespaces for odf extended formats + +-#define XML_NAMESPACE_EXT_BASE 38U ++#define XML_NAMESPACE_EXT_BASE 50U + #define XML_NAMESPACE_EXT( prefix, index ) \ + const sal_uInt16 prefix = (XML_NAMESPACE_EXT_BASE+index); + +@@ -82,7 +82,7 @@ XML_NAMESPACE_EXT( XML_NAMESPACE_LO_EXT, 5U ) + + // namespaces for OOo formats + +-#define XML_NAMESPACE_OOO_BASE 44U ++#define XML_NAMESPACE_OOO_BASE 60U + #define XML_NAMESPACE_OOO( prefix, index ) \ + const sal_uInt16 prefix = (XML_NAMESPACE_OOO_BASE+index); + +@@ -100,7 +100,7 @@ XML_NAMESPACE_OOO( XML_NAMESPACE_CONFIG_OOO, 10U ) + XML_NAMESPACE_OOO( XML_NAMESPACE_FORM_OOO, 11U ) + XML_NAMESPACE_OOO( XML_NAMESPACE_SCRIPT_OOO, 12U ) + +-#define XML_NAMESPACE_COMPAT_BASE 57U ++#define XML_NAMESPACE_COMPAT_BASE 80U + #define XML_NAMESPACE_COMPAT( prefix, index ) \ + const sal_uInt16 prefix = (XML_NAMESPACE_COMPAT_BASE+index); + +@@ -108,14 +108,14 @@ XML_NAMESPACE_COMPAT( XML_NAMESPACE_SVG_COMPAT, 0U ) + XML_NAMESPACE_COMPAT( XML_NAMESPACE_FO_COMPAT, 1U ) + XML_NAMESPACE_COMPAT( XML_NAMESPACE_SMIL_COMPAT, 2U ) + +-#define XML_NAMESPACE_OASIS_BASE 60U ++#define XML_NAMESPACE_OASIS_BASE 90U + #define XML_NAMESPACE_OASIS( prefix, index ) \ + const sal_uInt16 prefix = (XML_NAMESPACE_OASIS_BASE+index); + + XML_NAMESPACE_OASIS( XML_NAMESPACE_DB_OASIS, 0U ) + XML_NAMESPACE_OASIS( XML_NAMESPACE_REPORT_OASIS, 1U ) + +-#define XML_OLD_NAMESPACE_BASE 62U ++#define XML_OLD_NAMESPACE_BASE 100U + #define XML_OLD_NAMESPACE( prefix, index ) \ + const sal_uInt16 prefix = (XML_OLD_NAMESPACE_BASE+index); + +@@ -134,9 +134,9 @@ XML_OLD_NAMESPACE( XML_OLD_NAMESPACE_CHART, 10U ) + XML_OLD_NAMESPACE( XML_OLD_NAMESPACE_SMIL, 11U ) + + // experimental namespaces +-XML_NAMESPACE( XML_NAMESPACE_FIELD, 100U ) +-XML_NAMESPACE( XML_NAMESPACE_CSS3TEXT, 103U ) // CSS Text Level 3 +-XML_NAMESPACE( XML_NAMESPACE_FORMX, 101U ) // form interop extensions ++XML_NAMESPACE( XML_NAMESPACE_FIELD, 120U ) ++XML_NAMESPACE( XML_NAMESPACE_CSS3TEXT, 123U ) // CSS Text Level 3 ++XML_NAMESPACE( XML_NAMESPACE_FORMX, 121U ) // form interop extensions + + + #endif // INCLUDED_XMLOFF_XMLNMSPE_HXX +diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx +index dcfaad0af773..52cb938a8e0a 100644 +--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx ++++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx +@@ -500,85 +500,87 @@ DocumentDigitalSignatures::ImplVerifySignatures( + Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos); + css::security::DocumentSignatureInformation* arInfos = aInfos.getArray(); + +- if ( nInfos ) ++ for (int n = 0; n < nInfos; ++n) + { +- for( int n = 0; n < nInfos; ++n ) +- { +- DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( +- m_sODFVersion, aSignInfos[n]); +- const std::vector< OUString > aElementsToBeVerified = +- DocumentSignatureHelper::CreateElementList( +- rxStorage, eMode, mode); ++ DocumentSignatureAlgorithm mode ++ = DocumentSignatureHelper::getDocumentAlgorithm(m_sODFVersion, aSignInfos[n]); ++ const std::vector aElementsToBeVerified ++ = DocumentSignatureHelper::CreateElementList(rxStorage, eMode, mode); + +- const SignatureInformation& rInfo = aSignInfos[n]; +- css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; ++ const SignatureInformation& rInfo = aSignInfos[n]; ++ css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; + +- if (rInfo.ouGpgCertificate.isEmpty()) // X.509 ++ if (rInfo.ouGpgCertificate.isEmpty()) // X.509 ++ { ++ if (!rInfo.ouX509Certificate.isEmpty()) ++ rSigInfo.Signer = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); ++ if (!rSigInfo.Signer.is()) ++ rSigInfo.Signer = xSecEnv->getCertificate( ++ rInfo.ouX509IssuerName, ++ xmlsecurity::numericStringToBigInteger(rInfo.ouX509SerialNumber)); ++ ++ // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) ++ // to find the parent certificate. It does not take into account that there can be several certificates ++ // with the same subject name. ++ try + { +- if (!rInfo.ouX509Certificate.isEmpty()) +- rSigInfo.Signer = xSecEnv->createCertificateFromAscii( rInfo.ouX509Certificate ) ; +- if (!rSigInfo.Signer.is()) +- rSigInfo.Signer = xSecEnv->getCertificate( rInfo.ouX509IssuerName, +- xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) ); +- +- // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) +- // to find the parent certificate. It does not take into account that there can be several certificates +- // with the same subject name. +- +- try { +- rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(rSigInfo.Signer, +- Sequence >()); +- } catch (SecurityException& ) { +- OSL_FAIL("Verification of certificate failed"); +- rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; +- } ++ rSigInfo.CertificateStatus = xSecEnv->verifyCertificate( ++ rSigInfo.Signer, Sequence>()); + } +- else if (xGpgSecEnv.is()) // GPG ++ catch (SecurityException&) + { +- // TODO not ideal to retrieve cert by keyID, might +- // collide, or PGPKeyID format might change - can't we +- // keep the xCert itself in rInfo? +- rSigInfo.Signer = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") ); +- rSigInfo.CertificateStatus = xGpgSecEnv->verifyCertificate(rSigInfo.Signer, +- Sequence >()); ++ OSL_FAIL("Verification of certificate failed"); ++ rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } ++ } ++ else if (xGpgSecEnv.is()) // GPG ++ { ++ // TODO not ideal to retrieve cert by keyID, might ++ // collide, or PGPKeyID format might change - can't we ++ // keep the xCert itself in rInfo? ++ rSigInfo.Signer = xGpgSecEnv->getCertificate( ++ rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("")); ++ rSigInfo.CertificateStatus = xGpgSecEnv->verifyCertificate( ++ rSigInfo.Signer, Sequence>()); ++ } + +- // Time support again (#i38744#) +- Date aDate( rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year ); +- tools::Time aTime( rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes, +- rInfo.stDateTime.Seconds, rInfo.stDateTime.NanoSeconds ); +- rSigInfo.SignatureDate = aDate.GetDate(); +- rSigInfo.SignatureTime = aTime.GetTime() / tools::Time::nanoPerCenti; ++ // Time support again (#i38744#) ++ Date aDate(rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year); ++ tools::Time aTime(rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes, ++ rInfo.stDateTime.Seconds, rInfo.stDateTime.NanoSeconds); ++ rSigInfo.SignatureDate = aDate.GetDate(); ++ rSigInfo.SignatureTime = aTime.GetTime() / tools::Time::nanoPerCenti; + +- rSigInfo.SignatureIsValid = ( rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ); ++ rSigInfo.SignatureIsValid ++ = (rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + +- // Signature line info (ID + Images) +- if (!rInfo.ouSignatureLineId.isEmpty()) +- rSigInfo.SignatureLineId = rInfo.ouSignatureLineId; ++ // Signature line info (ID + Images) ++ if (!rInfo.ouSignatureLineId.isEmpty()) ++ rSigInfo.SignatureLineId = rInfo.ouSignatureLineId; + +- if (rInfo.aValidSignatureImage.is()) +- rSigInfo.ValidSignatureLineImage = rInfo.aValidSignatureImage; ++ if (rInfo.aValidSignatureImage.is()) ++ rSigInfo.ValidSignatureLineImage = rInfo.aValidSignatureImage; + +- if (rInfo.aInvalidSignatureImage.is()) +- rSigInfo.InvalidSignatureLineImage = rInfo.aInvalidSignatureImage; +- +- // OOXML intentionally doesn't sign metadata. +- if ( rSigInfo.SignatureIsValid && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) +- { +- rSigInfo.SignatureIsValid = +- DocumentSignatureHelper::checkIfAllFilesAreSigned( +- aElementsToBeVerified, rInfo, mode); +- } +- if (eMode == DocumentSignatureMode::Content) +- { +- if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) +- rSigInfo.PartialDocumentSignature = true; +- else +- rSigInfo.PartialDocumentSignature = !DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]); +- } ++ if (rInfo.aInvalidSignatureImage.is()) ++ rSigInfo.InvalidSignatureLineImage = rInfo.aInvalidSignatureImage; + ++ // OOXML intentionally doesn't sign metadata. ++ if (rSigInfo.SignatureIsValid ++ && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) ++ { ++ rSigInfo.SignatureIsValid = DocumentSignatureHelper::checkIfAllFilesAreSigned( ++ aElementsToBeVerified, rInfo, mode); ++ } ++ if (eMode == DocumentSignatureMode::Content) ++ { ++ if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) ++ rSigInfo.PartialDocumentSignature = true; ++ else ++ rSigInfo.PartialDocumentSignature ++ = !DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]); + } + } ++ + return aInfos; + + } +diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx +index 6ec834053a17..22c056e70da1 100644 +--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx ++++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx +@@ -402,6 +402,7 @@ bool XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Ref + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper"); ++ mbError = true; + } + + mpXSecController->releaseSignatureReader(); +-- +2.32.0 + diff --git a/SOURCES/0001-disable-libe-book-support.patch b/SOURCES/0001-disable-libe-book-support.patch new file mode 100644 index 0000000..b7ba1fc --- /dev/null +++ b/SOURCES/0001-disable-libe-book-support.patch @@ -0,0 +1,144 @@ +From 702a1ad668167a7a8efdd694c820b710a765bb53 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Thu, 21 Aug 2014 16:10:51 +0200 +Subject: [PATCH] disable libe-book support + +Change-Id: Ie915a9bd2acf7f3aeb8b0933252da33c17043bc4 +--- + external/Module_external.mk | 1 - + filter/Configuration_filter.mk | 8 -------- + writerperfect/Library_wpftwriter.mk | 2 -- + writerperfect/qa/unit/WpftFilterFixture.hxx | 4 ---- + writerperfect/qa/unit/WpftWriterFilterTest.cxx | 5 ----- + writerperfect/source/writer/wpftwriter.component | 5 ----- + 6 files changed, 25 deletions(-) + +diff --git a/configure.ac b/configure.ac +index ac8dbc5..bb08d21 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -7696,9 +7696,6 @@ libo_PKG_VERSION([ETONYEK], [libetonyek-0.1], [0.1.5]) + + libo_CHECK_SYSTEM_MODULE([libfreehand],[FREEHAND],[libfreehand-0.1]) + +-libo_CHECK_SYSTEM_MODULE([libebook],[EBOOK],[libe-book-0.1]) +-libo_PKG_VERSION([EBOOK], [libe-book-0.1], [0.1.2]) +- + libo_CHECK_SYSTEM_MODULE([libabw],[ABW],[libabw-0.1]) + + libo_CHECK_SYSTEM_MODULE([libpagemaker],[PAGEMAKER],[libpagemaker-0.0]) +diff --git a/external/Module_external.mk b/external/Module_external.mk +index baf7215..397ad68 100644 +--- a/external/Module_external.mk ++++ b/external/Module_external.mk +@@ -31,7 +31,6 @@ $(eval $(call gb_Module_add_moduledirs,external,\ + $(call gb_Helper_optional,CPPUNIT,cppunit) \ + $(call gb_Helper_optional,CT2N,ct2n) \ + $(call gb_Helper_optional,CURL,curl) \ +- $(call gb_Helper_optional,EBOOK,libebook) \ + $(call gb_Helper_optional,EPM,epm) \ + $(call gb_Helper_optional,EPOXY,epoxy) \ + $(call gb_Helper_optional,EPUBGEN,libepubgen) \ +diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk +index 9702332..d250173 100644 +--- a/filter/Configuration_filter.mk ++++ b/filter/Configuration_filter.mk +@@ -346,10 +346,6 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_writer_types.xcu + writer_OOXML \ + writer_OOXML_Template \ + writer_layout_dump_xml \ +- writer_BroadBand_eBook \ +- writer_FictionBook_2 \ +- writer_PalmDoc \ +- writer_Plucker_eBook \ + writer_ApplePages \ + MWAW_Text_Document \ + Palm_Text_Document \ +@@ -394,10 +390,6 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_writer_filters + OOXML_Text \ + OOXML_Text_Template \ + writer_layout_dump \ +- BroadBand_eBook \ +- FictionBook_2 \ +- PalmDoc \ +- Plucker_eBook \ + ApplePages \ + MWAW_Text_Document \ + Palm_Text_Document \ +diff --git a/writerperfect/Library_wpftwriter.mk b/writerperfect/Library_wpftwriter.mk +index 8993cca..b6e11f3 100644 +--- a/writerperfect/Library_wpftwriter.mk ++++ b/writerperfect/Library_wpftwriter.mk +@@ -53,7 +53,6 @@ $(eval $(call gb_Library_use_libraries,wpftwriter,\ + $(eval $(call gb_Library_use_externals,wpftwriter,\ + abw \ + boost_headers \ +- ebook \ + epubgen \ + etonyek \ + icu_headers \ +@@ -73,7 +72,6 @@ $(eval $(call gb_Library_use_externals,wpftwriter,\ + + $(eval $(call gb_Library_add_exception_objects,wpftwriter,\ + writerperfect/source/writer/AbiWordImportFilter \ +- writerperfect/source/writer/EBookImportFilter \ + writerperfect/source/writer/EPUBExportDialog \ + writerperfect/source/writer/EPUBExportFilter \ + writerperfect/source/writer/EPUBExportUIComponent \ +diff --git a/writerperfect/qa/unit/WpftFilterFixture.hxx b/writerperfect/qa/unit/WpftFilterFixture.hxx +index f324781..f42edb0 100644 +--- a/writerperfect/qa/unit/WpftFilterFixture.hxx ++++ b/writerperfect/qa/unit/WpftFilterFixture.hxx +@@ -26,10 +26,6 @@ + || ((major) == (req_major) \ + && ((minor) > (req_minor) || ((minor) == (req_minor) && ((micro) >= (req_micro))))) + +-#define REQUIRE_EBOOK_VERSION(major, minor, micro) \ +- REQUIRE_VERSION(EBOOK_VERSION_MAJOR, EBOOK_VERSION_MINOR, EBOOK_VERSION_MICRO, major, minor, \ +- micro) +- + #define REQUIRE_ETONYEK_VERSION(major, minor, micro) \ + REQUIRE_VERSION(ETONYEK_VERSION_MAJOR, ETONYEK_VERSION_MINOR, ETONYEK_VERSION_MICRO, major, \ + minor, micro) +diff --git a/writerperfect/qa/unit/WpftWriterFilterTest.cxx b/writerperfect/qa/unit/WpftWriterFilterTest.cxx +index 8bc4c7c..eca43ca 100644 +--- a/writerperfect/qa/unit/WpftWriterFilterTest.cxx ++++ b/writerperfect/qa/unit/WpftWriterFilterTest.cxx +@@ -30,9 +30,6 @@ WpftWriterFilterTest::WpftWriterFilterTest() + + void WpftWriterFilterTest::test() + { +- const writerperfect::test::WpftOptionalMap_t aEBookOptional{ +- { "FictionBook2.fb2.zip", REQUIRE_EBOOK_VERSION(0, 1, 1) }, +- }; + const writerperfect::test::WpftOptionalMap_t aEtonyekOptional{ + { "Pages_4.pages", REQUIRE_ETONYEK_VERSION(0, 1, 2) }, + { "Pages_5.pages", REQUIRE_ETONYEK_VERSION(0, 1, 8) }, +@@ -54,8 +51,6 @@ void WpftWriterFilterTest::test() + + doTest("com.sun.star.comp.Writer.AbiWordImportFilter", + "/writerperfect/qa/unit/data/writer/libabw/"); +- doTest("org.libreoffice.comp.Writer.EBookImportFilter", +- "/writerperfect/qa/unit/data/writer/libe-book/", aEBookOptional); + doTest("com.sun.star.comp.Writer.MSWorksImportFilter", + "/writerperfect/qa/unit/data/writer/libwps/", aWpsOptional); + doTest("com.sun.star.comp.Writer.MWAWImportFilter", +diff --git a/writerperfect/source/writer/wpftwriter.component b/writerperfect/source/writer/wpftwriter.component +index 8ab4366..2720023 100644 +--- a/writerperfect/source/writer/wpftwriter.component ++++ b/writerperfect/source/writer/wpftwriter.component +@@ -38,11 +38,6 @@ + + + +- +- +- +- + + +-- +2.26.2 + diff --git a/SOURCES/0001-disble-tip-of-the-day-dialog-by-default.patch b/SOURCES/0001-disble-tip-of-the-day-dialog-by-default.patch new file mode 100644 index 0000000..7233a4e --- /dev/null +++ b/SOURCES/0001-disble-tip-of-the-day-dialog-by-default.patch @@ -0,0 +1,26 @@ +From d6e2cdb0023e422546e3ece5bf9915f7c490ced8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 20 Mar 2020 14:24:05 +0000 +Subject: [PATCH] disble tip-of-the-day dialog by default + +Change-Id: Ie7f0e3fe3dda12c2ec88c376d2b57419253ae5cf +--- + officecfg/registry/schema/org/openoffice/Office/Common.xcs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index e7c339e2e22e..9aa88ef1aa02 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -5570,7 +5570,7 @@ + + Determines whether the Tip-of-the-Day dialog is shown on startup. + +- true ++ false +
+ + +-- +2.24.1 + diff --git a/SOURCES/0001-don-t-suppress-crashes.patch b/SOURCES/0001-don-t-suppress-crashes.patch new file mode 100644 index 0000000..fcd1f1d --- /dev/null +++ b/SOURCES/0001-don-t-suppress-crashes.patch @@ -0,0 +1,35 @@ +From a0e6d2abeed9d64fe7862a7664ba80a6178bf3f2 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 8 Nov 2016 11:50:06 +0100 +Subject: [PATCH] don't suppress crashes + +An automatic restart after a crash makes the crash invisible to abrt. + +Change-Id: I3854e619356049b144b08575879d289a3c12e4c9 +--- + desktop/source/app/app.cxx | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx +index 53365f4..3a3bac8 100644 +--- a/desktop/source/app/app.cxx ++++ b/desktop/source/app/app.cxx +@@ -1312,14 +1312,12 @@ void Desktop::Exception(ExceptionCategory nCategory) + if( bRestart ) + { + RequestHandler::Disable(); +- if( pSignalHandler ) +- osl_removeSignalHandler( pSignalHandler ); + + restartOnMac(false); + if ( m_rSplashScreen.is() ) + m_rSplashScreen->reset(); + +- _exit( EXITHELPER_CRASH_WITH_RESTART ); ++ return; + } + else + { +-- +2.9.3 + diff --git a/SOURCES/0001-export-HYPERLINK-target-in-html-clipboard-export.patch b/SOURCES/0001-export-HYPERLINK-target-in-html-clipboard-export.patch new file mode 100644 index 0000000..bff8b33 --- /dev/null +++ b/SOURCES/0001-export-HYPERLINK-target-in-html-clipboard-export.patch @@ -0,0 +1,64 @@ +From 13aba101eadfe4f67a930ac7231d26ece658bbec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 28 Sep 2020 14:55:47 +0100 +Subject: [PATCH] export HYPERLINK target in html clipboard export + +Change-Id: Ia77e4bd8a5b54636d0e9e561360128202a81420b +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103557 +Tested-by: Jenkins +Reviewed-by: Eike Rathke +--- + sc/source/filter/html/htmlexp.cxx | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx +index 6122c9b6c45c..13792201c8b0 100644 +--- a/sc/source/filter/html/htmlexp.cxx ++++ b/sc/source/filter/html/htmlexp.cxx +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1127,6 +1128,26 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC + TAG_ON(aStr.makeStringAndClear().getStr()); + } + ++ OUString aURL; ++ bool bWriteHyperLink(false); ++ if (aCell.meType == CELLTYPE_FORMULA) ++ { ++ ScFormulaCell* pFCell = aCell.mpFormula; ++ if (pFCell->IsHyperLinkCell()) ++ { ++ OUString aCellText; ++ pFCell->GetURLResult(aURL, aCellText); ++ bWriteHyperLink = true; ++ } ++ } ++ ++ if (bWriteHyperLink) ++ { ++ OString aURLStr = HTMLOutFuncs::ConvertStringToHTML(aURL, eDestEnc, &aNonConvertibleChars); ++ OString aStr = OOO_STRING_SVTOOLS_HTML_anchor " " OOO_STRING_SVTOOLS_HTML_O_href "=\"" + aURLStr + "\""; ++ TAG_ON(aStr.getStr()); ++ } ++ + OUString aStrOut; + bool bFieldText = false; + +@@ -1174,6 +1195,8 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC + if ( pGraphEntry ) + WriteGraphEntry( pGraphEntry ); + ++ if (bWriteHyperLink) { TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor); } ++ + if ( bSetFont ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font ); + if ( bCrossedOut ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_strikethrough ); + if ( bUnderline ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline ); +-- +2.26.2 + diff --git a/SOURCES/0001-fix-detecting-qrcodegen.patch b/SOURCES/0001-fix-detecting-qrcodegen.patch new file mode 100644 index 0000000..e875a37 --- /dev/null +++ b/SOURCES/0001-fix-detecting-qrcodegen.patch @@ -0,0 +1,40 @@ +From ddf72365b7e7c67b2580e328e55de6eb988b8787 Mon Sep 17 00:00:00 2001 +From: Thierry Vignaud +Date: Thu, 30 Jan 2020 11:19:20 +0000 +Subject: [PATCH] fix detecting qrcodegen + +Change-Id: Ib945b57420083489273cefc5655eb50932b5a3f8 +--- + configure.ac | 2 +- + cui/source/dialogs/QrCodeGenDialog.cxx | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 388bee3..c061349 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -10092,7 +10092,7 @@ else + AC_MSG_RESULT([external]) + SYSTEM_QRCODEGEN=TRUE + AC_LANG_PUSH([C++]) +- AC_CHECK_HEADER(qrcodegen/QrCode.hpp, [], ++ AC_CHECK_HEADER(qrcodegencpp/QrCode.hpp, [], + [AC_MSG_ERROR(qrcodegen headers not found.)], [#include ]) + AC_CHECK_LIB([qrcodegencpp], [main], [:], + [ AC_MSG_ERROR(qrcodegen C++ library not found.) ], []) +diff --git a/cui/source/dialogs/QrCodeGenDialog.cxx b/cui/source/dialogs/QrCodeGenDialog.cxx +index 6277e76..f8dd327 100644 +--- a/cui/source/dialogs/QrCodeGenDialog.cxx ++++ b/cui/source/dialogs/QrCodeGenDialog.cxx +@@ -20,7 +20,7 @@ + + #if ENABLE_QRCODEGEN + #if defined(SYSTEM_QRCODEGEN) +-#include ++#include + #else + #include + #endif +-- +2.26.2 + diff --git a/SOURCES/0001-munge-cmis-headers-to-remove-exception-specs.patch b/SOURCES/0001-munge-cmis-headers-to-remove-exception-specs.patch new file mode 100644 index 0000000..d922768 --- /dev/null +++ b/SOURCES/0001-munge-cmis-headers-to-remove-exception-specs.patch @@ -0,0 +1,1922 @@ +From 9300cfc3cab41e0ba50eb515792286932dbcbe1e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 26 Oct 2020 19:41:16 +0000 +Subject: [PATCH] munge cmis headers to remove exception specs + +Change-Id: Ieea3838f4acbaabd8ee5c219a69967889292a5ca +--- + include/libcmis/allowable-actions.hxx | 130 +++++++++++++++ + include/libcmis/document.hxx | 146 +++++++++++++++++ + include/libcmis/exception.hxx | 60 +++++++ + include/libcmis/folder.hxx | 83 ++++++++++ + include/libcmis/libcmis.hxx | 47 ++++++ + include/libcmis/oauth2-data.hxx | 76 +++++++++ + include/libcmis/object-type.hxx | 143 +++++++++++++++++ + include/libcmis/object.hxx | 217 ++++++++++++++++++++++++++ + include/libcmis/property-type.hxx | 125 +++++++++++++++ + include/libcmis/property.hxx | 88 +++++++++++ + include/libcmis/rendition.hxx | 88 +++++++++++ + include/libcmis/repository.hxx | 117 ++++++++++++++ + include/libcmis/session-factory.hxx | 149 ++++++++++++++++++ + include/libcmis/session.hxx | 100 ++++++++++++ + include/libcmis/xml-utils.hxx | 167 ++++++++++++++++++++ + include/libcmis/xmlserializable.hxx | 46 ++++++ + 16 files changed, 1782 insertions(+) + create mode 100644 include/libcmis/allowable-actions.hxx + create mode 100644 include/libcmis/document.hxx + create mode 100644 include/libcmis/exception.hxx + create mode 100644 include/libcmis/folder.hxx + create mode 100644 include/libcmis/libcmis.hxx + create mode 100644 include/libcmis/oauth2-data.hxx + create mode 100644 include/libcmis/object-type.hxx + create mode 100644 include/libcmis/object.hxx + create mode 100644 include/libcmis/property-type.hxx + create mode 100644 include/libcmis/property.hxx + create mode 100644 include/libcmis/rendition.hxx + create mode 100644 include/libcmis/repository.hxx + create mode 100644 include/libcmis/session-factory.hxx + create mode 100644 include/libcmis/session.hxx + create mode 100644 include/libcmis/xml-utils.hxx + create mode 100644 include/libcmis/xmlserializable.hxx + +diff --git a/include/libcmis/allowable-actions.hxx b/include/libcmis/allowable-actions.hxx +new file mode 100644 +index 000000000000..24998761d10f +--- /dev/null ++++ b/include/libcmis/allowable-actions.hxx +@@ -0,0 +1,130 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _ALLOWABLE_ACTIONS_HXX_ ++#define _ALLOWABLE_ACTIONS_HXX_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "exception.hxx" ++ ++namespace libcmis ++{ ++ class Object; ++ ++ class ObjectAction ++ { ++ public: ++ enum Type ++ { ++ DeleteObject, ++ UpdateProperties, ++ GetFolderTree, ++ GetProperties, ++ GetObjectRelationships, ++ GetObjectParents, ++ GetFolderParent, ++ GetDescendants, ++ MoveObject, ++ DeleteContentStream, ++ CheckOut, ++ CancelCheckOut, ++ CheckIn, ++ SetContentStream, ++ GetAllVersions, ++ AddObjectToFolder, ++ RemoveObjectFromFolder, ++ GetContentStream, ++ ApplyPolicy, ++ GetAppliedPolicies, ++ RemovePolicy, ++ GetChildren, ++ CreateDocument, ++ CreateFolder, ++ CreateRelationship, ++ DeleteTree, ++ GetRenditions, ++ GetACL, ++ ApplyACL ++ }; ++ ++ private: ++ Type m_type; ++ bool m_enabled; ++ bool m_valid; ++ ++ public: ++ ObjectAction( xmlNodePtr node ); ++ virtual ~ObjectAction( ){ } ++ ++ Type getType( ) { return m_type; } ++ bool isEnabled( ) { return m_enabled; } ++ bool isValid( ) { return m_valid; } ++ ++ /** Parses the permission name into one of the enum values or throws ++ an exception for invalid input strings. ++ */ ++ static Type parseType( std::string type ); ++ ++ }; ++ ++ /** Class providing access to the allowed actions on an object. ++ */ ++ class AllowableActions ++ { ++ protected: ++ std::map< ObjectAction::Type, bool > m_states; ++ ++ public: ++ /** Default constructor for testing purpose ++ */ ++ AllowableActions( ); ++ AllowableActions( xmlNodePtr node ); ++ AllowableActions( const AllowableActions& copy ); ++ virtual ~AllowableActions( ); ++ ++ AllowableActions& operator=( const AllowableActions& copy ); ++ ++ /** Returns the permissions for the corresponding actions. ++ */ ++ bool isAllowed( ObjectAction::Type action ); ++ ++ /** Returns true if the action was defined, false if the default ++ value is used. ++ */ ++ bool isDefined( ObjectAction::Type action ); ++ ++ std::string toString( ); ++ }; ++ typedef boost::shared_ptr< AllowableActions > AllowableActionsPtr; ++} ++ ++#endif +diff --git a/include/libcmis/document.hxx b/include/libcmis/document.hxx +new file mode 100644 +index 000000000000..ce123b081efb +--- /dev/null ++++ b/include/libcmis/document.hxx +@@ -0,0 +1,146 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _DOCUMENT_HXX_ ++#define _DOCUMENT_HXX_ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "exception.hxx" ++#include "object.hxx" ++ ++namespace libcmis ++{ ++ class Folder; ++ class Session; ++ ++ /** Interface for a CMIS Document object. ++ */ ++ class Document : public virtual Object ++ { ++ public: ++ Document( Session* session ) : Object( session ) { } ++ virtual ~Document( ) { } ++ ++ /** Get the folder parents for the document. ++ ++ Note that an unfiled document will have no parent folder. ++ ++ @return the parents folder if any. ++ */ ++ virtual std::vector< boost::shared_ptr< Folder > > getParents( ) = 0; ++ ++ /** Get the content stream without using a temporary file. ++ ++

The stream may not contain anything if there is ++ no content or if something wrong happened during the ++ download.

++ ++ @param streamId of the rendition ++ @return ++ An input stream to read the data from. ++ ++ @throws Exception ++ if anything wrong happened during the file transfer. ++ In such a case, the content of the stream can't be ++ guaranteed. ++ */ ++ virtual boost::shared_ptr< std::istream > getContentStream( std::string streamId = std::string( ) ) ++ = 0; ++ ++ /** Set or replace the content stream of the document. ++ ++ @param is the output stream containing the new data for the content stream ++ @param contentType the mime-type of the new content stream ++ @param filename the filename to set for the file ++ @param overwrite if set to false, don't overwrite the content stream if one is already set. ++ ++ @throw Exception if anything happens during the upload like a wrong authentication, ++ no rights to set the stream, server doesn't have the ContentStreamUpdatability ++ capability. ++ */ ++ virtual void setContentStream( boost::shared_ptr< std::ostream > os, std::string contentType, ++ std::string filename, bool overwrite = true ) = 0; ++ ++ /** Get the content mime type. ++ */ ++ virtual std::string getContentType( ); ++ ++ /** Get the content stream filename. ++ */ ++ virtual std::string getContentFilename( ); ++ ++ /** Get the content length in bytes. ++ */ ++ virtual long getContentLength( ); ++ ++ /** Checks out the document and returns the object corresponding to the ++ created Private Working Copy. ++ ++ \return the Private Working Copy document ++ */ ++ virtual boost::shared_ptr< Document > checkOut( ) = 0; ++ ++ /** Cancels the checkout if the document is a private working copy, or ++ throws an exception. ++ */ ++ virtual void cancelCheckout( ) = 0; ++ ++ /** Check in the private working copy and create a new version or throw ++ an exception. ++ ++ The current object will be updated to reflect the changes performed ++ on the server side. ++ ++ \param isMajor defines it the version to create is a major or minor one ++ \param comment contains the checkin comment ++ \param properties the properties to set the new version ++ \param stream the content stream to set for the new version ++ \param contentType the mime type of the stream to set ++ ++ \return the document with the new version ++ */ ++ virtual boost::shared_ptr< Document > checkIn( bool isMajor, std::string comment, ++ const std::map< std::string, PropertyPtr >& properties, ++ boost::shared_ptr< std::ostream > stream, ++ std::string contentType, std::string fileName ) = 0; ++ ++ virtual std::vector< boost::shared_ptr< Document > > getAllVersions( ) = 0; ++ ++ // virtual methods form Object ++ virtual std::vector< std::string > getPaths( ); ++ ++ virtual std::string toString( ); ++ }; ++ typedef ::boost::shared_ptr< Document > DocumentPtr; ++} ++ ++#endif +diff --git a/include/libcmis/exception.hxx b/include/libcmis/exception.hxx +new file mode 100644 +index 000000000000..16f3573da2b1 +--- /dev/null ++++ b/include/libcmis/exception.hxx +@@ -0,0 +1,60 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _EXCEPTION_HXX_ ++#define _EXCEPTION_HXX_ ++ ++#include ++#include ++ ++namespace libcmis ++{ ++ class Exception : public std::exception ++ { ++ private: ++ std::string m_message; ++ std::string m_type; ++ ++ public: ++ Exception( std::string message, std::string type = "runtime" ) : ++ exception( ), ++ m_message( message ), ++ m_type( type ) ++ { ++ } ++ ++ ~Exception( ) throw () { } ++ virtual const char* what() const throw() ++ { ++ return m_message.c_str( ); ++ } ++ ++ std::string getType( ) const { return m_type; } ++ }; ++} ++ ++#endif +diff --git a/include/libcmis/folder.hxx b/include/libcmis/folder.hxx +new file mode 100644 +index 000000000000..9f17e3883898 +--- /dev/null ++++ b/include/libcmis/folder.hxx +@@ -0,0 +1,83 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _FOLDER_HXX_ ++#define _FOLDER_HXX_ ++ ++#include ++#include ++#include ++ ++#include "exception.hxx" ++#include "object.hxx" ++ ++namespace libcmis ++{ ++ class Document; ++ class Session; ++ ++ struct UnfileObjects { ++ enum Type ++ { ++ Unfile, ++ DeleteSingleFiled, ++ Delete ++ }; ++ }; ++ ++ /** Class representing a CMIS folder. ++ */ ++ class Folder : public virtual Object ++ { ++ public: ++ Folder( Session* session ) : Object( session ) { } ++ virtual ~Folder() { } ++ ++ virtual std::vector< std::string > getPaths( ); ++ ++ virtual ::boost::shared_ptr< Folder > getFolderParent( ); ++ virtual std::vector< ObjectPtr > getChildren( ) = 0; ++ virtual std::string getParentId( ); ++ virtual std::string getPath( ); ++ ++ virtual bool isRootFolder( ); ++ ++ virtual ::boost::shared_ptr< Folder > createFolder( const std::map< std::string, PropertyPtr >& properties ) ++ = 0; ++ virtual ::boost::shared_ptr< Document > createDocument( const std::map< std::string, PropertyPtr >& properties, ++ boost::shared_ptr< std::ostream > os, std::string contentType, std::string fileName ) = 0; ++ ++ virtual std::vector< std::string > removeTree( bool allVersion = true, UnfileObjects::Type unfile = UnfileObjects::Delete, ++ bool continueOnError = false ) = 0; ++ ++ virtual std::string toString( ); ++ }; ++ typedef ::boost::shared_ptr< Folder > FolderPtr; ++ ++} ++ ++#endif +diff --git a/include/libcmis/libcmis.hxx b/include/libcmis/libcmis.hxx +new file mode 100644 +index 000000000000..540e5af127f2 +--- /dev/null ++++ b/include/libcmis/libcmis.hxx +@@ -0,0 +1,47 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _LIBCMIS_HXX_ ++#define _LIBCMIS_HXX_ ++ ++#include "allowable-actions.hxx" ++#include "document.hxx" ++#include "exception.hxx" ++#include "folder.hxx" ++#include "oauth2-data.hxx" ++#include "object-type.hxx" ++#include "object.hxx" ++#include "property-type.hxx" ++#include "property.hxx" ++#include "rendition.hxx" ++#include "repository.hxx" ++#include "session-factory.hxx" ++#include "session.hxx" ++#include "xml-utils.hxx" ++#include "xmlserializable.hxx" ++ ++#endif +diff --git a/include/libcmis/oauth2-data.hxx b/include/libcmis/oauth2-data.hxx +new file mode 100644 +index 000000000000..000f9394b034 +--- /dev/null ++++ b/include/libcmis/oauth2-data.hxx +@@ -0,0 +1,76 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _LIBCMIS_OAUTH2_DATA_HXX_ ++#define _LIBCMIS_OAUTH2_DATA_HXX_ ++ ++#include ++#include ++ ++namespace libcmis ++{ ++ /** Class storing the data needed for OAuth2 authentication. ++ */ ++ class OAuth2Data ++ { ++ private: ++ ++ std::string m_authUrl; ++ std::string m_tokenUrl; ++ std::string m_clientId; ++ std::string m_clientSecret; ++ std::string m_scope; ++ std::string m_redirectUri; ++ public: ++ ++ OAuth2Data( ); ++ OAuth2Data( const std::string& authUrl, ++ const std::string& tokenUrl, ++ const std::string& scope, ++ const std::string& redirectUri, ++ const std::string& clientId, ++ const std::string& clientSecret ); ++ ++ OAuth2Data( const OAuth2Data& copy ); ++ ~OAuth2Data( ); ++ ++ OAuth2Data& operator=( const OAuth2Data& copy ); ++ ++ bool isComplete(); ++ ++ const std::string& getAuthUrl() { return m_authUrl; } ++ const std::string& getTokenUrl() { return m_tokenUrl; } ++ const std::string& getClientId() { return m_clientId; } ++ const std::string& getClientSecret() { return m_clientSecret; } ++ const std::string& getScope() { return m_scope; } ++ const std::string& getRedirectUri() { return m_redirectUri; } ++ }; ++ typedef ::boost::shared_ptr< OAuth2Data > OAuth2DataPtr; ++} ++ ++#endif //_LIBCMIS_OAUTH2_DATA_HXX_ ++ +diff --git a/include/libcmis/object-type.hxx b/include/libcmis/object-type.hxx +new file mode 100644 +index 000000000000..a8576ec80f0b +--- /dev/null ++++ b/include/libcmis/object-type.hxx +@@ -0,0 +1,143 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _OBJECT_TYPE_HXX_ ++#define _OBJECT_TYPE_HXX_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "exception.hxx" ++#include "property-type.hxx" ++ ++namespace libcmis ++{ ++ /** Class representing a CMIS object type definition. ++ */ ++ class ObjectType ++ { ++ public: ++ ++ enum ContentStreamAllowed ++ { ++ NotAllowed, ++ Allowed, ++ Required ++ }; ++ ++ protected: ++ time_t m_refreshTimestamp; ++ ++ std::string m_id; ++ std::string m_localName; ++ std::string m_localNamespace; ++ std::string m_displayName; ++ std::string m_queryName; ++ std::string m_description; ++ ++ std::string m_parentTypeId; ++ std::string m_baseTypeId; ++ ++ bool m_creatable; ++ bool m_fileable; ++ bool m_queryable; ++ bool m_fulltextIndexed; ++ bool m_includedInSupertypeQuery; ++ bool m_controllablePolicy; ++ bool m_controllableAcl; ++ bool m_versionable; ++ libcmis::ObjectType::ContentStreamAllowed m_contentStreamAllowed; ++ ++ std::map< std::string, libcmis::PropertyTypePtr > m_propertiesTypes; ++ ++ ObjectType( ); ++ void initializeFromNode( xmlNodePtr node ); ++ ++ public: ++ ++ ObjectType( xmlNodePtr node ); ++ ObjectType( const ObjectType& copy ); ++ virtual ~ObjectType() { } ++ ++ ObjectType& operator=( const ObjectType& copy ); ++ ++ /** Reload the data from the server. ++ ++ \attention ++ This method needs to be implemented in subclasses or it will ++ do nothing ++ */ ++ virtual void refresh( ); ++ virtual time_t getRefreshTimestamp( ) const; ++ ++ std::string getId( ) const; ++ std::string getLocalName( ) const; ++ std::string getLocalNamespace( ) const; ++ std::string getDisplayName( ) const; ++ std::string getQueryName( ) const; ++ std::string getDescription( ) const; ++ ++ virtual boost::shared_ptr< ObjectType > getParentType( ); ++ virtual boost::shared_ptr< ObjectType > getBaseType( ); ++ virtual std::vector< boost::shared_ptr< ObjectType > > getChildren( ); ++ ++ /** Get the parent type id without extracting the complete parent type from ++ the repository. This is mainly provided for performance reasons. ++ ++ \since libcmis 0.4 ++ */ ++ std::string getParentTypeId( ) const; ++ ++ /** Get the base type id without extracting the complete base type from ++ the repository. This is mainly provided for performance reasons. ++ ++ \since libcmis 0.4 ++ */ ++ std::string getBaseTypeId( ) const; ++ ++ bool isCreatable( ) const; ++ bool isFileable( ) const; ++ bool isQueryable( ) const; ++ bool isFulltextIndexed( ) const; ++ bool isIncludedInSupertypeQuery( ) const; ++ bool isControllablePolicy( ) const; ++ bool isControllableACL( ) const; ++ bool isVersionable( ) const; ++ ContentStreamAllowed getContentStreamAllowed( ) const; ++ ++ std::map< std::string, PropertyTypePtr >& getPropertiesTypes( ); ++ ++ virtual std::string toString( ); ++ }; ++ ++ typedef ::boost::shared_ptr< ObjectType > ObjectTypePtr; ++} ++ ++#endif +diff --git a/include/libcmis/object.hxx b/include/libcmis/object.hxx +new file mode 100644 +index 000000000000..fa8d465e7c3b +--- /dev/null ++++ b/include/libcmis/object.hxx +@@ -0,0 +1,217 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _OBJECT_HXX_ ++#define _OBJECT_HXX_ ++ ++#include ++#include ++#include ++#include ++ ++#ifndef __cplusplus ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include "allowable-actions.hxx" ++#include "exception.hxx" ++#include "object-type.hxx" ++#include "property.hxx" ++#include "xmlserializable.hxx" ++#include "rendition.hxx" ++ ++namespace libcmis ++{ ++ class Folder; ++ class Session; ++ ++ /** Class representing any CMIS object. ++ */ ++ class Object : public XmlSerializable ++ { ++ protected: ++ Session* m_session; ++ ++ ObjectTypePtr m_typeDescription; ++ time_t m_refreshTimestamp; ++ ++ /** Type id used as cache before we get it as a property ++ */ ++ std::string m_typeId; ++ ++ std::map< std::string, PropertyPtr > m_properties; ++ boost::shared_ptr< AllowableActions > m_allowableActions; ++ std::vector< RenditionPtr > m_renditions; ++ void initializeFromNode( xmlNodePtr node ); ++ ++ public: ++ ++ Object( Session* session ); ++ Object( Session* session, xmlNodePtr node ); ++ Object( const Object& copy ); ++ virtual ~Object( ) { } ++ ++ Object& operator=( const Object& copy ); ++ ++ virtual std::string getId( ); ++ virtual std::string getName( ); ++ virtual std::string getStringProperty( const std::string& propertyName ); ++ ++ /** Computes the paths for the objects. ++ ++ Note that folders will have only path, documents may have ++ several ones and there may be cases where there is no path ++ at all (unfilled objects); ++ */ ++ virtual std::vector< std::string > getPaths( ); ++ ++ virtual std::string getBaseType( ); ++ virtual std::string getType( ); ++ ++ virtual std::string getCreatedBy( ); ++ virtual boost::posix_time::ptime getCreationDate( ); ++ virtual std::string getLastModifiedBy( ); ++ virtual boost::posix_time::ptime getLastModificationDate( ); ++ ++ virtual std::string getChangeToken( ); ++ virtual bool isImmutable( ); ++ ++ virtual std::vector< std::string > getSecondaryTypes(); ++ ++ /** Convenience function adding a secondary type to the object. ++ ++ Behind the scene this function is basically computing the ++ properties and sets them for you to avoid reading the CMIS ++ 1.1 specification, section 2.1.9. ++ ++ \param id ++ the identifier of the secondary type to add ++ \param properties ++ the properties coming with the secondary type ++ ++ \return ++ the updated object. Note that it may represent the same ++ object on the server but it still is a different object ++ instance (see updateProperties method). ++ ++ \throw Exception ++ if anything wrong happens. Note that the server is likely ++ to throw a constraint exception if it doesn't allow the ++ operation. ++ */ ++ virtual boost::shared_ptr< Object > addSecondaryType( ++ std::string id, ++ PropertyPtrMap properties ); ++ ++ /** Convenience function removing a secondary type from the object. ++ ++ Behind the scene this function is basically computing the ++ correct property and sets it for you to avoid reading the ++ CMIS 1.1 specification, section 2.1.9. ++ ++ The server should remove the related properties, there is ++ normally no need to worry about them. ++ ++ \param id ++ the identifier of the secondary type to remove ++ ++ \return ++ the updated object. Note that it may represent the same ++ object on the server but it still is a different object ++ instance (see updateProperties method). ++ ++ \throw Exception ++ if anything wrong happens. Note that the server is likely ++ to throw a constraint exception if it doesn't allow the ++ operation. ++ */ ++ virtual boost::shared_ptr< Object > removeSecondaryType( std::string id ); ++ ++ /** Gives access to the properties of the object. ++ ++ \attention ++ API users should consider this method as read-only as the ++ changed properties won't be updated to the server. Updating ++ the returned map may lead to changes loss when calling ++ updateProperties. ++ ++ \sa updateProperties to change properties on the server ++ */ ++ virtual libcmis::PropertyPtrMap& getProperties( ); ++ ++ ++ /** Get the renditions of the object. ++ ++ \param filter is defined by the CMIS spec section 2.2.1.2.4.1. ++ By default, this value is just ignored, but some bindings and servers ++ may use it. ++ ++ \attention ++ The streamId of the rendition is used in getContentStream( ) ++ */ ++ virtual std::vector< RenditionPtr> getRenditions( std::string filter = std::string( ) ); ++ virtual AllowableActionsPtr getAllowableActions( ) { return m_allowableActions; } ++ ++ /** Update the object properties and return the updated object. ++ ++ \attention ++ even if the returned object may have the same Id than 'this' ++ and thus representing the same object on the server, those ++ are still two different instances to ease memory handling. ++ */ ++ virtual boost::shared_ptr< Object > updateProperties( ++ const PropertyPtrMap& properties ) = 0; ++ ++ virtual ObjectTypePtr getTypeDescription( ); ++ ++ /** Reload the data from the server. ++ */ ++ virtual void refresh( ) = 0; ++ virtual time_t getRefreshTimestamp( ) { return m_refreshTimestamp; } ++ ++ virtual void remove( bool allVersions = true ) = 0; ++ ++ virtual void move( boost::shared_ptr< Folder > source, boost::shared_ptr< Folder > destination ) = 0; ++ ++ ++ virtual std::string getThumbnailUrl( ); ++ ++ /** Dump the object as a string for debugging or display purpose. ++ */ ++ virtual std::string toString( ); ++ ++ void toXml( xmlTextWriterPtr writer ); ++ }; ++ ++ typedef ::boost::shared_ptr< Object > ObjectPtr; ++} ++ ++#endif +diff --git a/include/libcmis/property-type.hxx b/include/libcmis/property-type.hxx +new file mode 100644 +index 000000000000..56be22347c86 +--- /dev/null ++++ b/include/libcmis/property-type.hxx +@@ -0,0 +1,125 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _PROPERTY_TYPE_HXX_ ++#define _PROPERTY_TYPE_HXX_ ++ ++#include ++#include ++ ++#include ++ ++namespace libcmis ++{ ++ class ObjectType; ++ typedef boost::shared_ptr< ObjectType > ObjectTypePtr; ++ ++ class PropertyType ++ { ++ public: ++ ++ enum Type ++ { ++ String, ++ Integer, ++ Decimal, ++ Bool, ++ DateTime ++ }; ++ ++ private: ++ ++ std::string m_id; ++ std::string m_localName; ++ std::string m_localNamespace; ++ std::string m_displayName; ++ std::string m_queryName; ++ Type m_type; ++ std::string m_xmlType; ++ bool m_multiValued; ++ bool m_updatable; ++ bool m_inherited; ++ bool m_required; ++ bool m_queryable; ++ bool m_orderable; ++ bool m_openChoice; ++ bool m_temporary; ++ ++ public: ++ ++ /// Default constructor, mostly present for testing. ++ PropertyType( ); ++ PropertyType( xmlNodePtr node ); ++ PropertyType( const PropertyType& copy ); ++ /// constructor for temporary type definitions ++ PropertyType( std::string type, ++ std::string id, ++ std::string localName, ++ std::string displayName, ++ std::string queryName ); ++ virtual ~PropertyType( ) { }; ++ ++ PropertyType& operator=( const PropertyType& copy ); ++ ++ std::string getId( ) { return m_id; } ++ std::string getLocalName( ) { return m_localName; } ++ std::string getLocalNamespace( ) { return m_localNamespace; } ++ std::string getDisplayName( ) { return m_displayName; } ++ std::string getQueryName( ) { return m_queryName; } ++ Type getType( ) { return m_type; } ++ std::string getXmlType( ) { return m_xmlType; } ++ bool isMultiValued( ) { return m_multiValued; } ++ bool isUpdatable( ) { return m_updatable; } ++ bool isInherited( ) { return m_inherited; } ++ bool isRequired( ) { return m_required; } ++ bool isQueryable( ) { return m_queryable; } ++ bool isOrderable( ) { return m_orderable; } ++ bool isOpenChoice( ) { return m_openChoice; } ++ ++ void setId( std::string id ) { m_id = id; } ++ void setLocalName( std::string localName ) { m_localName = localName; } ++ void setLocalNamespace( std::string localNamespace ) { m_localNamespace = localNamespace; } ++ void setDisplayName( std::string displayName ) { m_displayName = displayName; } ++ void setQueryName( std::string queryName ) { m_queryName = queryName; } ++ void setType( Type type ) { m_type = type; } ++ void setMultiValued( bool multivalued ) { m_multiValued = multivalued; } ++ void setUpdatable( bool updatable ) { m_updatable = updatable; } ++ void setInherited( bool inherited ) { m_inherited = inherited; } ++ void setRequired( bool required ) { m_required = required; } ++ void setQueryable( bool queryable ) { m_queryable = queryable; } ++ void setOrderable( bool orderable ) { m_orderable = orderable; } ++ void setOpenChoice( bool openChoice ) { m_openChoice = openChoice; } ++ ++ void setTypeFromXml( std::string typeStr ); ++ void setTypeFromJsonType( std::string jsonType ); ++ ++ void update( std::vector< ObjectTypePtr > typesDefs ); ++ }; ++ typedef ::boost::shared_ptr< PropertyType > PropertyTypePtr; ++} ++ ++#endif +diff --git a/include/libcmis/property.hxx b/include/libcmis/property.hxx +new file mode 100644 +index 000000000000..aa6560590c11 +--- /dev/null ++++ b/include/libcmis/property.hxx +@@ -0,0 +1,88 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _PROPERTY_HXX_ ++#define _PROPERTY_HXX_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "property-type.hxx" ++#include "xmlserializable.hxx" ++ ++namespace libcmis ++{ ++ class ObjectType; ++ ++ class Property : public XmlSerializable ++ { ++ private: ++ PropertyTypePtr m_propertyType; ++ std::vector< std::string > m_strValues; ++ std::vector< bool > m_boolValues; ++ std::vector< long > m_longValues; ++ std::vector< double > m_doubleValues; ++ std::vector< boost::posix_time::ptime > m_dateTimeValues; ++ ++ protected: ++ Property( ); ++ ++ public: ++ /** Property constructor allowing to use different values for the id and names. ++ */ ++ Property( PropertyTypePtr propertyType, std::vector< std::string > strValues ); ++ ++ ~Property( ){ } ++ ++ PropertyTypePtr getPropertyType( ) { return m_propertyType; } ++ ++ std::vector< boost::posix_time::ptime > getDateTimes( ) { return m_dateTimeValues; } ++ std::vector< bool > getBools( ) { return m_boolValues; } ++ std::vector< std::string > getStrings( ) { return m_strValues; } ++ std::vector< long > getLongs( ) { return m_longValues; } ++ std::vector< double > getDoubles( ) { return m_doubleValues; } ++ ++ void setPropertyType( PropertyTypePtr propertyType); ++ void setValues( std::vector< std::string > strValues ); ++ ++ void toXml( xmlTextWriterPtr writer ); ++ ++ std::string toString( ); ++ }; ++ typedef ::boost::shared_ptr< Property > PropertyPtr; ++ typedef std::map< std::string, libcmis::PropertyPtr > PropertyPtrMap; ++ ++ PropertyPtr parseProperty( xmlNodePtr node, boost::shared_ptr< ObjectType > objectType ); ++} ++ ++#endif +diff --git a/include/libcmis/rendition.hxx b/include/libcmis/rendition.hxx +new file mode 100644 +index 000000000000..2e386515e77d +--- /dev/null ++++ b/include/libcmis/rendition.hxx +@@ -0,0 +1,88 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2013 Cao Cuong Ngo ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++ ++#ifndef _RENDITION_HXX_ ++#define _RENDITION_HXX_ ++ ++#include ++ ++#include ++#include ++ ++namespace libcmis ++{ ++ class Rendition ++ { ++ private: ++ Rendition( ); ++ ++ std::string m_streamId; ++ std::string m_mimeType; ++ std::string m_kind; ++ std::string m_href; ++ std::string m_title; ++ long m_length; ++ long m_width; ++ long m_height; ++ std::string m_renditionDocumentId; ++ ++ public: ++ Rendition( std::string streamId, std::string mimeType, ++ std::string kind, std::string href, ++ std::string title = std::string( ), ++ long length = -1, long width = -1, long height = -1, ++ std::string renditionDocumentId = std::string( ) ); ++ ++ /** Parse an XML node of type cmisRenditionType ++ */ ++ Rendition( xmlNodePtr node ); ++ ~Rendition( ); ++ ++ bool isThumbnail( ); ++ ++ const std::string& getStreamId( ) const; ++ const std::string& getMimeType( ) const; ++ const std::string& getKind( ) const; ++ const std::string& getUrl( ) const; ++ const std::string& getTitle( ) const; ++ ++ /** Provides the stream length in bytes or a negative value if missing. ++ */ ++ long getLength( ) const; ++ long getWidth( ) const; ++ long getHeight( ) const; ++ const std::string& getRenditionDocumentId( ); ++ ++ std::string toString( ); ++ }; ++ ++ typedef ::boost::shared_ptr< Rendition > RenditionPtr; ++} ++ ++#endif ++ +diff --git a/include/libcmis/repository.hxx b/include/libcmis/repository.hxx +new file mode 100644 +index 000000000000..a4435d89ae75 +--- /dev/null ++++ b/include/libcmis/repository.hxx +@@ -0,0 +1,117 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 Cédric Bosdonnat ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _REPOSITORY_HXX_ ++#define _REPOSITORY_HXX_ ++ ++#include ++#include ++ ++#include ++#include ++ ++namespace libcmis ++{ ++ /** Class representing a repository and its infos. ++ ++ \sa 2.2.2.2 section of the CMIS specifications ++ */ ++ class Repository ++ { ++ public: ++ ++ enum Capability ++ { ++ ACL, ++ AllVersionsSearchable, ++ Changes, ++ ContentStreamUpdatability, ++ GetDescendants, ++ GetFolderTree, ++ OrderBy, ++ Multifiling, ++ PWCSearchable, ++ PWCUpdatable, ++ Query, ++ Renditions, ++ Unfiling, ++ VersionSpecificFiling, ++ Join ++ }; ++ ++ protected: ++ std::string m_id; ++ std::string m_name; ++ std::string m_description; ++ std::string m_vendorName; ++ std::string m_productName; ++ std::string m_productVersion; ++ std::string m_rootId; ++ std::string m_cmisVersionSupported; ++ boost::shared_ptr< std::string > m_thinClientUri; ++ boost::shared_ptr< std::string > m_principalAnonymous; ++ boost::shared_ptr< std::string > m_principalAnyone; ++ ++ std::map< Capability, std::string > m_capabilities ; ++ ++ Repository( ); ++ void initializeFromNode( xmlNodePtr node ); ++ ++ public: ++ Repository( xmlNodePtr node ); ++ virtual ~Repository( ) { }; ++ ++ std::string getId( ) const; ++ std::string getName( ) const; ++ std::string getDescription( ) const; ++ std::string getVendorName( ) const; ++ std::string getProductName( ) const; ++ std::string getProductVersion( ) const; ++ std::string getRootId( ) const; ++ std::string getCmisVersionSupported( ) const; ++ boost::shared_ptr< std::string > getThinClientUri( ) const; ++ boost::shared_ptr< std::string > getPrincipalAnonymous( ) const; ++ boost::shared_ptr< std::string > getPrincipalAnyone( ) const; ++ ++ std::string getCapability( Capability capability ) const; ++ ++ /** Wrapper function providing the capability as a boolean value. ++ If the capability value is not a boolean, returns false. ++ */ ++ bool getCapabilityAsBool( Capability capability ) const; ++ ++ std::string toString( ) const; ++ ++ private: ++ ++ static std::map< Capability, std::string > parseCapabilities( xmlNodePtr node ); ++ }; ++ ++ typedef ::boost::shared_ptr< Repository > RepositoryPtr; ++} ++ ++#endif +diff --git a/include/libcmis/session-factory.hxx b/include/libcmis/session-factory.hxx +new file mode 100644 +index 000000000000..b0b94f835f30 +--- /dev/null ++++ b/include/libcmis/session-factory.hxx +@@ -0,0 +1,149 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _SESSION_FACTORY_HXX_ ++#define _SESSION_FACTORY_HXX_ ++ ++#include ++#include ++#include ++ ++#include "exception.hxx" ++#include "oauth2-data.hxx" ++#include "repository.hxx" ++#include "session.hxx" ++ ++namespace libcmis ++{ ++ /** This callback provides the OAuth2 code or NULL. ++ ++ The resulting char* will be freed later. ++ */ ++ typedef char* ( *OAuth2AuthCodeProvider )( const char* authUrl, ++ const char* username, const char* password ); ++ ++ class AuthProvider ++ { ++ public: ++ virtual ~AuthProvider() { }; ++ ++ /** The function implementing it needs to fill the username and password parameters ++ and return true. Returning false means that the user cancelled the authentication ++ and will fail the query. ++ */ ++ virtual bool authenticationQuery( std::string& username, std::string& password ) = 0; ++ }; ++ typedef ::boost::shared_ptr< AuthProvider > AuthProviderPtr; ++ ++ /** Handler class used to request user input when an invalid SSL certificate is encountered. ++ */ ++ class CertValidationHandler ++ { ++ public: ++ virtual ~CertValidationHandler( ){ }; ++ ++ /** This function is provided a vector of X509 certificates encoded in base64, with ++ the first certificate being the one to validate, and the others are the issuers ++ chain. ++ ++ The result will be stored in the session object to avoid asking several times ++ to validate the same certificate. ++ ++ \result true if the certificate should be ignored, false to fail the request. ++ */ ++ virtual bool validateCertificate( std::vector< std::string > certificatesChain ) = 0; ++ }; ++ typedef ::boost::shared_ptr< CertValidationHandler > CertValidationHandlerPtr; ++ ++ class SessionFactory ++ { ++ private: ++ ++ static AuthProviderPtr s_authProvider; ++ ++ static std::string s_proxy; ++ static std::string s_noProxy; ++ static std::string s_proxyUser; ++ static std::string s_proxyPass; ++ ++ static OAuth2AuthCodeProvider s_oauth2AuthCodeProvider; ++ ++ static CertValidationHandlerPtr s_certValidationHandler; ++ ++ public: ++ ++ static void setAuthenticationProvider( AuthProviderPtr provider ) { s_authProvider = provider; } ++ static AuthProviderPtr getAuthenticationProvider( ) { return s_authProvider; } ++ ++ static void setOAuth2AuthCodeProvider( OAuth2AuthCodeProvider provider ) { s_oauth2AuthCodeProvider = provider; } ++ static OAuth2AuthCodeProvider getOAuth2AuthCodeProvider( ) { return s_oauth2AuthCodeProvider; } ++ ++ /** Set the handler to ask the user what to do with invalid SSL certificates. If not set, ++ every invalid certificate will raise an exception. ++ */ ++ static void setCertificateValidationHandler( CertValidationHandlerPtr handler ) { s_certValidationHandler = handler; } ++ static CertValidationHandlerPtr getCertificateValidationHandler( ) { return s_certValidationHandler; } ++ ++ static void setProxySettings( std::string proxy, ++ std::string noProxy, ++ std::string proxyUser, ++ std::string proxyPass ); ++ ++ static const std::string& getProxy() { return s_proxy; } ++ static const std::string& getNoProxy() { return s_noProxy; } ++ static const std::string& getProxyUser() { return s_proxyUser; } ++ static const std::string& getProxyPass() { return s_proxyPass; } ++ ++ /** Create a session from the given parameters. The binding type is automatically ++ detected based on the provided URL. ++ ++ The resulting pointer should be deleted by the caller. ++ */ ++ static Session* createSession( std::string bindingUrl, ++ std::string username = std::string( ), ++ std::string password = std::string( ), ++ std::string repositoryId = std::string( ), ++ bool noSslCheck = false, ++ OAuth2DataPtr oauth2 = OAuth2DataPtr(), bool verbose = false ); ++ ++ /** ++ Gets the informations of the repositories on the server. ++ ++ \deprecated ++ Since libcmis 0.4.0, this helper function simply creates a session ++ using the createSession function with no repository and then calls ++ getRepositories on the resulting session. ++ Kept only for backward API compatibility. ++ */ ++ static std::vector< RepositoryPtr > getRepositories( std::string bindingUrl, ++ std::string username = std::string( ), ++ std::string password = std::string( ), ++ bool verbose = false ); ++ }; ++} ++ ++#endif +diff --git a/include/libcmis/session.hxx b/include/libcmis/session.hxx +new file mode 100644 +index 000000000000..d28361a15005 +--- /dev/null ++++ b/include/libcmis/session.hxx +@@ -0,0 +1,100 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _SESSION_HXX_ ++#define _SESSION_HXX_ ++ ++#include ++#include ++#include ++ ++#include "object-type.hxx" ++#include "object.hxx" ++#include "folder.hxx" ++#include "repository.hxx" ++ ++namespace libcmis ++{ ++ class Session ++ { ++ public: ++ ++ virtual ~Session() { }; ++ ++ /** Get the current repository. ++ */ ++ virtual RepositoryPtr getRepository( ) = 0; ++ ++ virtual std::vector< RepositoryPtr > getRepositories( ) = 0; ++ ++ /** Change the current repository. ++ ++ \return ++ false if no repository with the provided id can be found on the server, ++ true otherwise ++ */ ++ virtual bool setRepository( std::string repositoryId ) = 0; ++ ++ /** Get the Root folder of the repository ++ */ ++ virtual FolderPtr getRootFolder() = 0; ++ ++ /** Get a CMIS object from its ID. ++ */ ++ virtual ObjectPtr getObject( std::string id ) = 0; ++ ++ /** Get a CMIS object from one of its path. ++ */ ++ virtual ObjectPtr getObjectByPath( std::string path ) = 0; ++ ++ /** Get a CMIS folder from its ID. ++ */ ++ virtual libcmis::FolderPtr getFolder( std::string id ) = 0; ++ ++ /** Get a CMIS object type from its ID. ++ */ ++ virtual ObjectTypePtr getType( std::string id ) = 0; ++ ++ /** Get all the CMIS base object types known by the server. ++ */ ++ virtual std::vector< ObjectTypePtr > getBaseTypes( ) = 0; ++ ++ /** Enable or disable the SSL certificate verification. ++ ++ By default, SSL certificates are verified and errors are thrown in case of ++ one is invalid. The user may decide to ignore the checks for this CMIS session ++ to workaround self-signed certificates or other similar problems. ++ ++ As each session only handles the connection to one CMIS server, it should ++ concern only one SSL certificate and should provide the same feature as the ++ certificate exception feature available on common web browser. ++ */ ++ virtual void setNoSSLCertificateCheck( bool noCheck ) = 0; ++ }; ++} ++ ++#endif +diff --git a/include/libcmis/xml-utils.hxx b/include/libcmis/xml-utils.hxx +new file mode 100644 +index 000000000000..afe5985dad23 +--- /dev/null ++++ b/include/libcmis/xml-utils.hxx +@@ -0,0 +1,167 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _XML_UTILS_HXX_ ++#define _XML_UTILS_HXX_ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "exception.hxx" ++ ++#define NS_CMIS_PREFIX "cmis" ++#define NS_CMISRA_PREFIX "cmisra" ++#define NS_SOAP_ENV_PREFIX "soap-env" ++#define NS_CMIS_URL "http://docs.oasis-open.org/ns/cmis/core/200908/" ++#define NS_CMISRA_URL "http://docs.oasis-open.org/ns/cmis/restatom/200908/" ++#define NS_CMISM_URL "http://docs.oasis-open.org/ns/cmis/messaging/200908/" ++#define NS_CMISW_URL "http://docs.oasis-open.org/ns/cmis/ws/200908/" ++#define NS_APP_URL "http://www.w3.org/2007/app" ++#define NS_ATOM_URL "http://www.w3.org/2005/Atom" ++#define NS_SOAP_URL "http://schemas.xmlsoap.org/wsdl/soap/" ++#define NS_SOAP_ENV_URL "http://schemas.xmlsoap.org/soap/envelope/" ++ ++#define LIBCURL_VERSION_VALUE ( \ ++ ( LIBCURL_VERSION_MAJOR << 16 ) | ( LIBCURL_VERSION_MINOR << 8 ) | ( LIBCURL_VERSION_PATCH ) \ ++) ++ ++namespace libcmis ++{ ++ /** Class used to decode a stream. ++ ++ An instance of this class can hold remaining un-decoded data to use ++ for a future decode call. ++ */ ++ class EncodedData ++ { ++ private: ++ xmlTextWriterPtr m_writer; ++ FILE* m_stream; ++ std::ostream* m_outStream; ++ ++ std::string m_encoding; ++ bool m_decode; ++ unsigned long m_pendingValue; ++ int m_pendingRank; ++ size_t m_missingBytes; ++ ++ public: ++ EncodedData( FILE* stream ); ++ EncodedData( std::ostream* stream ); ++ EncodedData( const EncodedData& rCopy ); ++ EncodedData( xmlTextWriterPtr writer ); ++ ++ EncodedData& operator=( const EncodedData& rCopy ); ++ ++ void setEncoding( std::string encoding ) { m_encoding = encoding; } ++ void decode( void* buf, size_t size, size_t nmemb ); ++ void encode( void* buf, size_t size, size_t nmemb ); ++ void finish( ); ++ ++ private: ++ void write( void* buf, size_t size, size_t nmemb ); ++ void decodeBase64( const char* buf, size_t len ); ++ void encodeBase64( const char* buf, size_t len ); ++ }; ++ ++ class HttpResponse ++ { ++ private: ++ std::map< std::string, std::string > m_headers; ++ boost::shared_ptr< std::stringstream > m_stream; ++ boost::shared_ptr< EncodedData > m_data; ++ ++ public: ++ HttpResponse( ); ++ ~HttpResponse( ) { }; ++ ++ std::map< std::string, std::string >& getHeaders( ) { return m_headers; } ++ boost::shared_ptr< EncodedData > getData( ) { return m_data; } ++ boost::shared_ptr< std::stringstream > getStream( ) { return m_stream; } ++ }; ++ typedef boost::shared_ptr< HttpResponse > HttpResponsePtr; ++ ++ void registerNamespaces( xmlXPathContextPtr xpathCtx ); ++ ++ /** Register the CMIS and WSDL / SOAP namespaces ++ */ ++ void registerCmisWSNamespaces( xmlXPathContextPtr xpathCtx ); ++ ++ /** Register only the WSD / SOAP namespaces. ++ */ ++ void registerSoapNamespaces( xmlXPathContextPtr xpathCtx ); ++ ++ std::string getXPathValue( xmlXPathContextPtr xpathCtx, std::string req ); ++ ++ xmlDocPtr wrapInDoc( xmlNodePtr entryNode ); ++ ++ /** Utility extracting an attribute value from an Xml Node, ++ based on the attribute name. If the defaultValue is NULL and ++ the attribute can't be found then throw an exception. ++ */ ++ std::string getXmlNodeAttributeValue( xmlNodePtr node, ++ const char* attributeName, ++ const char* defaultValue = NULL ); ++ ++ /** Parse a xsd:dateTime string and return the corresponding UTC posix time. ++ */ ++ boost::posix_time::ptime parseDateTime( std::string dateTimeStr ); ++ ++ /// Write a UTC time object to an xsd:dateTime string ++ std::string writeDateTime( boost::posix_time::ptime time ); ++ ++ bool parseBool( std::string str ); ++ ++ long parseInteger( std::string str ); ++ ++ double parseDouble( std::string str ); ++ ++ /** Trim spaces on the left and right of a string. ++ */ ++ std::string trim( const std::string& str ); ++ ++ std::string base64encode( const std::string& str ); ++ ++ std::string sha1( const std::string& str ); ++ ++ std::string tolower( std::string sText ); ++ ++ int stringstream_write_callback(void * context, const char * s, int len); ++ ++ std::string escape( std::string str ); ++ ++ std::string unescape( std::string str ); ++} ++ ++#endif +diff --git a/include/libcmis/xmlserializable.hxx b/include/libcmis/xmlserializable.hxx +new file mode 100644 +index 000000000000..533308590073 +--- /dev/null ++++ b/include/libcmis/xmlserializable.hxx +@@ -0,0 +1,46 @@ ++/* libcmis ++ * Version: MPL 1.1 / GPLv2+ / LGPLv2+ ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License or as specified alternatively below. You may obtain a copy of ++ * the License at http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * Major Contributor(s): ++ * Copyright (C) 2011 SUSE ++ * ++ * ++ * All Rights Reserved. ++ * ++ * For minor contributions see the git repository. ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or ++ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), ++ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable ++ * instead of those above. ++ */ ++#ifndef _XMLSERIALIZABLE_HXX_ ++#define _XMLSERIALIZABLE_HXX_ ++ ++#include ++ ++namespace libcmis ++{ ++ ++ /// Interface for objects dumpable as XML ++ class XmlSerializable ++ { ++ public: ++ virtual ~XmlSerializable( ) { } ++ ++ virtual void toXml( xmlTextWriterPtr writer ) = 0; ++ }; ++} ++ ++#endif +-- +2.26.2 + diff --git a/SOURCES/0001-replace-Palatino-Linotype-with-Liberation-Serif.patch b/SOURCES/0001-replace-Palatino-Linotype-with-Liberation-Serif.patch new file mode 100644 index 0000000..0385761 --- /dev/null +++ b/SOURCES/0001-replace-Palatino-Linotype-with-Liberation-Serif.patch @@ -0,0 +1,26 @@ +From 06b19641b0eac7b7992fae861eb4807397c9aee4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 28 Oct 2020 10:03:23 +0000 +Subject: [PATCH] replace 'Palatino Linotype' with 'Liberation Serif' + +for consistent font replacement + +Change-Id: I3c124c0adcab8ac2dd7f989c2fa5c97182e32b64 +--- + sw/qa/extras/layout/data/forcepoint75-1.rtf | Bin 88740 -> 88738 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +diff --git a/sw/qa/extras/layout/data/forcepoint75-1.rtf b/sw/qa/extras/layout/data/forcepoint75-1.rtf +index 01a52963757d8568e5ae8b80b7767c924c37a407..263a585c57e162caf1c9f9dd3aee4f3d8aa3edd2 100644 +GIT binary patch +delta 85 +zcmZ3om37fp)(y#wVm_HksYQt;nfZAN!Kp==Y1XyXF=>XA=QD{5pi50&#At*e*!+}n +M`%^~7{Sk~@09cV9Z2$lO + +delta 104 +zcmZ3qm37Hh)(y#w_5q1Gi6xnN`3gQjqNK7Q)w;GiCe1J=ttdY?F)t>$Al)D)Ejc5x +ds5rI6KmkMb +Date: Wed, 29 Jan 2020 12:44:52 +0000 +Subject: [PATCH] replace boost::bimap in sdext pdfimport + +Change-Id: Ie324a0b81931bbd427483878a87beeca455ada18 +--- + sdext/source/pdfimport/inc/pdfiprocessor.hxx | 12 ++++------- + sdext/source/pdfimport/tree/pdfiprocessor.cxx | 21 +++++++++++-------- + 2 files changed, 16 insertions(+), 17 deletions(-) + +diff --git a/sdext/source/pdfimport/inc/pdfiprocessor.hxx b/sdext/source/pdfimport/inc/pdfiprocessor.hxx +index 89f9d601b7b0..9e08d6a6a765 100644 +--- a/sdext/source/pdfimport/inc/pdfiprocessor.hxx ++++ b/sdext/source/pdfimport/inc/pdfiprocessor.hxx +@@ -37,9 +37,6 @@ + #include "treevisitorfactory.hxx" + #include "genericelements.hxx" + +-#include +-#include +- + namespace pdfi + { + +@@ -160,10 +157,8 @@ namespace pdfi + typedef std::unordered_map IdToFontMap; + typedef std::unordered_map FontToIdMap; + +- typedef boost::bimaps::bimap< +- boost::bimaps::unordered_set_of, +- boost::bimaps::unordered_set_of +- > GCToIdBiMap; ++ typedef std::unordered_map IdToGCMap; ++ typedef std::unordered_map GCToIdMap; + + typedef std::vector GraphicsContextStack; + +@@ -178,7 +173,8 @@ namespace pdfi + + GraphicsContextStack m_aGCStack; + sal_Int32 m_nNextGCId; +- GCToIdBiMap m_aGCToId; ++ IdToGCMap m_aIdToGC; ++ GCToIdMap m_aGCToId; + + ImageContainer m_aImages; + +diff --git a/sdext/source/pdfimport/tree/pdfiprocessor.cxx b/sdext/source/pdfimport/tree/pdfiprocessor.cxx +index c6baa7fee8b2..ed2eaf6510b9 100644 +--- a/sdext/source/pdfimport/tree/pdfiprocessor.cxx ++++ b/sdext/source/pdfimport/tree/pdfiprocessor.cxx +@@ -54,6 +54,7 @@ namespace pdfi + m_aFontToId(), + m_aGCStack(), + m_nNextGCId( 1 ), ++ m_aIdToGC(), + m_aGCToId(), + m_aImages(), + m_nPages(0), +@@ -65,12 +66,13 @@ namespace pdfi + aDefFont.isBold = false; + aDefFont.isItalic = false; + aDefFont.size = 10*PDFI_OUTDEV_RESOLUTION/72; +- m_aIdToFont[ 0 ] = aDefFont; +- m_aFontToId[ aDefFont ] = 0; ++ m_aIdToFont.insert({0, aDefFont}); ++ m_aFontToId.insert({aDefFont, 0}); + + GraphicsContext aDefGC; + m_aGCStack.push_back( aDefGC ); +- m_aGCToId.insert(GCToIdBiMap::relation(aDefGC, 0)); ++ m_aGCToId.insert({aDefGC, 0}); ++ m_aIdToGC.insert({0, aDefGC}); + } + + void PDFIProcessor::setPageNum( sal_Int32 nPages ) +@@ -468,12 +470,13 @@ const FontAttributes& PDFIProcessor::getFont( sal_Int32 nFontId ) const + sal_Int32 PDFIProcessor::getGCId( const GraphicsContext& rGC ) + { + sal_Int32 nGCId = 0; +- auto it = m_aGCToId.left.find( rGC ); +- if( it != m_aGCToId.left.end() ) ++ auto it = m_aGCToId.find( rGC ); ++ if( it != m_aGCToId.end() ) + nGCId = it->second; + else + { +- m_aGCToId.insert(GCToIdBiMap::relation(rGC, m_nNextGCId)); ++ m_aGCToId.insert({rGC, m_nNextGCId}); ++ m_aIdToGC.insert({m_nNextGCId, rGC}); + nGCId = m_nNextGCId; + m_nNextGCId++; + } +@@ -483,9 +486,9 @@ sal_Int32 PDFIProcessor::getGCId( const GraphicsContext& rGC ) + + const GraphicsContext& PDFIProcessor::getGraphicsContext( sal_Int32 nGCId ) const + { +- auto it = m_aGCToId.right.find( nGCId ); +- if( it == m_aGCToId.right.end() ) +- it = m_aGCToId.right.find( 0 ); ++ auto it = m_aIdToGC.find( nGCId ); ++ if( it == m_aIdToGC.end() ) ++ it = m_aIdToGC.find( 0 ); + return it->second; + } + +-- +2.24.1 + diff --git a/SOURCES/0001-rhbz-1870501-crash-on-reexport-of-odg.patch b/SOURCES/0001-rhbz-1870501-crash-on-reexport-of-odg.patch new file mode 100644 index 0000000..06dd7ca --- /dev/null +++ b/SOURCES/0001-rhbz-1870501-crash-on-reexport-of-odg.patch @@ -0,0 +1,7987 @@ +From 6f1fbc68420a5d24afdab7dea75982bfb5307a3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Thu, 20 Aug 2020 12:56:36 +0100 +Subject: [PATCH] rhbz#1870501 crash on reexport of odg + +where SdrObjects in a list have no navigation position set + +a regression from + +450cd772aa734cfcb989c8cedd3c0a454db74a34 + + Fix fdo#64512 Handle xml:id correctly on multi-image draw:frames + +this just reverts that and adds the test case that crashed + +Change-Id: I1a49dab9578699c42fe845e8ec42de40159dec3d +--- + .../unointerfacetouniqueidentifiermapper.hxx | 21 ++-- + sd/qa/unit/data/odg/rhbz1870501.odg | Bin 0 -> 403275 bytes + sd/qa/unit/export-tests.cxx | 9 ++ + .../unointerfacetouniqueidentifiermapper.cxx | 97 +++++++++++------- + xmloff/source/draw/ximpshap.cxx | 9 +- + 5 files changed, 88 insertions(+), 48 deletions(-) + create mode 100644 sd/qa/unit/data/odg/rhbz1870501.odg + +diff --git a/include/xmloff/unointerfacetouniqueidentifiermapper.hxx b/include/xmloff/unointerfacetouniqueidentifiermapper.hxx +index a78713f85d13..332005e720ac 100644 +--- a/include/xmloff/unointerfacetouniqueidentifiermapper.hxx ++++ b/include/xmloff/unointerfacetouniqueidentifiermapper.hxx +@@ -24,6 +24,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -35,6 +36,8 @@ typedef ::std::map< OUString, css::uno::Reference< css::uno::XInterface > > IdMa + + class XMLOFF_DLLPUBLIC UnoInterfaceToUniqueIdentifierMapper + { ++ typedef std::deque< OUString > Reserved_t; ++ + public: + UnoInterfaceToUniqueIdentifierMapper(); + +@@ -50,12 +53,16 @@ public: + */ + bool registerReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); + +- /** always registers the given uno object with the given identifier. ++ /** reserves an identifier for later registration. + +- In contrast to registerReference(), this here overwrites any +- earlier registration of the same identifier +- */ +- void registerReferenceAlways( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); ++ @returns ++ false, if the identifier already exists ++ */ ++ bool reserveIdentifier( const OUString& rIdentifier ); ++ ++ /** registers the given uno object with reserved identifier. ++ */ ++ bool registerReservedReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); + + /** @returns + the identifier for the given uno object. If this uno object is not already +@@ -72,10 +79,12 @@ public: + private: + bool findReference( const css::uno::Reference< css::uno::XInterface >& rInterface, IdMap_t::const_iterator& rIter ) const; + bool findIdentifier( const OUString& rIdentifier, IdMap_t::const_iterator& rIter ) const; +- void insertReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); ++ bool findReserved( const OUString& rIdentifier ) const; ++ bool findReserved( const OUString& rIdentifier, Reserved_t::const_iterator& rIter ) const; + + IdMap_t maEntries; + sal_uInt32 mnNextId; ++ Reserved_t maReserved; + }; + + } +diff --git a/sd/qa/unit/data/odg/rhbz1870501.odg b/sd/qa/unit/data/odg/rhbz1870501.odg +new file mode 100644 +index 0000000000000000000000000000000000000000..cc4bcef193c20dc4bb9417a58f1bb019a4d414a0 +GIT binary patch +literal 403275 +zcmafaLy#~GtmN3XZQJ%Ywr$(CZQHhO+qP}b{_oxPvYV=;E0=U`Idn%}3K#?m00062 +z;M=oLJ`b2~m>K{8;C~VV00+Rv!p6ke!`?(i84>{ayJt!Ff6~Pr8UPUF92fxLe~W>= +zy|smrfwP63ExoI)F`b=(lZ6wVoxO>zv7M2Njft%@otdM7y}5;vll*^VDF01{_+PTI +z99{oAYybc;TmS&p|H$MmjGSE@O`PZ%8U70}}2dUz^Q%xXCBoG_kSCSDs@ROEds1maK^Y0}&yJR6vPH3UCn)2$)NXfFLUO +z&vOGUf)t04^*{;6?`jD_5+ZnVAN=_2O@ADH`^lbmkTY|y-RgSX-10chA%9{N&J2#v +zNQjG%6+Yb$AaivxFE2Sg@XQ$Uy4=9r+|dZ>jGZ5f9;wtQ9g)U`okC!FouK_p9abzVW_ +zfa??ADJ%xZ?X|1XW*AZxF;gACgPVUS4!cZ5J`6G=#`#TSipt<)2ac`Hg+2g&5OqaI +zb+#gHQS7EnNW%y;7lbIrTO414&s5Ly3ocy7+AY_WlwKV6elJtrVD`0@mw&xzrS=Z( +zCaBO;w0_B-iz#m>)0l`kaGWppIR4EF;(LJZ+DI +zx+E}}YL$>luQ8dU_4uMs^@)-pL*gsB^}g59)mtwaz1V%_7!3Fzj_Anq-78y8CZw~X +z2CrAjTa}dZSnBR)foRP%muo|>PH!*?E9RbFiAKoT4^LC5rj*|Wsk5|m(Yx(lm^ib^sWoM?oKkznq26X|LF~BacO!7c +zMUIL!MMZ>%jI!`I&QSd(MI5BRs%Cvdhl@ZSn$ijre-ltd4i@PL&_Fn2G_ajAFj3cPlLvhA8xe| +z{9Yo(J7q4c!8(BGA|Te2>L@(B1zFq{SGNvu0OIV}AOu2q+Kq8XJoPs>TYOiJ9l8w~ +zq>bT33~IsgT`vhsOC0~n0BP1#X0EYqu}&ce?ZPZ^D?GjbtXnRHm=3l1!Lig{Qu4O%6pD&zxx=R-5*x^4`P(qvtu +z{kCVEp%KGJl}^n{*^qxbM1g{`k{%`>mgtMA;ezW$V=gL`WqY&84v)>|sHLPy?MW!w +zy&jK#M{Ep!eqcA4tT1(6gxuamP~m8w}v8|W|7a$Cx}?+$DrFc=poSmcOBl5UABP{q*F;oLDCMniq +zgS8Wbfs4az+qdo?UjuJx^oU>g(8X0Kecp0@?-n@YsxQ8Qj-6TKi7=tDA}eKs_XQd- +zG|{_V-Xy$`l+FGNQrbiAM9IM}*+U2bwT5Aq()9!8KOyHw@KD9Opi8w0sEb@dkB#Rd +zmp<5IGSoJwFNqdvaJ4b7ZM|L6T&MVN~{BHPwg(!1-m|yX0pmvi3%uRFe&_!oE~Z@QEfen +zX~Xg<$5Y34^<}e-erU_1{g^sg#NwFUU|7nIzA0CF9S<`Z1k^5vOaLzVx4%m0Z{3$q +ztf@a4@b^-bPE}Ucxjs6jB&hh$i?~Xh0`hVJ0nl)+;qH-QwG9JvD^f0VGEV9H!W2qg +z(>8F54=qwf#qjamJi)UxFTY0$=Z^WCyL+73!Fm*Pxu?-pOv;encTPXrqvKDJ>8#sg +zdb#lqlT1dd8nG3ZL#xF(#yUR(NFzH^kyjiH8wwVdswGOH7dktisu|qN(x%2&1*c~= +zKpTcn6zeV`MsvmS^0?p5#z}dT8BF|WyD`cMynND@sD$G%-z%%Zup>kHl>GYl1N5N2 +z1LTJX6aAF;J;?%EbVH*{_;lTC0NtU>Lj1R +z7Pv@WP<`0$IXuhgDxB`DCkqW;v3lrPZoPqlT!(r{H(+~G>4Bor>G^Vzy`|Tg^jhb? +zL+Z(W+{`8`yeSvDdzv=0TZvFMi+YxdH9NQ-aGULb9-^MvMXfql*x~itc9|{UE{RKk +z%9w2y+bo-|6@$k4Ew+$}Bj#IZ3^RL597$u|7dxNJ(@#C`@3lpF!tinYqSrp-vOHK+ +zEg6X##?zba1?hR^%?k4b-8AQ63Oi~BK17^-{MYHMyQSOpF8i@tqk>J_F4YNBgmCvg +zzNKNdZzx5M@G^fMZD2YQkdAzm88ut-A$9Jc!f~xG8}32uA_~k&}3Es#O%Av-SkoZD&Lv_T=fn*ESnPpFiK^oE&PwI<&UN3X0-+(`W}a4+PaUkbec3fw7|zIuH5)I +zK&Z8K7YhD^tPh<>3o6&rx9>zjj)5h6W0OSNGj@!kuRUOlcPJ6|w-igqoD>!S1cP4d +zU1ZkNU}I$yp0vvEFVXodEyglYBlMc-dGL~Kwj;J|7(D}(U61iDin_M6*fZ>pO5oDE +z=nAFN5Oa$BAHExu3OyXDw9v6IV2C~6#$gjK4heWAYKYOG@j^m>b53#Gt>4SFsyha` +z@tVtUWyt3d)t=M}t2D^_^QIRCnl;ekHh*JpNU~1g;1C@0+d{^2tVR+jzh;yQSFwNHHx9Zj=3m0-1Ea +zYo)P;as@c5J08pCGWyRz}&WFu!QAM#Gg3$vOjz6jTw>a +zi9DM;hz+6%**9*$Tv-T?N!V1>4@WZ2x^&N{`1dBTZ73u*eO~KKy~hzc2oWawmz=Z8%*KMI +zQeEgLTYSu|>}ldNAv +zZ-&GyP~%rZ9bR$-=#9A>Y{V0@rmqU2_LM +zax)F!6eKgznRE_%ahTL`a1|Rl?0mL%G&g&Uo{7{?uBsMA{5Qj`^wr8o>gWj&Bv?Jg +z&Bf6-Rh%5c&hgg@z%Qv#^%%?%plWL+IS~RN7kJp!$a^|fDByMlq3MPlNtglooQ}3Q +zsyy%uPv;ChJbk)!t=$OdLGLICPjk*$8*XyUoQ4j>tsMwczib0NfQu&b-kBa$Sz{N~ +z>1+fBW9x^ImQS(wDN=A~VEUMv1?}#M6*$amg$r14UatU$@tQHu2IZZnpm>zA{?ux$ +zvgCf_JH}=`6DEs&j;K@X*vKg~$g(Rgmp)LNz~%;?DrJD>ysYk;tVdryX=m}ftRwj- +z$J}QVr&?7NyABoj@1HLe#ez=MRIk{TLEpT +zqG0aS>A0DWGyYr~HL1zgbp(cAT}fPhxttP@UC|$2yBr}7TZEVfwu_Y|E)vm%=}$aI +zHnbda9QTY3MN-{u07t=zZ#1F!`I?r+c$5^6j4%H2NAq&^HferI#)-ZEfI4(iv&NKI +z>P#)q&DKdGUtTcl4!xvX1HqU46vxbn`GD-%wRJwgdoLA1=HrwVUDMJ@+~s9%(-pD< +zf2T;R?0mcmy=;A)5pPErU#LQHP?kK^jPN#29#%tFEy4Amder{h?1AMPb=W~KU)6** +z9JJL2cyVIW39SP`KtY`?0g;A7uM90Db+5YRfwf?-{~jYXU}B$I^Sx)u4Nk4zuKOhY +zo|nI28(#u1NK4rX-^;6oC|EjSOqZ^WHcffa&`EoL8Y*60UbQ^#e^}35VSX$_i{dAO +zVNfIuwFX%_a60)(6lIw81Yo*#)M5&p!FJ@nJ{kG_B4m`$UT$F6q^d+gF)Vv-nznwQ +ziCC!(^Jf_JZZf{W`fviHv?!IlAP%nP`1mx4j|YE_+9@5nR0`+jkN`C)Rz>>m`RNT2 +zv(hgqL64yHZxyqX-ZXZ|z=vtyyR@S_ezaZ0{{aKs%NvQ~a-4S~Bj#&8tZ~}+X_~Y< +z#lOx@dh~WCHc{%A=Frb{G0|)3VL>X+xQ7*aa!2XyU_2id1P;$Le}jA^@PVJ<*(wwi +zHqtaU(H@4SSNR;0pAK=$W|y^XC6vj2~Z-Y-_ +zq)ClR6;bjvX6MB1@rK$DVCic!;5XlX`Qjds7?&nzAXD +z2H}oJM&tv}pICM@g&+T;ZCjGw3HU(EAq2HfOS}c+OWTN5^4`g@_X7tTZbiflI>gLr +zA;b_Tcg*5 +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 +zYEFsKB2pm$c-(I+dU3xo-;w0HC8c%x<-6; +zusPS#(;L0`*;MY?NT)mrc|y$?y24Fc)!WI(psn-I98A?0k+1*I5S|g7B>U0g&gYOx +z1;n3GZulLEV!zVBk%nJU9H}Y=0{RLTj9>^rf9-)GQ#I(+U<2hkLiV_rFHS9SDZgn$ +z-gULbL3mdi%6gG}yu$tC%tkz^%)IQdv2a#yPW+kMR;%|J&u@zM5|z +z@Rr*goT{dfROBPJK=RtrDfb~xE5AQvIVT54O=}}1t$3r+9=SGhIrJvZ`MzuE+{9K91q{8k47lf^>r}H+N-$lz4WmT~uZ=mUc +z-|86a@>l`VzTUN3ROn6E%x|?_XPg?6PtG0T~FH%D|NP{ +z`G*y-IGlw4yzTz@Ee&a3Zo^ksXn!Bac`Oq-L91yda +z@kLxeWBE{LnJGDwR(2(S>AcFoWJ9%oA)lU_e#;%RkEly)blK2JVg8Pq!rF~il^lc? +z+G-T`+_?HA`Cqe04mqr@+-yi4Kx<4VhFELq-~oWKKp>;MbS`auFAsrqV}qAFoUlQq +zp`;a%@zu=Dg;;Hx8YF|$hUEdHvWLawXlbShwRxl3*7X-TA +zu~?rc2KLZm`vQF1B2Ev#QOam09eJNTfZ?|&ZG10I?E6TUg7-rz@t>2-Akn)2nt_^f +zU8LfVFz}H5i1I_*CWo?+w73Wz@_OdcX7aDRVIB;MXXtVsd+V!7IdIEnoeb_fsZj;_ +zZ-?FEMe^Z+{o>sr=D!wi0kj!(QsFu6tBiS$B9kMfCa1F?0Q8?)cJ|lqY&(Yn7_p^LGnq +z){Hs)x&1rQgIm;H7`teZ-{

?Y@sXe*e82EL?4g=$N`idZ~(heTysX?V)8};w-p+ +zJqB+jjeKMxE%gfOD=;aP|nLS5U}{zjuP-K +zRuZFe!%HoMjOk~yXCh@lLB3%7PMWM~5C`F8P#XEp@CWzCq7zs2hsy`o%NVj2@@@vOr|+6aqX9pzTeD +z5|+m?dSvh=0gh26Fz>V9i%k{Go4xGW^02U(;f!)4CS3%-C%qrOUd^h6z;lC=4~6QP +zn38JVG9?_h@kzpUfHFR9F>_4P*bAW@uDHV!mu9XO{+%iq^hEtg +zo_2c%?~)ymNey-vsJg6Kk3lQCI(P7Zk5hfyGBGh97(ZQ0K=Q8w1ReSCyeKE8><8bF +z>DHxAAt&kvwc$PH%g^KM`D~hq{S02MvHZO{aAu|F_c`mB^taNB28f7jhiy06Bg +z-@fSsMN`{J(5!O`u&@^{DIcCmU%vYZOxk2TwJJzXJG}FMNie}`(g5nCqK@27&RQ%_ +zQ0tX1%>-Q%$%J+Wv0Emr_PA%Vw!6=E-0mbEq`*pCO;LCxiW3~%nE(~>`bcKSgsDL) +zY3a%P16-a!pEmUJ^sGLIUg7K%W3W?HGv!}y4}yn#94d%6*eD(2V^f~JAfT}saYQN| +zHRs)Dy8cX?h0`Ju2Al@Tlr6q+}^+3yb>rI^iKRDikM0WqwcM% +zYE7%ao0Z&nbDMN#e2unxa0(&_7{jSv)sH=EbVrQ*eWblGOFZ*;y`WznYUAlui<4jC#QS6sVJiR +zzAL2~Xf8g-utiO+jPXA-#{D?JC1yhnx&osMm&*H8i%_rrjcfnjTZ@mRxpU#*;q5Zt +zYunKbvDN1tKJZ!b)_(e5MY(+gCsCCFM{(7EZGmDS!O%j@#N)7|s*`2pU|MDQ_>Ivr#*nf> +zO|3%-UgN@5iW>8Ja-qd?c+Gw#d{Nl34(m&EJ$EW02>O~RkiE$%`RO6-TpSRBKt6fh +z@HX^^3xz +zz7YDRWZ-YyK-9=yIDL~q_cnbado7|#NU)&Pr12~sFQ>997B5Zj2U6*V8$FG~8Vxxu +z#R1T-J=q!g`1H{H9>3vhDy}-CNS6V#Wr%=Pl#;b=Zf(;v0t@e++2pFZ-AQJF!Joz> +ze}xVu9-g;14FQw_9^3da%5?Y=`VUtj2|2*$R>}nbB|t~SMmT6Rr1I%ei~!CpJv}zt +z_T*g&z)96MH8riStO#@z~Q$ZY(-LNU8M4HazQD^`Duq&44>Gxh0d&9jFr#Tmo|H +znq>~%CvbhIGX-xI4=?i-@sA6NJPq1EF#PL>5VxmViCjg?MA@SoKQdRNcOuV+7^DrF +z!*=j^)R65|s4}Xu5=29tePw59lzeDeUvOtRUvt|R(u4HbV~@3h +zD<|vYY_TvbngEmgk5XuCmtZFJ`4JARjtsgKg;|7)EovVGLTNgm4brH(#9>&Vw~3Ew +zs5|4}4O)objFZj-k?Q)Wt^p7Y9bKVn44)kLUx{F+zkZ>_B=5xl4`X84}2%D0^v)}J3KTNlhKepZezX(_Wt1P>2#KE +zKY-;q=mxxiBV!vr#l9sDKGCPy?c3y?z@!^#6b9!Zb +z*;mhfQ&kbB+|mY$fA@mmOUCFm{sU=#gGIao|F^DzVD&9Q>Q{EdT$W@HC?)aL?ACYJ +zut9*}L-M`gX2z24qH>0POZGt$Mu9_ghp~=(hGNo){Rj}K%_B0`G}D|0i2GJFHunB+ +zvfU$_3q0e%{5&JfC$QY2fImXdh-)yVJ?+gCgbji41KMc+q@XcNBr6~eLx{$S58uZ{ +zaE{fCWalAlfW_OLU|#2ztJ$Vd7(t>T6V6vr_~N$!W%q9dU+{$=8PdYL@mSLjIbeFc +zc2>|H9M%q8w9kz@NbhwA343SCZI-J6*M%27v%-*IGD%;NSDKFpzeByS4)Cs0QL^@e +znPj*r2~}Hip!XNd?C-e#%h~B%By2+Jbn5*)ASJKdR;`;}^1kw-*hZy1yL#y$HyR4@ +z8eAd${E$k%VLR0KSU0g^m{GC>eSzRgH!_xF;_lg`E_YMiV7El}8Lt<`5F~j>ayU2$ +zohngX2nS|0Hf~cVUFdf>EdQ0$E|dOA;9JO5rqwt`8VM6(*#;-EZpq~$)XK~k*9v$% +zHevsH3hp#mS2gl;c^IX&E-TO?z34$ohr9?h^4$DD)5-2NS@@O=?H2ySfuwc!i8*vU +z7aB%1K30`#^WM^;_JhnwM6T(#&?iT&N*7TfCAIZj0B&h*W2t!aczSwZP$XD6gOC^z +zg<#?N3Ie=LSPuamjwGr_QIuEUr9?Scw+qLwd$B*qppbfya2)anA~t*MS)ME5=N|IBl~%1?i@Y18Uug&3Djzm94P*F4BXqmc>?~Y; +zvIkxD4r2{0c+;K|*CTPBhI7b*VsO#~(1%f6FQ_7g);{29Q84itoVdstA}*uKmr=5@ +zq%WExyFPP}SM|}YQnP2^iOr-r1&G{QF%3qYZ>&iSoHMqylcTg;(N{>TT$m8_7ECBw +znqU)VMH?`;f7-Qc)pWn6-C#bJy@r)}XY7um$OVJK-Ux*lFyiMm +zR5k(r*@sTfN$Y9WuguzQ8U3;4HE#Ryc{^J>i+jQwzfB~>w^{h8i5fzNq!qaw`fkQcTeQ@lUKKYRYmS(0-tkyq74v-~%hR*@sp+ +zlSE#wT~YlWTsUP<0!6ZJO0N>vrWzf<=mSYZN1v`Be}ax#UJ2SWxJ8MEb^oK@ckxz? +zg5(twufO{|6ryHXZkP=rWc&FfN3PS5L<@+HJvDwU9 +zuF*#Os}=gf^3{cL@gqUE@rdWKfzoQUaAMJ6FqIvwR3ew4@8S7xr9;h)v{3L3 +z4tJm(0_M`m)ugT7Rx_5oG0?Gntu|z2X+Z!#}&vU2i +zMFy}Id;RcF?sA|Y8@9O%IwxbmI@WYMfyBM*a`$k4tQ?6u?e!)tJAU8-3P*D$%!%=Q +zXi#4+EB8q5Lhd8tv#wgN8)dub--848s$pTEpRPtNYY&5RU9bpnxVrA3L@oN;8WI?XTLj3s4Ox`@}Uo7j+7F>_*$t87~J)SOL~7!z%y}Z8$aLan)n1& +z5j!?-Q*wc;<<>vz>~++#eji~VB_ZN~!_kW|1Amhx_s9GI@gu8%n_q#mkbx~Wr>Sq8 +z$ATh$j>fjUxd*awV6QaPIMi5!>*E^~qT$t(kX8P^h&sRn_+DQ%=HzJH%ZhWv{aQ;Q +z>i&UdQFpg5its(3m#4IL(a$lF>J`Sl5^8^@;kGkEo(Qy^63XfC{=F!VnGbs#ri$iV +zyI)9@3OcEar-VM=oQ*IND;FS}0?$De4#eP+A +zXr0^F-3wQbE>Dk#aUXQlMN|_H58F#fGhF&ukU`2c5u5Y~GBvdsK?!%oN5S|wG$3oq +zDnM3@q3?XY#-(4WK`RV)3b%I+7@drELF%b}bw`oR$jUJyU{>63xaL+{n4>dLU339q +ze&}$b@l)?%)^PPQBWElLbA|2~uaNci_4%9*$Oz%SYBd_Z#abK3050ArUmr9r?$^6_ +zkIN`JbTIpx8aL6WLc7m*)h2Wm1;QF*1d++HT8O +z&J`5JU$t5qiZ-zM_nZc1^doN+L-hXKJif#CuJ6d!i68}rt;gyXJGa`5+rt#MLjeH& +zUiy1Bg3E%9Lsg+P%OlkbhykEH%lI1;6$(O2I~O$=M*PS^QLA54F+4zasV1{sv0asw +zl?W$^%2cdLHcWqxl#(W?UW$=8levsj`Cvs~JP +z7|wu-fHP&wl-X|GCJQtwO5tg@hX~6HSZ&A332l_J6%pz3{^g%GK^M=l2crgW*z+$MyKn}1JD#@(7PQ4PQAVKTW48yOh>6r +zQJv*{@ghc3xefc{V2O899+ANZw!i{5;vKQs%3fvow|gj@;@mc|GSRzMTJrH}2wcer +z{Ws1pr6nAZ&7dAY0F^!+=)ck@s!E^}=wHE$U%yU2LdziiUA%ls=+mpX1R2HW=An3`N_Ld-U$$HSANl!_He`vYHJi0bhXLac_!kZ(oM((1VI!%#EvUsA= +z>wp-wyhe;MG26vNz1|)`7y|%mYHC7AiELc2Io^GFh`yW%@(gVlJ_~?-`nj2pu71Bh +zExr_d6Xf}Ew0E~;T!+2Ec*v2P8o2UYue@90P{T&==PDAIWVD0rF{i{Tl>f>3MqsTd7wA!>=<7*L7k18Ujxm +zt{ufSWnoqu8rm){FHW8EtRM6pGb7u=y5^0;((d=yq7wTyzIlt^&aKJZO**HlMz2^s +zIVeBZh;&qmJU}VXH~F{Fp8a9@-jmUc-6UKKkZ3*)DNFh>T!^$MX?u-Y+Y`$X9pEj4 +zy;*nc1|w&2l=#MLIbaG5+63RVv +z9)}6EB)I6iwS>kEXWT*vY9GXi*s!ulYI4ifDd{qHWw%E)f=4%T5=zKB??3asE`a}f +zCsYix(C@~+l(jkRa)ZU72sy8P)2uma>`_0J+r8jrl{}#*t(d&cq}y^MH=AlX;Llc1 +zo8Z~;E~>4VWP?9YcL@+?V@>~%&dS0{noN|Y*5*CA^*_xpglQOCao1vsw7h&Q9&CRj +z-u48HxLEn_khd{QT6N^U0qRhD%)r7`3=!a9baLsvRKhcNrA|4_UuZaj#zUIzUz*=K +zb&hi>P5y}Ywz?83+^rY7cwh7i7(Ki1(;}3)mZMT#hCDIb{GCo)YZLy>AG~q!N7Lg* +zE*o%pBU^cbHalM)dc6SpUAu9;GYuO_4J#wv{+ckuFibj&6_?(Iop|XW!ert*HH~Wf +zRm`r+?g7hi@I1y;Oi~fNzDs1hDLWt+v7a*umyYblj#Vt{{m;{JX$Nnu6?ER)j_*wy +z+^lpK@P9YuCJMwhh*_g$m^7?8jpD@!1O7n}TQKm7LvdFA))5eM`G<68zr`CZtz`#$ +z*Y=s38p!CS%3=>*8Cl3>@V<+d;$7rBRt9bx4RwTHTBZ+QQ8cW7`E}IP$P69|8X8*Y +z02wtV4ptX?3>V%>lPagpnFP2x`!MT~7_CKSq!HmX^Q(y6h5+N@=m5+fElM!wrc68xMCu-zV_*xJ!`-r+NnhubcnJ1Bo12}XjNyRp-Jf+^Zx4~9AW?NQnk7q0PtGlVtM*7~S_KrY# +zV8LuFWK~Nh2|hNy8^@#TwBm7!f{ey@+rhgCI+f~KcblfpL`=q(f^eq>x&YzNZV;0y +zGrzj&d-?_zQ8)vt#WQh&5cip?bCpJ9@T-qD3xyQIWTE +zl@1S*UdDjnF%igrmZ_AXEBW}x46ZZ2g1T}d?+{OV1W`BIrkd7#AK52@EuM})C5cU) +z#JxwlLj7i|LLHTsGe;XbG>6_990W8#N5d2bsOMq=-n8tKg>pUQ!;1=Cxrzo{-`EVE +zfqw@kbIG$Fbo8oT!7iy#4Jg#KW9Q9XzWR`B&IC-dHY~0Z99i1(L#8zQBCLC;MoL!XK +zAB$%RJUI8BQB9sYuJ6^3`9?2gzaEne7mFs=+tR#wkHXWFIYBHSnNmKm}D8;otvhrGCEHn`Yb_oyXQ=DG^3O5Mn7RT>b3Uc#Q%mW*2|B*gi% +zP6`JTMo&|YV^Fkg5!?Xb8_?pZFck=ZxUYywW=P&w7eHU=geidvBZ$2vF9J>n%AsX2=x57Mw_Y0Fx_v8qZAp-iXf= +znweK5s*4@IEOxsq{g_LSrGPXMFoU`5n2iO-go61c#44%V0qDhOm&o-Ac;Z?1ycwpL +zl*9G#&h`xZ;L|&D+3{gFEu&YOK(d@6C+Et +zku?_GvS}((A^uyqyKO?TKaY>tL>fdoC0#cXq18lJPhwl6L}*!0wHtdua`}tm-*_bj +zP8}Ioq<&D|7l#h(?u>>fB`osSQ6w31d-IY`!C|5c(CL5MICTDX +zju8l8St_5us2JotHKSmNQx>PKkYFl}Kr?cBKj_n4Pt^>LntD{{> +zr2nqlSWlXBEICUe;Q=acp@`yj;UFJZ(k{sLg_r(bs;!l +zN4xqO*ZWcC(1tsBnp#ypVhmI4BVFyp`rC&KW|y3cxzA_56>1wSXU6VSVMq@pH~Tss +z`9M9kVLNy}kpD9#AFa@AcN=D8hXgThw_5j`sDa +zNc~wU8rxvS{9cVg6ZtxUQxSa2=mBrpoCTzA5&4V1-1?nW0XK7SPz48{Jr|TTGR1!n +z+DUZ7kI$U`DS4xGP1pOn?9HT0lUI6P{;GJ{4N0lxNGeqOa#a--7YI%Kt1Fy%bs$I) +z8U8T_$TEdO?#vy*p%6NL;?tK6&6vhDRZ&2*6Xv8T=JXt+F%nMfkjq*cK&R#sY_d=Q +z!SE>D%J+8SOVPw~W7_O03lv-3;;f*6?CflVe}HHK+U?2&6A#YuNZ*8mT;yu(c0Fl-&`vk!mXerC0GEZE+&pP +zH=vhN{6bl6#q<%6hfE`x?+cq=%l;%7K7x|Al#r8qk2VS>YN9Zb>QGksl1<#@oD8N1 +zf~9w)XZF6!hqKiMapd+$SH~dS*E#)NyS)LS72;qE^#%OSZ1c`Pd*myAGt|*~if)+B +z6kEO=e&5$u*WT7?D5O4EU}hmyq+K(Tf55GiD4%Ckv3_OIB#$-2oTT5vcv63Zt(eFB +zT?vDXjo*iBAC6WtVJ}bQWNvI1nWlTi=FrF<-wlaOK=A15@LBB8t8%Lwy<-C|jz}^b +zYPn==op=GiJoSub-uWRpQO6cT%j!NA`RZRVi6#$ev3yoTC7dX*@Q_|=Zc5}WhAxq6 +z^7g&GpZ}}_nO~u39sJ?gjx*PtM`Oz&{e`A$(KG6r@VusS(;CZ-WdYmG&KJThFx*vT +zP&UA>apLvVMl@Jt_^l+S$G{@bVnRn-FtjvLScSAlJ+nmH3Llj(vNm_s_hWP+aZCC% +zU7QmCc@4f=w9~E1xh1UGV4;L_N%XD7GC^4IWl9E`+iT}5r8awp4=x`Pckm`FhX`fH&=(*O)0Rl%>E3&6r7Q&tnzP3w +z*k-}ULC~(E*l<8?-tVT`Z>45=NXXF!SQ_b-o!;`e$cj +zV>;M1Vq(J@_Q7q{g$Y0xcyg#v0EDQc4 +z(bu0VOez|TG@Nejr9gY#pirS3iPzm-pM^IUg8^I)@Fxe=`@=H=#3>9ThB(#Us +zTj7LCAdfnG%fPdezyQjIM?G$MoM$+WEQhSRNwm{#-}>EzJCC%=1~_e1O1?#oyWaCN +zQTg2yAOXxhH-@axgj95mh%AiHIreKMB>hdSPGm&*W%&Ow@p{w+{)b)7!tnP9c+^HPb +zGwB-S=jZEB^`)pv2zkK$cZ7exq3aC+6+mF#9@j9bYu>-wSArNF;kVDKYv}p8V!u9M +zrqXX<7*fQ{cf>fcsz`{+m@;UHh=}nqK{Zt!6-ngd3nSb=lF#UZ!69Ue%>nBgh3%T1 +z?OL7Xuz&~=+i2}H=OAx;XQ76+1~=z#f8`%T1n`l4ab3;7OHKzwOEf{VGk16E>_30%S&(b`)_I)50%IKm5CPqZA3omSjMuvJLGD=k1WdKcl` +zas7}=KHh_KAJ-P{_Gm~Pi;i%LRHk^7cu9Cem&W(pe$V34SZHD!qgyoJ*i_YMezx>v +zWMp9dN@e{>>EL7DKhb3a!!SV#3kDd!1^g(iKlA)d1Hb14ss;dac}}Cozhij`Fh2?c +zr0AalKH}8(0zcn?qyYfHp&u~34?DRrS%+wm;ai*u+d0?v_B+047rh0TX?ahr4NEpZ +z*cb+?6q(dZQw!-QG{YEuIL(C`r4h!b{3A4V%19vzu)FMJPdy57^>J=$MX-E8CegEO +z9U=2?$=&1mg6XEgA?ZM=1B-L|4bEemTzkqn$1Pk5S9|&!Pl7 +z$XGqgC$^OF4EE3xvSIcdvSA}VcMr!2ujcroJL?t?MQ)u`+z)l_YAgaiI52U`-j>H? +zg2H00DICVKyQh&vw@6j+2nX>ERe2n}lWPNGlEZ`IT>&w7kueiROr+ZPn5Cs&bhLaw +zQ+yAF7^)%I2+j +zC6kMrp*t3ZtQ<53k3Zl>fc-3`v$E@ZUqZF)jU>IZ+&%^S_#@j;jJB(ldJe&fd%(E% +zrosxkbY=57JC)wc@E=$pe0WyIF1{r!p%AkCqr$&``Hj>yb2(!c7+j;x*XUY8;ZV@p +z>Z$JRPtF@tiMalo+_4;Xl-Eh;mgQ)^uWuo_uF?uuh8{C){q0(7us;?wcGry~Oqsjt +z;N9V=A9$MJ_aW&e4#7Q+;xcAAk4chwpy?!I_VaPqm(Q@>*k4gx34>E}U_K%jaIw;n +z*#~$^OQ)_%C{vUI8?~wZZ<1{b6o+$cl+00jZdy~|E +zPOkFVN`ME+61qAvhxadosk4)enC3@GcblwiG5Mkfeg+{CH*Kf~-bX>#mYSeC0`5fb +zTX}dW5aTTRPn7}%Dbt=q=aNEw%dvCQhEIz3&9^?Cvl{KA8I^6!dd=mz5!-u<(U$R$ +z+Gtanp5>#w6&R@{n1xuh3W5Uxd84W`eP#g|~iR)DO=%hyGAeudPPLl4(I;}u8pA{%e+EHos#mb5^ +z0xJ{oHCU;#n21`NzBQrkjkvxw=^cB+3j=zZua5k+Q)_8cDzS#f0*Vf{DSReFaxP9? +z(}M|A{M9c^ZN|z3sY=3!GziiLW2K@e!$V*ZHw(pZ_bnyrAtC_E +z(&&E3`#;skGs4Hh`S%z`#+&5Tj1g+~ejSw%YSWpQ6bmMz|>6=J1#28GrjdVn1~Lzh?S(@HGOP2-HXAN`5c&YN02?=DW&7+Gi8RPJP*=e +z`u6DBe0<96sY>5m-LDcorLIjDysRuq1vL8JUMpys+5d*l<|;CbOHb~oln&s)lGMWE +zt@2hI%3@<8ZqIPm+f{4!ia*m<4m%pEx|xK0M$=~%O9AO_>sH|J0YX9Z&bItRN2`@| +zcYfvU@QMVAdb{BRnFYJ1VIpV55qDii;fSZ!uEFMtS`g!KWE*(W(vpNhd;J(`EaGw8 +z;o;!D}M=nTSM(-gy(-FHo+lRGMXTfB1FKJ}UtjFn22kOXYXuKA$ +z82scyaHqivajPwhbqnJ5IXc@zed&zwZyr +z8a^cOQe^amAr;x>acwlK|K+X%cgy}sd7)c|t%XFDP19~yQx{mC3L-vz2)YH2XI=7o +z1(ApZuEmg#>l>l|+fczwM)nO=BK63y;_nwpy6ziR8@l=j@14{9t27@;5{PoQoCK>vFf&1OaNM7tXF(1r +z{>g7<&N!K#Lb$iU_2Y*h$F{9Qbki-)5X5lUE2)L18AJ)52YySy6J!*mNw`%y +zV{&sZSaEgljABERK(gC!nTIV{jq=_uxABOK#>}yiN9!;pa17)nhM&fJ5iohKP{07YEW`s<@D41%+eB5;SdECLI%nVCWQPxJFFe=G9HxGYBs$Q^XFmv +z-9T&`#@XuwBH7H$?Kj7-!{e=_c$7|E>Ige%Uct?Ti#zj>Ea|2rwoh%5(BE?V9Laar +zTsgNVGlnN;*HUH^r(%LL-7=RV84)JxE8KRZ;oQXAL|YA>pk)OK{;b?s0&do{WplEA +z|F7ifnIeDb*hC#-bYMI)WmfYGpvRNOJOs_Z?hE+T(#x&N=_ebbYXrFsl_hPnGuR=7 +zF}WKH4FmQ*hW5qzIhuh1mnV;c%;9!9$-Hb4*?a-FkL{wvRS{quG-RS#WS&}v=|1CP +zeS4%4QJhU=O=z0k(UHqhp5c(xqy^71dDwlZqv +zv(@ac8Cg@7cVH>W*q{P*ceT8L2bokKUbxtGPKgB53RUkK(h#aR_tpmp9p2t*%D53w` +zPVwhpo!5#;{;;ImL^{;tul#mLv$?5MS^~60mxo)L12W@{t|+IG*{<9iiB_6`4!J(N +z8%#aRXPp*v+-wi|Kqu;?BT4J4P&oYRnYQfV&4KuPb#MB#H78%oO<$fJsDXr&&$iNk +zuOGW?$_{#u72<;46OZJsD!(M`PmHW;ZAQ9m`1Z1A#3irEGRAY7A#pCQg!#w@Hdc2Z +zK?v=Y8rE6M6ivVdvhqy5MY@AST85iEq2HLlZ#>YND$W!(gh@FIYv9``?|09*N69udS6w6h3g>Ihw;OQtJvtVm*z3ImTRT_J4^xF=!uba1~aE* +zBv5v};V>rukI>?29d5N#cVmQL;x{0I(vX7H)c}4uL3Njk9W59!p6^+>LVu0Jww6@? +zcbX=iUHs)c;fvyL_C^{x?uB^$eqU-tR0sVBvd2NWwNa;ozLhs;9qRfZdcz!vZP(7> +zQFHd^f@xM#4l1FoN({8R6Oo3sMAGeX$TmJ3=J(1mNCPw^N(D4?6jbuO9?`=9e*2p4VPz +z6bxVbSUKXCS$;}#ikh$zqYj6PpBUVK@%;)gAnaofU?x82uJYWG>B4zZ+EmnSi25}2 +z&A>f)LS%!Np^BsJ4VliE6}e2o6Noe~{N(K8Ny(NXWGTN&9ly|4g8KNN12wJqLK>890@e1OBZJIG +zE;$kv3-*ERkQpS}l(Lk0B&|(#U%L2KzAX)|w0~c_I&DLJ?XG|7aKN2Fw^0Cg-5uVGb8wlW;1#7kF)>&d@HXbwy!#hLvgxjv0 +z%pkr&&fwBo&_s79=Kdsd7Um!eIa2*~ojqb_Pwz2{hRCTpvudoe%8bfJlp;JDo3-<` +zMYg13p8)Kvo1qw2V=R6C07(swhUo +zE@hc%%lH=0QRe0=+50T+r|?luRlp|`@w>WI`{pt#9LF&tx7)!Y)SE?pE9Gf^pFEdV +z>7cuv4jkdU^FNS?b3jho5RT9LW!dodRoL+f9QeY~`hKg7nnH8cK%gmv+}pw-VLW~; +z5UATgjCv&LVIqDiixr-Zotm6FxES;xjaC&4#9fejWZof|e$eCDT^;`GM;Oe_H;Hwh*&Y$gDzSAX|*_FgsbBN2DM>sI2_f!X;Kd50RARJ+;NO +zG8gxQlHP%X=-Ov{yA|a(Y%JtG@MbDoT8{!E<1An2=;PN^87kv(5J(;*GUucOhithL +zxtM@)hqSE!gR*$+iTzZJ9!WC}L)`ArfRg;%{kx!!g2_hwPi@O`EnBtJp6ekhYxJvk +z26KCd;Rq7l8`1}!F!>}{7D5Bb$wopCX0dvaTUcJG2I_X8z%soQ8gbtPJ_Gwf6JsaU +z-z8q6nMK6%7>g!=%sa0fnl@ooH1AsQQ+SECo3yx3%qx!gSP9=u0#Z+oBv^vEa*Waf +zS}sH@ZLByJg+c1U%zb2?f|LaI*)k_tt9L!JYY`y+^>Y!1c1cj6ueSLMzjIlroa8~@ +zYa2Dq5+d)c52OR5+b~9PmU>$`}0aq1Q~J3-U))S#?zqSzb#8KP|6oL +zkmQPC*t0mYfVchE;1S$2@U9eCI0kcAnd&rn%Q);0II+S}yusS#s!##qG$RsMLA?+T+%aU4Z`VVe-x=LmiCXmc4@)SB|pxs-oDB@cj>j75H>$xEniQlU#HD}>U +zOwYGT6v;{xaekD3cF0~|pBwwPwcVqLZBh>dBkFB68L}rx32AA2m3*R? +z$JGEM@i1S2H3TO=a+dET{)}^h%V`EvFPD3^Vo!IrB?tv{Mfu|0x_)PRDViLM?@kA) +zf}`&XLOY6c +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 +zS`^@Fu3X3!p&uR!I|=OHgie6WY0!zTN& +zTP=ky;iZn!fz*O5JEW;mH!fT-$gZ%&2^FT})k6wQETvF!i+CRG6tFfm>lozy=ZVjv +zN@iOOQ19bkJJoUkZrqD`3^x>zj=@LSM`a@atraWvZPOEOeFM6#3v{oQkvX9Tbs +zJx$t$Yb~+?%HRXqK-%{*qaI>MrXEKih!xa-IQXGZRE-fPv;Wkm_RHrfVYV+<4t)p| +zwXJ4*tto^iU8<*)w!*co5HroD5U4Bwf@BS4Dv#Ap&!+sNtgGOIBU!&&_NOv_&fKX! +zEuRb6!7D&vi%Z7`GYY@lj3=@Akz@a)P1UW}`Zv8K3^c4QAV>UTOvQyiC-FU{QUpPl +z5v8t7N*~u+rv53N3{;jhRzApXz#T++7Cr)ZoIF(oa}3d1X$2FnDHvwS2`YkdcJV<% +zDp`xX*LnVqs@LSFOG`GaY62bVW$k6ZX9}-*pbMJ0*Dbwj{=3TRM)KKrE4=*7BGu(h +zj;=In3E119P*ScP(1219%b1?~Ub&RQFt++c5VgISP{>8>_kG>4{g`wYS42$AVEVL- +zZC5SJ1Ban;LX8DFkf!YyayT@L7@Q2Oodr4Qt1khB`}N=0-55hhsaYfnJVp+>i68|$?btb%)e0Mc^PPh~w%TC%Xo$&i +zSc_NXl|dH}2Jp%$v-vB)2`GUL5EeA14X=1zuQL3&&HQ+Oq;Q;sO*ffqNrf)#p~l9z +z%Z)P{!^sjh(YC@a4&Q9(3_?U9aFtV0HxVtdLvCPk<`)RJy>)(aoE(Bds*=qJt7G@s +zZd)a!f@@BXcM6)u9Ir_oyMgWHcm=cDTT>H9v5-H04h~F~-UoRyxKnKC`KeV9@7(ua +zV;Q|{4rEyvI{QGtN5~sNaU&=nK0@Jb<|@T;99%iIv~SP!J&gxVi}eT(O_D+n2wKSRTp_wOS9qbGv$S;4E1{we`mDk$Z8}^( +zaN~9r_U8k+uNw`(kHET$pll*RkWbM^vwW{dq$0IQDQ1}8eE +zC;DZVm4mj#f5XROLrSM>G~yarXzt^&N;`-Z0tyc_pk6g_u`NIqeq~w@g<2qBmVCt091kO}<`Z +z$gB%b`x<-dXOsqyR5_gg&3k};DdgvV;uV8JTkA0OuYdYuwC~@?qq0rKt6++jUH$n2 +z59le4cppbZC-Je`Y^-<6wyOmFap{0^pa_(;w+4gvZVeQDq4~VcE>Ba;1L3uRc8?zH +zFrL%v6E}M=SWK_-IOT~6I5mb6uavp_rGI=GbAEG5mz`OS8Lj-(EWy>qfogL76St!d +zew9n`X(&cRn=0%CbPnzHD%2HLRdxp91=MnX{?1=>1KOn?+~R7Lp62M|*f6fhiWzoB +zk&=Y%VhC_c!%^ARB4Zl(?;G?OMy)UiW%Vs-B_ZNKB=^=2?~H;HBgq*C-d9K^F}R$g +zwdiSW0rB7{AdLx_J8E*+pTNaIkzx`*3UguQAHvRIOAsj8qG?sywr$(CZQIVQv~AnAZQHhOcC9yilkU;|g}5i;>`f0Cblp|h +zX&yBL?OB$`rdD!{I4m^Tm*AfuJBEc!1IPbf9L}fkFbxHc~wgZxpRK&04 +zU7q-mBL=!@e~$!V^6U62w8Z+GWsgNM52-1i9IIY|hsGs00*w>sAQ_KtbuzlIP$NBBQc)3x1WZYqu`rqhI*gd)+tKj9lzX=pN{Q#}3j +z(3N~vCFmU${TbYMb5Z +z%$NKpbadb)Q>I|hdAQ8?Eoqb5(YijpCx1e9Z4n3ljQWoMA@w8wEk_Qq3zvdzVzjrj +zA5QprcNCa79A)ba9#7ht-S6-TU0PbIS%f=oh1*I2?w5n-w#)l2^3)FoLBkDSOY_qI +z0fg*M6CHvC<@Np2TH~>4#(%$8g06u8w8SOJk&#i0S{a59^-YIF)Dw=cQOWvxHFmh& +z{yJi<2Bfu|v?0yuAJa^YL+J@gfHR-1{9&Ay{ocShO6`*OF=IKv`P$8Ecy~rO8_LI` +z8Gtt8kgbR5EmuJDcmVy^Z@a}iddJntBdN#K-ewNVu&(4#r$(I~*ah +zbjB7UkKRx62Bmf9-{t=yC-+L-3S`UzgUmB`9ML|9kA4D4-)9Y3kiR^lw1X{e#`Z>J +zd3)Z-bmu0r&}Vpq9hApBx7yQKh<2-9j77h4Bx3W~=P-I_&g}tRZ~0YKh;(72C42-d +z;ales6lxJ&^Ff1rXyA^+eMbfks^kXpxT(^|hcN*m$a>zDMDnbJ$N=CLQVsJr9DMEE57H6~s=N=EfNwtv^ +z3nUPA%-j7+Y4A+J!=odnGQ1ZY<1>>UnsC^cm{E5EL!kON(!FhUhV}=&3hx6qx +z#oR&dvzlu*=x+7$MAXO(Jlak4I$gGK#!B`k2gytBU8jqhl~?-^ze64^)|`Wq?lHQ5-Zp32)MMx~lq+C78BIUPDzPH;Qr- +zI;MDT?06?5WA@Pm<6H|^e5qiCJr#cN9k?up-jlu78Ld9dddYO3x2E`E?puhbc8kgR +zfXMb=3LDX7>|Lul5NW5$9AMBq=?rCxaX93v|J)lMTzwf$VmXtsw4WSqm2aQEL5#fA0?z}5hTf!1^{=AkFVW+KQ>GzCj5`GyXM7(K5^M>y^LWfkyc3+KQkv7 +zT*mOb4oXwu87-r?NtFu3Z?WvaZSQ3Kh{Nnm9sYu^#jFk}S0eF?9m|5CtQsecPj>%- +z-}d+ngYG?#s~g$m8D^B#&2K8YQR_#7H1Q{*BiPZ12^Tg|7ZL2Xnt*-ndnFf*c=H`u +zV#I}Gsc;U^sVW0Lasf&|b2DlPoW9boaI9!X!*2H(I41(rXi+68r};@sWg(ziK#cSs +zNyOwK{98tYxa0TDXs*>`e;T5JFgjy@0X?`hcK~sEz&+0hIJi;w_Rj7@HJz^FWG1!15iLq%McJmyKpF@l4Y3sp +zj=qDqvpqamcj?_q9H^s&h(l~0BvV76T*ROQ<)s|KMq>j4+44S9ljh)-u$Nr9U9&3a +z7+`V}#M|J>>fi=$8s(?Nn`Uz*|IoP+Tq_GidD$5Nr*GL4#rBzMw$d7Pe-wui215nc +zj#4ukJ12WQA^+V>rpJ790idr|TX%UlZ2I;56VgHwENG#SFub#ro_{GD-XAPEIN&O0 +ziA8Y={kZM49L?PC;a>gMn({(iGX*H8s6{1XX~CY96pjVh=IUfidk>b1p1y_jpwyQB +zvnM8`>S+calgj0+zO*-tBcEzDJ7l-(-0zA|41 +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 +z$rsenA(f+GFSYd>#{uH-urrd^iL?e;sDg(Ad +zDKkgWnW(%IJDCbQP%oyw(b|XD)+`uuoJAEm3wzR&zlcbnYd!BMUqk%ItC3IbIj#7= +zkEfd1yafkAJE_vX)I9^q2+xCq1@~~!>j3{s`dlq89gN`X{X^r8PTSND@uTU1d~z2e +z!>agKxTi-pe_24E&vVJU-I7=Fk41XYwlUJ##@Jkr)o-=Q!5cxIlV`N~<(S?ywIKCu +zJ#bwtADw!T=i84i9%5)|5Te&_6Mg>lKFON9|7kbwA-as~@C?8@-}nM}z@sqnO=WU6 +zs{8aod^$m(M1^V=1!9W*(ee2s4bXW6$dLc>?f@a1+pQJGj&Pg{Z1d)bAV@4e6RynC +zVTwMw4a&n~f@8whuHE6NAOA6{3cs=kzmvAq`h+Mq-%SkM0+vJ^NE)pJG#|IVGi-BE +zDLLJ(z!mn2Ykhi1_{^ +z%z(;?aRtg>n18;IJte2iiPSa*E7}90obPnF|NI3w%b+uVX~8|^2sS{F^&aUfaV-G$ +zK9fZzA^o&V);X?=A1kqt0W{3F>UaR6l`^&(vC}m=hHJ2$l&;scaOcNlR2@|bUHaDS +z{=H8I`A{R}^zrbZS_~?K_zFTztHhoJwy^EV9!+y#o}Hx->ZC@foL#mFnC5>BQHUO) +zvy!bG;&qMw!FWxfYAD72!R;yNQ9>(<-rY_i**E}~N4YK+YwVFw|31peB(^g&>w68K +zUfOkrig2LrC@qIG`75-R^fmYEwz!k5zZ7+knU-1cdCqP~InxdtAsUu3Hi^(lW-3}M +z8oFU%Y9ruJN-I=YT2z0Xc5QloCAIQFTc47z!`S0Y<%v_>DyNdmlXCq2ZnLxLHB*wi +zV`O1Y?^dR5uROX4%L@%k_P8Iksy&b5N@wfk&d~bf*(0|$#HGB(&z8`Bz!z{{e~0is +zqI=^sN@I@3u^Y}5SGVllB2)4-0=dfN1?5s7eaoalFr3`00Mmi%PyPY`9hPH%$9bL*(|TO+(^r6w7JLUWE>!Z1`ZPZFrVkOBc32)MIMAo7BtRT7pgQ{D>yv+ +zU?koWRda25e)c4~p#WsGMQYb_o)9Z+ROm4u=3QHU43p|^-y_WD<9EuP*zRW*;RakV +zUZ}A|OEj(Sd4|v}ouAXxrxE%{IQrO3G`1U!?dD%;NcPZ-gst9seAtofJh@vURR=l$;$e*#>y8 +zhvq~43f@}cd7+c3{=!+c)y8pkzk;TqGjE4#V4y=XSlL$fn(kh|$wz8JFA;SAf6cjPcT^?VO|rculA1Lc&b{s_XUs@wJ8~ +zEc~{FhF>>#E)e&8As<{zvto%My+Sd}M$x~F1ND)H{WpIn@WLLC{O|k?{s2%thxfmEFcN`(F&^T~)!SRG +zL=&qBvO0DT=$f3q$V-G=H#gVYgbsJI7Xs&z@hq9I`q6NI46^tLuM!&x(hc<%@|%9{ +zdsXRpLPHOyVl66>$$AdMQIjl*<_?&-noHtHhm$YOyw04=zpf{P8;}M_n6RxqHn!CW +zz(zx>0OAP841UQw&~Zo3H!Pq_>6^XIZ;67vJLN6P+$bccm|i&yvd +z+>fNC3{a(NkmBo7T44>CxPr`r>QO$U%{f;=e1!^kx2WIhpISSYfs;&>D}eK^&2}la +ziSv{qC$c~fv|?D!g>0TUKUgQ>U|Un_d_e~gJ9(Dw)al>;p?g<1%P9=1>WHw(AE}%vT&hhG7~Z+RRGlSpEO(*NQHFO-MXg4-s~CtZ{jjS~qDUg;YHx0`RRzg3 +zrU1~Sl=UTKyif{m$Y(Im%v}T8O97M-hpL#>Pvo|1oe`Y20=S_@_c~L2KH#G@61Y6c +zqikL5-X_8he5pmCv0N#f^jZWiL*;p_7t`N+F~)C-HxZ(H)SbNt`=VoEOMdmTe|Z1K +zu*&@*uEU7y%Yjb7WC10f4ep6e@7=7^xj>40Rfcuq#$pdIs{|m6g@7ry{u3Lt47cc6 +zzeovJjFB!3ZVnh7Y|Kw4q8EyB>Io +zUW1?$JUg_LCLibaS+1_3NLj%Oik2@h+Nd3L=6wT9)LqS%15cDVqgbeKTr9vUiKp4s +zKW>#q!xX$D(J%MUaWsk33;8E$NhyY<&z=*XTQ3??GZJ8%sRWKhq?@uUon}0T?c>f= +zFTI)=Bm<_h1y-7kxXXN@qoE7)D?*bRi1=jywjy#jvgTE;$9${O2GGjT{?%}|r%Bg) +zs2WhnI$~4qKRC8ZRjIR|a=Y#&cE-b9*kPytpA48}s`q#d<`eDqYO!?feeH`_rbh&JsIM1I@{j`)1NV`*%@~$(OcBtuUV2e3YmTsp7oV?DH`Ukbvc%+UvEwnBnDW +zKU+OCv1Y~I($F|OBmfXt!8LBeF09sCgpyo`o>YCrf^6hRR=#l8)zfG7GV_@MuMhVF +z8LG~Pb~%^^N8BYUYhG+%%YKv;a$#ceL?n&e{77NJ@qt3WL4>x1mwQZ)Y7@n`5zX(y +z(e35n_b+%ilB6hv& +zazxAacDhb?DQK{=aC*u!%9dod!~0qmaG9!0Y!T#TG`|2XjWM0KC#h)Aul;_(4H;Lo +zWP0^rHfkxJ3IwxKpVwVKSL^!ZaHn`^qQU$+pBiAYG3;MbuS^k%%9xW>q)w2awzj95 +ztD9v5#l!If%n}N!T4*1lPd2q|z;K;36B!;3V~NX^E$?SiLT^U{y3VACXseh<@>->n +z#<^&DAKOs|-2|6T;WE9kLyy8%-jk?hqNmQjGR)PTc6)3~E_B9QZ?iLaN{I?EZ@3Rn +zPjiS0gh)C=g(13GReCHsd6B5zdLj=c{lafQ%lETxvz5$gADHUIQ+J};b}pzOaZE-# +zZ$~Qt*^tJmASS=>kNJ+laqm-EsKZUyi-O<<>@?|alY6SG%?W(rq_C1d*Rhiv6@$V&D@R7Ul9WZpYX2*TpO9A`iOSBYS}|7Y9dER$vsJ +zwVO|z!fCq0K)>V&Wd4ex<}g=gHu8G9p^EwN4%g-F&MW_A=kC&|Ib9H|;#H!NN++b1 +zf)se=ZCECp=0<`^x~?W{TD6rK2Q{>?iFgX{5sfd8O2{uyIy^Vq^JpD+_oPb^gz|0k +za4<;O!7cCZueVv9?#zw+d2YYzI7jI*%~nmw->4;}pKT6D8s?ScB(E>EB5%-ZYE3$= +zEgMpXy{WulmN7Rdjt4eAN|bX!vH>px;kJDBM2s(+}`c- +zKR%o_oT{n`HSzNUgWlnHCB!HG5F-Ce$rTT-t((OlDU*%|73qp9cg*UR?vUYnhd)r` +zn(PxH7_5jGt>OxWD|5IQcJ{(p<*?%Tqeryl2T>w5 +zyjY;6)hgSUSqg!Ls?ZT-u^@l;tj*G^EX0b3tQ1i9KQZW)&z5he0ecQhxbd0m(>vm( +zzK4VFg8R`+=CnfD&)~P=OZ^<1P`ZiYdA%4OZo4VBXuPl&)5{qs$T8&b?++C9_igPj +z%{QMo(AVp)K*Fya#*ZD@`)|qBFAwpr8^#aP4CuzEKh1_R>bNcPUTRlVgfr+G@!c=b +z{|Ee<{(bkpAOQeCr2KDyUj|X;{{#H~dszep*oB3KL|8;wm{|ol1pgP{ci7WIU1@ct +zr?s`(raSm{MO6XBk_WIFF+vr7V2?TzLYW3=WDh=xf&dX8kkCHciU1!Aav7owgu((%FD +z{6a2;TH}Gje%;4@JfTYj7ZeA|5QI=ko#-LvPtuJnmej=Qy^v*eiPwub|6GP)Hx(5!rG)J=` +z64U(zgy?HBQ9-W*T#>M63qv40F9+&t;b9VqV82vQPq*6 +zsx$uO9oRnYh8b}N{86X&X7#g$_LYizbVVy$SGHZ6hIyL9T^_NzRP;}*FQhAl<;B1$ +znk}8lb&M5W46iVrs_HVaObiDPnec4`CJmd#&Ehtkf+ym^gR0U)Ds%-c*H2bSa(kx$ +z^w&M)%J7OT=8PD6%#{pXL&^4;0bX}{j#EpJ7nERI2f(KSJ&B9VxXhlu_BT(TeB +zN$TAXBQ#&fT2rNAt#M`3p`*d6=m4j)N((1VQxuK{$5_m(yOz1>EB}i8meS%oAT33c8_BPEHH^gSNfh&@ie&0I_~_j+C-w!lj&b$rsuV; +ze`oC_PLhxmi=c+q5{e7)d+7n^80eQ}xP>p4?Fc4Po(i2DUzXc&;?i^; +zDJ3gJ!$Vgnz5Eup3f}DZja3{UhM^6^aCrQ%Qr +z_c7}!@v|4&u%UUm^aT=6TY)u4Xs~dw7Al}h=12?TgQQpn2hT*+xRJ8dWn@vBE&CD= +zOOip(6ejn`+kvoP4CchW@O +zyyY~5uf*+*vXb(P+)dh6zr{#cuuDZGhDdS>Y&1(pY)6k%B_)j2eSS1`9+$Cdq8ecjA>yw;JQ8`CF$m*JBT{}b`RcBT#d;*Bw^g@rl#(9l6a+>2O$-v +zFyCR6mU(5lDHbOkweDOGNt$xYTy2-W!8;!ku0CL%Zp?e*?&%64tXa+*UHh)5_ofsZ +z=UvBnN*U%NCq}sBf`C4a_*I7i$C`YTk4I +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 +zVZvj0?#cN4wS>=p#&I}J_JFBrgaD76CzaKO7 +zoxXGH))L7_v?6(p_bdo+pLU^e +zx?fRL7!NeD>H!f$PA{I#VthzXoiDCe(WOX>;Gf|b<{W$L*W|2muZDhyaxskojUgtj +zkWQUr`3xQ6psk?TTm`OL3;X9jIddLe(jjT|C0XcB3IaSi9y#MGqD|;Q +z%FJQTbIoaPzN9Z8zq)XSojv=oRn93O=S0Dre#5Bt$hhiX`y25VWKmgLoJVN_1LP+C +z^R$o2iMTw2i8ZNR^r)$DV`@hk=WH9xF6-@rltwtEHtgJ001$Ck#2qZ50KLg)5;>KVar{TXPSE4(f7JYQ^0EvSP+8-G2e +zr??L%xjkrfDj~Y&f&YQ-x!7tFsk+$BW&FP8K~r(kqO;m{Hk#b%(Zg?4d78NfWn{%} +zr?n@gFV|)KB%jH2)l|4Y*#X{{gir(Qsx|@B#(OXR29&8|iX>DYCZew*7`Tq6V7X)+ +z$@LXep<$OW>w4;PV9oII!P2Vya;+hG^$lu%S-7Czw7eDPAseHsYeLdAS>NYvl;TSh +zA6DFJldcO%@%+sm(85rDf-vKQ$gMR-(`jEg;58BG+Zr#k$41_O%>LV +zGDFj&2x@<88Du~Liymk~DkBn;`*+GmzYDvHs3$5UmDucyvo~;h%;eYcwtrH9(vEx$0HCQGTP4 +zGTU7XeC31-R<39TWU%>=1gZm-t$X*7j*@LPrJ8I9<#YOb$dnFWg(cwcX=fZKZ& +zB7;wCdqLiOfi`on>y$Y_Sj@?H4@dT0iiweEp6gI=_6D|Dph?0Z+uW1eV +zg-q3jug}}daHcQS`B``wqS|MK=Slj`H_83AXp#&G5^bYE5!$H{MBfwf2ACVwn>W)u +zuJd$C7h=l{`ElNJJ6KFGz6Sad`NORCFINWBJVIdh +z2d>7`XFhonwfnuItj{SKG)M(t8&s0^*fbUj+H^f6h$KF&i`g{Yv=?Y41i;G1y(8jQ +zFDfi{q<9CPOYNG~D6|TCLfA<1(l}LdQWq5xiVsp_-F1O-OLJM|g5_ytpd~Gvn+igi +z*^XYW<_S0*uVU^=j|-w$CNyv&P+aqFY&tZK0zFsZYCE}%gAF{N*dBTK&jNk->N8Pk +z5$lDp%yB&Mk_<^@l)r(Y96+@*T`1z=-0m~m04x8d;-kl%S`!S_3>P+Je&OJJp&LK=rT6TN)rlM +zbvlozV%OYZT1%XsWk&6Zr5^;?&t;|eM-|kLE1{(q82Z-q*>MsABj!XKt-OC1#5U%4 +zjj|N(L{~T!5J5my#I>A#S4isTRtU;x>9J9WU`ArP!s3V95D%WpK>fwI5{wXPXWedt +z!3gp?<6^RYkkz6H%PQGt`Gh^`WS)`01i@hQFV;F!uQ|O^kk2gGll;e9F4z*Dw_MjA +zzwFy1)BkW&o)YXW=?ZixKV>HP18-P_>I*M4=&H3FtM*&`1yO+zvpOwhn(&bldE8!AxH|6J3B&8)XFB%UlDdwow|=aA(WyV%Z^ +zq@dCw)eN{r1AdW*m|EEEADLu^E;G0`q&G&3A_HDejrQ^G$~e>g$#>xx=oW<`Q(=Wu +zn&T{(2SEi@4!RfB_q6;C;cGR)OH5G|i9^9BP!y%oP+VgTE+eI~XC;2fWJL8OK?(0`owp$D0s +z=15Xxc?F4I+0;^(o>tw^Y4PBIQ<%k|gYV8{d%$E8TKaYJmSYko@ +zuu&r;QRAu8CAQT9UdmYNusLle&wJD0#E_V>*eF1v_5>nE6$bvGkT0iIuJqnHkEK4f +z{h{bLCKQh#f=>MCQGlh{r(Pn5B$W#?3)Hy4%3Sp7MQZ#kdThQ)O0&gK43nMrr2R3E;Gul9vxtxw&aIv{#0b9n|i3s(kL23i^)BFh_c(6A3&Sgpn25rl30!!?Vt2?BAoWB3d;n8gB`?Kq +z#FSslNYVy<7wIJSHVSXSqO3fvLOeb?GX(&Kr@v_39i+MOI-lyoq@)!3@0KK@k{e^W +zLGRyYW`*QseaI%HsJEWiL*-4ts+$?o^{9?~SMQ@zTu(~UO1{k+lxO&kO{iTQRJY^o +z4DUb8{iv_EE9a38Gp8t|&+p;gWuRwS?0gOAH +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 +z282g^Jm0<31H?V}hjz>Tn`=jD6M2*Jv^1ZM +zZ8_c9Td}9JK40$l*ss;(dWN>V^8vZdv<;oGeht^a!o^}lvmwtGuH{nnigPJd%*zkVsOe>ori+gWw~9W7xpnK>=q +zDR%iti&LKvN}R(9VLxRAEMcBD;4hI&ZTmk<*A`jpXO|s1DlQpIn(2F0NS)e5AIYA} +z)F$fo%9lt8(%6pj^+MYlwSVu6wlbFL_zWZzoIG5x%p7}V1w0w2m*9lEE??{xCxkY0 +zMascD874*y*-ThTX;Uqzu55kh6~drlUQ)gKOwJT>wF|=RW6683daNED5KayiMyn7-Fw-=i)&)zs!nuS6PEb5pHkWlhgeKh)xnT5)I)Sc9GLixoW`1)RpjT +z&^x6SEIFM%tO&_}VaFcBA#|*Y7^adqU|KTeiKooFGQ|<28V|N?81`ol^9F99efFx2 +ze5#`(d8fU?&6T~1&^-1Q6(ED+>F;>9*jzYw2Jal_nLQHae0|AGCcEo|S`v{jvP5HGW=eWU5RF9Cq3$VK$A+Phbyq%Am*z4E$s>n5QtwTJvdTP;HI +z+ENiq+a|3snXq&a&>^qD!#5C`%?p;NT(h1+W+4z#;}cE!!}jm6xs +z)tWs=I)>|ao$k`W?~*0UAl``lVMBv-{Xi@uK)ds0Ge%S7-&iO!_i-uNq)R5{&-TLc +zR|u!=+H0AoC(M!*mztiZH4R01OX#sZO?7`aYdX@}j%Qvj_Z8Obq^QQ=;1kBiRevK- +z39)+=1_A&oDl^cQt&9oE2A1?{Q5uzdjE{^O!V|ys4?Yw}SWmMHyKQzL`w_FwJwz{s=X+u*LqR`Tt$D2r-(>{k> +z&U$#c>w=x1o9tA0OU>>*xk43v8vEip>52F@Qu}48rIT%S+uwcvK}`>_JSe&z +zpN1=cCMsxnmgQ@fn<8cCD2-CXcK7QXXdo7~-d>BkN(WYVe|xD!M79{$$?54OEWK)Y +z27mF*5;A6mS`~;kCmZaGZJ-X0R!2D18||yp?MS=5EkyUWRM|B8&939}*GgdoX{0mf +zP|zyP@*$i`R*Z`kqi52AGPNr)dcuOsp +zME-n?exFgj##lfvw*uAXJ4JF6{f&UZ)>pi*%XpW(2Dv8PP*-H5|{VmZ7o!k0+{8Qzn~-M8eddD +zkOEcH!_5efJ7MYOv-kBfy=#ncU +z!Dv)38cSO<|4w?{5;*D{?Z{<&87pPHOD>tL0C(%lSf7P|U!C0e9T~G^FKR~LUZ8A( +z;Mgi`d|9P%cNXj4TAKL^ABkol9}ZM1ukSY1?VM@CU9P3))0KZ}0iSEbiW4#m2d~u` +zE%hJhM}KmKBFS3ULQJG~)iSgWzrhG`8O`L9p~$*SZr1_1CGG2_@I6U3cy$^7xn&|? +zeJ}icSS!vpMrXBD8(R{a71H@H)TbXRvd5%tNeD)Ic%i(<-8%RvAVY^ZUy8^Z(0;Np +zbvxUC?>7MBT&HGLWbhj3b;2V~L#hyG^X_F%328QD#iGx86 +zTULu&d&f)_ +zdzqCEASR6lDhofe4wo$iJt0mYZ3Jq75}*0|s4~#zVFSG=og9hX5BVsX7F{RXnQRpJ +zWZ9N{?+LG&Dfkv9vI1=Umkp;D+LY=2;+)Wyrh@#GH75O{zb`G~ut@^5ijcdzQM)S( +z+-pHI!;}L?Df?ITrJeCxCS0mJ=|)276@+{pRywM;5Ep^{W*oDPojq^xw{jm^5JkRE +z4k@Ptc_}(w56sQ08aA#xRMX_F#ynm2=~&s%ddeb>n-s*;US*IlsUZVvLDDOe#0ZGGjEb86dm*7t{i>?44gQq4s)WoSDT(P512x +zr7fK;Diuj$YqnWZAU=pT<(lipvo*6S2<$YS5Vnu0n0C6U{k+HmSzCIckHQAPgVXWn +z!sQR#-hgo>R}tB^`<}~RDpSk3X1XIE&>1Kagcm1fC>}51x?HalzT#|5YK5~W(IPRy +z)nm|nG0Hy4R7|DrBT*n*`SJ!8{_TbvGT*Ok{Gdx1P?1Ri3rk3OhCR|o&B{IwqThOB +z!sj7ZidFm9SK|_Qt<3rWTvZwF432g>o#M~v!2LsgtgUhf8$5Ue!eKs7t1hx~XD +zsZhx8W6Lq_3Ha;Og#UiD)}%XxYzeU<19ceT)O4OR`4S3#s +zAA;uE_HYH6GlZ=`z~G@b6&|TWIPe@Z0h9insu&gU)XZ3ZnxNOXR<0qsb1~P-92~^a8)Lebd3RnWy-w6!@We4BGZNjpWD`N +z%jycGm>VsJMVJm>piT>J?nA4!zMsSfP@l?0$fW&Vzji%s9{DyU!ZX!#7c({SY>wte +zRtIQ4L=&}dJe&yvI?pUn3;BOgvu`M4l`(U+Wx|Mx(b?>CNg5q$Xm7Ka#UV_)3+p~< +zix8dRv7D17l-=kPl*=Tw3Y9~xX<)9T1o**iXj4&{s!+rSaixQ%55<953wH~&o^n2W +z#Erz&?+lX(vbPV?tpq-{V1PontQJK5B`OyA!cO=Dk_T%L@?DEYhgeiNZd9-cqyxE8 +z#b7+gOZ|-sv`4E*y)~Bt;(}2%8w@08PE6*U1oW!37limrc^X^aG^S)IHfi1XtIMa+ +znpo@0F|d9PKvb}&Z)BCL5Q&?No2~NK_cxIz=7YYhNWNPH|5a7~yf*s-!%6ytoHGdx +z4=xdX&ucV3|cP3^N +zRxLlNr6-GVN>ZpR;Z3n0%>>-+sbf4NoD9PD9C7r=gk@r8Fy^gI<%_0gQYPuhKD9l2 +zNiwz@qd$I?BL|rL`$L8^905C5IlW+bb?AdZUd2_!-zoa~=V}!d_l6f?v-k+I7MHgJ +z;r60vtesCC2RzN(KP1GPS)V%_U< +zciN^z=&lq^+iO9m)Db`?XJ-(OlX`JMETH$mn?`qmcSVUmyv^21GINDfZ=tJN4Z2hl*0lpg%>h@pJdvC7`F0#-tjFm>X`$FaXKz*~s15#%)lPUW^X69Y^ +zfrbeszRk~Mm5M|ElxVnR`e3J{@{p$30*W#A;`^kax$ro!!FE +z3Zd+OWq@*{9t*}D*ypWIw?*eFVOLnLK_~6o{^x4drIlLiEH~c4dxt8xOos330k*7!+mrvow`DG}DKjf_DE0&I;`S;!zBh%RPrILGgC|xu{ +z=A;6#^H`3PAv^%D%E{8iwHkca9E~l<2rJcO!1^FVXpV`xYnL` +z`5kQnBJSP=>8~5FT;51m5rpBm1mJ}OV7gxBHt5iW$$UP`npVzF0rnd<*Fd{AvKJB`S$Lba<~JJ +zA9)oWRneQ7{ygP|u^XE}q@Rc29y$|wSe3SFM^R5JmQM$eL-l9|5jwUtd6T&f#7ldh +z-+zxx3Gqe*8mG9c9^;Sa_JYC|gn!e0WI7)SKH43gp~7DZGvCzf&H^}``i9@$q}Dw} +zSxMlg9t56~L~8zV{Y;{D5|^aO$MwfnUf?Mp-#U=-%4A#Pw`CTypws+0xmzC$$)6uw +z$1)dJ8FVGS@{{4aZ2tEO3vvie&`M-S$7y;Ih>+%tf|N>4;!AV#bbxMMG +zy^9_pz}uY@S-L)SicBWM(3kD3dNjyLAB^T=O2@4pUcd$RCm)TMJXIqBH+j~{PMwzE +z#bx}d&GmZk;_LYA!(to!K~C$uv!t!8i9EhsxQ7W(m_JVok{LY74ZY=rL!HE-oNF^j +zq&m0#M74^zES${ZX)QLV|C-EfcBeVRvs1iQV@=sWv<9a6nh+xdI+b9Plvm32$A6#_ +z0ha(Ho4tNpGM7=W)gu@{&mU1sJYsV}pfqK)K{3sXyI~AX;d@`yx0Lm%1=A-u>mY~n +zXUr6Y1>xGElUZ$TY6mMgh*x7W7|K1=Fxhj<$0n{B+)`4-w^5ej)f{&%h6_ez&lf&nI-GO6^4K+$8zO+P +z$c=P_ch_}jny%W4xI>MA5u6Eyo6z4jYxpXMFi4e~__zR>xP)Vw)loO@(`EQi)FkUQ +zi;;t(_WoZ5&v+50VsDZ6zfl-)>;289P%1lhOSlba`X%Q$Q!&qs$F{&Y#jE2`P&-zxikS +zO+cZxb;V&&GVA{3alM#6rGjNBd@dAzjsRf>V^_@+oQuhOfss|?n +z*SU?a_+x8NUY5w^xod8v#@{Umw1haPX6}kP(HuDY!Eciwc3sTNBIPSqKM@IU&KQNd +zRP*xyLhDu?`GlMHO3NIF&$o6Z;R%bX&b(}$q?=^XfkWBT{4N>k!!f6SLt;Ea(-2;s1R +zuL0UP0UF&@?gOB}eS8+UKZk{<9tl!f@9^JOni3QTp;xRT+B0{{_5)b}2qIRnEvd0n +z;fq*6j9eSKghgL0gw}-kME25ECt=R=>#%sOKoUNQ5H{Sh_)OT?66fsIWuPj#fYtW& +z`qKGAhn}nMEbOG#)3>cpVuwrV*s%ato9i}x%u+x+L)-4bAU~R`pOoy!84ntms3W9% +zm7gT#SZiv|)2)+No=Pi^D)uk`k}S@8kFA%7g<5s)2#J8vBZoJw?1n1b;g9ww<<%FA +z>PLmBnl3E3k%9O)A +zr7g)q@UwES0+_j8(OY}&82r#vkorOXFU^-KG+K%9V2j1$iOpiJwaxOQtcyQX)T`k% +z<7dG=zSM3;(m*NGPB}+sR=*RnMzmYDqco!A%zHQFJL3n{3wzO-`3cB6EvY9F8z4M# +zgb{B?wo`At0nTQ{7LkhXLWpQIzxDd3kRe|#LIO_az}~&@G&dhb80Vm2QlizdPqa%Y +zwG!41oM<~1DKMTd;#*GyXudieJ;@_h?WrmKAB8_YaQU~0e18;oP-$BtiG6zWmD*Fu +zV{WNA`ePqNWb$OZW`NxoZ<;nRd``4ryTO9PwO +zm;b`NZkfHXG)hJ83fiSmxl(VN-+FAc9x%JfUM^JCw(9>i?I!ylxi2^$YIp7sTGgue +zMtIhUCfFBK-HfXViV^;hi8sP<8OL*)9{5}?E7y)7)+O$%J`>Qt&dBc;4Q*^%Ht*JT +z{T2&YgDTnS@Yc-fiF>qB(F(ik`6B|p@h6VAR9PEttjiz1Q%XEGe_q8aqP7rk5C-Ai +zd%@p*($O&3qJOvQ?igN}yD~fH_q2Wa#rv8Kj2jNd+_oO1R8jwQ8hzeA=aQhI(qg#iCHDaVtpob`^4}MJ8~x%}&h1JOe(PPMpJBfaO8A(s +zEDq=(RwoicgIQf~CdSHSlC9;0;_a_`^xg@-W3XvSD^2Tz7*#Riu=wgm9`X(N=49{`pMsSkI023+;gN9cXTgm(hd`Z9Z{TejjfG?yOu*?t^e$)s?$^leoU +zj?pVxG?;fUYzkBC*>BW+eFb)s6_IR$p2L!j!ASSQ(ODvQnYpf!GK1o&=U6lD|6nM{ +zFv2+lVz!?9gDu<&bHdht7OVf8$r{n#8wDZsv$p%0bc&!)HdxGpl>`St!R#n-Ny2Z~ +z3Ux!1CXdA+!vl69fEYJ;m}hho6xt(|Ei8LAT~}`hez-9nQv!zvPW4?NL16@)C=37Wo?8ctfO3 +zqN^et^M~GqfG=#nFq(I=I0AItFDaIAs*OmOvPza)~Kdx +zYHvFExZk;7F!jU+iR4=X6+D4pcf69sxoV^M{P%FK=LHj^WW@=F0qc)j8(Pz{;`9E< +zIlPe-tFMw08Gq2}>sITw{o;N>Z(4XRSBGM(5c$+2q4mB}f%$qSq1 +zi!L2LCMU~r^LwX%v#ZOwwUvW@*V?V}%zLyMMVD~0*gNN4oNdC%3MZ^GZM+;kH%R)W<0LN3j<{{FFC;zKUE-=7@QHdVU_fUx| +z7juAZQ?zef33Wp7TLE&?#{_ZnOs~s3#sX~Jywh18 +zRHo3-OkUV1{X5Dg?Vf+Y%P+3PyrDka!Dqh~D&soq;nj +zS91^D_%b_Wl|0_U<>5mIOTze2D>GV|QFT*DF$z+l87L&5-Ca8K$+$3gvl-GAue%h@ +zRNeaaJ9UN4BZCxLX6NDr4&mbo@J}rQzZ-l;tFl|*Qgb!=@mfei7j@>{_*;QBZC!@} +z8C*4IpCvp0%zcuW-9_OsAo84I&Ggzau)gGq->_G0b*c{^GM-6X4D1_}h_t0f8Cs=F +zsJRyuJ=wDFd>IN2YLv+U83q0j<#`$o6>d$HaQ&kBQn1U<`^dF2DrEh^0^d)E4L#|+ +zrEr}H$Z`qK4}tlXIyw1|{wN`*LwBXedurO!3)IinVNZg`25|RSib7+SCV+>Zinc!J +zr#zSKRLF}^u)(+m8KbAYc!eYW#l069$QI0A7CE94WAdfAn4fIMPS>=72s=>GB^%T8 +z2I2`+r>{}1Qi40QMq=z?7u|Ju!qynq%sA$DJ{OIWtYC5jN;D><^(hBc#}DY9-U^icN_Xq=a( +z+YHRWYB7Ji1$G&N8xyM#{(P|vdOrFfynL>SE6vHbHWO5e1Duogw65*vf*l470t($c +z$BSOBxAfQdR;l1sXhtlMz>9@dz(QR0^(}P!B4priq1RRXiuhD32XkN|fx~**ph1*NO26imU4oPx +zQ$t%2A>dcPp~WJ +z`3zwO%f`b^43-Pw+vhFDx8-v^tsyAQKP{F?J_Yr4t{F@u5LZ9XuU@@^8gMU_a|H&?D7;BxWL +zhXw!H+5%(f!T#Y*BPwXjUsRKH1i3K_#YWMjDC+4FQqWj3bU0^r@we;btOA-pTA|9T +zO1sBlzICCm?9SM1t;AQywZY +zZc&zHfbqrf=?@QMTY0^TZa)eBX^GG4a1IR4VO=N&ptAqOnvcw5+96_u6!0wDMk9At +zQBH67X=>io3|ST5v-J`Es`=j2yc)4LTt={A(e~O6zgIL3o;!O7Uyl^y^f4#M4>%I+ +zZb6EVS>W;nun2kjG=mZrC;#D#mAi`}_Th1p=z>G`ricid+EOGu>ug4-xX2=5ObGbkYcndsPF=NSc6x07!Nh#ByA7=0R64E&2Q0w2o +zUK-l#J~8oZa6*5P=O&c3;d*XvkX@?V%zt6L_~TgMo7t@uq;5Xo9(Qk+y*75r)7P=% +z%jS#JZ3jpi54Po=k%@y4t=;l&(}P?*IRz8E8u<0)4*zwAqIZz8b_o1wCFofGHnI`P +zn=|^!7=Xz#G}Z3#H6W&}+byQAW1v|X-CC!`(#1)725p>kZ`-3oR$C0S@REs?iW3a^ +z(B4b@wYDW#sg+=yc+t^b`>-i1+G}yifK#=Ih_1}k0_2*_TvsW`4kCR~08l>v +zy2HlVVhgZ%{x3Ira&V&+7AqfrIQ8$Mb{dc +zV+}Vuek*mkZJqKX`|*ZeBKzt{hhRbfijn$tkUy-YWlF#h&{6&ClYDSH*j>U#j=nn +zww+Z*dwm(n&P^mE8+1_YvSls;=qEyXJ#_*Z@oMk!Q7~I%!B%4v;*9IN;d^fIfxxL( +zLgH6CRG5};*7Qo|8SJS>Z6;+|&0d?aYz +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 +z@L|ytsTD#}kBgt~0;v +z1j=5sdZjNbtYteC*lV~=1ruoTT`r5&Hc53B<0cAiJ?5y&zSxQO6_M%9>(VZHy(Duh +zTnHnL)Rq=LU$ulU7xQ+Ptz(*HKAkb^qmwf~1w*WMcm&wcmE{qB&6hUqtW8Z(kQPC8 +zGgF*AeP&}ZnW^p(eP%XV2ZPE%Qo^L|fm+48UW@Hmb`?Gk1*@sKb(VVrg0fHFTxQwn +zqSkf%rq(N=P@lA3cQ#V{oiP&}Qg>M)wPC&R4~&t-o4nENxuki0IO``Xcu)mDHeb&V +zB)z)1R*grtRBN^ZuKyNHMYTW+&U0Cs$&m|6R+%*RP*;%cQYZ605?W=mwU{EFi-=Xn +zs6RHf4n!4-oDtyzPi_(co1kLQf@sstEpX{CORk|8{oMveY0pX!M0e8%nyNxo&Ty4? +zTMFV{)~JQY^;2Ec5jFQR+riKQpFZw1t|*ZXHqq%aE~r@^qFpPx#;|fejO|-EKe*jZ +zHfuPrdfIMv+^(I*d^iQ*6F#vKMn=aSjD|7ON|LOfw2qa-ntaQH2amK^#-K^1D@X3k +zI%w8tpt%3Dr=VZ4wXGO-gTl5RZ8la@-|AKF5SU;7ukUlRGiT?=kE7CSP+vg}p3(r~ +z5^OM-#h~tzgo0Q6I|&5o-px}(kxcAn1hdj7SN65;^2I`YJ!ytYbQNV+8VG-#cTr=d!k&9nCReXZs105DGt#zg%O#C3E|Z%EJ?~s-O;FHz~erG{vWskzo8JO +zZZs|g65$jp{*R8dXOO|ch@#Lo`Hs`_!qTfl)1kn^GsiKU^6qps>H40NjQk=nFfmjy +zF+`+19sHJmVtNM@(nezyM@DYk`S +zsd2X6E0DzX6CX6sTpyJI8P@;qBWa&Sn83YbaYAFt$;3Mr9OQN3&SIhX1?h##G?Vq= +z4&LppSC&LHFtkC*y=JpHpB_o?CXik=6%`! +z2a(I#$`EUMe-fn){-mu(S3f5#hqEORgu|6}FW0?9>x-%9S!f;!ZgT&r6`|KAw`Vt_ +zrh%&)6f*E}8HF8UJL5V*2M*(b>dFDCmj64@OZBDULg=OMl1~**q_1suuqJlR6-n!b +zH~=kb5-V{&8#O%8QFB>;Z}*?6s-#SInbv=lNp$W;_8lb_`Eyl7^_D83jPQY&260*z +z^AZvNUgtd+eY(=V%J^nrEtm}Jc~`m)ODm@!#I$P}1bllo+{nj3?eH?-itwpjkxOq6 +zAomgWFGcexh^m8iHc%%yv}1w8bPMHnsN*HdDk4Z+mv_D1_t_c=6 +z9m~wIK%~ppF`(w|p%t)hzgCHrY|rz}l#gtazonsi!d}spHQBXtM;B*QT%Dl$#L6G4 +z3qNO-Alm^A22LHi?j0YYT*Bo+;d>!Wx>AX&wmaN)7RPs(44g)blioiF)VT7|#`D#^ +zla7HUe8`-iQXyCCt(mE)4t1S_+a^UQ!&l}UlaL0H%)?p`ha0=3emI;H{HsLz9^ +z8Q{f|p0_c(ohGxh$h|4NlN(6Bl=+g!55tK0 +zW`dasMyQ0T$q=@L3BKn!({DTr8G%a>Ol*or*vRu!I^d^8p||=lNtLQGOQn}NKZgPj +z`TFqNIqcds<6-S$WtUc1n2Ad}2vBSzT5rOM%u09*E)s(kq^ckXN=XFXI*<84eBI{1 +zWnY-4S&qgT(a7F~vOexy#!otmXx+c|KbowPm=g~c7$YcJr?+9LkFfjNTPEL>OFjY5 +zWk?heWBb@!)qFx(i4&PK=AzQ_{!4r1vGukeix7KVp_fj0#$(r7Mo|P=u72s59xUVE +zSNb-SCHOR&1)^2++yFGWKF|^mo@*xB@{t%aPb&6!3U+IrSG|L5?{gX^T~%zLJ5aPL +z=00|fW<{!JD0nWKy$|olf`T71{L){e7UvWb6(8FsjR4ywVTzLqjj;We{h&sKO19{UgM;$ +z>W8?&Sw`Sl)sEk3K;!W`;mNa@K?@Aw)BjQ&f{Uw0gS}&`_*e8bRZ%NMBs%mPgA&2? +z@zF@aYj?&P6~UyTFt1-tcXQFw`9Ox%-xu@_6eX9N1X9Oe+0Z&OyIWR5pPS;N0&9Y{ +zukx9Q$Tg+x#OSsCqP=T~*mASrnYEm{wh$b)gEwuR@=K(WI|{Fbk;$dI$cbXAeHjl| +z{D@LGYA18tIkk4GP480Ew6tVD-qg^Yc+04WF}qZj%7Wcw!1>#X?$BKm$0N_VeZ?=d +zb|(o&uV6FC{_}V#lq#rXhgEKI*URN}%>FMGsL^d>eS14YWWw~3J9rLH#QxCz!^?|P +zUN!$KvErINS?cKAGN!9%T3X(LCrSN!`h3%maeHNxvqs-Aa>CaHv&&CslcveJ=pU9X +zM!THDYHN}4xEQ!_r|o)s;I9%ajbd0|S`|bFPUml~{SWIHXSRLM=9CZ_&6YNzZYvuP +zPu{Wu{TKOl|9IH@h9OpAwfRdFL+^nn9r`!prj=(XhtBV}D34(D#94AVNE)B6Ot-hQ +z{>6Ytlq_QnKtMfS6(3i=709tIq%)vv?u`A7EqH!b1zQ5YCPcWjmW*hrpI{EPp?QL7L7@GdoYg+ +zt{#$WQcwz=#j}lCjDE_zFG3{zT$G0QldnkxFaSC`m$^K0Gi|&D8p;EZ^7wuH*F4LO +z(tW^z?JzT=9qH3DRZ`iQ7ysgov_JS>rC~|lg1IEt<#h7ge?~3tQ-#>=0zKSy0tR{R +z?qc}nsJCcRoh4usQhH_K980xTwDBQN^izhT`^=6PGJ|{fxp9_*qUVSQJt-*~qm+&L +z&-YjJTQpUCQ|m1EEy%5NQie6Th+J}cP?rjDGfDGnHRTW+G1y|y(*bh_hAA$ko;H0kPyH@z<7Sh*j$1U7H-Rezppwy6d|_1W%ed>H8LhcoYS`=6Coza9gtD +zTH5wH)F=aCH^RiYr=cT#37oU;N(R^G8^YxQfQhi@q6G>DdTY4}dD|uS{bv0TzsJlI +z_J)ot-=Cm`8ak)?pv;xL;G^vhz1jnezIg-1_nGER*#IxsBN +zecN1Du%nQEr>T@zG^4Zp)QdjBmw&^xJL{al)E|#O+xBe|S!VWObMD!(OWYXoc=if{ +z%PBc!Xk;@QyU&mXr-G)oF+*3;;)G>Sv#FCiY{?Iu +zpE6ge{U61j^v-c16gPCj<34{(f*JWkadzBV)pu2Hgu#PpH#yjY+-2cr=&r820yzkl +z&@3#}!>5^Smh&$T#lH1qMqHxZ&DtlBvrsfg67(c6;rzs(d$oxDaKyfnp%BKp +zhYQ>2;CC6#t640r7bmlg&;d7m^2<;&L?HE7B!sn5)iw|PRCJo~*hzo3by-kQ04t-d +zs^{qoaKKqE*QCrXQH0W`)S~qxe_BCgZq&(aYRSaN63VXR+-l1BkbKlXb{Dxs+YfKD +zx83!gvNPlR)zNK~`<0AU?BBucf%p`<`iD7W4RhTN?}Cv<|HZUBdk&R#+X4&2hW-6nJY +zAbm0K{LJ9rvxhpj43GOZmt8iqiE0QMvzM(vfLtje$+7ZZeV;oBozsh6XbSX*olowe +z?=7K}rL*8vCCdkFDJ2OzIE!&29qy_h>h3kzTM#!R%~}u;2LQXUcFaH9gx;91X0JyT`*UPs<)M2f(A~w2cn1R +zltt=#)>rxSJa_(#M*c^qXw5IT^jg`W1?(asn`L6Hj!MqA*ZyIW>+qv&U}~y=J?{kB +zD2JE(!0~Lzb7U3OnFs-ZcW3_@T`tb4?3O;l!K=vVrufRC+Q#&E2bX*sq%o6w7&n57 +z1a*F6c0MG)u$^mds}K7W%{gt$8z}z$WiLGs;m=6$-YeTmp6^*=-SAL7#c1QgyW3 +zgpb?1+#(*&{V2IpGqAjG_vcrmKr+zviJx6%%W7(tx_r#D-vH7$2?dSSLnZ4YRVkJ=?@!BLL4YvLZ3x>8GPwv|OZNYblLNbC+^3gh|ggJj`Ij)2xBQFa6i~XI81o>U97?AnUZ7WPF}P#jv2aQDxK~sYk5hrHp&#j{IC7l9ywf^ +zs;~#Pp}X_gUpShK@2nc1AEhOt@0BO*&&G1`$}n>%6MSt5F}ed(^Xt_(kAV6sJ<|@8 +zv$_+-7M|wS0SeBP^gI*0@mSSPhdb4|9_JeMOsw7B;=jOtpOXM4*EwMnYe7Dg2a7V>I?T`)Gyq`C4w%^{7WBsKc>&{`C;mHMCX9{-OwN}OGUgNc<>h(nl7jFnSZ=zqg| +zwB)>~YtNwG%TUv+Mad+RjO^eO1bI6mj_im80);9UBUMW}SVUpEhaVyg?9gjCP;GMl +z^!9cC_Gc%1JI(Iqre`LJvW@r +zw0CN?PZZn#6O8~wj(Y@O@9^dS^r6?i&OYYxs~jq&B`>__^36U@kfrrSk82|BW7>Ph +zzp$E6-305@(b?4__u|Fxz+&G*#+Fh8rhBSa=o*#sudgNHxMMIM!P+ZW+V?~^COqjy +z)EY4`)D~BFl`z*ofY^MOkzqMu?X}F_SGIk0K<+@-{Mf%g5r0FcfA{PyKGbLQf8ooS +zX3tB1Olbi%SZ-UbCDb|#0v0RDd*ty@3r{P3FKJkvcK*{p=*szjgxTLub28D=2E|!^ +zgmfKF?R= +z*iYlQ?8lVJ7M4}1ez!qrRc2IoZRlb#FXg!xDt>=IzM(wcq0KYSlAUf8NnLlI+e#^O +zeeWiVRmq${wc4FmLFO8-S+?*Vj0;{d-%UAYMB$X+thsrt$atv>7+s+fsdp2;ygM%J +zr?=`IY%}^zFJ3T#>iZ({L^po)HX{#8DuarOn$kAlI#00zgaSpEGD1AsRINkvW#R=8 +z8{<4HfG*zs>iWFa#<;)bXqx|I1=L0fPLaemSc8J@Hz`&;4=y&{XwP$H&$_RVrL1KZ +zz4_*%;7r@>W;Z$S!qBTX`-c9V-mRwV7=*vo*+!_#pk#Hz++DK`GfoB~u>-YGYI`(7 +z6oV8M70!Iy=xNCZ-G1FgrZKEQv+pi)DjaMf`EQOI%|eja8>!%e&trIBI0wGQjt68p +zM{VVnA-@2Wuaw8X(v7f+65D%L=>~J%=-6m>+kMx{3UXZ$?wzaIzRi% +z5oNN42ng}`9ZmLbzeeS_A-pBo-s@VoV2k4=uA5PWsGMYGq9rO7KC_)LUgrnZld;tE +z-JQ(^M)pJ;$^|tcb+6gjaPZC%3S_jI=o9-$j#erFaYNuJ|8CoFU^~HiF5wHzJ(OCz +zeM^js)i`Rt$!*w4-9kN_8dJaR_+Z@Pe$^)M&Jh(^yxCOwv8{wZTJW9(l9c<7^^cKWE3+A*)vulB +zvbah=%2N|$9cB@vTi8Akr3&i2Vs6Z5ZYI~d2X|8_YS2Wg!=PkaFnVaKCmD)&5UzA? +zgI`@wx7AY8GM5HB`3ve7xI{K-UvEs<0^hnu5uw}Wk>xw_`f>BX6_9?j9SG0 +zOp%c-z=Ec}$~X$GaF8Bc{bEGcn`}E-c4r^dxDIcs)XRqBKX8^b%;3K?4JE5i@xLV5 +zRg#?H2Z&tRb6c=_NVV?32sJp>O#)s{gD-7BkU99gd>BjWRLcL(yn)o?M3oI?Ds79O +zu|D!%Na@KUK{zaRuiT9<&HTdp`;Q3WP0zE1yg!%H{H4@C*!DCU!p!M( +zUZnCj7!JzZdf!ns)TKEjQ8>ssN@|^_a(k<`>U;(DYp47&zM12CExj~US4DNw;Dk%J +zUmrDyb0+v&$iGb(_b0V0X|_hIDx4H3;v=s_U6G=4`t`c8^nbAl{lSjDX| +zzny+FZ*6uc9p0z^Ueu?IOOby&Nm@8~pAqXmA(G7&<1FCw&KL3Tj|)q!h!`xELI^Lp +zTJqxcCf7TtiD(lqRhVG`f2Rh>dLG~4j^Y+Rn%ZYrE|==7!q71DB0>!)VQU#v61=$r +zl)lDJq2oQMPlu^3QQz2-s{|rR=#4Aj+AX%WSj*6odT^lL`z38&|M5UZoS8W$SC(!m +zXz&%lYYKqD2*Z!7O5IuQ#GwWjxSYkebOA*_Gb;#2EO7R}zxz&-ybL&Vpyd^M($;8m +z${&33U%2*U)p!&vkVljMyRiD0rXdbypsX>pIK)LaS12%|KFf7A6s_;?kU_0Kf%9rL +zA1n(5k8iaU#t3gbg?&E7rjaKTd!wjHj0l)gd+jOc8wO{~X=drGfKK_dW-a47m +zwIYo+elCp-sWVUs&%c0Ez=L#fw5mt4V-Ni$vN&#y9b^k0pkK5F+&9oa7))trcfnk1 +zoy&ixl|hCAuNLwZbWHovI# +zH-o-z!`i+JqOhq5-`BDz(UJq)oS0MmSO!D3(`cLvK6~E10}wGIy7dVs>yc_l23<{g +z03~%zDuaQ+arpZ~UKPp)XxV_ep1=#084cp@dsZDw5G>x__27O8$gIk`S))%#Ymg=6 +zqF#A9{nA55rF%M?OOWI_hRo~VVx<4fe=y_{zaaSi0k0_ZjabHisBrf88Sd2!JWuA! +z8IuUuAS33ba&qMzi4m9de(Sm&;G929vZD$%pu-k7_xm>a7AU?t$O21$tRJCjnYwF4 +zDV`tbAs}&q)X3R?2MZ;S+R}%zrOhZJjQK1L8vkAJe$jJ4(gv{bnMZCXNzVke#Sw^# +zOZ(bhu<|L94xAT`27$Yox0|!zt8bfwy)RpCubpN>u5i0Ikr_^=&=z61f<-?1QT&u# +z2zzjb8@*g@BN}z)p+z$5H+_F15aW<}L0v|K`agl@dhNSfI7FLp)Yxt_MJPHLAU7CD?S1;1@>`y&b=-8pluW)MJbtENud8j +zc*|I>5n_LqwCa32L3M{hvCjUwUPp8l`Mb$zSEpr~`kdUl3%QRYJPT#j%23o%PD7HR~Gxyj6@`?Arqm}YDC*2crj&1X4 +z$6jnChcg0>3i>odTl@ikoAvlN`$~_qd$4XN^pQViaGf|rm?{!GQ*Afxjd05Wnt`bf +zygd@&ylV>62kr|Z>!_db+QvS`P7|Km3b!Vn79hbQMuf5?$mEg1N!uRm5~V#xiC#7~ +zIp$#_SjcCtv^_5i$Hgh$bt!x7u10k}!o)5`Ia^_^hjgR%T9L#0C83JsdMFEZhe>;} +zb3Vim2wEinRTI8KJSB~Il1jI4beyYtGMjw~;cmTJ1hMWFWF+ +zc(DGIg7|j3Ho@6EdcSMpyl(6|1@U-~f&cdgGz|DT>0GTw2~jkCm62Gt@<_SzVkfM~ +z&=R@&j(1h4f3qC_f@Q^M^5Ug<&Zw)D%iZk?8(B~Cl`Q{HEtBs@8OEdUik4*`_if^4 +z5d}Sjr+x_L +zjEmN>-jPJ5tDtBw4FG5#M0Ut#jtn+Xt8si@sq6O&iO;&1pM%C`a1P})BaKxZY>T@q +zLK><(Kp$gChd{OGS!$CQTpgf=7oe&poQ!s?WlLWHie2L +zpM+k_@jG~~X2C-^)|Jl68U=23BUA=RGA<$jZnTu-0H>rX`6O4*+CPepC`+2!m2gOq +zR^4BE?LvbywDg#Kks>$|lft86L<@MUqm$cMSD15~f}^V}{jFjuh(#5w`Of7P_f5Tl +zuEE^`5@o@sdsY@vrtvtkqhS>5kx(j8(dV9r2_+^2`aO*6y#-Fjw$;8m8TVuWfx{&! +zm*pdrO!P+QB)<%5}M8S1QrhaxwRhMOz +z`WLMM*piWBf^Z!x=O)G2?P_{L3V&RYrIwp>c$$;iQD@}9t{7U$n_z5-IexIm^0BNP +z7Bpm*sBwD?ZAQMAGE(}a=v~;OEsk@D_t$uSX!AYC8y@DQ?xQ(X2M19buRpsJ*e$TO +zNs1@_=*nrvh{*la-1JcI;fU*?`-`Y9jVc&WO08=|r5o6^LI@*TnI-g;#U(b*&)0kn +zmDl0pG|DU5Pd&4LUTq#r6x9`xmt$ENDmHx^<07SNw-<$2otcn~ghc4_I@_?uvo^<~ +zr(AlCxi}Hv2R-qyC+J8&GK`ONx#hNP1QT<9US*1Qx@yy2mB^Bfidkj8yyw@oX*__Y +z;sgEVJ;L=C;rBIsThWCM>Noq7vlDDq`1#I(Fv+H@$A;gkVy&jyl9H>}nTL?}kHO?K +zrpQ<4lBw(ZbD~bW=**1jOO%M@B^3kC-1Kf&V2bZZ(@0aIia +zf01ekAVga?{E(Rr%W#A3Hy +zyz;g1hjXF$B$`Vgu#(IgrA~0s-T`Ff;ax2#_HVnLC&(AIvudKf60wBQyVu5p@3XJ* +ztClo@PZi)|aMPM0b6UMMc_DoARiMcd<=rTU(a*A1p;&3KyV9c4W+JM22EoiAl7XU6 +zpSp{vmyuO0+YJS!L2%mBL@sq>4!bJ-6(-feqpo1&@gw77guKdON8(JWKr@AMcJZs! +zjPY&$*)_;5dd4!_5*S^zoxMm4+Czq0V{-iKR_&AJLxrHziT9$$6}kAnOyNw*A$s%Y +zIbgPqMhB5GD>GXjz)e-s3{1KlTyrNB_kQEbCwE8oe(k2n_hxo$OVdkIx2h>{(6u$**c1x=`?hDtL8AK!Q +zM4sFwOTz^msAKKwdb?)cImFb_a?@l@HbD9tLKz;< +zA?OhiA$-(rH=Fn^wv|!Mb9{VGyh%`eS@ZS16&@QwKUFe9sPyjXeJMy6D2${Da(5Ai +zu_ph?HRUzc+y!s_p!)fgu;;A&+B(aAu8m`G*_AtjgNz;C(#Nx`UYnm+4p!M{cC`D`ZyWjr!s9@QU-{+ea4};R8kei&7l}1h +z=?%G4g8C}&9NO|sEjGp%*a7)m5#e*K+jyICgnAnf_>n%~jwpc{o4+b4>L#utOMZ*X +zxDeDYv#a#iZg=*}tBdFcM-IqB!%&+q` +zhNb3e2#?eety@PA*J1XnwdR}9B8pu7KeI8sR;DomPj|C(|4BW>w^(4?MMCDkb)Wqzc^r{=8Q%|odXjUGNX +za%B$Bj;@_RqhK==iRqNCZMiVGVmKr#;_5ufx|!cRS&~T{zP*DC&y5>R{1p$YuR^vP +zy!*h}3w6ptQ=f+KGK1$}dE4)w>4)1!V~|&)!piKvi&wp>m&)dvaDkdL|5Z +zEP)$zpzOlmsA$D%*t;b0*qyNBYwK$@)3mb((>u>vS*`-#<|cIeJPX<2Ep;+L(zvdh +zczWdX2RUJ20|O;EBmO41f;p6kz!Tc;%Zo02z!L&{VSc$^J2-@-eQcZ=-BU>Qd(yhX +zv0!4Qp4wumwWQBp(SlSLO7`6jg$Lcu!&YO6n5H(Mt5askcPMIVo=-X=B;wB%(uRp{(-wNSYn><_% +zP+!h>o2)~2l&M{T7>sGSY=}T^j7fca$$Jv1h4~JUxK+MW`Mntag+;&(qkrIYG%#`Y90jatdvhq`05)7;>ZSjP{yR^w9EqaJESqm~r=vlpEexLL#F(X_ +zz|%S*6s>KOWeup}MEiGB2?W-_FnDxx;!bIJW=Ajq-lg%EPu*F(?V+IzUAZeVM>=sQif*Yp3856eLl$HXp=ioQgVuZ +zm$Mh`2_uqQo0W(pnoeRu$I8ufGh<}S5m@W3+LTbZi87u`%>e43-nbzFI>pJ=llTo1 +z`4M3dOKL|cT^MEe&hnC{%5qm0SLJEu?d-kwH846xRR04``@Y{P*4D_|L|#D9e~m=+ +zM*`-Z?puY>MfVf*ZMWQ4F}{)H%k2%#HHQn +z3OaTg^8#nPKW19wSioXm72V)ZW@R0>d*6_kSO@Mn#>c}-yM8_a_1lSvPMr<^Z6 +zTvN?z-az6M5$~5Jv(VQ=(8uDu9pPG9hA-LLxrP73ldaW&l$mcmohx{r)Zz3TL^B*> +zKH9!fi5FEut8en``&J-#S&oQq(u1k6(1qg+$vL(G=C#9BQ;?d&CJm3%4DQ*(jbdn_ +zw(z;8_|ak}?H34T#$#}5EpsLx-|x0k~O~oZ`P$>}Co$Or!O^H@vP` +z-i3S8nQ}Q>C>HyhxT?$R+MbGD)11Fm(=0Du< +z+}{#iPaa^mD+t?U4;mLgkwa{iKvi0lB?$hE&*Yrqe?w`YVRg1QKGe=T?F+$W(J;Z& +zzgM4~Dgy|TJNw^nB4GMH)~`gX&r%yg&#q>WJXxR?L6hj=uFg~#d?eT|Ge43VtODBM +zj|ETL+WK|Wt7KDz?M8vcla$9W#Iby5vj*ID+!1vocouvda>w&ok1QCD!JIYd4jpv- +za*j0*`!i5rrl;kIa|NGqGw$V~OV(f4mxAe$rxrpE#r~#a^M}5oGAfwwDJgQ$5A3U@ +zq4o%>I3aFnDku&set54I>gBYfA(k1FL|6we8jBGCM}TAfL2Qx`(7B6h<#!MkRjD(cxbsTCE(_gH7XsccPxf5#}s9tlDQ%pe=wC6s! +z3?ynG#`1WY=Xi;mMX^WJ_(@NlCY18s{v&G7p&10Si}n)OK)MRh9}A`W=84nNn`~WJ +z8is9y2EdGr;8mMaQvd2Ao*&Eu&LP6Pt%i%%unIs3lWIci@y4*(^VRiasEs_Do*|F3 +zqN(n(%R6YsKjz9#16OlOsC+NcewshA*!&eMsS9#=2HIAhlIeC<1~y&eJPSa3U1G>L +zRAgzis?i=cNr5$T1JBrQV;4UL?8|`E4_^l`JYp}I=jtJNyYkJ>m|YtLSBb}b-+W}W +zQ~EO+sU@0*6NiDg+8POjq-WBsXe)Cg&h&w*j_=8B8C}sC^>c!2|d2* +z>CW?) +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 +zNGkaxdON&Hn{+hFFw2khK#!ux(f +zX4Z790)O~}O8-4llai=H6{zA~kNT0o)%CI1j_K70^(dX@;*<1o7KlPOY*b6%z&6a_ +zyH9%IVM@h2uZa4r&Z9a1D9W)lJGPDNkN=@h0scLs9rvC7lU_D|UHAB_xA53)qX2{* +zHSMc4d+_&e6F2rRKOU +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 +zA^#9H(~GPT<@J?n=G;da_%tu$xd?tJe+*r +zZhY9I+BbjD9ToF{TWv?K{>_Dnp%!GibqA6f9*pS!rq1Jf{YsUTJD_`lt4%&C;ul#| +zz%yv*FzfXhqOR^BFAMoBr)T&R%;FVJzmcB+l~`LfkWP>>R1|w<(eOz~shHqOAldMj +z?>kzTDF6trX^;Iw6Bd#TeJ5*2g$YDDCT~4#>Ax{%7$(AaiD1w`kcRzzML=bySSxbF +zKKi263vHx>z)6fyK2Gg?L0{m_;IZ{-fvp=+lfvt3VPG7oh#vP9;b +zi*%tkS>L1oq0n8YcdGQ{ybup$D5!&gVn?l5z2gc-LNdj%Z4kaY_9i#m+Ns( +zkE?fifj)vzMz-+2Vab)n3Gya@d|cp~yb}CO2$b{9!?0kg{%s=AI+FN&7$j0(n=Xi@ +zWg%My$1Q1Exe@T3%cZ|m>JJ5EA8msIt`M?#J&LV8OkuDRfu0As%{R1l*6|H~}_Vkk@Q*%J;;`D8?I~ +zw18!0$n$MhYn%Vw>kE6CHU9qqc0h^0QFOLlo@~y{@^X?vBUK^&vO;dZt5msKg99w} +z)W^-2Lqs=3ote81N;Jx6#;oOySQD#6kZd*=GO~Gp_(-!snr>fRI$~nudPK3u`Ps=F +zAzzO;^^YxhNn=HbZkAIjtmu^j{G6`roKgd4@AXb0Z?m5N&7`5a=qtYA-|jRVPZH!i +z`jJ}Lp6dc-8}U9|G*9J-vMNT9$4WjPwz@E$rCWG4wF$gi=8dw~ASN}}o?`IKF1EYt +zsaLbn=h5r2y&0or(!ppV2vWUW5POZx9I?hUX`#mf4tOS>x??0XZa?l_f!ySa8}1(S +z3a}-X;%J9&h#iAh4HEDUt(uMMGw_zuBlb1U +z+|)vBq-LQ&C~!W-c;l<7RPuOo)Sf-sT?&VeXEUp9L+?xExH3YI;;o+^nVSGD7XRud +zj+LRSOEKn(T0~Y3IljBhJEpXqFd;FjW24J*PEaxWN!2P#QZ#%+hBH$?8P7knDZVZX +zG(U@4DlyyM_C4NY62!2SB>2YjGRQ-FPkb=Wb2Xu1)fgp4PEH|?=4g~lwS>bjj_b-c +zxHQ69ywYInpjTCL9UVfhdjSUJ{svSscs>KAPbgp~-W13%w@AOt88y1G_dqu9NlV;I +z_P^b)G-;7ai{o!n;;#5exYQCoF7m%j+>5u7Nl +zOTC~sekrq}J)I_$>!n=k2ctkZ{+x@DtL^g7XTCi7BmVb={kkKDxW|nZJlwezE2DR<2!BS;!3Ra|wazD2 +z{+2}!zTvVt$wlSn(JWx(c5hlaqny(Dbm$Rk7w*+27F!-`!VRl19FoH*6i<3}SuDQh +z`K~`dI&U$%m;D#qCVdbO!q3@QmkNHjY|_M(L8^k_}X}Q~MQnT6(%~>?a +z^V&S`S`IR?2z%n4^U8*{g405#!bH?fT%jWTxBipuyPQyttw>PC57QE*bgK4Ov0A+u~Y83ZYm?md`AW&aHIndr5~ccR6+|E +z%scl#?G=I(;LH-X$`LUt(W~+f4HWm`)CCGV87dDiiW!xHpUH$sl-KR9K6Ey9fAEDV +zHp&far**fh>}sg***re&@xAR>n4u$W%lx(w8<@-ZX-Dc|8XwLt^!$bQ?c24woJdbQ +z^$|Fety>?az8?zEU+qKgmWg!Br|``h-m-gtee(Sq=w-o2tJV*3z+i)*;|K@z-q)P +z=CCNSkcY4iab|h!R3la}&&3~#XXcQ@a?^GK6voL73YofQ?x_4Kf~CJTE2_KGR`&*J +zCRALvO-~ivRY{(pANA=+*3q@mf*ONUPCE%>KWrMm8w`cwKm +zB(PgP$qge}S6f|B5H+OfUK2&?6@ +zZ*wBD?8_%0sLz?cVr%HuSvQfIr3psiQli-vXSxAjq|`2a(ADPZRop+!h0vR;x6bJ9 +zf0{cG@X5_af(n@>_x0uOH`T-8I!g?<_z%h#brQ6fnt$GO%uHJR&D##`SpN&!^Mo>< +z--N(TT>9EE23k}W^lU^%1)IG}%T!Y;TO=_FwBaorc|oDbVeMdJyy;o*(^&Y1n_4b& +zYY+RFI1wiITbb)ydzKmdXQ*MIeF~%-|k!r +zuTHHp!b51P%lo7e3GZTDOegT7D7OBvtwhQ^)72SZ#eVI=8Wlh!IqKbk~%^ZhVPt$+HdS<_2)2t#JnrAz7Rk@4wA4-D7ahkM^>*ISE +zc8d~7L-e)^!yTXBDJi_BdjRhr;s&b7Mt1?nz;02axe_Df_SRp%6R$^sKW(}!3FiRo +z2c=8$+OT8yyS@Ju*KbI5WXmAX_xlur308^4Ob1}PztPn`B&4)Q$Rnfh{r +zgjZY$8`cKpL;Rs|8s~hH>wz}^V%_G%p!Et<3?9ge86I*@$E6_WlNp4D4v<>;B&ntH +zS+L8s4^g^~wfD#${H!JUpnhM&wYZ5NZJD-3fCd;gY>j +z8@fx8J*Sor9P1wpSYHZ~o;7*#b+Kk{DWx0Cj5u8w%}Nb(E&nKy{^%4b_>7M7u^7Hs +zTNs8HcY$vOi)=B=@7A}gLr9;N%NOj6l}^tuA84pvzY;Hd%8IY*2)>AxLjZHrr2_O` +z0wQok)KnuR=~=r+i{&+$FUgt)&KB6kI7l;%8aoNIcPF8jABbBwT7xj)amIn{=yBMO +z-n%^VC=tys@^LnmHnXo}ZEr-3rgv(D(*M1=*g){)GN@{7L3`qBggAYr@&1{n2k}>` +z?4N8U@^hh|*-iW`(f$TBBk3<6rn-n~@dZ1KzfJ!7tJXSc$*y~}TD-0Y3+nSWEz0kH +zVstBSf$|E|vT_4aJJwf~&E;70zu23F;mAK&sTD@53#3~DbIyoeZ&>$Q+L-MrHaG7` +z{$aKe!mQN5wFANw3JdEpGo_rbM)N459Vo70oQ@%1_vSYC)qXq$< +z1j4#s2VkBO#Gz8SsRfY3Hi~ERGC9QLnhe=TypzJUIZ4e-Z}@uGiq~ym-2t2qL0_Bp +zqIBjY+vF>bHZ#bTq{GM@_^>mEWDy=*aBQDFup;$aH~&S2)tQXOMkFw=X(SX+vr^4J +zWYouI!ixSf8i1k&4scb|2c3Ow&VBAzN8WvrD9Z6SL{JVZBHVaPYT6t27!@iAVGvYt +z%8MXc+*5&fEU_ronxtR`a8u8Eac;MZm9}lvITAEahwRyN$<9%)zjJ=(8zYEkc2i#) +zV`>TNsW_vG!Q%uM|IHFUCo4x!?d4h8TAj^^g23ewjItgmw&hVmnRxz-dPK6`w5*aW%q_VS;3&m2W?y--uTtP$(>* +zWM|5Y(9kq+A{Km0=R$!kId*Go0ULc~l-!7Njq3N7ECI5j*wopZXrnGwDR?GnS1`B|Gm&xE)j-D=8(p%dOP`vh!n!b3vN0yTEKZ!w{?KdYlu0k&XTvOJEs|fxN!nq +zny{&#ieA%|uRmsTfW!VBR&6%>DoMapCdHY$)B%qJqykA`EcikGHn{n{r_b2Hw3-Ldw +zY;qb3XXh6U#N&)E%e^uy42^g +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 +z)=WP7tx)~8Uj$aG)) +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 +zX +zAP!{=c(ls+GtiZR`c#boECKOBa|3aUE~hy@bASETg`}&SE(J-R8WPZhM`xi=pn! +zV|Ut?tJl4hcDm2EUJD+)?Ot#6C)rA)_HSKG2-2%ILWJoGqY0Fk;YXwwiqt-W=E~R>>44J~a2MvrCSg7rVejYQ@ +z2xbU`eTWsjr!=92VgAY~|81{VN6)MmVVgagV8z{g8p4CLk^{b_0b@9R5{BNTa{Tuv +zQc>BSzaD%{RbK-hft-sTj=P*gjs +zdhLMT=b@)=FK2j4&_`1=my!dz36C#AqqW>UX@_;f!ZI|wuQ0fOyL1^DD9bcjFKM0c +zxjd{f+bQ*Iv6ghUE^IVz%Gw%bEER$4mxItn4Xl%cG&P`W>g_sZmL5LeZ!Xn&bz8vY +zQ0T+7qU3U^>@cNl41}(~uRa~VmNyq%I;NHd^G`x}GtoTo~2Y+4wZb+C8 +z)@>s>?%tS?a3(vBDJ%?ia9kVvnZdYb1nHZqvS@C0mi1$thy$7+aCezuVJUZB6@EL| +z>u?)1P?t5N(-f%d8P*fs)H{PG^6}UpHD43pbEpfeNx8dEA2z4l^(1YdO#9cO2>_uJ +zq@3#CiEu5krmJK`;g6ej3gqE9xXUTGi&}^>WsBvO)dfQ!M?NGTVc%d@IL+q +z)>h5-zDd4=F{tqP0;t6Hk3Q?01UjhIa>A;#df5$+bob3G!JAbg-PY-vYM|g+!|6}R +zQqmezN(Xw647p3TK?`{UP}I?{xBns}pWyd+J-{7rz*!XQ;=aP}3Q6#t6PB0)6yk^P +zB}t>;ZM)=k9O9w_;_MZSJNz(WYv@t^!Vli-t@?JVN7l}N)-&YigRqXUodm=MxX2zJ +z&Th?-q9T*qaLjhmcjs|#88|=>Py+TNUFQ{1KaB_CGkFfHlVVrCEL|!zi<**iy)a-;(&&g0W*M>6uA9X`g7@9f%(x|YWT-ITDsYTwZql31pvsxz>K-;=nv(CjI0 +z=f=I6>dffxA8cexp`6O%s4(?Y5Mbc3G~=7MDS +z;3`IM)R;yKzov6e`DNrBk2C9Z_JGn%akajbWuxBOs(nwe9Y32FP|S2^e}-iR^1g_B +ziue;Dr&Jpq7DvMk-X3|T(Cka=l%OZ+rOyL-8W3(-c2ln_gyZxp=o;X<*szYhhDrDD +z2E;)o^f3ilFLb5|VON9d9&+r~So5lM{=<52sLS*M*pfC71%COQ!k7onv<-1-3D%jZ +zOlS{wSFi@34*ZEv@pzBJ)AZr9)O?JSXOsS@xdZ1%w|;C)yhK+5ASY%}umhYS(+`-Thwyvx`#T9gtD~$_Kms9gKD54d3#q +zrWXhiRGhTXc_c`i#70*US6Y +zLH(%2rk)o>%B$H+n12r?3e+pyKN82$qMenq{Y2{(caKEqLz=Y{#AUlHUrr2jm?nFC +z8klXXuI{fn4bd-vlPN<4Lk8SYw3O)acCE`OD-VBSwEv8>cAX*UgVUN|u*F(U7UTv1 +zqCgL?8R$N@7r(O+76r`$tb2M7{5S@?Le*BIM9rt_8<10eVf&%91?NrHeZ#jg_Hv{@ +zrU5-)g8Q7JmAw3!KFfYZ!4qo1T=NBTZN@qFUsTelw36~ozUe(6lpV(50Z5zGdtZ-c +za4fbU0->|o`Imzig$P5$YWDifL5%1!QY*o)4O{}*VXsG8^=pVm2N07^EoIRx8xz>U +z9!iDWiS+S!E_@=bG3z`Lo(V2=yYusjX)SH>JmJ_?oZEd^ZGm~yb>Fm|!(G;4FS?5J +z4IDf;iM=ee6@Ljl9|-1Mzj4ld*E1w#-=t323ih>HszWdZz +zfGlI8o+4u>sA=H7>dJo&3ah-K3vt?73#8&L=aiRTr^mp>L5Z=O1y-OKKuLJqz +z_U?Ic8re?UaM`>eT0bt0u*+rp)InvuZh9ytCVDSN6SzyP3Z0hT9Os^7yA~Vi>PLUE +zfHOcv)@`8#_}kUd=T*-yIwwEBB^OA)4Hpf^g)5ZELB3fw|DQiALB5I5>8(GOe8?G> +zn8#I7>@KUQyaUcKBqt|l>7%p#66_Mw#fy9u%TgfOm{NSzmV-_EH`l#Lv)G*XBOhHc +zuzJ0ehJPwrqN&Dz(tJ#^)`>-r6)ltMV%cET4YTVbmDC36=e#Fqax}rHP*(d?d@`WC +z)-u{UYM;H?*W(5~2k3_1#tf5t&>6P%oT^B^cZ%qwlYjQey8Z{}R(d!< +z1#!MgOANk8vtkbUahsc)m+UcncI(R%QD?Vo0~x8TX`=LS5K>z40_-aiOt~Dr;L+1Q +z9ye`Hxml2-<<(-Uf-~9NzACo_Vmhr=Uan*IZ`*l@XOT +zO@o9V$<+m&NAbgdOcnPXIl#bHH@taK=PgN!=O|ol+7dO$kU@15AP&L_aF&zX?bCr> +z5p;DocqdtOj8cEYq`)7Bxs$GSuxGOI$XQu=PIt=aqxWP#yG}qqWyl1`WI1K=Pu+7c +z9{9sw`2D;nI@#CjhCT*=1Rig*;O)E-jahq4S#)rMZO+etdSCp!a{6%o@I%nvw)>Xy +zg7fBIzAU=(>k$?9(N*_H>KVqlV+F03Q45qZVnv8k5@r|Q0J$woL +z0dhly3K?^`jr{pXDruH5PDO=eW{0tkH{mFG6Y@5L^!c)%phyw2HiiL2KkLLgxo5*0 +zk_(lOrZ14nf>Ch^`| +zbWVk=BV$2wcyv6jaFB4=%)Sp;>C5zCD4%#Bvoa-}Z>4O*T>cY)@iUh5DEX(yki +zS;AA=;amFO>X&4(?l-UR`LXY(;TkGP@#pX+#5>6~Ypx%2#?ja6jp(M&HAgj{Lndrd +zn>`;`rOx3;XVg;b`J0xhpTPa{9OqE@MKw0xoa4V&frF@@figxt`rHz)U)IJ!OE$)nW4qWZwkuz)|37_WG5aW0C{qGt_} +z8zSm|i_USux@417jqS<)zEcZTvs?JtyTfE=$Drc0G&B*oH|;3md68gE#UKWNHo_@ +z2Yvp@D1Xt_i25W^XgcfAopwrEtXJD8;u(5|r8l8hrB@HYj(cjW27X;kJR+e5#v%)_&eP414LT1yrejaG=IH%xxX!z4Jjd)U +zhy%E21#O%Rh)Wv4ZoE#0kzOB{DUdgG&a{WwkvQBW-Y|nr2dq3^%w_DVqe!7n2D}*L +z=^2BM7Y{b}XnT+1onK54zlz9z@JXrrq5zx)tU-neX-`}Qe44kN0=@0G0I~^>(Fr$1 +z`xdKHt3DKci%BP1(E8_8G6rauYui<@8k+G!Ue`Q3>Q96A63dWHkXSyrR==k68F18* +zqqoDJh;q~#V}4|GC`X}3<^6t9)m06J_|+ddd!;P~McL(vX-KOP*lkU#?;3q^)wz>@ +zuf3_T3U>DUJ3<^>;E<2Nc2N~c*4PWjlFM2^QF8O|cq!@?^O4%t-OcDpt*|+}9UEX; +z!t+uO0fW9!FMSK|kol0kJ_}c;w!)i_4ZN!ZTSdc1^*7Ugl_n`!_ARWY(@9xNBh#{G5f(X;c +z`IDG-&xiq>RR+Zdj|Z!@AR`a&XaE4+i;&c^T>L!w3sW4t8)^L8911;lT7MFPVJAR$^93*_8wSdn=*X#!1vH-7)CcanoVaL)7vbe%p +zODltfi$8#7sy$cIObgHk}vGy0gC1<^i!` +z!Z2?Zte{V&U|nS_+|_zL#e3{q>6<@658s)mWS?$d1Bhj+b|03|L+)CEEq!=cR}Hvj +zJxQn)ZwkUAEjKkFV?8Y2&9|Vn7kDSHc%7iHGyW5U1mL73yT9maStzfbl=+o`?#?G2|G>{i_TP9yEumRWgGZfXj +zqzB=(X4nc3Tbtg*xfwaaMsc~>IZ!U9n&+EZv}5(`5QH0k0r>*>!fGQgY?Vw+TBjTg +zG4^x2+4}gqmV65BsPqEr6YAcKYvbqme!4uH93|y!I2W0T>JZl)WNl2{O@1C}O-23P +zSkjwD5B^uPQ%wOg&itV{3+-3^W+#ZhQ#7sjx&dr2IEGld_8#IlCT)XRS +zsdTrQ1w9zg-xTayq8IOsVLiH(EC96Tn6$T8G;6rFv`!D-8h|I>ZiAB7q=Fw`V}mu> +z1*6^2fIY|RH_{G;h~eYQ;E6|)f{hZFyr8+cxqj#1bYi_Z`k`c2*>`~ryiU3B48XhK +zS@UpxI_1f`mvsLS7A{PZ)HYU8u?h8V$My6gObD2D-YYSv|54=PnCD*U)c?@(h}Vbp +z+^6h^Q>`?#9Uy}{arCm +z-7qbdjFoakT9(ozoF$$irJdY<-;d_J=br;LuqtJucIlwTPUe2KJ>YG5&iQ^VqYb|< +z#NHnXZ2xo)fjj@4)J-;-Q=gQyxrNF5$i|6p)}4H~dHd>~1pO}aO;YO&>z-wNwEiV= +zWpYsP#V~E}9PnD}U{1&{fl_z*iqNXjZksgF#KV!0T@rKayVuPD5cTZzlgMn!pMsoa +z#4m8&-L_12cw87E&e(9W$845^(GoH3NG|sI5i5_2IzVg^V)yx9^9wl={4DJfOz9Jz0qSsWfC?KFJmnUC` +z?d)^FsUBm0*R{Yuj6f`v4JZ?!gqnI7GnZI9W{h|$`^{?WzEMo$CTF{!mZrO_YCl}( +ztDa%IQcphtAC3E4V&%GShWE3~4I8-(r!6z9RP};?J>s*cqhqAd+rHpp@5q4$ejNTz +zu!ssr5OIvAjX0{+iKdTx#ei8n*riuOz!M~!cHkEj&dSp$_$<1IbX|ScSG&E4<3bB0 +z8GZR%(Ic6Mmg^S>e%#Wi6~!6~KK0gbCto?o2gvP*LBktNpP+BISWcU;c;gX#S6(dz +zVc@hq+&FDTiZ=7XYzyIYspjMw8F-EB`07#MEf2Vd_0=PuD-lh?1s&>ehg>g**Q9~_ +zMjyZBL#vEZ#okD2qmOQANNd;Q@J)VjNv%`*`kC+;>1xfn%47*<=-SOoFxSp}VYJG# +z(3LqIjg_DH{%St~dUJR4l)JTaW-d`F0RJ?7q1L;;EM*(|4{jVEscGax-Y +z3&+5(y29ih8Lg#oNvjZfhZ}ApeA?D~?BXM=t@X~B$6ic`{&fiC{OWjL4_vI);o9_u +zI-m4X8f*Cw?JXCvb)(nO>Il(u&LpbN9pe&mk?E`i+kjgf>~3+b$)5Ti3!!qtUl!E2 +z>G4NRi`Z^Y4xlXvUX4o^m@HujY+QJ;pDB4^IGvFWD1ZT6$+HjE7pGv +zYZCY}C39aTd+g0Ud}cmd18&scODoPFS5{I)C~GNlJGh-_$JFF)oMYL%+9s{Ulz;^;&g~5Zp$%pd_m#PbU +zAGi;D42mhIqjliMwPK0NYQTsPLBf(6B*b6P37p}hfBU6~WA@Ik&d#LZVH)dPtk4f` +zqhNuiFpMNt{N3<2#)?<13zW>)8JI6oG<&knk0q2!rdpZEC?K?-7sI1*)Q^AIVzLdr +z8mPBubGyZ#Scf97)Fzl0A-N*44BaB%O@%a=7Te4#Bpx$Dg`% +zh%;-$+#czII~>Xsj`hbhs8~VU*YJ^pv3d*QhyvOcLD$V31k^`K)Gww5GNJ9d59|X +z9hBE;7w`4swhc3GY1_)9)+SXBc5%2k_5*(VC~`2ryHrG&mVnaX7b?0NT$h7!DD&OT +z^4^f}0K8|+PBkpL1M}Livm-IO=kC0nTv*p+a&tTJ+d$X>7vrq +z->t_oQ+jkN;n_=IG-otf#iJ8hViFuX*Aa8J>EI0mAOYdc&`3pGfbI+S_?Z2Agk}Xp +z?=VtKoRTcOuIGTET_MkMoZ`<+Cd|4Fhs}38o7ibpMJh(!f;9)PCwuRQH&<-KPR|XJ&GKZO^xH0?mgay5Pw(8i +zL8HkZQ8I{Dqiq80wWItaAPDWHBBYdV>y=$T2!Xwa>H3^~`$!q$4rW2m8l}Ub7^Bu1 +z_y9<@Vd6Fc>$$xkQL-5Vh_mSlDwJt8{hvddA&mHZ?tERkUBG*!`e^K!HSCF(`;&Rt +zuT1lbts4MEK)S!;gRo|d +zt=zz32YP{lU(_9<-LwB>;|wvhakBFKyLns)-wxebZG +zz2ss3Rrs4hsQ3*0Yaz>|m|I#(IXfGRm&CMgg5iZJL33X!J{oB^&}(65$2KZ!3+)hX +zW=giSYSdpE7H$~}c0lTDJ8)%Y-o*tDQ%}jLiS^PgTkc!Y;EI<76>#LfPq1Z0?6rVA +zWF{qu(2KQ69ITX^a8U8>#CwD{;dC$VDk*B>ORp`Bwl5XQ;57r{L|x|O83=RZ6DPgi +z>$$P=H!Ju9+55x=_VO{Ymds^zu-wm>i^CiF7Y+P}uX~Z_yztj;Me(j%ME5pD%URtf`f%GC2&%L2cYZ +z4Gob`xXa0B0{89tHi6fVhxgP?t^-U(cu{rdc31sO_Al#@iZ{)^sJAvd@bC$tqg2y% +zj-Xtry1HrmZaE&Qa^0_-@AiqmtOCAd)$uO?xYv1p*Icw_oskYN^YY17uN|CY^yL0Vae!Tf8xznb3^O{+5NWbc9wnop~aWMY?gy}?dSJY$q +z*Op#_JN@=1)4^b2*`&zM7`X(|b;fkp>9fas$ypCO#mP(x8z{+BcvUc^XAXDtP>Tn? +zx%ie(l1s5(5;c_p26r=oOf0SJh+&kL#j;kf!DS<@p8m~UB54jRz&;c)`h(d0$(}Nv +z>!v-i$3)T+lmkAJWC7q>+~`-63u;t}uDsY!;H +zZ1UgqsNZji2xscqQ%SYK-YKv3c2S{i(>uV$TD|Or&H7K|_-WWNhX2I>9P)Lycz$?bLzJWNbe?zyqL`SX|Sr*1%Z^y|6a8~|WWP}L1? +zd+jiRf9=lB2LN*mA~j8Ti(sj(N+o$SeRI9yt}!jq=SNav%{xZ)q@}UHbRBiN8x62S +zjJ!^6sCJAJNN8`!DP$Q_*AD5gn8BYLt=f#}VNMbjtnVFx!%Cyw2`?Op9fGa5 +zS^7Qrr3gwmT9^FjgZHxa;yFg-O_R+=yT+d_sBi3JS)w4#?P`9FWFl|y=BFhmcU}U5 +z`}_3fi27xL2aE*}68OP&p|90%l+kJ&KBh5_t+Pt4=V+t*t@^cnb8WbFVDCJ2YF{Be +z9wMS6d>Q2*RE5kCWUo)>FQ-%97gn)7TX&VDmr7OmV7e8lJ&q!7yV~)-Y=x;w7W6myLpOxD$=0vJ+lgD?2f_2YUU0 +ze97B85iD&!$*%p-BL^vbK!k-S@v#O)RQJR1T5YcT;~3ZlwgG2K$$iI=n1{HwGP8DQ +zh{5d(B>ej8kLU|i6e+qJZLyhbNoPD|?|uvT8jj!YKlC

pefi@V3C?6q70C&wN!Q +z&YI0ybhFh4lru~axBY&Lh3-iZVg#F*Lez7!;cwA0Xq=Tr2p&LbZt^l_gfn$G;`4ZE +zhmf-A=4aP^`@`XUyNwZP1vD$mKXfzF#%oh8=2b2#)-Gz+F6mY*$*W@J^E?Ic^j#nG +z{-?m-HJUy<$QIl*tP(bmpfm)qm6s7JTsFyoJjU#4{acB!CH(EPVOC`QCh5E>J@k=OfU2F#_s=#Q|M$?)iL_p)L%XCt8EIg85^ +zt*I)q*f=;OmJ0 +zw=7w=F0>D?XncztS;K1wIY-jb$#>o#%cR}*`-a|D0J^Z=Me^jGW$M(EXK&)d`|Bl0 +z=o)~~KJpg0PCsT5j@EF_3Z-T{lrB_hPgC_&n6X$~`q@>uc(w +zw@3A&V!4yn#>?CJCQ2EAUGo8Uy=YjczTg)Buk-8Ll&wGeq4uiSEXSw$%Sz8{XJAPE +z5(2Jnfae#)0kfb@eKNOZPtE#7izu7nfPxOSIx_enZO>?IOgH~#8EJo;O|?wyfIFuH +zj|Nk=Wwiv|H#ZJPJmhABIvUA^>uN$`BNOuU$q~r!?ox2W3%wWScgq!y2s;d`JAqA< +z+IT;E5*3%j+w&3H%Aa^xv_)vNa@HGr9(`8*oZG>zs>l$0or>n3;0k-pegovW;f|ez +zyS+iLjujOK+Q#>H`_4W7EvavupnWR9|0s>msJKy5-;_7YI +z4>iz|gb6Um-b)GNgGWBgW78_;Qak7sBvW9I735UL4I6lYYo45nBQ>XGDZ8pL>Ad~@ +zTO|6ev_`HCkodw0r=n48uO3{cAyZWmj*O8*bkvFc;i%B$9xa*N!2+bL5qUa?mg(>* +zesq7irzdjH$pVjewGW#!cK6lQA?q`Z8jtSk#%#|+b%#YSKC2%vTiqP%!U6jlSD&i) +z$qXFRdDL1?u4eL#9ojGQ;Sz{A&Eqmd2jA~n7uI^Y&FP5mq(kB_w$rM&!PR;!`+!mx +z4h;{lJziw=Y+#JB+Jzc)Od}a02dr8I-#vGCTc=f9hX6zCD2S8&)S9iR9@u$=Yo;BK +zYyP}_s{(iGUp!}LpF=9IE5yzD^^PMp=D`gU?RjsHe~>s}Oga#H%Pq?j+%lhsz4p$l +znXbr0n#*DPH)?HJF>&58BdfQ#bt1r^OR^?e|d}+77 +zyfK4jP6mdgtscKiS0jBZoAjOB`PA(amdqAcyy)sD6DnuZavbZ%LU02aPGy}GVjGWd +zrQ-Yb43P>JeVRkvG=~`AgdV8b^ra5lH41HIWvNwH^&oU3WoJtxoE63422B058z%Ytt07P9n5ckTafo3Y~ +z4?oEWVw^yR08~hoZM1C(bzU+PTEiKpvw+X(}|dJM;`XK4blhxjv-lb`SU +zM=foyy`2TH8VB-B_x`4`iAa@AHrtmw^~A6ZkOKDdMbZ8kYit}IdBd5 +zqaIWecNCqpw6f>pRgNEVZ}TaP(5B%0?mE`!MP#t^@l>+Km^%)I3&0|K4D8SE)wGpX +zY%M=-6D96qcQ&Q?LBZb6lV|5liVN^;?Fgf)aZe+mR1Dr~PO1!r>4f==@-8~=vavC} +z<=xw&+*QJ523vV#%AK1zxkMHE%DZ|In)lpZHdCo;!HT7li+4Shb4W>-Z?Cz__a4%W +zV*?(>oqb(RW9s3MeM7+I0vGrSWsCyvNz*KoVQum=m&h;FcT?T9b9A6?OE$8|6SLY1I*rFrKG$Ex0hYEX3q@)gga)5QX_UfKF$5ej$ed1W1 +zc0NfLMI3k}R{`rnOpEhrl;*&kY;XJHOL5#Lxd)`Wcu}fMiH2GlwANArAGIv%Bw(g1 +zy@jakHyWtLM@5I`U1MFGe%Dr8+ +zcest=v8Ck&_(8%w`D~9nykghEE-2=G*yXcSt@Cub-saTP-SDsfr<08rLM&9@l1f@7 +z7w0?Viq-&{lS?qmlVouxGdLq=XLoT)*8{ZEq(}GE+kheR9noRbDJfEBw6kf7G_)^zW(;M*n@_3(EYj}M1;;-bf=$s$qYMuNHXyn^7^ +z;yVKN{0^}|g>2T3s5DoIucz&-Z%B9@n#|&gJ@t|jHokCjhS)Fi_yOt*Ckq!~r{A4? +zu5JONZiU6z@fsWN@?HwZ^HXyU(0j;<1Mli|SQ9(6?D<0-i7B&L +z`>Ei?Xx2Yr2fZU__i=JSM&mQ~qr#(*69hF`w>-S4K2VCIu5#a3?d*Z}35RBCPN(d; +z?$pPi%3}bc7C;&Zhj2>lBAQxRvEm79>fY{#@#$9?hl1JEhGf^fy72<-kor)6zy*vP4@TV`+l&ILu@WxrH4=?qTNovDLt +zNVM7X8`onP*oV}&FwTOBs|qp34wpOWgE~r8xL4&I=TXhtRPRN>=c3M-=9_zO9I*{< +zI!HKFUj~xe4Q9S>etI!9Ha?XlwBF`Ku}F +zyg+CWOGw+=O;+bca_z!xtu +zof#9nZw29ReP^!hpD?L$;R? +z7oR|S=7XE(mQJ{$&O3u54D?QeAnFLrF*%*s>htp}qb~3#p=;a{c_h$yEcrgMEH!v< +zy*o^faC_KpQjIK{E<8oD|4KW`e4mW>nDUv-=y~#CQYpsfFgAC{gFKUGu(2#2)Gt62 +zURpXMEdwCwyM!D^H32qFrcX4q+ude!%ox4}DD33$1JC3FDdM +zmNOZ;5xxr>APgL(_3>vh+GnR|cQ14dZ#t>j^E}0zI_euj0cSE&hK0_>em>vd-}lQ- +zO)Wh=OHKYBV9r(8k_|rcCxIsywY&T>p}KGmpPfqDx~^{Sp}Dr|>)JZuBGt(Hcma%- +zAEQ)_LGSX#P^9DYP7sJHZodQ}N;S}&PM9;SDg=xOiIY*V@TbIG(UZ>RCBhna7~-M{ +zbeL_p5ld5OGTJSelxwQ4_+m}fb+$3+>GbP>x?{r){dTy;u!N{z1q2JIq~TVG&nu)A +z>~$`vdSHwmI$Uhsl07)tLQy8*Em7P9a#h8Ld_oT9< +zO)9jS0>hOQT}6Xi(OSD$j3oGIUmU@VawnUd3qs6GPAtCLm?~$Y8ArPt9m1NfuC>G+ +zRSX`dYcw=Ml+jU^j-cCYjU|d8VHfC;NRK6l!*WMJ%?_VhxXOUEG;kul +zj2tS|&>Oz@_BrS{QwWg86#RA*rifmRC`TRVL7mI|YJ3#&3Knmm2N^K=0KI1ReY#CU +zoMZz9+=(E``;mlHq&EJlLZM7-w{!G~C#}9cs36EQjlT+&h|q5W9t#gd|6ifXSh9${ +zFP2?x)WqI+)Y3QBHc{z~K-X-Fotb$1GlNcr+#Vv_tN2f)hQ=;r`&ot;eKUy +zK%aoEpxf@n@M}runmW(!z@FBXpQ2f76=U2RbMK%#rrR+iBO`oSsj2d>?Zrjk15oG8 +zsHz+0r!Tt`(|m`19aJ}x=SJC=$pUt>o*cGap +zI8}}JZ7L`OoN)QmBqSt&lai9&7s>oDT!+;fM6Nrw$KguTYu6#JXVDd3hqm4)Mr%|n +zKGC*HFn-wQ^M}uc0D(>wZI#tL1d2^@z5LD#f-P>k6mO0Q(w`X-4lnS%hCm%NUXf+c +ztq5irJ6H{#Z~obBy`|d;sQBkmV@}AhcE7m5Bh+RrBAzHDP=zZb5)sD?6=$$<-gcT_%jDjU&4}X0MDO&tY=%R<=0f4c#1cfwHbeawgH +z8h2aOAH5^Yp{VaN1T<>Q#mPAuS(Ytj?7qz<`^xGw(4NiS(9m$##m8oDc6PR%*Z4#! +z*X6|0xR1Gyf`0?@dKQ_0!($fn#wQK>ED2e7Aqhc{f}fj*J%WL3MO6#xEOD6VXvT>z +z*oY5omhpuX#0H<=QSOO4*S%&PRD6y;u_lo*L|)pgzH^%EPte#LpdU76X(`dbg+$xp +zERj(S2~9t1;F6ZpSY{dOwF>_t@JEx|(NTR%d-X4|z7=agp}yu*#WNp(Y~-jcReh~I +z8^5ZK?Zu*x#A+7Rd-N(!#qY#t|9d;<+s^d=k#N7;HH!gx4H7^<9FX23K4lmw3b7jsQr><@; +zooENw$P`^`jnwl&N}pO~e53f{17TibGoGbRd5mqyii7)+LaJVf3b-~urd^ND*8P)T +z&ug3eKz?b!F9b!veuVg8)2aHVZV*%V4D*rPfY`GBrScDt`&AHW%t`2_SW+nmV~aR= +zO3+|=j8GUt+~ByV#j*7s?r3_G+Aj0TXN*J6y8_M2x|60`0H$ba03My_gqE%L``xh` +zxcAz#bPhzpr{q)07S$B31uK}`R!~zIcDPPYG;VZ7kYRj3>Ar?da=n}`I>VO{XEKE +z`)Yt-1M(36lCYs?f;rS~k>>Vr(JaxusWsg(b+TFar>X6SE}pq{WpzLlNeU)$99Y9} +zr4<}8Pq4ttoSQmjYaG-q(Ml={EwcG-4^8(S9a{1bbzO-E;8A81`F7dfGVNbajymB_ +zoN=&ETlHGF^c%}Y&+i6j+&%R6iJd#AH5&^`e6_glNY6{XY1q%|I)R$kJ<#halt~e< +zdrRLDKI>ooP&dcL`i!RB4!l}91|VXhkAYw?HBKM+nYIH@z6__ptV0ouKu)qeX62M1jC!lw90^~~ApV5&C)B9q0xgwno7>ZSoOi4T +z{|($X*BuS`BXUVa9{!rro(N<~hV8m;wHLRS4p0sdx=8V)MY2dyzz_D@2aU|RRzB8^ +zaiDtq1yrRzmqKGU){WwSY|kOx#P2CuJtGNhxQ2dH +z9PO3Z-NWNny}AUz?@}KvZYsurJpi2=lu3BgB|`s)se+6k&L!A5bd*)%>VqV~SBs~< +z04IFh@4j=FNQzYeMTvy&mgb2}X@W4mDnyF7vH1zLzf0j*F+$=Z-aLyjCsYvxiAahq +zMn#W9j;vXSD+WIi8cjM>NPP=(k>v5h9@q +z6$WorCTyluGi6hOdz1>Y;DbU5f#AxCJTH6VR=Y8r1sg#M4A*6xH9Y!QEyZ?S(kIuz +zZ0cMbUcb{v%96H=ez0CU@nf26(t*vfxVq9g^Xjs4qOHdG6_`}rEN16CFOOW1q*Sde +zg7PLbo1D%zyC}Th5I6F2H9TUN|3DA;ks0PWw=j^XBX_<=$r5=b#1h{*;XAYanGVQ7wlAsSD +z{ft*_8!YWK1UZOr+TatiZ;>9s<#Fn4r3WErU{~j3;IrGhWY3rSwwpKJ!1c09wp|aR +ze50=(5^nE$REnXR&6$RzgW3}g9UZ*9t6~+20Y$P~1E@6dfO#|8C#q&&EFyYY)b(;s +z#%@QF13-E9Am7?8X$xvH?L|UormL$9=GGE8AD8W&*VWcY!=2I0`WD&o{Y%hH6e!t% +zQJ0xVuG#A-?$QJ6<^lIqou2QbG1mFW_)S^1lK0NV$2j|nd6mO9*LUjv0tSa0KOW2Z +z8%PVknp@3vB0yR($=yKZb)SSHrPvW0T7yZ@cvg`(y~a6n@OUMLZhv|#gdjliN#kTm +zn5-cSEd2-}?b@vyrM)?&HkduB)fr^v36@VBJG=&lAOBRLJg5@Y$T4&Dh(Y(#a!oEQ +zBKhPD#OlGF6v5dgQI~Z5wgKo^v_84@GD_u}0O?p+fS|oEBQ9lIWdc2x%vbrDN^?;% +zVCfrLEWX#zxv`L3^-Wm%1D_PXju(hG&&lB$l^g)wDAQ-j>#NP~SR-hki>p|#7rNn3 +z?dqG;9cP~NG0wec`Gb*+?1DAR-(Qz@z}?@N+kQ_X|G!jsDY4VsPTSrefRRKE^nkeP +zHecX@$6NAmsySvj^R_(xfjMVYg)TbhV{qM-$6%_Imb#SrAizTzz3fe6gsNsd7pu#x +z!@uLPU$0TqY@u|ZGIpEwC*FxuZCkjz1eND%pG%KUq0t3G;3v1XDbFuxmR@2e^0uSxPw@GLTkrH@v6kD7a9|^78MYOp?U(!JYrh +zoo*TN{oWmX&>CqK$r`rd``^*b_YD}%O|HTgv=AaAZJ$OGK0hH^uNn{Oi94i>`2>D7 +zd5b!s$}ZggsZ}?amxmw*ILz~m&b;r9t9rs_pn|RwBQ~{TFuVf@-fv7O$&1plhR_&27=N)w=6n2EUb0_bc9`wLaKAKNSqpOK| +zh}_m-T)YjzYHtrg6=LSXkme2ZCpzZF0MQO71nMgp%ZC68k0@ +z<%WAHMF;CzjPB9S8MF0zy8*J!!ol&PM@C9o*o|lTjRiU!ClKw6B<2fnM2EI$ScK)T +z6QP%R;91EnnN2REMl2I=<5)R3oIy5!++EQ5cQOJ?LWfgZ=E6s5%e%tk&gow$Rnc{Z +zkoZU>DFz(IZLbjp5mCHgY$(ZP4jX{r$D +zg!o%8?rE*H+_-gREVZ;*>-%BeTXC;^;pm9UJKj_#9No-$l`U3clg4K|@ZeqXjUQew +z0R?g%==7GE57p-!N*z5i>P>jR=dUcCbf24M>s@*xHf;2MZUJtQCrP$9RsBtF)Wn!v +zE1kg23!oKfrWWw8LA6ZP_)`C7jB^@N{y3%xGIKSi9Av7arGZMe-7`MbhASlYi&-RdDB!|lq4e4 +zfoWDO;sSL`W_+K+M`@r&vz4gsTkh +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 +zK@E!rS_-E%95ji`(*)})wY3~+X|oSWfqsu +z{9(6(AOi0$@oJLxdT=95BEw26IGHAc?qYTL&2=eMB0r0=+qxq?rN$n35GylW*6%rcz3xJ^lPv7ntqV?j5kQWb6 +zZn*;+E!BKW+M37vJJs$E(4!m9V?_7iv%)c19f7r_t#}Osvn6hU372q1j8H-ofEtRJ +zd$=7+;>8yxu)lLZISFw6@bC`5DUZ>LBooE_UDUZ185nO`{fFqjn;z>NHd$CTMbmK* +z4RDRmkUH?Z*X^CR!P8wKOxvN7Mw3l%&1$d4HB&Cx1Sz{JAy3Ba9563@XzA)}2nV(1Yn@x(S>>%&7*IK<-09#OC^Qu|?zu>JOVG>BMGjD^KSp0>~<7w0Rod0s-n3my_(}^$} +zI||=D%hb#Da`_k^NjW2<+@xk_0qioE4)G?FhT7}~iVHh%N*jtG36-bbWE1lUw`0)g +z_R^VZN#&p~2k>swMj|?!w3v1iwXSvb#GP4x07Y&(r*WzPT=bC3{dw%3*A)gZz0pMP +zqvjhkwROYo3NEf!r{rz0#4D>c=u**I$p#6Icg8W+)ANMCtZA-k0uo1d4EJJCY;8FD +zyV#k%sDA{Gj4D%Flh(%}=#$~VzpK|QfDf1#fEN~KbNkDR7r0ZGGKuv5LHWBXurjiM +zZ(kG{WeY0PnCH6BLKd9_HqXgseMLuKS*Q$xD@KqEWDb_^Txaqp{GoLwRmB+Tkkc0B +zF;ifIL~nfVQaKA9kb7lz?iza- +zuQ%c1X>qKKS#P;1_5=FJ=t;Q|_zi5dn7h0F4S~<;8Na|*owobZnM%O@L?KlNs +zxN?;IdiyGW8HR9)tm+-!=aKk8VeGUyv0{P};il?E1jic8PZ?5Y2-@*OIlfN?I?@3!zh<3c=AWnfuFhp^eULhvLE_gK5RxEvM@sG_ +z+4^(o+&5^Z_tR?hm({wr8x^iXy5iaQkL}`Ro&_*A0$gQj4r@AE2k)j9jwzJ*0B0YX +z#411zTHJG52rqQ-V00E+b~*ktpAmvL>J&DgP#j<;1a5$W4RNenO?E&F$ +z;ZGB2y+9xe4CnmM(0-9F$>%~~z-@!EIyHG`GiJTDG--&}Oz)Z7c`JH1AJn`8tS +z9Ii9Brsi*PdNGUVTosvU27-pZLKwJ7-5_pkgDCh5jW-rHJI|bJ##;!YNLW4c+WZQj +zWOh(pk(@@aT@muC*;)=mh4HXC&ts~VrDL4tCF#3h4KEN-a3)OT;ya4t$=0Fj6S^$j7LwD*-)e6cZozX0o>k?Ql4I9Kw3pyAHX(sxr_ +z@%kWaWrf9TrIxyL|32g&KD2c$x7j2ZGdhK$|Tp*vx@(9 +z2T3g=10@1xqZUZclhYN|zF?#d +zCw!NDv*t_&%o-acU|mqQ6EsdvzC|a&3f;BRLJMrMHQk9aZwu@`p+wdS3FZkj6KM<8a|hQee-so2ag%V(KXBL)@%DG4qu1inFqoyrTAk|0v+}U +zy=CV_uMRWK0rI}3t)84E^tT$`cU>EGx9UmtkNU}ky{Q=+*4>=ts$S+=Ap3gV{gEfU +zdz4NR$p5Fx98Bht`(b#_Dalvdl&`n~oJ0}1 +zVhfs#{RcCBO#3up`e`T=;_dzgUBH=AM+2j@xcc0I&LY(9coij=E!*6In>H&Z&HJhu +ze@?wbAK#UITM{p}UPzd_7!vIosnPn-kz7%L#A7=zDWz3Wp-dSyHYeO_^pH1hg7zfF +za(zcRf8FiB%iU)mY+3tp+;X%Cy@HNXH%DW8*|x_|*?9cI4GB4vk70a1Ed%#(D|%}W +z+d4Zf)(@&1QVt;tg-c*sm8{|gbpa73r0(Mr953e|Or><^d! +zb4E9<#WxZi;a$gA%W0!lo{{vl)%MF*58d4n|6cOc_eftWA4BJjX=bempw3&~VjGOC +z5Tf?#dvQwY%ey6qFDgD!oLmi+P2u$LzGtZZt*+*f<7H7hr@Mdh>fSj!jUixE#L&xr +zb-=MiUb~eos11K~$QY$2Py1AC>e0>{69g&n;{%-RzlN*)yqdOu+f*#y6j9#KC}<~8bIH?BGuK{5adV$hjYEJdwk +zyTd9$aIF|bIucGFck)bb$sti<1@?7ToJ3I)Qc1!9DzI=g>PYE&o#ko+VOizKglOG# +zu%+xx6-5SpX9_ysaK*jfJnY^))7rhKp>mts0LBG4H^#!sA>`9K3mr%te7kvpdVKWT8lL~fT4S1Pujy1H@A+oK%VN$*G +z_W{~A#WpE_=4}LZ2L&FzDet2_o(#|E4xCkX$;M5t8ekOAzy7nk-@k)PYC8VgwQFRZ +z*DL95$1E?{cI}g-k%Wr&J_5`gI4!5lx>r=${KUuOM5{KBa8K%LDf +zD4s%CIN(ewm9j=aH(f+^Aj_+2S>MT1$K +zxP{s|0IJJTBNP4HO!3JGwG+9^h|_IWdd9eKg%p=7%bnj13>481c%Z6v26)hl97{}^ +z(4y+vxy10ce7!I7Td%8YD4qiDn&WQZ7S#bmH7p-JEE+<{q5odEKCZCiY&+Uo$KQBl +zLktQ=4g8otCDviyacfbxaeKf|u-D5DZ6WxF!vHnRGU|RaePS>^&u+k+r)6fo*B~P! +zOX_(w{aZXOswzrmw>N+e6s{xWtDCmDPbnh+pibk(@<#2WR-9vW +zOJp@iUF8q@`MbeZRrvRS%Q!21BSg*J5TOu%#6T%DE0Tk3#LRi-kObl-IPt51iahQ1 +zcIpZhr9R$MUz?e=}wg7DriW3~9o|9d9SwErM{WXSyhDk!Heca43bQf@|g`?vw +z9T})oUcG8I` +z>-{DrVLxq{WGTSx1{lW{Wd3n*_I>0}eK&6!An_Wigoq5w0Oxs03Xs)q(I91{*+G$h +zkNy-qk6E=&6xq21+F*VOK*I%D{&s@W09}Ou^p7fNU=K%pnY>cyNH(=M0Qahn9G`}{ +z0Gngt(qY@$j_-(0)|7EYQw~M;rHdVPO6`7ie;uu9_}HLLkr%vfKaS1$)C%YUw*_P` +z55;&aU*D~&j6NkRi4Au#kL;1mvAhmsz`?!S;9vUv`*+L3gWA6h`D9hG4;Q>B8u=9v +zTQtfh0t)59?R9j3gL-lhMCXyxQc?h({9Uv{coQpWmin2gH4IU8z#)ip+AiCyN@uNK +zPEBy7x&V^}OF?CvEEWn57o?djo@kJVMB-|WMi_cmF8%Oy-?OQFDSz^Umk^frR(~h_ +zv18Wu@K2zCr*+_%syhem-pBe1_Nl%i2Gvd!m$}`xPsGPb*(L&?py0V^=D6~Ps@C63 +zQZigXO#AE<9qzw*dRPM#$O3#zpDu0=H4rT}Sv_}4{GhL?1IV(_qY#@p$D%rtD%@w`lf){IO(Vq6er&3bYmd +zX-tnBg1rz1AYG6lj#V3j&Y0tispV$CLCrtYaV6-LAx>cHyIasi7dWR^AtzOEn62gu +zMHU*?ayjY4!Q(c!%=L!}yO1&T3PFb;cuuHvq10F_xSf*^g$ +z==9NiT~Q~2e+!SE89q!d--7;%)K2KHdx%-UI>RFR!hG{~eWd4Uvw#<9erKS0wGWi9 +z-7LAA)l&e)CNyR0i~%3w^PDWACCFJi!t!pC21&c(K4_|M_g`gf%ok2{HLb+5iR+Q| +z(t5j>vQBWh!XH(6JEzm+g1ZA_+=Ohm&67W=ng*5gvjODp4e&H+m`+e%6}1=aeg17B +zzX=ZyH+t2q{8wX3Rh0FdgEc`?vISWQG;Nmq;L$Z5M>?)R5Ff`Qs^p~vgJ-2~6hWR6 +z79N#Lv)zgpAq3LLSH}s`Crr*9G5`5N_@Q{l{hP81CiDQIBD*P6rpVx1|5^MnXBP`L +zAS*&0hB(XGbFjEg%Dz$*h&sy>dRUP@*C5|`)NN;Q0y7_ZzdF`&w~7qTYQ;KhxF@&< +zze8^`@vUPI!8OOR<>cKY$GMnZ$PV-YrF8|J);j)I$uFYX$>q?RWwo^32WdVhRaVZ4 +zGJ8%?nAZO7ws8nAwGwj9OIX0;=WBkC(1a7($wH_Zwi~f;K9G}>n(D5m7yCcJ2fS9> +z$Q{b{WMXHXKfORpDUB?(06jp$zf-2n|E5bmDF_h?8hK%y4qF@w#@s8;;^ecTa(blV +zI7tF7DRIcCP<_&*VmV4z+HeY$ciueya94<6b1tLVG7~L}_7(^dQ;gH4MkIt;k?XR% +zO#x6uC$^lm9Uy$d!ErI_5+!v?5$~PY&br)_uaC)a03Y>Se-O>gH{|NAOWf<+g2T+F +zYMNk4hI;@CuPCYIk5dzey|{6cwo(dVs20O2<3TeB%mH%LHY-w-?%JwC^5YtdjLBhUMyvvKyc-u%4P +z01wWrf|?nKQ#&`xI&#hdcQO4Kp>}+J&jhgn%`>FF%&fevG9!v6-sx&Ky(;jN2ed-u +zBz<8*#DhzehjaHqn43RE{GMT@ +z?ErYk*@uO5gK46998dNRscWh!m=&tdNXI6r_0>~BQghsMY@!?1zS&(Mq~zFtD%CA? +zrylOE&pj0J(PnEJut~-e&U12hLpBjr10%#VfI7zZfBzQN(98JF1zTl}R}^!d;HcWd +ze8hJ%mAX?JUx-u6Onmub1cM33BK{$w!}!Pg$Qy`u>t8mpE8E$d8ZoqRyI~_Si0GdE +z+vZOMPqdRDMZnQbUTcr*@c1g$Y34a*xyvfr+Yd>;$s5YI)&A`Ux0-5vUdczmk4LgdzVWC1kx2;T!uC>FXs5~sTC0b|h94&RO_dy?=RSR1>Bp_okk4gvc6VV~ +zSLTl^K(0VN@bA=deihSWQ&%s5zK-J{QZK4Nt*vreTy@SDk;tdia5;+W<3(Wn^B8}Twov>m~0OqrC;-8jV +zGb~eQR3DY>Wvu4NP*|aZXF4C}8fj!j@7JaUz|3S-Y+x6N<_n%S*zs99fQ4eXVntzp +zOnpd#k+#~;Of9c8y)8fQ+x^#ze|L!paCn=%IeC9R`^u_DT5b9=>g`8%Jl-rAfd~B< +zfCoGVV2!7<_6(THSsh+m$n|Y8O7%7xqy02~ceSOc`Cj3;`qLwXw2+JkIpbP)>YMf| +zS5$Gtmo(7AhR!;V-Z8F`djSbpaz?M$)~+CFuN7Hi&y4JGQu1@={~b;M>YTl43xWY$ +z&IwA1Y;&m*nL34!(uN{BgGz=HVE4BnPNq;sv6AKTz%BCEs2o*ibLeW|@DrssBLk?V +z;#}bEXBT1Kj#`OS?*UXJ-JuAyr%7{@soRPVUhZ-a@5bR3e70NMdaCicRgNdbe-2Ie +z$nJMyTEG`vG{>EjQ`>tt#fCBm-S<=?r6tz1cVO+h+4Vr*1@Ge1=nC6rBH}6CZ9=st +z4yd*84cBBX51+urefs7_(p_#2t8KZ*1m5j%#h6~Zd*2!O9_$ZfmZ7KLRTK}_UGjdI +zIUh8B^#%a*sZu840e=G5R=nI`4@J9oBC%^xCMkl$;n?2~*Ax}G5RXom@SpXUkA3GI +z)EGs4<>oAq%Yr3yVgKWmVrZXR|1d`3F#gB2o*i=t?>ukCWEPJTM*hYZjeKip-&mKB +za-HVp!ZSw1NoYUp__A7xz(JjD;L +zh{!@%{PpcmGApnAl8!ujkgws#ju+i2cYrHe0ZV=Fh(nT#{hfDPtoPT)qvga4>ouR6 +z>4_BA%cA`ACL`VReL)4z_d^=FJK~@#C!s;B8oddi63L=jd_X?2IMsJ<0n8!EU1ZB( +zB_7s=#k6vChN`E{=jR#Ly)DX=rm~XwNH!+SUf^E6B*~(hM9CuE50>fK+4h;j1mPxH +zLBCm8OQw0&AUjZre8$Sn{8h_5wF=YE^OgB5L2|H6tS;RG69_hr +z61Y!|({shVaDTD?_F$-ul$+$dOGs#$q^Qh@`iY!hQqmMj|o1C7ic_z4+`eLMQ|Ooh1aciHfo9R99yJ# +z;&xy5Hd$f7^dnF(KA+K?INPcc6`tq0+!&`$Ni_0VH +zij7#B)D#q0X!IzU9V-Dz+3vGjI*cvj-co9a6o#&$%^-!t>ewz@GZ#u<+lN2%vN_a +zJfgx?aoyp%P7M+WuJzw0eO5|DUaW92LX>Rg_~A#UUOfHXbi6S6o#6$Ko(#R=-*s3- +z&q6BC= +z1YIy6ftC@7f0E{6Vy?>%!}8M8?UU2D4G!_&w%Aqgi) +z1(FH%hR=+*3 +z*P(mZyKvqpxB%S4SvUg|7W!RIe2hE$-y89Ke6L?Z-Y?GviqF`{7od$iO@HjmM;no? +zkBZ+Zzr4>Fq-QV@GOmj`{dKHA*n4dtG7!0SLA+~bMBYIsnd`m1PDwxC$D2!k9P9Mr +zBh8a<;Z(Jdw2bzwxT37ZWj%#F#JcJHApvX?)LG}5Kj^M6t@zp$VVl7Bt_?dv6I-Lr +zCoKHZd;JPePF@_=SPk;k>GOC{B4`O1?GG|}zIU1Zx%V{!td++ArORrqj1qMJOl+v1 +z%gM);foI7amECSKOAi~0wICcm=%O#Dv(9(ZdGM==`|xz-nJa{#w2voel2N|KAdl8o +zx{kpci~M!YC3zhtn|XEUXS|A9CCY~^t`TsK$8g3k*|(zJQHr4pD6>!f +z92|^;#RHQeOPY?+aBVuVTL$=cc8MBuXYQfSlR7v3^luHyUag4NnbL5`Zh8K~*oIjS +zHy^q{Fvr@_^(h3vm~DFg&h<(kJVtW`%op#OfheRK+Q_-lKHd| +z^D!$F_0eRPGzf9O}4lh{C?(1YdnI=sUZycpM-g?X1Ros20jf{-6kdcz=E`6!}?>tQS!#}uZ +z1E`$t-m7GXsiZpA=WP$C^xGj|wrHnKO=u~9!e{|a?w^*XWMzt4UU+jR6W*N-?t8!mM{X6MYBxRb3;30n%fkK{npw{pdtQ|#1) +z#KP=Sxg5OSi8+5i0PnJzCv;vecXTpMGD{iG7ZuEaKoVs`{G@fNUmUa~p7>}>i{&BE +zgMTCPcBki?c#F23g%({OC5Cm4|+p_qAoJ4Cv(#r$B9{Ja}J9Ox(<`+!P))L!PXmqhneq1M^?S0Ji4<-2YIH+{WQu +z=9}mnRItP)`0!?(@>;>e%jSvg110bYDt*0t2U0O`%12Wk^s3_KZ?SKk&~5MZcZ&wV +z#UH9-6mm@(I4Hi@CEf1mrJ0FpvEmWevp2K+yam2s;eNCNJqv~Rays%T*qn+=vD%Ou +z_**vn+8G+|Hhym9|HoU2kJmKfKDOn*5ar+PRzT1$#_I|n;8S*7$~v=cSNdRVbBec<1E0H3AG&At63(S +z9S++g$6Z4A^#w4v($dr>PTCiefgMjuc&ZrfT|km+(!#@l#OYoEoE$lNY)-l8Va#eA +z-9hDSDW#gI9=i8z!uCoX5VB&T+A^xuOp(8aVH}}Zg>+uCE86+OwE%1pl0!rE)@kyA +z9@K4Ucis^1sO>CE>($XYWfw#fqM49>qTlZ&BqVHQrlzJYe(C)$^Td6m{98bU2W1SJR))tl$UK|W-C +zE=-k)fHH#be)J9#bene+N{<94glm&c%y17_3$!a|?RXQHHRWcvaR2=;4BKqQHPh_C +zQM|LjF8e#YKK&jyxuj#xI_G@kR9s}|cs#%`gZL2$ +zQu_#I>KE&qZarNu&g_p)t1nzyJI<_X21W&%tpV%zbu^l-$2i_RuRM*bs)0>Bd`vWw +zg#*)w`XG=9AmcztAII;dhb7IvN>4ApU)h)l1mOA~*(KSR)%KHRr>DGEFQ;5vVJl!K +z#rfBcL_rs2=Uqj2#uw>dEDs^hSz5109Bs^^6PM#Pcb?oMXEP{nw3FJJNT5&9ZA?sK +zcTG5VqB!B(eWT=TKe>VHXVV0aDM6g2TLpBCMMOEQ9u}s2*{)Ib)qDmEnh+mrM_Z}E +zcn?$ZXcX3V;cQ|O4#^KpAzpu6*A$nOd=1afD>EFM0f9oH0C?ugoa!Kb+QJy)?58Fi +z472VuG+b9Lv{dW(Ap+eYU;yizq$da$4S%gewy4umg-4veEH0poKL{n!ku2Oxw}lEhkPq(DL=}02C~Fa@cr8aQHV;AM +z|6z;@s{>nuLcAszQMsaME+c +ze%JqlhIed?v}@W%gNbe1&ct>mwr$(CCbsQ~ZF^!n9UC26d#?L=cmII?a8%WSRcoE% +zSaYk9$_IMsFlSpyI=hFBf+c-vlK&#q;mpXo3`{iekqDJP45+2gYtUyEih7 +z>Y;+?kkl~gbzYjKFjvqt>U42qb4q_`+t393$!W#@M`^w +zA13pV$3;*=ZNm0ECB@WS0{hC)B&K9PiVOdsHzNqWK{gxzqSl%zeyF$BNLwY{Y*4bJ +zVI!#rFmEoY#x_=R0~veHZ?oBS0+bCPV1ZSE1Cn7EjWS#LL_CHrQ~zgjKC-jimQG8-%06Qs|PPBF(# +zc}Barj3s!&258iZ1t4?ab|L|25I#$1!&ez5!fiokt9!f;ZDn$O#ld|0+H>y(``QKP +zg_u|2T{0cjqZa0*5utd4rVhSg^Ol)r{36rVfqBSWAYJ%zMH_P#OCNg;0El6xjYytN=+ZpGzjEfym0>t@bN~Qb=WCzO3RX3=I4^u{bhJ?g3{oK6-nfdk8XIlY +zuN6nX1)reCHv4IuJS9k4#*(ggByl?Yzw|DRP$hjH|YURd6KX +zM>i@^x00h@nnoD0@EdRkC4jDQUuGeAi>jgwuOa3GM+wX-Qc_cE)R*yQTE2*FceLMc +z@9<(53>DlyplO>%Fv%#NcaNbe2c)$+SNV38dRkEM$O6ZL| +z6n7iJNY+`r-!i~2H?Km6xg`(TDmEau-Ed&s(j%E$rXSBehL5ipLKpk-tb@@{p8)=+ +z@U9+v54ZvEwAfu~-2d!~;SIORVyeDoR_DyJ^ji*z8T2wcFYoK3qJjqJf%_j`ups<% +zkPlZp_}qc4{Pjd7kY$LiumL`Zy;lsLZ11aJw4A|t;H)Pv1*-#F&O;15jEt#KNjaI3 +z1{!Sz*N8Pm)Tj{Sip^6=gf@ZtLlXETX@g2^I!Qkt9``)?16<>m`O#_{swL*_Fg7u@ +z*%sgN +zJTIa^!n<~=a*_FQ=~xpP9i1!C7UCIZf2z~jP4txd=`iXZg;%rwT)t^o>dTp`uO4Y< +z5M0$hq^v%-QaiDY6c~M +z`m)Bp-I=s8k3Wb>$MIxcA6(1q;@aiLL_g~drV +zU5|eW(=0X#Dz&)gbuqVATm8n2DcsA|I|K#KThLKi8SHg3FAyg#LiMYw1a*%bIc7g) +za_3Dz^rg+H|Df3GWIZzlfG6ZFTGRi +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 +zZ*>i0tc_)n~485 +ztGEve|BsKV?utYij*-!)2R`tpCKijgqDFa%ldV7 +zehgV9l*_RrB5mH9S%B5%A{Xjh39C?1Tjz#<)0Cc)P#31%{2B$fZeqA=rPB&}wv8NH +z0~1f0rDjdD$fT8&pRJI7k7&fI6ya*w+0{NK$eD3)`6Nq){p{>y1!vVx*L*J0x%VFS +zy*TIY?-K!c2HBI0V@KRE|L%P9G60x;!5a(PO@?yVznyY)fb))b?`Cq3d$usJESz +z&_Mv!%&pSFRlH}Z*<4DYXBlbZ+jPTMxLc8{2;@eczoto|UfJ_w0`&AtzJHR~QYO)b +zV#IevUkIVYW%61^cj1+-5pxq_RmI76(oEZRP^Hg_W3(a7 +zM)*^mUHtsy}r%oci_L$VDer#KO0cDOEuI)!#DKX!p&hIw<{P9}j`H#4h`mq2S&io&e%cdV_r59y7ityb(OF +zWa;pP_ +z=YjVeN9jc&uSchOj%$n@`w$kvCjyKR#Tf)hsk`)j_SxM~^!kjQ +z>3eL6@3InLJ|MjGz!7|@>?Cht=HKJfzIZ-j=G7e6O0Om{EbF)B2^SAacqX{oIKB}8 +z`>kGN?r2b|#^VXuEx1zgosDMppMZJn{6N +z04USUTX3P0C*>?W6@rOH{~(qWbL{mnz)pFiseEp%5LGs^wyyB`(Jb9ZSKtk0^*|~@ +zhiRz{0wyny@3+bLOt7Q<{(~q4LWHy^ivnr^gP!DNI4IkTi+h1vN_FSOnYeK(atI0S +z3hXQ&Z*wT$_Q$_`WA^=2$lAR_v~b@a;Z%hFsx!A56I20v9H45w&#C7th|59-1dw!Da- +z6F?SMDf|uH`ScpQ)3nf=V#}b!3Lz;4o&qu=$Tu@LcP8vx^?ye$N)==AL`b!RX{!oZ +zHe0cG^(O2NjD>e@f +zT%uB8jn$i;V1K>3BC62hGtj#e(ywp}=KIB)-f2b+HdTFY*Ki*ENa{wUN+IHaz0MWv +z^Iy;72o0Ui9oHhPjjK10$Wd7UhE5)Urv_3sDB +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 +z##8|`(lV3Mlyt>nQ_F$LL%8sgc +z5_5XALd__x^LnME(S5P;L==ynh-way%F!pQM|WgQ{FS1fTOYr@SAD8~?0wNDkpo2} +z(_#r%B14lRLOuA(bxB{xV|RwJE^Y;%k#j}jk&m21_v|lucU0(vZgpSGlz+#y_gpmd +z=;5URRJ-&G-r;r;m54+gsJre#IjTO)TZVJ^LwG`$;A{B2T3@<5&@H&>>+TDtCcQ1_ +z^OkhpN#z_Qc%*os>zqitUXO;W0)6sJ;|D{Xh~$1G`h2?xIew9@ZYi#o)n;Eu-F{lB +z=LEXlMYkCpaQX62n;n7PhC0(?T5$R*3ttXVt;D+&NC2WQ(zK>H2)sDmh0vAIGw%hpC=ffDyH~DQyda$2U&slgCdFu~nhLBwp3s{#HCRJ4_?dh9-DT^A +zg|`qOT+;KC7{vg0JC2k>@NS}FyPB2*ab{;JfKUe3|N1g9&aM^N*Lk0Ei8ZNfb=z}> +z9%EeL>J|4}e0z{ghOGDfzOnyrpD$yn*gfe-MXkq*7B0>vSBB5&(1JZG4wjg}#p3tJ7= +zhdLi6pSMTR^riF)*Y!xxuwHrRoEP$kVWMK0iZJ;yvn8*Lp6#^TBNa__wkSV;E9py; +zRGAyBVPpm9>L0#68V$v*;jSyzECL`jVI*>f8GC#$H!qm80}10Z@mMeeoJ^tmnl2y@ +zDaqO&oP)e}`nmlbuUUH^*F|pV-tCVE4o^FiMY=i%JzFcnr)Mwya&%l=^cty +zkeo%W8~i&+`%!k+-=Zo@ojx9Z>eG>P>e`!h$X<2RAE^P%;F`_)S_hdfeKUS9uq5=N +zy;O~lk1NhWLBXQ`F^Yj@iS&N7F}QYB_S@V;njJ#Q)M?CoigYUZ8;C6mjYcw6_J}`g +z1HdAH3&EBzi^qM7T>XvT*F0xliuN7|YKXp9R1Y;*#m>Ny9Q4N<_xtz1(feB=um# +zBeN+{Cbd`JHtsqke$C0Y|C(OG=LA2?qm&<=uPiF0qs7rP5WFx4Ow{n)B(xd(dfDrk +z+&^FW#{KIm%|;jcFXhU3HTJ<8nR~o<;0VtW624>|GF&!a1K-jsJKR9XC)uUGj)_j` +z+QwIG4DCiMjfnGVKRlD#+dl&K^$4J46}M*|D%dYvYHzb8{dK1*d|kO7Etpy3(1FunV`4dz6`bHM0Fp!hxXT>5f9v +zqkt;dq>V@a)j=m9Dw3r`rcyb+GQQyrbA&*xMp;C+rGbCn*(D3|US3}QZEbB$D=Clq +zKc&m&SwngPAWQN79IZlmxxLqEtT>JoDA@{E3{Mad7xy?Q;PpR=jVxBS>Te2*B9EQM +z=O8H>Q!r2ljG%QP!-F44woTqXuq(@-7(uRp=`d#*%7wOJxXHhI1Rlc_Q^a^nd`NWd@n@Vq6In@+ +zN*1xB*NDYN;LiN*p8V6eW~?dEq3=hcr%MEOSfB9Qkfv_?7cv~4W?3r)qNFo)IAG8G +z4L8*<2Od}w>qn9&L-dIKQuwQ?Vl-qfkoZKU^#gNKjAE>Hyh}8y+ifn#qoX}|` +zo5wRR^zkXbG+Tz|Wc^yA@V@G8ZTNaQrg%-TeoJ3eLLJu3r74w8dHxv=Ia0cw_Q1x@ +z%gTE5og@0c%Z%Xy_TZeNK>d{Ig>X +zXU-&w37TSh&nd{Gkru!4>-4}1;*D724DnDS_kZoDAqd6Ko*bY_O3hSrW4dBxz?ArtiTKdhcFh-&GKy}6y4iI9v}qz27wYCscC#j-SL8&+eL_*@|OkbDAz +zaP+AyGOI@YvfspZh$FMcgZA&<+`N|R)VYy$_WsQPM=%8IOow!MS2327*pDLaQ@n6f +zB2~B<1%=pw4=~lL0=#sUE<$S_Ef>7ci2| +zUi0d82QwXaTAPOocETzIABPT|f4wiNqM~8|`*!%hw=uO~Ac95%R7fF7fq$`6()uU* +zq4d|B<#M@|C`NxGD}_$+1nS3!*n=yx`3~A)ap!#GlMu&E^I=jp9ApQG)Vmuauff5S +zZGEK5$u$32X2; +zNZjQx8|vy>!BMl}mf_BSq0tN-$y4&&n9>yF20ZVrmmgXAqh*b@5C(Ua6&@+FF~=*s +zL+7z@s?0EP=A7nBa}47B#-~*?s@Xie{Xk1~UmUA5ShaXY&tBntFtJ~{lWvFRgjAZY +z$mZFJSMnU+;NTWEZ|w!RXwEz8LOd&%;XbzcO89EIL_W(J_}Z6tp!3^&GisTNlT3uF +zESCI%HAN2hE6GF)4n=0*hT~6a|6DG3DmFc%Xen&VMjDhW{qIf6w$PJ~y5sf-5UpK4 +z34Ex7AC_>@ogD!LShu35#gP-g;gSm}%_ +zsydXcmIAQBhX39w!_!~AnS~}-=I=RlAlU +z8BIcg(8tSG*}0woio_muFn$s>>@RQ&+dt=VNSz?gop7g(Q0R3~^9$f--sn2C2r`|H +zP^6P6V}g9vS^%mr_Yjvpn9{~GqHR}xEA5?9US`R2LdiZcE{AH&xW`^wo72{fmznMa +z`@#f{N8m~EU?qmRQsnK2?F{Hc2Ha`wsEN2cWi;O!#6te`LkI!K85$ +zTG-iFkP5sYD}I*7m^l(r`9kl6N-!uazfY2>NB;@Le-A>{Q3b4EWydcmOnVp +zS0Q-EgKRe6-ApQP%l-3P``sd=J|~}5XJ=>sx>|+lho8%TZQVEhXkbG8B-D;1 +z2Au+(QiWVKI6GxmQHD#EB4_wvl+;Dnpq0z^3~C|8ag6nc +zxtkJ3>e09HtRP$iuWm^<(ZmV0pCTSC-rkgC$M*)4>eN1zi9apf6SEY({Mk>C&N_Y~ +z)*Rw2(BZxJdcza4jT{qzv-0WT6W6_qzL|8OK+<76rKoeNr&nDVi;I~DruI5PLhg5~ +zVu(%SnlxU@GNy6;oR3!1q!DfKR0HL~gx@rCuO9_xD~hoNmj~lL*Eqn)EVB)3U)P4- +zQfCZFHPCeIVjrU;orXxP-m!%xe68On;iP^|A@+PUdAWWSk#` +zCoY}{i3+P-;zRFHb*1L6b*)u2xZnAJN;2|m$>@)N7T63WYjx$`%3X=VI$%Ge%?^#@ +zGNvYJ-ntjrfy9$0vyi@d#wFQx)WpD{2O%ouGO{j76(L?n4tyaqel#AdYd76UQZW`)mw$@A=$66n7 +zQLly3?}U(smTh6hd_MX;{z*yiv10ye)I^cL&Kp$csj)Rl__eU*;WjMZ2fIzb%Ks5x71-oCYg{A(z;t8`n_~w3az-P;iipofm*0XQ4-!CESRkdki`3PReOh&8 +z*HdGAd%#U}uWH>2T<(Tb3k#JqXdg)eI$2@SM--9E6>Cv7|KdASue(`CnkAQ)DOPW@ +z_L=zeUQ&)Q6lvd(m)fC2j;RnPB4W_~YaZ5U&HBKnT4zB<8@hzp3Y%a|ofNkY*NV1t +zG)yGvnf7EnD$AkEeRLIDD#g>%YPfB_yfH+~E&4(|-A8AE(@3q4rcFpG+{=k!llxc| +zUH&QFX~;Pbw5Rj+^@rW2NYpeSgf&N-z}D2>PH=Z`3)-X#jqy@|Jb +zPy6;p5dcJ*(8aWYD!8+D4vnw!QR7we{ +ze{llDuWUxZ?|)w&*eKFY;o_Qw{F_d^yp>Vh|Vv=0jUy$qySs +zTC=fyoy8z7OR0MM4Q-rXrLm@j(WtF>CpjE__cQeQk8HO*s2Bsp9Pb$@iE_ctFq^F0 +z&C?3Tw)L)MGn^Jlewx(jDMw8s`*!StW1-^%Q>a-BIPt@n!A+3@D=Cf+RbHHQtqR$p +z4C@326a)*O3}+&HwxpusmKXWSwoQ%iEiyc54?VYFFv~ZMJ*@ng8L^|8vBQ3|G?f|f +zrL;Ae4~%Jh9;Hk-#b^rdQnz|xu-BS~o>6aI1|m6f}AEI$JTD?7V7%Q`KDNUIR@ydm}U^eSx1 +zwy&42KM*Y`i+Cn^4}7%D&_Tk)ZoFKA$yg8&HXp_6TwYz#{ccsR+R?n4E7RP>zZ@e#op(xm&O}bTlks;0w +zp%a~0Iy_7bL1=d6t9Wb-jscueypeUl&UnPWgP}KU(>MHUbJL6-Q->Gsn$$d;IK77HiM3?s8Ck0ZK@#BmL?NjCcQKbw%pr$oP(*7 +zWhyLdewo9AJoDcUqXoEqe?Dsz`?#Sii3NV~W5#P2tOTVxxt*+|s_N)TD%U@DrBBzY +z6Ha@D6_G)^!sFUGs`g%bX+(8=YKta`{fr$Z?RxBhaPWAWZ^@h9H?C7kgtr7p4d*P# +z{^T&`)$T65n8L*zdenX)%MKgt$bdW3sv2-53wLI~-Xv0PpN?UfrcBF{@FqQF@`0h- +zcYWY~rwY4B&a>lSF5%(ix(4max)bhP`e>xUT9AX2qg8I@<*3r6Z0ZzmFmftNIh@&V +z=m;bPYqL>?2uEe_T}E3N`>O{26nYQZblSJZ5G~JqMZTtj3mx$wF5|WMAO)$D(Ay6z +zGTJ3v#0TPYkG5HiQ9lGel!vF)H*!thX^(rr4~E^VqL!%#t3Y*~-y1}}7zm65Z%dJPW=`8nNVUoZ{M_a3Us!qF%+nlvEM +z=92sjHie&Q_;WWnYE{S86m{^1K1%}&af}`h8%pJ3^*KOv@*7(qqN*(Pz-pF4+mZNY +z0a&=1@8kB;tF1SSlT`@^A-=euI)$tpwT+to8pZ9$lD_gzQ!~Et0Pn4{d4MSedqfBX +zy2dp!pZqoLgq0*X#!PuLqwe*aPce2g##C|frC)1sYG9A$ufTUJoYe{4kWog{{iPAb +zK8}OhDYuG-daWanCF`;v-Tcg5%L@%*awgsOqck0UBs<`GS9rUR()XhxP(eX&RwF_^ +zN5{!B|0){tW4{vXC1@lkTg{LzgjGUE||z +zz@npY%RkT(6ff`zLIsN_o}o7u+_czu?!K96GKzw5y)C5u@;t+r?xw?6fG8Tcsw9R2 +z`u42&Cy95Njv9gu9-CUk7TOhjoFRRFChv~8_B_bh<4ZZLpPTTd1s)57OtSy@4Z>l$ +zFsA=Wd08*+=X9C*G`b0$_C0~baA>+wzMXI<>L-D&H+Rp&Tupfkr41|VsYv+g5JcBP +zN8DnRv61$TfISmW6h>rGpQ5VFSQeGeg%xZppaLJ^;VT5Ge2hc%7_U9+q22yHpX>L^ +zL2z*-Tlv(FwE~#1Qr?)ds=O-b`-`@o)n^3Y$%%U38rnjD$GP{HljG|}$ipw}5;}jc +z$NO%(OUF}}AzgVe8y#ODH|ejw`eM(Q)J5$)L%-#PHUA#` +zeIpfvR3!=0^u_dY2g$@1PO(K6EhuApwMVRgr4omTfaL*$0!Q$XSF&uoD%x>w2$Dk; +zMjUV>?ge5_%;4277hUWYy&kcpW@TCrc*!^yp=TjWmd=^WMQbdERMX{(s}K+ks8_wY +zZ|?{)QD-8%eCMxZ$(F)h(jF%O5V8_P>giHV?5x5=n*onJy^lWpn)9cUiflW+d)X%l +zjx5^A8Ng=VfUGQ)Ns7b5Olezg&xAZe!$!@1W%=jMlIxe?P3Y|FtGYrd%47)lbf`bv +zzmOM35>2yo7gL*t5hC_XF-Z6ebSvG}FL~eL(9E5z-Zd)^l94_B5 +zauW~hYW?GqTgaKP!nLoLZndXoy%W9~G+LXwm2_V^eF`QEv`#|McJ_kOIp4?9-7l^S +z8Q26G_BaT6Tmtcw5n~vGo#)?CyRVDc*DF5>5TbalrGdwFRmp)vvXs;1>VQ$Gc)y@# +z0H4Qd5%*9kXO@rWLDg@QrpF@!-o4)vbt_N5LewWZt +zll(rDj1$cik679t$}fb}uzT#@7?R7{l!yGCJ1(nxI*>uALC>0hPlDf%zCQ+^4&*Ep +zZXf0{z8!ZUbdkgWzlwj8f<0Vkav{!Wr=%!K5vR=vHG(-~Yw<)Ln#=Zjdy#)|#~Ke$ +zcArCE&KXN!X@}O$AvgIC=RBrYP{TGb4gdWQp=z=0XVRNx+blKHeV?fnHU`Q%f2L?m;B +zVAD7?!T_muEf)!eYTO*Z3L~3wX@KsJIb@!$MQ~XRi>*ry$er^wlX{2j$+5sY>c1rYx@6ArUc@NrcWv;uouGlw$^1_!? +z_SxH@lbv6p)-`={R6$CC!8iv4kJ+zlbP6on^gVk9*)}E??G_Kj1_B)m-))Xm^@PNU +z1iMJT9F9cS!K$nm=c#JhN@LJGsF75CHBOGt81x*hgh8cf`Yx@X7+gk +z;WF9C&u*IYUBvNz|s1cEq)pv&IWx^50*<88I3`b0*pZ@n8^=BZ5pQsI +zBTyrUv*{;|&nkt#7#n_jTxJ@nU3AVl9Wi7%(s_p6`NcE-iN~V=#$6q_+^T_0jiP-B +zs&MLG1+ZT~mVJZ6zkmNAh^H#{nFx#K4N{OOCyAo2?fuPmYUGrJ7AUf=rn(s18H7z8 +zvK+cb4I9FiK1QJ71RE)$BPeDIz{vArNB+j +zIITg`0>8Lqj%_cB#-bX#Yk^z!Ld&(zzWB2Y`O{n7fjN<}y%^%?>i3vZE9F`)Zb7&} +zo8h7XI&K*Z(qfHIRl4-4Mb)ht2w_g!Y-6_6?7Wzdo_LYbH)kr`Sz4WD>Pj*SOt@l3 +z*05yNtJ|I*EYl8uV|G9vX?J`o*^j=KJ@Zxz%)VRu;_W+?$fhs3633R-tBK(z^&AE~ +z;BI@`xxoWZ{5LNGHj0busq?{T?6X0m>r0c~DLEWojm#3B+ +z21%VN>qpm?KpL(Y+g0T^>*kNA14M`&u#f9gN@oZ4UYz?;SjgPnOz1HJNvQ6`UNJ>MBVFXwO#tSt& +z@kVtPFa>kks3K6R##b&EKNfZ;eFNT*57Z-ti+`VWm!aklDuhLz+XL3wn+j3_JAQRH;(Pf6G1`zcUv{#01s?*NK4 +zT9Av0CSCLrMe;zrW56-0n#3OQrnd)5R&KdVRlY0+cBI-SZU$xv9K@n}4u6F%)ItdH +z+B!o;A@tj +zO^^2ozkD}2QcYQ)&+=LY3O942#`HwHSI@i`-o8Ig>TZiC^)EoraKFul7<}pYH+IaO +zND_ckTAwFDNIuAGaf=N>^NmNYe_ob4oEP04A!sooY++qx-`NqJ9b_P+Cv^I;*v1_yEw|?&l +zaC?%eEO1hE(*U!Lw@tm0Bk4TY9L4z<=GRiG&oTRnZ_KyACU&0sKNxjuK9+GYZ<6~b +z|Ka^!gy;D$7QCWZ&H0Qum2_juu`8x}>cCfIik$3!Nmxp-rmhk`?_P +zB#>P@)xR(JXPl4=)Ie6;vX*{>7fV`SViZ>^QJvsmr}W<|d(3S-S_o)j2xz*pp0QG= +z9?0@rw`nP38NSoC_-r;DE@rc-QlWR*70VA&n41c63GFDG|@We{oP(9?$|tHQ_HzJ?R>$Kzf_$AOmI!2zDV +z+2o{xi^}WLg?4~VpP$jbwXNuZDg8j&qsPsyMxJTA692Q^Yi+tGpFC}9)QR)H{Sfk! +zHAZNG4Z8USPr$$F@QLdgRUW&@sHgy5Pgq%1*gpFWfs6%0!ehJ1vyt&XiO0zG3xWwA +zWALY*Zjd-H)B7d=>wz84w`p8;zu+X{n%*Z%Inr=b;;4`03W +z%dF{JX(MC_D-fALro;Q!>z!7+P1bn|lHhFQ@Do#t;;i#-?5}u +zv=r(|=HCr(} +zg_+Kii1X9d3Tfu`2>|h;&s{#T2q4izOoo~&YMi=n0uUj^x^p0J2?VVa2fp-JlWXRL +z5bc=5#0oLF0<3G2J1g#(psJ+s;^Sb++28THH|&JyeOQ5hJ5m)lpP%LDNl#hXZG(;d +zL1B8{ari{VYFmxHP`pp(K%Nt6o-I}!qxI79PF_Ivw&t%@H{}ZS$uzU3&g}wyrot2` +z1Cf@dQxR%gxr3&ID~j+!#EHxV5txMrd)7 +zHlJWECP&jeGt9=gj(nqSv%$TeAFNYY#1@Z$X|J6-D(*EdwDR3FX +zNnS~qG+T{1T#+5EkQZ96uvB`@8M>4}cpPsJ6})p)iX1JkTNtUo13J*Fe)7*v<0%J+ +z(+}=l9%O?M;0$&Uo;;4YOWa5itR_7VK#?JEd>FpVG_DB&X(9E79(!J12PQOhd3hZ% +z@T~>|W}F%7e(B2#)p(GkjGL`QzSIcOR+F#Cq;DcB)7chBXlOA)A=R8Y(WU7Tv^=9$ +z)<@GbDMG0VR@$*S>-;6v$EMaA(np1xa)R|#dOFNes!ie@?0776$kaMquN1#^Nyy`K +zPJvPC=0s-Y{$R|#x3}8e@HJoejwKG&_vqg!j2O+yLc0$Qt +zb72iL@0veGuMInZ2Yy +zx2r&c-LN8~xHH{)auJAx6Zg%^-t1MBe;JdZ{B?Jx`xrf3Rpn*uS15&r&$3q`C{!(X +zMCT$bH +z52Ltswr~_HcWo}hyOcV1)Xr6VcV*H${lG@#E(X$}w@7Kp^|qU11ax=;f}=#A0&{=8gS_2|S=GjuV@aUVwA!vs#YE*Mj|!wp8)Z?_ +zX&fs~l&x2H64&n5?um9=-I!wKw6UBc=$$x>QE{1(^Mn;Ke0J0+E~U1g&Y{l*K4&sD +z&0qF=idy>~F6*rGvO4NHwd4)c)zX`2)o*pP7FCYTu^F;t)~|8@`XT8m_qda6~M@6 +zk5Z1b;A2NMbs+MHogj%Ft)_Vy;<{Hn6=h$~$-RpSAFjpo#KZVqFwhorWhu+Kfg6C@ +zxjEv*rgl`9R(BK-TjTdxOBHlxk=FCKPpez-;qK2FPrSYlFYmz#$l3H)pufozc^}KG +zu7adsj%1VBr#Y-q0--a#hzxT47!J{_u@=vxcVXmr`moX#yZ3KANQJfmd`n*NWqwJ) +znlTgMOJ{S3awclS6 +zAVz`=Pm*EUSN{eND@{nx(ejP +zn22YGV_9zh^`Yz3B)vX$-k|{eS4{7=+#|bwm71NE00zdR=XgC2aq}r3xk=T?njzlb +z(NAch*@3eX`e*+q7HB+Ux_u5^!PR5FS&%`Qw8e^+$IMZn^7ZGaWp8%m7Mt>n3s9%7 +zX6`4_x;N9S8^)<5Ez^)n(KXCgiDmfKWN8#}VQ!99j>_rx44K=mn>Ws`@pkge|nuux6_*$Y$*Umt3e& +z`$)l{UfV&$gQzYqGk_8E(PGJ_bLJ$y_P81oNm7p-n}8MU}=$`ILKP^K!+Lbc%zu3L9JkX)a +z{{&CQnLG~>>dugoyTmF{Fof`jm5hr>DJ?@ehEC*mt{BPIyBEI|6i-Q0#;N(uL~W;N*CLB?bnNodJ> +z^~)h$uK}z98mSQ-5Qn!vJm?HKCQtZh6+U;CNozWW@ZM~$$EK=O6e(v&scXVyy!`L) +zUnej^tV6|AoJv)AShB@_!mcanPVS#q8%F*-ugW*5UU)Z;E77wlcwX?rp8##cHc}9?|OgE*A6p315?R`6pM! +z5uyrGO)V +zHWq^IXf_}UN!JKeI}!w(6WqWTLEpunMgHLOYODr(#%W>ay}sVBFbA!g*cnl3 +zdgE#sz;6@e-m1 +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 +z+ICB3*No}9o!qcHb;l1c{sh|mI +z+kdzrQx;=Q57#joPSo|pX^2rRd(;r?A-eyKZHJ>JVYT-PR<41EeNsQQbgg--9HJK1 +z03@dswKmpTNgoaD3^!lXhxPk)*}=)?RqWZL +zZSID_X7A=^X_2q-6{ +zIo_r;4lWvMJL|e@QG2z>!T)_j_3GZ(644``@UW^p&8ag{r~)!GCbISdnuIH5>Snid +zny=S|cm0>iwhPvnc~wUUQWY;Zxt={OE~XA8aQEb??{Ds+1k=M#U-T_!>#WXT)zjIB +zs)#3+#9to{>C%Q>Xf_* +z_sj*)67cFhPHGw;LGhLkzI@<`>6+L5-FJVZ|7H95w!*j#(v9_UaC%Jizs1&egGeeD +z>G@h^T;UJ-#eU>%1M_t&ZBwISI6Mh>vSle<2LJ(xn8l&nm~9xH=3zmZGqD7 +zVg>C$t>sVL-HgheN+()z90R+qJ)v>1bxCd=$b|k+rD76tg#VBv?5;tEp9Nkm7Ws5O +zw5ylXELxH~wgZd6yu(Ou-64BCl&D>V_%hUhAl;EAk&(nb{kgeJ`hLw-p|6R78 +zw{?5IZ5n?B`*XolR|ch}!52NBq+%0v>8a_?4}IHf>obYyq+u0k4!7Xv=}DX`j&6bD +zcz*AWdX>tJG^1dtPuasYr;fawH7e9$Z=S5)w5Dw#cWPSd5dY!G_-=6#GHFFva?M~y +z6DIUlp$S%qE@N}V*q+a-=m_PQYZr!Y^7VHgz$JZy^}ae=Y9@DZaA9vYS*37aHc=5~ +zHvL{Ni60?R=6>_nCVNc_AKrW#yzdeAFG2`rgt$zBKIpRR<{Wgp&Ac%B +z&EREyU8qi?taZfp+e)HBoi>Kx<71r<3pO82bS;mTi(mqr0cFo)Z!ym#H>`>z5SMp& +zb#{1;4UXi2qX7I;#>~qSU@q`>?!EvQ_+Vtshq*ZuVdLOV!J?nju%CkyB@s}}q}y$_ +z*=i@4J$r%#764*D&`tJ(RsGVMPalHq{l4U`w;L>QXthib^W8^PH7B}mfGUJ}S- +zkj?|U*?T{3Ck}4^4_oIRv%k_dpBRAMWmm*5!0%K?Cf9G@K7XE5@BMb?$O=OD-_iqL +zuHnJ$%RC;o;8O5;wlCEA=FK$lQ{rq6ebmriw~LiidU|r$ctjGd*uwY%aHpPm +z(EGHiXfkBj^NB$vsjQq5`P{vlccu-0LZ63U#1W&&l!%>3>&J_^9u|v$lV-5C=N6q8 +zZ^!{Bb-OFizAHah?%*R!dPqmM!YhHSE;%V9X&PA`F9+K~RvS%tc5BN@g=2Q;h2T6~ +zH9cy`YDm`Dj7>i3`o>@!GONuL_~f#(Vz}iLX;vMXnDx{d>Xub^uzNWYsca6`Y0dYP +zRJ>zH*>p1r>xQy26P~0JlZd+2x}NK%TtkmC;VStGs|DAVXNGJkPe0-uB`#B#*%Gjg2j}JlfE$AK}g-Ax1`dXUl0#oSsOb4aX!)5;)ZXKEI7p +z-D(%2(MHt0h8aP9g!GzkzFR0wRbVMEalxPJC($N|P_&GXPh~qI!#Clk +zaoyx;eHD{Dv#b8^tA2r(!g-gu#1Gb+7^uIH36Hhua2Pd+#o0k}{S5sqTj9Tc +z?dmM}CKG1FB#h@+G#+QZ`El6#4EWt$JKS^}ks6XY5;=aODeyI%e7#@qU<3*M3${29 +zlRrcJN2l8>wW&gY_reYqi>buI1od-&N!#0}iO9uMG@92DcJHymo+fI$67q$N3N-QB +zgUu75OXvjts7|NY*}!}k6fD1@ZOOjbRN%{3^>UoQFA^I|g51DS<(?45`>1B&N +zl{T`m`F)j%e6j$7UTJE^#VU8bwY)E?HobpAw{^@Vnr2m+hX(kQ%rKI?7toA|bqY16 +zNL2pTZQy4j7SDMwA)-@zJ2gvo9iw*|)gd;VQ +z_>AIxw68yaL(vM_Y8kIA|B=y`LULm{HcE?T;7sSfS2OG#R+jTW&sx>Yg(Je~NgHo) +z15j2jXx6LDFr5D&`prMvh350ua@ysUt`G`@`B=_rC*`KB#6g +z)T2lnZ(20Wx+!kh46 +zTVv6UP%nTt9=J6SzVXnZn_rmNn#I@Z&WqIR4fQ^;zH*6OU-?*6XyxneOGd=^k_$w# +zfE3cKcg0z{*j?J_ya&d3oRlLc`Ct+J0If@Pz6uv#u59W~Rr{XVWv;4Xjrl7*HZM-Q +zvpXK*G+nOZ@SQ*NR01|ei4uWS;}ZlmLw_J-RT~YMnIevt2h6PK@&4w#a^WhCYMM!{ +z3d7tcmO`8OtPFi0lRz_+i49-+0FVBL-a_PaTqlgb=IV^2vdw#L7Qa6y)E4xqEpE|W +z_I4P=*u~hq`;t8daLmj2r&OAn*q3>!v8xz;yyx#y&M@;Vt4(~YSNAo +ze}!&EM{!B2mcxSqse~`$%uolLxaR9k2i3avg}S;}PN%?Xymu9QVL7dNzJeUyH&qRZ +z*Z;O7^aPqCsvV2GO|Fv==61){bh)?RWkKXDZdRiWhsnuxlv@w=v%TK>!GSmG3$5in +z^X$&|yKjYxIROf+bYW5IFjT +z)NBS$f9oU1ypO&zcBoJkej*Uj3-n-QYlHMu_$jgc +zlSk*lFJRJ|B0PH;7!<$vNe{NzPfx&ZGxhu(xbYZ(-yX+=uZQ71PH{y^wEl{&5}TQq +ze_izlp<4qPQ^$RKU_hGE)hA2&+NuT#UzS{F3@yxYF# +zLo%l1^6LQ%PbF21wY;#`{TD4OHyAn4aOTcbDb-`3K$mJ@U}2 +zi1XLY3-yl=hDH9WaPUdCrPF#Ib^i*LKaX22KiwLQ_{qtqV|gim@&~Tx+dE|J+Cv}a +zHD}Li;h^*C8*x*o7KVR|q`W0mynU2g?E0gLu5Z#$1}RkE8Dr>h?=gGL4lzf?VqSj} +zPZ2?&)1P-Td5^!h1lia6oYFm}4$5e-(roUJXw9~ho>jVFr4UWYIisj6dRFMa5v`}> +zUwkz~&i(aEZE+V)MqO!X%AOOe@2UH9Be|b?=Uq8?(e;}z15z?t_?)lTiB|^oXwKvV +z*w0Lq*_|3*!*H6@t8qn2#WPZ#zulG?z%Agf)TOL{dS-Vv)E)5A^|kn5zMKES+M265 +z^v%QO=ERfPJO8K$`d-A2PNe-|S1Xfun}5u8^ZJifRenJHZ}D-2TF!^ +z?+6EqwuEx1n8BqRp!B5p^I|{`Z4(M$H2vG~pNM<`nKWVT>ie*~ck*iVLgXxMOExto67OF|Ipm&24=q@J>B;fvgu3A`?sB}@1E*HYYs4peO +z+9|x1$X|`6v!ha_*>c8+$Er*B7ZP6S;5JsFkxL1NfAqwK%-43GBTLRs_{23ude!q? +z1B2JAaw_GDFD^Z#xTBRXx+Ayyg56oa2AUj&z{llSySKyn)rY>tH09a<}kk?;vV +z*mEI?ybd;A5O{i||1FrqF>JXW7Xg(jX6Hf?j*Nk#n?z+S>59b-v%IK6N0&?P8Lx&r +zGa@{k0o&yR>5!T>mvdf8oo(iuj2?F@W2CEDEw3hbpHnK^aSsL|SR1R}HdKRKP<#KN +z2`qCY=?Nn2&3%O=H2S(BEKw+d8)hq~^VykmjT=ka%YP2&y7$U>C;r6J;GfltMhesS +zrWiUbe9T^VFg=;gnmtIA2ZvP49a|OTrkbP=CC-&k#+AHjxu~;fTPUpH35hp^>@i!x +zV!OL=HURyScOEGa6f4u1(gjargSs2#rwm-}$l(o|=5uP1QMDD&gN8k8xhU +zXEZ#5$QjZfls`FiL-7OV!RskeuX3VAx|%Kk>+S+3CMCSBEs +zW@G$0ylQDoKL9Q70vgr=R40ia2{Yl!-1zf`YSQ?FEYv~|7ta63vNr%p)-_F!ZQHhO +zn>+T7ZCg7#wr$(CZJRx|@$d6~e@EPo=;*i+_f}SAWu8+<)~RKgYurCaJG2zT_X;DJ +zi9X{tkbU;yx&Aiew7~Li?tjNVAIzsu6Ybc#=^oxGwJt%|TzH}_ap(+k@&Ri;ZZ6#3 +z2kUmS!$euFLhTyr-Q@0$XfII&hT;`#$qfW$T+ +z1<(T?E}S)d-eF|rV`JP_Rusfm!_VhED#F~hVo*T05P#7?ag7TBuNyC^hyYF5;{rkbc6t_pLeO0FQg7J>>*y#3h2nP>z28UsfeL^N9 +zQI2FOetLdq-6x1xuIdzKUz^sVUZQ803W#$y>%xDeH8IXJuf1&#L^_JyMc)H|rC{@~ +zboZnr%K8Kb>?BKTe4YcqK(vO +z6L?9myBKBwMBeZh>r$o`UDF(b_+1xjhmLXzj5}0ecq!y!;~b)*avr`C^Fy5nUU*^K +zwKS5+69_biqb8g9dsJo<#&u#PmJLFp%r=hmT=%AK|JfWG^9>3Z88x>vGWVofNXsqt +z#kN%Uq^r-avUp`|hVR3Cc=O>23i;n)2TEvza+2dO(BhCx@lqXkf+;CV3l9fgu&RB7 +z;o(=(6M;(&fwmk*UV;){%3IG#UKwGGekKECZu@kRPA0YYy&lEG?BhFFwOIQSkz8r9~Ut{1vx$ZMb|&CdA^kaHLY5g!FrD0E+%xnFz4b{ +z?95Q~;zcqi>b|2IL8>Q3*j(Wk4o`)-0P9udEtJ3C5@wn8L534ykok&WPr$tax?s%L +zwvP~#1zYqouNkZKFHPO*oZ|cYgtGGUxuPY8yM@4|5OWIJGaK^=B7 +zN@>Tt3n8^Ks9d!eTaFmWCl4x(C(B!4{kvyr7>yZ%*IfZ-bMo*>D=YaQrNjSVsP#_B +zCy47YwqX8ootEcnffDo&w0=*$Jk<)KMdYD9fd?lJcn%E +z41I-m%&g8HN(2lJo?t096-?sD>)E_nS1YZ*$Gc0Q(8+L2&^ +zCeg!5B0uA5_`=YS&6*L(8tf>(T+zb+Oe?u3F1U-RtFMzg%*$MD_H4aq%VI_zfsduYd5!f`9elckB^Vn(&`>d;PF2l +z8lM^)!{tnw`rNts`tA`7ovq!Os+3?@*Bg$kKUI*+K`~xnpFP}8q)by-R!XvKmmQyb +zD+RE#nF1{oc05=ND=P+>zik%%>O1pP(5O@scuon9!kQj(eyA3&UV)pWU7oS;XsT)h(Xg +zS;{)(yc|{LvF~~T@#h1B8N?bv%JVk|>IjY&JIEUm($|S40B=q=1kpBz8>dr@w9ZsI +z1b46{m(F)2bg6~xtdTTfV8{ghc4D5%a|e3V-#O`jcTHz0lvqrynS_#p#E42lTu8*a +z)K7>jvL(HMwE`=m3|MzAhdYg$GW2pz4XnZ%ZGy07g_iRIT8K4?%+9%_HC+mR;Zr0- +z;4A3lPoY;rk?0(-s6gZ*0II8O8MU|f&Eg%IrQC^mkcdFMT$}cc*W#dNYbOM0Qf7jU +z!!a7lJ~XKEjL))b{hSbuyJiIh&Cc2#H04~F%pUIX!K`&Qoi!a%XPn;GgeS`3G&8ir +z_9YnIHkY$&vP@C`WjPCkFMJGYp&z3mis}JPVz&x~bi*$y(+NL)#7(Sx>s{?dw~XA8 +zE)f2>sAeH_B%}z<&AbIM{;YZ7*edZ@40se-JScn$OG~QWN&)QEyQ=1p4*DJ_RHO*V +zL3PXcuIurRGA`$a@8$^hn$PC!;s%8p!5Kr%8EiU$b~lGbM{f-Cjiy^71_p(N2M=HY +zt+2m{xjT>o@yE<{tlu3K&0VhpA(tPdOA-(6)@KkVvGduOW*Y{bD#zmOAv{Q19-cOub2AYi4$mPjo)x&LUr=bZ7t +zaCce5&5}Z}Q8M +z&gE3;%9wyZacIb5H{L>s9}0vsU({ka1AG&8X{eaTUQs^sR4yh{{l(Z%w=K(blwSuf&1S3tX+xn3ao1w{o%#G_ +zmrlO(j-IPS)FV7;F16rmnDD{&ax=eW=c`5Cp~;vqj?f76U>i$MeImbBWVd=Rh&;Cy +z_)34+no|^OI-xCJAkQ=%WFJU+PXyNAN&NK;rgP6a^$F=-)j$#}tUjEVTyUb5otf*&X6^C{PfE96(qWu+&);~Xfm4}U`~Xs9eV%|0he +zWG|P?oWe;s{JE$YiNA!h)8w-(=5eV-jjCm-px=EXi~C-9g~DupG_+#?tvl~HybH9A +zb$GB~krK?ExDCX0V^yr^#o+g`jS9>NiifsX>boP^(_*SwdIK!i#?5EVQ0D>(ZC32T +zR&qEB%Th||crgL)ev8_9&pW>EgsVoSKgB3pK&@cP2iq%%344(#FTrEEpeqHd)PTbM +z;W#H3=(r%_rpGSwclE;eZ+oWbwbLdHhyj0Lo4xh-qEAHa$=VqMcHUfeHt@vPWV5TG +zyX$|5HEbGv;RK$AGzSZyoTC0#{jMGpHW8?m4EWUccMEv-dmf1N@dt=~K7ZPKKVQCu +z6FXpyFsT!q_xOJNF*hQ2wCD{R=Pxq};3H+@!8-GpCqb?^Y?^ZzGjs;7)9k!Swq6(| +z{n-6uh!e^z$H!(8Tck8UcwC(7*4^C`4zd(am9_o@k7Fa!Fp+TH@uqD>ACY&aZNfkL +zBiA77v+50k#Y}%5BeAF|46{F}=YuRNzw8()(qG@PnONVF_>8%$FC^p0td>f?d6{Jd +zRZxX(kwbRK<-4gh{$6#G2PM7EtbGIJKO@Q|l3#!u#g@5EY7t)-JLb4rq_A$?JRY)R +zC})3Apyd3dz@ZmV(C54X21pnj1Gg@2l)f63>itFBZhlV3s4meyH|FA7Re;UM!7{jw +zIh*jDwX;f<9V$n_Q3WX(HYkZ)Wlvv!735nHG1?)Q{^0hfq|^nlfSWO(J7FT<9Yqqf&@lkJaVNw$z>PUU +z@M{7z`;@tGd>Yl+$Jq{J^MYfXD*<;uA^u$RB?oqt+CzQSbz=Y}gT|9WD%5i(E6;G# +zrjlXg^8iv4PyIW+aytc8M>oxGWqpqB;p&ra;Rm1z&j(foU3(;5*oOkqn#usT^X-1m +zRV(hT(azY)sJHivW|W$h@Jsz?Ef5rvV58IhW}Z0UAK-t0zBY#c_#&9U>_!s>Pe8o^ +zRZM_6D1eMr|2|M29yGk_30^IV4SU%QH$+KhW@)SbCa*t~UPvJW$ihJ_h=J?kO)Pmr +zkAYs$m)G>70X-tGMkugTf=+?~(H0>tSjYT1E`J@~CMD8a^o@=-HDKnlHxeEmR^m^g +zYm5|!qyj)>oW2q9fA +zkpk&i=N&4~(c@tUJW6>-1SFW>{xV9qbPO9e`??q687KM*oxs9G74p*J^sq6>=w!?x +zKW^W)rGi1DH2RHKGSW{2zDO5;mGtZ)ukN}QNBbb-3Z_9r)$dJg@r>3#ZxiqO#DdKT +z252G-wE=y>;EKIuJlG2&@r}!&cbu7+d;Enq9CNREIu=vWin~^#EoRa(bnbW=)wHZBh)2G0oyy}7wuAHkpBgd>$*^saOJrl@x +zdhTcE+C7k@ce;Nd=dpGXU=M_=Etp)6%%`zmQryl-(dMR4=?jgqKad@H>PgKz!Ogn) +z&JDEVz1J7$zx5A8z$(t+;}1H)|8Sf}H-GL07e-EIURbjTEH`3wAo%95kV=svj@Mkv +z+WFzLeo?FS`iZ&fg-sJOPGYk&jOI$a=F36bfL-f^(q+?SAZq(70X-fKuaT)&R?3kl +zGT%Jr0S%-#g7pX{p$A0zM|^s@ZVO8)RcYCUEU3%2Hmm;{m~F9Q5qiNmm(h}<<22qe +zd(wCgHHN$NJvd5ctZ0%-N~64jr%-)y)U9BYn`|Tx75K~wRPR-l3!ENgK?e%ozeEK2 +zQ^Ob2zMXAWtkLo9MITJaI^rm2ypc}>+q@?IdZVcbmrp(GAg3KHE{8Bw4x*(BaviJ` +z8F;2&K|625KWEu?<#+NAOnBABt(aqlcs-B-D90b#oY@#s +zz5ZxfSSrWd&x<7J-h^i~$p-IlIz>#%G*0bZZ&DyY?pmjN?E}u2YU%A&0RA85C{9C* +zK~)FredU2+JJ0;ga3OIqnXbj4F$x3%a3DN4q5*dmqkzr6~GJDVuD$JVo +zJSc5;<<}Hlx~235OW5PExzwiJg8+MXzbInM2GX|AY<43XI-oypoTpgL;KTQP_))KA +zpyE_WDl%r`ZQ`ew$RPFp2{amj+C?;-@#Q#8n#*p3)~iHz}02Y@-*|Rq^`AI7(Mg5 +zQ^L2p%cn8U*c^P!<`S8&^E1vfKCmq(%?$pA(4hL9DcO8$NBx%;&ZAy2rl^ox8l*?f +zZ(BKulGL!ly}F&v?Cn6G=(mge5sI^Rhnu98Z4V3F9BQ&fx}%Ip^q;K9;copF)M6L> +z*gYxnwqi%64aS>e-UU}SxW2WgJwb2H4tiaLNZyFZ>kQvK?{CMu55IFM?>ss_G&MS} +zryV~d3U@uCzsnzlg8!#OYYXG(4!}}^Y$;RiwmlO{ctb^_(P%7n-GF|4;NMG0b(EC# +z9aYNYvf!aeBMtd^3`W3bVIde;fQc9&6S}WgBjRi(=p2i*i*SNmc!WFR64K48zdX}{ +zVoV3#U;Tnd9lHakp!BPcQTqGFfr?^zqK_d7q%Tlg3`~Cs54;H>keE_R31(0?ly`)X +znBMmh@o|JISju-H_HF#ahSs$z=?hLeKZTYnwd$I~JM7VOclvRLTwl;VUr04jD1s03 +zd7x`g$RVbDKWAk2R2^+MR~t}kD*MFVBmxqFd9De_B*M5Iqb&r# +zZsH(0ZXF=!F+^MpfA06b2**JyBcbz03kk79MFa| +zfsovps|k+6s&n|x!M|viNlRRv^bz^A1CP@bMkF<%&=wMP7Xa`kG1fGx^V^W~Xg-+E +z=B>}%W|XQ}C#9fa-C*?Y=0Z$p)DA<7ng12Nq}%n$_bGu%qT2a*Of4D9pTTcjf`h?- +zfI76VJ$={P1R~n+PLC=G%BrW;`LS!Z+<4oC2 +zyb+1{PE;vkBdP6Zvqc?o1)>z7l|U&|iyk_rJa>|FP6s&!1|)NPNynD^z;ZzS2w&0q +zI4RA?H!*r0?$@uqnbyJrN5ecqVl!Lsn$jL`ZftT;*E!iWeF^I@G=coegPpKOnqhEv +z8PA)4&xT={W7(f!St(w(&{jL%L~ZP{{U#xGYjh@ZPAA${;=9h_8BCN-q|+?Fen_8iu$iW~o@%pD1utWq +zmw{6g({WqC!JBY1IOuQ`Pgt~7FRsL^M)!qaFOhaf3r$?-yErG81GrgD4HnHYT(z&J +z3*p2MSVTxm#g<+0V7{=T{OoxtpY +zF@czPIBOxkR2Iz1Iublp)uZayx;WmNyI}KfZttFC|@%BHs`4F;tGUVM-(Vo=ZMFel`Ikl_EGj49CsTvn*GCGdSQhL +zLP50fu$ZXX^p)9acw-wc{0hoqM#0I{z(|VQ+S|2Hs&h!#s6%ocxP(+J2J-S?p=jvi +z>_QkY{6tLWN*m1byb^3I!aTtD_@e$96)L5c=%L$vOnTeTaE0NNwCP*~YrbMyCXPu=Cw)wI)h?HMkDg@B$nsjQ%{oz`6nVmxO +zE$@gz5PW8$cWvJ9bc%HH^;phRQR0H +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 +zrZ!4X0||guhzU> +zwt=&~Q_i2n@bwpWYq!+}D$IfKu5UYi3wYUR1`_)!4strybQLP+rSwdj3Gi&yySNl +zX7+74_-E?0fb-%`H>WpOH|&&pyUKHvSt6hl^NtmoG3h+j7 +zl8|6`TOFo4~$)f!u;;kza{rp2WWrstQ2Jjmc^~{oJg!!`NP*j +zf4DZ0^hxuOKPGU(G$(V!9VlvvE~j4!A|Le^wwx(+0jJQqvyiNZUct=(C$zB^;f?|) +zGL4~l8UMa>gfSb)P3$(CY5Hbb3%3B5{yUpM^64}B2dt*Q%163wIdc^)0@wi<^iJE3 +zp#$+Y@f`)#cv&xJk%$YjN9?p6wDTE^Q15D@xLruUlB#0^u97b5>@Nl{&wv*c%^Q3S +zPwg<6Qd12z1L%clMOvUTpra!c-MD)goztkOLnyyb?DfCK6DcbNap>vD!0;x~U(Zbp +zQ`d++iB;sNKo$zCyu_|iTCf9L?v4`A^0>k5gw!DlRkT@^>t +zo{s{R^)-DgX#WZ->Mp!b|SD4Y;35u0>#LBC!8$Bk2u{Y=;%e#y0|wCui?k@R1qUKBuQ +zgEBh*qelw1iE66?1;RMk><(u}h#21h1RQWOo!4BE-b(?19I-M|ky2c>h{&WG%++*F +zWMI>UjP=DFBL1i?>)}7}*vn;HcIo4Gl-Lj?h2Ld_oCw$d66>}ceTvXl?|@5UVqnme +zOZWq#@B$nWurJTtsrzT9)zA>kBbEx~-kmN#S=7`*FChST)@^yEDXYt)#cafR(SeU& +zI)rB4e)*76vv>K~?)7BTCeRX(?FpdegRf|8nTGBCQ7&^~7{LhUvnw~?kbg!`5fi#q7znYu$+% +z;Gj!9sguy*nJr5SiHjl?n2eQh;+`fi(jVWenMugA2Jg6{O#;HLPbyy6@rL4tnumYS +z`!ev4&ybM4`T*9 +zTb1upU5RgN3+ygH4J>yOazFq>!9)xN$s=9&0q@R0AW#i|cRnj6k8Qm84Rq!8;i_3j +zWwNYW3<{-y<*HuFd%2~Z5cQ|vO^&C)-SYi-?GlX18YWeKy?BM0TBId}8fCY!s|qVM +znQUXe7mF%aX1T*vYylD=*&vQ1asg(OaBNEH*e>f3B?GkJoRNL@tupVza1IDGBj|tt +zVKz*0!+*B-POEMo9?HD=MKK!Yc5Nn&vkhmn7DFn;C}afo3lwKr;SVp;5-f1eX))jI +zWJ@)qXx(M73-O**OW*2<2B{u$VmsN{OyLc9UJv{TzYq*{F@cQE=YU8)*vRf~LjJ?t +zD_jiP)sYe>%oJd$WYnChATp$j>Mo|aHbEtu0Rw;U!J6Z)oSjn_JD30z@aNEJH$`%7 +z#kj87B+bX-)NY10J?BH39bZ7jKdrgpE1RLvIoF#KvuX-A`0cuQ(GUO0UD7%5g*SGD +z|Joju05+@9e{McLH<(1@iW`P3Qp_V`~VnedE3jrGq%JFwK5fbZ!B +zPzDiZE&YEI9F6-0m7JT8&~2bnCTG~@gRw0hHz+!MJVJXm`>W5QbPnV>3rs>V$UQ|K +zMlVJ$c1IdS66&DzwyzQd5%$0zDCu=Z?l^6eLzWTv5hdpexQT3ME +zkGdgM@%B&5#Y4rI!6p?-X9Wj1ub+B>a4(ywwj@C<;O9GV=@bz!^(Ts%4sid)DfngwP3vYCs{4CEVWcrQL|QR +z`~<0J6atRLB@x-{20Ox|Gw8@f47Z_X`r8)LJE-%p9fWYllM-F=#!hrrI3K72BHBx5 +zV*w{hoFyU@&DIb>dosJUo5APDp=YdhM1%NHC8caqChRc6hWYGDOu2SB=g*|Od=|o% +z6Ny2TVW#-t-u!&Ip%8Y{zGpUQNKuh4C&WrNg-62r?{tIpClYG*c9J*q729J*bz8-x +zEVv5cScAzb^N0B>NUcoinpijD-Jq}9uLt&1^gim_pC!K++|^Its)t9FHU;wpp+47h_`Sj6!dSr_ +zB=WW%QMGJ_3D>-ZR7F@>!Os5Im6-V^Jk|nNQ~|$BegAIuV#SFyRm4>s1%l+Fqo%Is +zQhyF$dqGkMI;eCBmRhxBpg6^I}<(n*x#$i>Cy9Ou1?^QXDmz!ri +zX~1K`N9wckC_;lIW5Z_`OfJvWO0Mo%G5u8ga>G@13*Vw|Aj +zy2f83BL2`OQ?4 +z0Jk96?T4GI-%O8P^wOXe#e8~at#wOBu=X7%Xrb_TF`bTZr#-WQEde#aR&yKf2&&0e +zGPVNzT5&hVl=}bU)nAPIIk}MkO8!o;cd;L-Xlj2%*yOtUXZagpoqb1{XO?l6AAS0M +zD|6cH2WoC_%j+ldS3QZpfeg?JC~R;fgec>qQ5UeWru3uC!R@y^l)5ofc(^2w;o=8i +zhPTqG#b8z0QMo=%a-Wa)Ia^=ZK!8*ZOfX;qD+te1_l%hfs|qXrY_f*ZqSmp`ZD}d~ +z?Er!}FRdkQ#aj4SlIQ-+IRjoqss4$>2vW!X2k(D7^oTUkCNE2RG7T@qSf*@jJERnkGi +z3SLUpFA@v=1$YTMSay>ba8NbHE7z$=w~16tBwQx2R6AwP@l6h|Ppm->F)%UpGrcP` +zCbiT~ikbVN1(#ES;5L&Ij~1qWe$1KIWjWYFri?K7MME{Ajw_n1{<|z>ZiR8a2$11| +zcbRe%dsyJdD6ReM#L{$kIhmMw;2Kfv3G&6F{EDh_4Wx)w0Sa<$`6d4yv>?&}#_tL$ +zg5d(^3SA8A&|4<7RC)k7+psZ*>V8-9$g`MhEHHz{&uvYSQ&z>awpjit70oAUu4 +zB7IfCx!Y+OBQ}L1CdJ$JEf2*|nN345cu#rtvw2@Yq}888nfOjwbEO{DWO{>0tHN3% +zfA^cAFn-~e$v>IQY{18#uk0gubfu&Yir|fu^DF%5?*j2j?C_>yHP@x +z>u&eOgd1;t=RS2`!)xf>P-$giQ=xsfsMUZCq$W7yu{;At;mROB#`uNOW@M`F<8-^>l^h +zf>L5Iz%TY}(shy?v|vDgYGO%9OeBh9dA#&;=b-fxnq@w;T6McItvCliC7*M$r*&5>WU_WtFx0>b{7qS(Ar0 +z?~ezd2;1)z&eQTr488DdX3gh16L>^3hg+_UAaxjo9r=6g@5wG$$PZQ`i4Fa!1qVnA +z7m?KkD4fF?#-vCrsLG*Nz&oDM5Zt44iAy;TrHi46+fB~+w6Y#Eow27TSa?8>*!rOo +zSZAGY7Rq1itT}HTxNd*G06Lx$nI5X+ +zdVWV+$~*4+=q`Gai)O$Kmd+)#%_?de97Nbvkz#W +zsA54Ub8M;j4U=0^X~iSi2+pVYxSEf6aJOw|5btXSth;~FtP>iVQfVcFSi;}(^>@WY +zuOz9hy0{E)CdLr9_@&Pndvcfo5DlhxhfCN6YpEHU%` +zf<6-F3SPuw`f6CL`0ApN>Fc{j6Shc&Fw7rT*phM8P-%ambg;2R69#4c4j?$d$AHf5 +z%A>eI-IwwY4#iL@$4=jADF?lMV_F>12CU&MmD=^LV_bn9`SpX6QPM~2Zs2hl|7KgE +zV~oGG>lpH@wjaDdPm42^YP$?5+Zd~dEE +zNg|^ly`Q2vGT&BgA=*&99n-TpevX1TkYA5bbcx{~vMsWg(>3mtp$WGdBFH_R?C8^bnrKA^cF2W(ppj%L+?YUXe($&XwvUD#lFbwstjA~V +z$;xrxG8AQ1JY|itf}@y*8&%9^94L_B#ECnmZ& +z6siwqueYLuVWK6>m5IZilUm3I{&@GF`o77qy{SI=#Pv|%RZNNeQEh?4Zz@ +zQMPJ!QP}Z-9U-N+0s7aIe|WJyoI~p7bPq+(UdJz2C174* +ztc(4hxVQJFJ3rn<{_$N@=wWMjJeDr-1^Uo#9*}g$dnC7jzPlXbBHVS$6cjb1Y%=ff +ze$sf`y*lL;cp1Kv{~UgO?oWTbpo4ZPwk?Mrx9|Ss>XgCvd#3i8y*=$~t=(=tzT!(s +z_j_Oh#Ei^lbN6>^!;34|*~)g^4h;K048UTpfc0f@DA|Jvnna@w{ucjlCWFcGV4?s8 +zhy{{UY6gwp>pTRA-vu1GKaR-g9wYpBNSvzxDK +zUHN$Jt&MK5@Q%?FgZ-!xo2fhxK2hj>`0Ep@@W%k1;3k7_TyUy( +z--c9lsg}>?aCiVpq-{&3dk$h#hKXyAui%<)51KfMh?N-VlmrV6im<4ZJ*+i0`#3(7 +z8mGnro@jt^p)36Wd!)UbEf$61f(Bo7Pr)e+CW0S7l4<)cM#C=BtcyZoSk=A|K#U_KR^3uX*}m< +zyjj1%k-`h1-sZc&40(Z8dm+h%_=%nex;dHAFX_J3FAwXy)x3g6nazPfUnB{XedWq)55X3y24Mm)TmiT_M2@!GnQ)l{Ljq``d +za&rYMD9N+6V=3ePefhmA&xcb41RpBjM+!O8hCgCKYWWB2grfKurqp +z?II#sPZAHOS$MHpL_=gW10&QC72vYHr&-cBQc=rq*DPM7CvC5k$yOIvN342aLa#W^ +z(Xr!xm;Q(m5Zy|sn3seMp(iHPh_bF8$h-{+C>4og*g!YP4BRrcHbthFJNoteDuUpY +z)v~28*cE`Hf}t4|^jMZD*D|&;K~i$+W{@fTJwtM8xMgvBhl}vPeDN7{=aMa5M2m#@ +zlkX&Q?&J4F;dgn7{PS9HIu?#WlRyTh;h$wN_-5AOT2LVO +zo_|19ap0ipTC@GY$`pVec)5a*Ggp#CCSMX$-ZT4ie +zy`1j`k;}y9wrH+h0muz?p~N4-WiZziYUToe-T8B+W%R8()&9X2-}r7+XD5h;T#(71 +zBwd)0jbzm~vwqBXlhAB8pV!iB`#d0w!t53F2E*@bEOFcKNB9#ijLOvYyR;?0`C7>@ +zN%U=g-+#0@x)o#>(g)iEwvV+Cm5-I@?vDVKxH1+#zNrtNEKlyJU5bvs%IU1e4e*Pz +zUxJ0E^e>n?G7G?elLNT-IfOYuw0|j%fza05pnf=kQG7=a;jB?QZ6T&wB{0tnf3Y2)w>;vw9;BT_ZPmtUM? +ziv|GLR5mt2lad~zu85J>dpkv9CZR2;3**@M5f5OgNz(4BVV9(3)tFsq*X-p1^rU`Ak!)s%zWg*T$Cv*-rujKR&M15Uuchj_| +zDLHmRE>*bzm=&{kpfln7{=?R|oS>%x-T}MbjR6b4XhM;K#>eS$PWLj%`0K(u4vo-q_g5Y~yA|+@m~|9n3KW5s!-+Oi +zNn_>e2h8tu&OnAAUfs%})MA)E!bQJNz +zbPw3jQH#(~sDI|)TPThII6$>vX4K9jZdqKaR1F3kf7G%`=pkG;hjG?s$XQ(SSdmzC +zWb48~4LSk!(-!~ta2S-(J9UZ5GK2qP9Jzl!*9`3XJOXB_TS4inQU00&1N@fS0nv7{ +zNyzl31f!uC`#}Tz0%L|{4x+G^u0O$QK5t6zELz+G>g?0@8|&vr3Z*aaXo${D;-=lT +z<|(jK`+4DHz*FWT=G%)7q3Bh9@K0E}>*w8jtBZFdq%Dl>ePpxwYugi%bvfJ*tA6HM +zRPCBRh+iaUzg#;~&@USC{5X>21&1sp1BPU;?RAgKwT0f-i(Y~Ia7CYkP({C|%G#Yp +z1)OGbuKXd>GOYjYC28y{TLQaGre-4~p~)cT)etL>L)g~px&7oKQ#3uEk~laZ^9#M^ +zN#_S&%p7ils~%Zy|0^BccT7wf&0YpIGq#zcLso$7pYd=P;`Hpt-=lN0wxQ3@5lJ=^ +zDW6AeA^l;6U_k0+w2COM#-OO2Fbfw|3Thj{1yoWRY%xa>e$t-y;HON$d8lJ$oJEtu +zu2XAI5H{lfN(NcB!qzhqD~esw%U;{kVRzv +zGgBH-^W398U;S8Vu4u9wwKR>XvWb788=>#p$1zHDJw8DEg~tZRHyoC}Z^vxY^u<`| +zlS&q7K@BmU38>4W#FLnFhdWOWN0*zS4WWpv=;`_ar|Y|Bz|zlEwxNowX9OK4tT`UN +z{zQ6nJBNSP{t*ic==16lLZJC%qz637js4`!purQ1R#S)qZxG9kyo(9DFA2 +z|1ZFOiDM&D0_p$OqVVE&+cuwH^ne1Zgk1Y^6B5r4z?si=7MISaO>7w=Ob!r!K>>P) +zA;Y~`FqI&UvQOiR2oWDVGAWrexSrpQ?17aFOXg~nCenid;!u4Q?pQS@LM6n4Q~GjQ +zsA9!6T_AOr(_7}sz=xKZcriRRjXjj(;uMkjZ=27B){*Ep=L(x%UJewRHQ1YbU$E(aV?|;X8=g +z<8ZyJM&r6@zNm;;jS+VDCvrb&Hu+B!kW1&Wi%ynR_Pd%w$ +zXii1iy7f|Jx*1t$8N=YKo@V|ZXAlYimxbi$8W6uXXVh=RrD_X?M!07$(|6? +zSk9%WxpZKWwdaCDGAbO&cn40-3k)2a3=+yjN^v7)HGWqrk>M_q$4r2jPM&qdq!c)D +zu?~z3qgXBj6xi^Vkj2c1lFh}OU+(~zuT$yKOS<$U+Jp1Dfwd9MT^|S14vFkX{cI74 +zL&A +zW01J-p#ij*N*BL7vMf$kC}>`q)Q(=x{Sr4+6>5J$YJ7&L6og&gdzu}yP({3U?r$|4 +zkm`mSf6nflR>rL3mG|NARhs+(3%;JxSDI;g8h?++lA#yGs@*?;_O6%D{hrPaN$yGW +zX!`2aLbKp3Gf4C>-x%S)&xJw-f1h~vhc_=auk$WCW+WH5aUAp(T%-9k +zp3t=2;GC^6_yxmkW@@A`$kf+iO +z*?CV%Cq%Zu9hYDO1&AKe+{IA)lw2}ex0B;xMB8E32MO^Y;fM=`9Dk)bBBhI0Q6XUd +zJ9ow4Si~YS4fu`-ar=wCD!p>x&A$;l5r7iox=}_gf+Xgv?S5Nj4;Q^SxiwZ4fg +zNp{KWr4Zzd7W8P`AjIub7d}O!88Jb6xVWXyuQ=l772J^%pa^U!(g74RSXOqQ*jRhJ +zYTl~k-uyRY_=lB0fwAB(dlclxf`S{JVXtWsOFay(G99;9 +z2=$BhY^=F+eZNqq<%@ljkbBLXAA`y4jk-d8yXg^$BE8&eqhx;`HJ|+H6r6}miv}i7 +zt?$K1gHL!QHL-1g+Rew{L(P0*Tjo9@uW$!6AL1ok=L=+}{k~w=t*zPBxsXs7q2W*9 +zJgO${ukYPMUR1&7@@P)O4u+d_-W5xFY|oxh@s%@leROW1hKRwNORu@yW$Y-lc3qZZ +zt9X{lkvr|cpVx`%tg>TZr@mYu#{F53cVlzK{Z$VBVYv#gvpctNtcp|noB;(3-BJ6Rsw1;5ux_2t?%Soyq|Q!_x$ovIOD(Wf9^(LTz7kX +z2OAy89W8!n$TFGJ#2{Jl;k=wwECk*3h^X`T_xF^KB|RfDpO;ZyzNWtMrR>Db(Q&Bn +zJ)q&fCg?D+1Bh=LqmL_2ioLAh5j<3kY^#F`q<52B6LGI0!1z~Sp-KOU52{&uY3l&* +zzi2M0!Rt_=*;Z2i&C*a^D=Uj=;x9il@-G#qH@xN%ECeF;N{lcz46~z&cL)^`wfxz! +z9tmXa$ +zo(Bv<^fz+Q`41k!9<#S4*~OZ^WjF3dOr0q=*=E9JU5#4RQFbKjMlxDwN3(V4;Jzqv +zx$SrYzOHnN#^}t9g9oCy)Jz;63YgS^Ro+bpZSAQbOC=2}ZDj`zP#96EzL>aL_rwHm +zrNB+yzbZvi#)l!4_zfGjaWDryBj2*cTh57jSwz*z;gI +zIc)yOHPUDOM1imec=c?&ZJ`npfU+JFcfh^OaQlLV1!SmFn#b1l@_00O$VT7r^XnH}7S**O7I5t~-B4#` +zh?=%sKuyWR=M?ZvRjtbHHoy3E<4opaF};iE-G+i2!Ut{Rho*&VTVZ?Rr`;vynSOIW +z=d>u7#S&lQYRlGak}WlJtip>| +zczV5*r-%D*%>74lKV!!HKDc|Aucs+8TMEkMt4qG5TBd(}X&Zh2oCP_@TaidGwyM->r +zdg)OGQW6V-DqwCAf%$2Kdb98&-R`w1AC}T!LIfLwoIlOnygB<{&wjC}rcXA>1Aj?c +zA+C@j-Aj;#Uk^Jm`*1+TttqQ5*a-ccilE$5lbNDv{~B$=bd~@8In5x!cCxyYe-Rap(N7{vgrFT5Yi0k4@>7sr4 +z%(h{A;n{tq33~M+()kE*x-&b~Vz>Od6n>kMd(m!CQkFYeaE`iD9i_{D#O`L0jLR`q +zqza&Q3v7IwxMg<49}}OP1fY_iz(9Tv<=@=At2SGmzWx5>+A+L8^Y3}Zkc~WTAl8HW +zeg@3m>H_-4-mL2!g`MDR*R=QBhxARI4EEq17( +zTlfDE;|7T7-;S!r*@^A_TGC}WlJ(ht#I_3L7PvnLVS&tn0^SB76zKA|JsSyI*EhW~ +zq?|lGoy8xK1BtiO&E)V=?}P_?pXH&D`7C}YKjw7G?AG#OTegNwqB^HiVQ&u^0)e>j +zpKZD692S3lY-%Lxp9wE8Q(PJ4{CQl`%WQCItAzx7NxkRkjiY;VYDmwFI`&5-sKCC9 +zxutM9$kj62x43_`ccjtY4=={5XpFdSGK>)V-_O0g`F=FQBEN~;TDuF3wZeW#%=|1? +zvw#2gHpG3?Jp}sMTks`Bu;BF}3-H%uf1UV*4ci4_%T^CkzkAZT257vPExRaejiAcE>?X=-{jknjIL0Oz)(7E5k# +z-v!PR$wSTLQHQ#w*zch*B=Oq4m7&OzrFK|&sM&1W$NpM;xSr1}-XJDv6P|g^K^N9V +zz_z2%KX$7P;-RjmD3f)k{dt5kT)o6gtrlsSKA_^BXgd(G0s^GqSxhF2tYx%1YnVRZ +za&K2so^X%%83&!0hB-wGcnr59=hb9(r7{+RFnj4Vrm!9${P`8Z8^L>2IOe8UFdzK< +z0!#j1-JN#|cT5FmgUW~5QDR?3h__%iaR~bE;h7OG0E3iYu-$a2e&7=y9Q;@edKuRI +zcDOFpe-Y+~25=B4PU+=axIkj&LMh2uLL#^b&NVrJf2>3SOIymW1epH<@FmcdCStf0Z>#b@t$Mt%0~bsKV)wRvLR;qC +zA(x>)yhB4_I&cl91^Vz_O@p!s2#lDUL3ZVW$@?WnZ&* +zJ~J|y(^o&pw0#KeWJSF$;VQ9>$n?N}KRUvVt#q2hk+BtX>2FcgdRoLk=_+?Xw|yJ{ +zBrU;4EIcFC1Dv?&dJfxz3q%~LWtLhM?H?dtdNGAN&c)kdYJ0Cgy29{U`E!Cl8%9SW=Ir##gVs(psGwNl%|XGHxD5vs&MG-%_U!KO?hI330pM$YMX1 +zd3r5+QN$gAJg_{7{f>H;`N!<9w?6IyE)bpfh$4uKQZf7P@-8F{5ng{wx#xJa(KuEM +zFfclW=?^lAAmx-Auo|d2 +z5ON`y7H168*jCBTxU%tn=RiUPCJsn +z$#hDlE04i*G&`fx1ybA)V947Jg{18CIZx0Eem`5p!$vBh!G{IEVVr6kG3yee3FqBc +zR`!R_J?LwRfVr?oE3$J8T6o(Ne0f6F_w10S+)_jOc06*&SvxI{@0aU4q83+IYmGW{ +zyH7q)QRQ8_QcIx2hQ;LKIP#7A*~;cN?ANVKGb2gPyC0SVC}f0}T?a_SRR$;=`k@1j +zhdhz(d$;)p{-j>?{uD;qKO{zCdYXM9Z5wiN+HFtVx%vH}}Kd3E#g{F@oZ0dZXMe%thnwh40sGxUV}IbhaL9MNZ!aeC2lDrR6;lx +z3`X_`?wAn*_XwBCL+%jgx;;x*LZVSVehH +zl=ZF$Zj(SwQEhN1W}GXtIYC7n9RPw&FiGE$5=9ngYZ#-SB(AXn7>lS~;>;`>&t%6t +z-(a$Hw#f0vx9Oc~8b|@7u)Ig?oTyOwveusx>vtrtzE^0Htf+c)W!euYGqc74=sy{#dq2;S)O6?d^ZN0~ecflP9bCKfu+>*gxvXD3^RRm30kxaR +zN#@)SJPrRk>E1QiFNzrG5T|yyZ3WV@H6jXPYjs@vFz#ab?aV4$c>pkLmwQXoIHO+%0HaD +zh&rGABfVgWJ+*r(aa}(oQF>6Y-=~s0w!Tv=E4?MK6MapR3jObYrvT8@pN?9vFdtYU(F +zMs`FOY#X~9MBwAsXL0ZS(jB|A`bHZhbo`DPuGFQXl}GVZ1kp`ttIWLZX|I&mV1qRX +za2hzAU!Oc;EA2QbcF9F){dhU?qr?I>a3`xCv>xu2KA=n9DeABR89O8KUIqXgONv +zE3bu9`XN)z3p(AP%MvpwCIEGYnJkdD^QblQ20X6m-xNWTbkdury0ZT2Q=Bq55_9Bz +zSn{uA8`SvM_bBIt8-*>IbRr7$u{)d@5iaXjk((HCYM`_@4}Z4PNA +ze_I-F&Jz~0U+@hMln9&ym4T_m5mLj<)yJPm0Tu2$0YU7OCr|fy6NIc%S!5LinRe{ASoy21f%As7;n6ig27HhJH895 +zO!l4v20V8ll#*GjnyDy}v#kkA_>##VyLVwwNEr^E)fS^C7 +z=rwnwvO>tCl82j-J7&E86H}B#-R^K`LH~56RYv=TUO;%FG%5Adye@r+%kOK3@~eA_ +z?bgn&)}&dDYoEZ)`}O!o&dEkT*8`&tGvp#*Puz}e;#YVjMeBB@gOQ5Rm+Go_2%s1Xad>gD5$ +zsdX@Ly=HQiBc~LH%!yb5vY-{KgGqvS|J|S=fw7`Bh~Iy7g&!$`r(b=IdYeii9NtYa!mM_gi4x>S0<#x +zoXssNEav=>VJSSG9*B0w%qk|rJc<{MRSw9rhryN?vvM*U5hFf9MtcN#B8MEmMUUCB +zXCWk@(B#|w6gB$@)twnW!k6|-8b8M`^y{1F$jI})?!L;eU1{RCLmj$gWeIk*QkK%Hj^Z5&xnj1jU)8zhKrW^F-$4S;^0NuX=`4ejQ*JO5N3Sc2V8RO +z;z4ruY?aj418<=-M?FF04F!E@HLtR1e9uSjjtot6;8e`9)Bv5i9`_d%z;zlAao7s6 +zk09iPto8IFsc@pgGWW5>t}cORp=2Dohfw^FVEX&eO~5AIG5;|CnU%#i&yITRnM6ehL$^6;Z&iq_O8^_z2NqG`zxl&fep3CoY%FHJ=0ay}q!JATXR^`BApH +zWOirP#F;~batp+xMn+-!$xjg)As1&ybmw@tKGFxNVC)1X9dnM9hbXJtu%n3e*0b{x +zQ>&Fp|G@!8OMPNW#W@ZTD1jRgT*;Y~X`1PYyTrm!E5)Vp{&k`kG5@7Ss+eDvp{SK*mpb-b`B4Hq5by;Q +zkHEd?PdaP+v@9zd#2Dq2=>o?PcxI^YFX1cxiGgw5VbV8<4_JErHNH6RM$U;wDa7k? +zTa#Ru&NYUS(s2Mm>{Rvr)-wtHE>?!iXp={ES6|{P10tO!xNcK~PvaV6(I>tk!Q4g0 +zc;z!+?q)~GKDZ#?M?d0xf$|FoL1p#53IM2?X?`_^B&T}#yUCZaHm5( +za`l0qjcR(JhdZrYsFFaU8`Yi1`v;!cdbq9l_YaTi_)A3HTD;M~#pax2KDx~9v+Ksz +zeEFT+v7w+MG#5CYj+WM&e@bdN%Nn +zJpLqWk@J2lRKpdT2TuUI!7#TW7dJKfg}%`3;A +za_bDPz2P8QE8ay?Cfkk_?!bvkZ&{3E7zx-e1CcDhc_QA9CE|A*rT7a0p*AXwQM6vI +zq_RaT;ED&+F-i(s$=8Z3As#u5w_GuNP!M|9w8r7WA(weLosCpxig)&_KuH;8$=DYz +z=U?$hEFY_sVoD?aApxvj;)U@Zv25S9N11y1(-P6M0Dz+cHiS`fd~gaU@& +z9zw=(-ky22mc4W;r9l8>gcZNpxL(~BU>IVcU+{87m(18#7EU$u;>C)3!6o=_3Jm;- +z0`@`zePk1ptW`{MqtYg*wK2uj^eOESYCd#mXzxB9^YrRSxV~R+XU|#ZOVi^TpSe?a +z{6kqA8k)%PAKX`gl5^>hXs}U!)8QO{s53__4EgddKPQqAu+4 +zd2qVX9NdsftMWPJ1V@I2Oky3JbZPpLKW#*`sZr)XsC8?!!bjy;ZbaqL};u2g23*8WgfD2BCwBBm@1%~T% +zUPPffIsc+@bhgiN^crrHop?tSDQE04Z+%v3q)AT=3PkvT`|>6mqp$>9ZZnfX>ScJha{st|iEnZD=PPyh@Q2H*qIF_4kP+0s +z98=nW)!FCjaWGA|FJ2vg@MRG25~x~wQfC|O#`}pM +zvsw8}5d7_75O)r%@&%khQD4Qf+wClvIw_!|qmx*(Q`l!OPi+3*hK8f94E1-pg;)TA +zSN>!O7&-i2XYdoy-LdP&lG;OHk422bT6bf_CF(=ol4-2X4SP> +z1{XaGLhRA1x$j{d7Ib6AXpP1ei}e=?No4l#;pNzl-}cC_{oiF2EUKy +zbo969JpG=5%v%_ZM!M%rr>vC4psV=DW2f38k*-n`T-tiOW-9rm6tg)~ox#O`C^I(K +zL6=^;B>O!-wL;=*V1gc^SteAIoDdot@!866LHl=k9R=^J4k+CiVtNVm(vq_L?0$G% +ze4_oI`^Tqb-){(e2_LFv6PqVjUvRO5-*}_&b9lZ$416w>H?W;j?PsqKR}}=tPB|E_ +zd1S%6avATII|+rU#AjXv*y29_Zi@C1LVUC53-EW83=Y^6o~BG5Q(?$Eaigx<4%4X> +zN~sT6C9myeY3>pQ`po6Z(IBRRt6Y!c9^O&sDQ-$GmoPAJ)`l*N4GNBoM<6q+1d+VA +zZA_{zY6&eY<_ua~y@wU@?$S%MU3g+*CV&@C_XmRO^p+vP@Ti>HN63xoLd-vA3OXsn=e +zWRRqkxp5opZTpaa=-!Q2iDhazvOQ;iNkkfl;!HpT>&XmX>X!aI+`7m5XYA4w%5+r7 +zogJ{8-{s=_MCNk4Fg$cYhwRyBdjw!cLe^}$F$-){TSqcx`#CCwb1vs(3ikc@nfQP| +z3od(RbF;@`Q4?DLAZ+DJ3oW@+29r??q=I5Ov%H0HJs@7`Zh3Q)1m!0i;#61!4ZuM7 +zYH@+v&O|)~&y$o?V!{P|gF(%ehGK`!AG$ITWy5EXo1KxsM+DQ=r^}a{27VF~XX8O0JCo0v{OK(1zcelmdgS#lfIh3cNlgw%FTx@4Bz3 +zl0CCGg0Frjh*^wa{)b1wK9s$6ydk`ugYVnV5WPO{iRy`7d--nm-r2hrp9ua_ +z-ifmn)=7>`clBZc3ITsaFo8RumHbVV0_N64+wkNoWN +zZpauL)CIf5f?%A!97H7}J^fCjdMOJMRVMrDx%X=8(jTz6RMMZq^kmeS$?<2R_$>gl +z5iAe7y^;~rRlh4T?v`Sg{^aDFz?+LP& +zy78xe(+CTqqo%P=2?#A`HN3`{nS>-KCI_4C3Eo{EdHlGR_bpIW%+$Nx*n&}nUo<$W>MvMbsE}4T2Ianw=E_X|FaH# +zQqZ!S5t4LlOF6puLM*3Sf&jqs>d`LaJnheB0&!8U?XSd*1B>o|M(f4dG^WKme}1&> +z=-1dv6{>f29+loT)e_e#oF3@GM=2zL@`875B2zbvz{JMdW|we!xowMj;r>xh%Ad3P +zNztB^+2T>tW+Ogvc7dCF6XG91TN1#`ShO~J0kT(_C_f-MZgUw&? +zq-jAG1D=EvL(r#ZyCx9Iqnji3_3&EQYnsWUy`#_Ex-uWLOQ{gD72qpXVIVB-+}7IF +z|KfH6HMEEIta%{PgQf0iyPR+e7qyx*iG11+^wsqGIDmu8j=T8ih)0jS{N0?0cq?n~ +z&#QCbgkMG(@bkUq4uD9oug1rF--^fiCxVy^ydOLjcy-oU)5tv8GEVjnX#DqwXg{YL +z5#i1u;aUwqzaQJKCZSU&8<@T*-}jqyL9fAjAU;>W3_zy`bt?qqE3BB#VTya6qeojqNxmy;7S#YCo4m`cec@<+J@2c$j};$jB*e +zTq|C*IcRc=n-ASI;1u@nCf@@~AY3x@s8znU-O29jHPF`fIslaB`gwc7{BMn#0QnID +zL_7dfTDKulBn*{DQgStt3g&A}n@OV6&zdZ>WOuasO+~suOUS#=DnDt@ic-*|e=Pyx +zlte03OFFBQyUIkUlio)G&5dib3XX`s<$Lo_sFG<+ll5Qae|I6!0fyGr9?7ToHG4+h +z)IG;2yZ<47&bt=Ki5*p%n#n_up@KJS@7$tQd$lV>Gpyh}BMEZWH~%{u(!BO=;nR;nj{zZ@)BkWO_{i5EYp%9Y8m-skleaB! +zBog<7bvCnh>kX>+e#Lof|5^_0;4t88{N6O{5Xb-KvUIW30rGWZQBm-#Q&v{i-)rl6 +zn*s-oJ{1Dg9gA8dT^6UyYmN#_Xx%Vlsj1#v*lS~3kd!}n=w*aXR&SJNL;zPCv7x1u +zQ*Y%NPC&J<*e&qpYU<9-m!fC$2KbvV|I!p;@0VpJZ)NWLbWxj0V1Ov!5-)A_9iVw3(#lh +zzt%jO>-P?bRDJ!A(Ra_M3kkjgJGs`%s4@h4CQkb%ty{<1rslE-B~_v<4uFN??jY$| +z^Ee%P> +zI)yDph+n4v(t-gTFn`ZS%&k-5P|y;M|C*>JGlA?*Rq*yq^tElq?lP@3SciVSdPOyn +z737N^nOFMbY>VpyoC005m|8uBjsM+u;Q76~T*ws|CB7iaJLWEfUUci(=4T27V1WR9 +zoq5jEFjIIV|4WdC;79x?VU~iFV@cc$-mO$QUl#z9Z_Avy$A5KposanVw-wbG +z_O|lx1amq$UA_Md{|kM3)b7^M8&!aJw`PW_K1% +z9n|g`-;f}ezhHJ?>Q`akq!2Wd!Di0s>aI_m0nfJ+nc$>_8#EsDGo4H4-pD>*38Ab( +zrsxyO!WRwbnRl=^Crw&Ouzd(NFltK}Y$cw6+G(oaE!SoZxC7Yh)xU?J{15+VY9RT| +zu=$eE2s`zUXH`$KT=CL~p`xt5#q9)<(M@tEYjjeam#i`}9Im6}RCv(Bcd#TlOao}` +ze8mQ&-$<>l#S*HE`@dPi2 +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 +zOUFu=f{ +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 +zHETRcB@@X^C`CQ02L| +z-#wzOx$&wUvu2On8Pi60=ae)3NMPlM2b1AVxeJ4TbWDHZu47x*==ypk?1+@-=1=}o +z=qXvpb;#4M`4M3m?r+jYJt3C4EWtbUxO4ZmXB`Ns6?x>>)TaET96W^2{rmX0>( +zU@=N)RQH=BH>Cvl%C72`EM*IO`)lE?QWB=WRDs7Anb5nTJ4zbDdPrXr9)v@MnU=*7 +zW2ZE~T9pWJ`zjfM7%geA*&Xo9_}ZiaZ^|JP7OtMp7TXp +zYWHJv&3|l0=-@pT?=IvDd0Gfa-EC^A~OW%Yltp=wk+e-z4T;KA9$V&_#U%* +zika@j=sMuNEoR~v61ucp=Q|F_I;Si#(@|3?l#IeKOUA{5G^cn71z)U4AcUw)J9VE9 +z(?;pB8aElOS%ZI(Q94$;a4revbJo-Dj}&1N3NdQ{fwzkzHh +z%rTq`o7{`+fSZna*fr755D&sT!g%Oye+O<-N*@1Ivf^%bXrZsUlPnq%lg%Pqs`AbJ +z5Gh!M`OgDAzfF#qGO7VnylyQJ>1}D7thw!xcS+%}?? +z89d=6JCBs<9Pu#K6?d@yySZn=zdcw`iRR$Kp}MqRSl#_Mzx!u?7rvz5p#A3RRnSjIw;)Z|SmCXmXh +zQW7sJrhGE5$pYMzZaPhZB{>@el|52gFIi^8oHDvek5JRoMj9vJ$@pp +zF6@Xqx)I#KzoLf)?i0Y7CAU!SJ9TmIq?F>}@{V}fBN6n#*V)nWQ9Yf-)$9rQ2M>7b +zRcKi}JS@2eF|AGQ70{3BOyy$}$a~#RBbWuvMQ;r`5%*M#H=uUI+^c{rgy~H-nRhgb +z?LybzBql!glI^js@3 +zf&aI_jHO(l6!!{SsZNzbpJYgSf({zR2zrq*XDB2JzWvzNJa?H6Ga53>$Za|SWFAWJ +z=?Ob0V!18?Yq)#?EdWZJP*SsO1tOc7S?~!GWcV1tg05TS8%mQBG2ce +zmKo{$_iIaeeMda=2Zu|*aus?}b>GEDek1KuU?rod1)-uhdqYIeiL9w?@6EJv@;xQ# +zBPTzA$!2t~XUn>H%IdjBlF$Xb_^URUr5#v(%^-FC;IfY{f)!W)i1T1o`&bG(T?XN&Ln +zmT7ByyBSq9i=Lz0s%}+dk?d~#x%Sn2ON-?qWSPzFoW$m8s_rsu1IN?96LKnor_nA- +zeDn0}Vga1Wr?cHxhr(w)jmmnRidM~f>|uFn={z}bF9{U$PW4g9++Rlh%d$5@E5f_A +zVXVQP4;_$&*rly&L`?3~i%VL^3C)fF9rIF>iPQ-h%KfN1>7)gKq?96Lu6e5DTFqtG$x+BF&D +zB=4*R{v-S+uy1p^U1>i9l>di@@-ZnneDG+4+CL(NNS~SDA+m`rzX3WXLBbIL(^bgY +zB1yj^Y{pZ<_@>L5JHuGsaFS)P3CDB+wYY&n#5H{22OZ{MoAtblu>Brd+~1VeoAj&S@#OeIjd(WylFM`2eUB-4!2T7Hp8zX`{D=2sIW7|PDEruTxz+Hx@$hPCE- +z^r{;hl`sRJXkA}HY2KUUE$j>XWL(=&qggi5Eo3+s4hChEdw~aEiRIY-g)ICwH;Z;@ +zW?rI>%i(Tn5~O)>+s^S3*T1r{&Mn+2Ss%>4;7XpfisH!DY!6ImLx*FQbEoQ1 +zzG*xdycEHs(J9F5oCf13^A8(eZaw(#NGNE6>;T6hJxbL*p|;OyoFaT<@X`gUhpv~> +zPu+19CE$Q-8&16^s^JabSvD>yvI~Xvn)*XAO@GP}D+iem<^yyN%({;FPs>mGxwa$y +z$)iW(u>G^&-4lbG6YgX82NZseR~sD90QLVT5o1(xa(ON25ty*jWkNHrqyA?xP<4D$ +z-wgQ9o8z7yvhE5gQ3SxJV2&yB;!Tw(;&j0538{xIzC1V*+KI`kjN6%;B`HqCfY0X$H;QdX1%+bXx*v +zNf}45Vtr)BAT@dZW$NQb+VRr#}Wq6LzJ7HWV27p#-VuSI84SM!DrSGN>{SCg_Vt; +z^b_7-{9m%8syoehd2i`@6SkkE26&=lT|PCsRSh8XniKd|@JTLNsuGUo7l<}L;-KFvSYh}RFmZ%Ty4wD*2-rNVXDS}5|%@hJN +z#hi-D-TtW-`SZO?lV{5IpT~4Bz3il +z0<%Ji>A(j< +z{+RVeN(#8PCF +zUnUgmr+`GD-A}mUuR3e>t8LO +zuFDPXjjcUu%T>k)WNg^nZ%Ip(T4e*TvgP(oaP0$f)s?~&uqd3nLSy}gEJ1} +zNqB^mJb^AS%_FVwKfKGdoP#Q_r7;;=C<*nmvfu?%6yQPcp(< +zRD?(KBpEg6A#=lIxaM>;kU+r^>mkslJ_@6-1Vl`Uz-Qdi{H0cEI0`g89^}MPxD7*a +zzM&(oK-$)KnI1#js8B*pc+Dxr0q#wk2KYn?t))}BhKwTiO0k|twZjoQGX_{pP0C~} +zPmUM|)@QbvIs>jgn80v`7|s(`{+5(1a#kN^F!6GTKqt}!M~43`@!XIK708(j3VCs1 +zOrSy_2GeGl1;PhnQsS|xx|3v@X>lQjvm{Iu$Ng;(S7qBPi1lSs6zlgb2pq@?;6Hg{SYNkC9;M}0DX4xK;JFnBcS1y +zsR%~kJP6co1_)H5{)8@T(_SNm5Q=p+g9JL~7cjbV;6OtDvVR32jw;0im6|_lK^Y1T +zh3671;S0?GoD|_w*#bEPgSBuXEKT}2Ag3Nwou2?aTq$kCRT&|7W#soH_cp>`q@6ua +zNcM2Q)UcQ#Y!AFokU5CnTb)?-f;b>FMF(=p{-7i|n$0p>r<5Jm?j?scMQFt8<|BJ9 +z2%#4i^MIbnSHCWE;adIp7@HGd|7-eDp7!O`39xANaq{#b!YMr1LN&c+UE>YIlDv9LWIQd3|F^V0vnm( +z#v9-usdJY^L~oZ*%E_5`b+nKYOB+hrp7UQDa=JO3!d5#DYG&u5323Mm3*)9e;X|z7 +zS8s8BkBu~8_)EtxnzFui=e(D52XUuX-Uo{>HEML$PL;~LosJRJRXQTYypzn0!=JlY +z-FlqT1i!J{2G)B~^yby*1wU7TPTHm2`eKI%py~dRw9Psdfj8{iS+Y=&)UggGl^S`s +zGW47^i(v+Z_2&HoCl%KwpUXc6xFOxk25fOBJZYddF!3)KfSr)5ufHC2>!VC~3A>~k +z^o$c3!Mus+ziqTSeIEgg|7Q^D54-HFbpLeDz!m>PE`8w*6Ug&=%Z2!HA*Omu0V>4& +zl9RHrhI9L^AcU(7m*Q9PzN`_Wxc)A2^SNZ~^EeD2aP!3C{BJ9)G3$g^7_2-61PT8n +zft(d;Y)UWdi}EestVz>UoFeVGz)y=+-|tMX5kZ{c;1pp!EqR$H3#k~IszLe(R7^qV +zc!*Mh2p|g4tmw^z#;Frq3YkJ!seelEL<4?m;ZIv=+IS%k<$abnoP1hiA;QnLlsir4 +z-(1RL`k?Oyt|>;)ndI**{C9Eb4||Q{B(2i3&(h_c{gEbz`uS6Z#-Bi8bQL$Zyv_OqUe;k9tqWJ2r?QesP~y6IFBCR +zLL$>tc1-O)B}sq+MGu}Fx5f5e)1=1Zzngfofvxi5T)A7{j +z7SPQ9?11U`y%61l##rRB^=Bq%$kBHUSU5Ns>|0@q8@#vbB!B`V;DLO~9&(N=S%wPe +zwA}>&T9IHlGY{AtaU}>P;E8L$Fbr!kLZd%{;$Pl<;gtaxA|>F#g22ze=l{{+^u|{z +z<)K06A|i1hT*^hSc`1%`-V1?BWQL_*T_7=S_ZblFMfdM#NsYpM=+#ej7C+0J_F&$s +z0Z**-KiBn0C1G}She85g8dK;i=9gr>7#S_leXerheDdxSWlI{4#Ja#!PlGts^;l{C +z#qpeA%p(Djt9iHF=3}Kg0Q+XRlI2~ER?%$v7RNpA6q+PhlBSp8h@lAG7ry-A+ZF#i +zml62%h}@(Fbbi5Lxc*>FHL1$#R@LXP*ise4Vf%lBTmLtoD7YVcU{td5d60DK0q@3% +zbAGuIFJ`W$)ltWixYPmip|oQqF_^A&RC$IXSE+*w7PI|lf<&cohMT@|tXqq(j~|t6 +z+2hRd_>Ugg;S9yZ +z(@jGYZdov6MX8n>PfjSWJP6UAGd_c2j}Sd^3ppRB+5bJH@*t2!>aQB^eNE*Sg-ghb +z0%ilC1~P#009hed*#wo?dhwt5rntp)htvJGOHK2-LZGIjtIpwayE+8PbpgyEj7PJG@c~r`odCTbi1FQ(k{E6vimi$OvZ{+ZCn^z; +z<3t>48JF&tB>6LXSs+V-hJ|68EFcH)!~k)w^+TJDBTV{ncK_b=6*YucLW +zr%`FCG$4M|a15)dRV%9YZe85r@qbEHvT&~LWlgobhoc3in4)pic24g49`Ez;fmOVk +zWUq5_|E|sPd0ORb?&#P6#gn6~PNB@KX0E?W_+)(MpuZl8ZQH+}Qx#Rc!HWxm0-%?} +zu|^^z*y)b{9_B=LO+^CHb`9N63;;5giuL +zmgP#f{L9-6tNIQH4Zd=FiEke&rgqpG17-T&ySuw<|FHn?w?HdzA87w=GgF$iM%n|x +z`ZmKc-j;ph%}OQWyQufwx~koIm^+XFo;$@vyH?3S>Y+~eYi>A`*1e9qgP&Jrz)%*v +z(QTBFOHD{y%=dwD+g=WRXsK_?YJ`lGA|N>~r_qkQHO4Q~_oHBke`O_16z&<-#1{JJ +z&>GL`UdcGT&HF^+ymz!m5)?>pP^nzOrBZ;hKI)$OhHDv}xVEvbjSu`VD-osIZh}A} +zBNWNkAhXbFgozeeZtbJgwxPB?Vq8E2e4JJ&B+Xv6OS@c(SLw8MZUhdY4->00h;qp82NZkWl>K`PEIk{GVleMcC2B<@$@?nM~6GN`qbT$nTy8ol|r&XoUM+_O> +z?}tH|Yo)oX-7`tN`R4$?q^g(A*Mg6remxAWFZ|W7SiWr!qm?VY6|xta{VMY4eOH7n +zGNx^xO_#5`rE(1O|E95nDe$;u-N)}$vMUMqrV-nO&k9mOcQ9SHx(wNKPv}XO6>LtGkrB15X +zt3y6+ucr%qE`SyU?3+NV1Go=#Z)fU+K78kl9ggz0?QxRU2j6t=w1-b5wu5$B59beW +zqQtqlU=L}#m`^a!l)5s&G)@T=3WDhj!(k}GBT_TPOD()w#{S?iIe$GsdRxGrGx46} +zab3~Zj&~LLaS;_-gV!c=tn)(&tUH^(>MkMhHdaLc!F0~g9W#hMp*?SqXTDGdE_yj^ +zEFROIW9ic3m7rM_^V;JM%#p0ca#)Lpo0Q9 +zDJ_1UeTwc(w00Hpm}?*BGy6oJgR^yK0v`ndV5MCL$T34{Ca5xluF?KG!$(v8;Sh-z`o;h8}^ +zf|7b52Vo#Y$fgJt>83mX#6et--`#2!k*N>d`y3YA_m|GemE4+J24jwHe6G?jmNo0V +za&MJ+7VbFZSHk?n&DMI7Q)(IRPzl-F%bQO!GF!`aknAc}MgtJzV)@M0B2ShdS04&r +z%fx!ZC72Hcrb7wJ8@nY3#b-3M&UB{n@TE|&o?TVB +zT_!CXTI+vI5cl71;!$noST-6Nns_sB{N~W(lt1$~O-dJN5*G<}J|%-}EaY^D;IxHg +z`Xinu!{RXwvHlv>ucwXQcUlJ7ZGM{n-h9KLX5xj^yHAP!^d~c`LgW47wz!$-jJauI +zV)4-Mg4_R_S$+95^7*;i|B+QtYV`pAY_USBmhJPTf&TIw%QEzB7AAKqcYKYf^^~*j +zo}hQ)$8P=nTzqxRVRf2dFvpj-i_l`@+xm%DsS36IeB#{Ub?)+Bg2W$#$6uXt>|Wat +zdnP<^;gM=I^UGA{6iEp0VD)yPfe?f@Tt|*Z>M%!a)LArq#hVSQ8YJ4uYxOpUp_)P7 +z`?Ft-V}ASqmmK8#>|(WEj~k%#U#`1o4z?ad0HS++@E+%Xv@!1CqxG_rL{*;9XDZdI +zAM39eYY)7K(r3}@Hg-#MdMj8wLlVDEWxXaN;GqVvi44;kt8oO)*f(^@SRsqYM1;FC +z%`ec7Zxs*+1}2|6Hq`03ckmbt5a>j^kPlV(xt(JiG*xGg=rmvzXKc+C@Q-b4un%o_ +z?|)$|oRHHz$#2CcG?}w_h9Bw0-r83*Ol~et))opD=WP&6aaCt1h7e%`=WDR +zp?`hyiMh+(?BMXfilM1%T{e3D=5cm*j@laFMXgAvH=CXU_QS-ecYhrglf9odlZ$o% +z|2lufzb*7~d1<_4L+}Y%t`KULO~12%&x5L)z-MgdUTPIZY=O)>b?$h#WVw$5ErbE0 +zTS9v^@L=`AKkW5HlAj*Y9+6P}8_2$ICM5`52;|e&B~NrLa=#2@065wj)<;CZS4(yd +z(%(D{^FIF=$GJAUx +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 +zA%-Gm46hCqkT~B +zqK*e{oOs5eX)P1pEfsP+rfyMo<128#xk~EAb0IFB>XAWclCWSpe2#TnM@w1|gYodw +zGNEbr=4RI;!U3H&>>lJkF%ks9Cz{ewa +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 +zk^g;gqMe81Cc$QY@7!$aHp0#?1w@v(>0 +zPa5?B-2GhN`Byv=6u4Y?AIj`P>)*n2=n;bTl48a9tRfQjgg7tlqUB#-cF;MWq2tm; +zgH-GF)}ahElF*&=OJq(>&5I5Xf9b%gZKiL;Ekg2lgGvJy_%V0f@xet~&e!J@J`O(4 +znRODj*VtEVD!>FoL8MM3F71q+&}~zM$r#y&`ZQ2Ab3hpSKTyklT6uo3aEqcismY= +zn7Z~j+y-Stf623OEpWrgS>86H=9_AsD1rrKSo8+%gE|$rxF=4~E13X%!TCMKmMu;> +z7tLK4jWG@VoEoJA(HD9`f$66x#(zE)Xe8wz}S!u*s#~*)dv)VMCl4rG< +zg)t=*5{gj$jR9|4Hc0|ES}(p2qNUgYpsjPEqOS +z1RFMv&5~%~jRL>V+=acXW0ctvLSf)hk$0TcD^#|+&e?ADxof!Dm{6c_BUNHZ!kS0w +zG#k5O+3m$!z(TIN-2BVc0e8;2I@Fr9F?P3RYcsmJ45PTR-hM?bE8>Z@WjvW#io1!G +zURh>IB{nx7$8hUnQ7Z8ah1)L+$gPIA<(iKDl*hmuvi*K*PpWN{B<)iEsA|>z)F5%bh3*6-h!pb;> +z*ouR=0vPrC4957Ru;`dzr{PXZv#@KP`k&-;Q(5R!_u_735?5NXMwVM-Y?t+Ob%p@k +zK!r#as+hyqfa^}I``I1Uj8;b|^6?51$NP#voX3{L#C)c4$1aeH;PAHk~VLdh?W)rQ&~u!vfeX7 +z4d!-tSXnu9(kNHs=mLnlgJU%DBi3`nS;6WZk}VyRYsPySHg~wiXfH`}AN~CQB1_#`A=4U`a~Tv(v!J5nkulEU*AY +zPj=`Y3JTTELJ&6u4SyZKk1QMvk+abU(V`Y +zQ^v58rnw&pEZm_*x?>TYbSY?tZ}@75uwLBEgMR&eIM~UH0P>ai5p}fpT +zzz-n4J8EibIv{4A0B>gPAIl}ypn5&IkpyCgLi#;?ebYeTIs*a!N+l$V$BTa%%$@G9 +z$jldKHl$#Otxf^veYk|{?ZW=h=Xd|ZL|c@F&?&85d0p@cU#Jdou`LO3MqDor*_DFM +zX2S#FfRCU9j@^o8tO-A#p9PV7`8yxZboy6+h4-w1vFw03m6c-3{UD09Su?=3oX!o( +z6UxdpJM)@pxAhcn%Mju+2XN3>gk=8t3znJuEHqqM6VM`BbGN@?N766y>#xnSq=Cr8sj +z>8M2>dje1vyz^ShA!}{tkUPK9h}Nm~v`QnJ%=S997ND%vTRzBWWg0!aWa~hzx0hB* +z2-xfv#56O{5`$(jg`v^i5TD-OGv}O^nY>>)tJH6Rcv)N}1Z1&H{cW7+Z-&buGfnm| +zFpBm}N9ZuPbu{7A(}nZd>Hqu^Gz-a4jVm{8eQt5jy0)KBj+Jtc0x0Rv`$PQce +zm|;F)2EL&t29;WPEqyNCn|P*|r!B~B=i^+0*paBg1G{iU>>yUc^wps-ZD6JH%`-zU +zPo#&_aRntO3E4G}M@J=XUO&Obw`Jp-1>oX4>p4v69=&JzSW999=UvKC)6#ymhlGSY +z^29bl%FS%EOX +zQ7U#q_RHgNQPeCJxT)?vU4OBuY{<%;t=3;V5hJ`R3?kP|`$H#2vVwI^mL=eitUw5W +zk9MR0P9q^k>Qf(*w;@i67=P0$@6=zq33#evqwik}joQ!3civMX;|9qvq2q`Am~Tv0 +z!MwMuv1GfM)8=LMjiF=%C6}z+&N4`TbR_%-+Mp`ItqLo;6`YEvi1}v5gllm^ciS_7 +z87o^L|M8}Kq1aN!Gz*93RC10srOH1GG^Z@mX=wzY6IsZa`LoEx{Xv^Cj<9Q+E4j_d +zCfl371MZk=8l^iOUl&_Q{uHZB6B^%dvOTrC(Bb|1aqe#3oU+z!RvO(O51+J{(P^v< +z{1WdJ0n;S}iBREBel +zWxm{eJ@q=7&ilK^PGWTbh;h2zX(0(r9<-~irRBwshMIce$$t%x|Jynl|D(9yj_2_= +zmWXp%B8IcpO9N;~d~C}f0r1ZDEr57TJc&+cC3@h4L+>kM+8+REB|OXafJ|W}LiQon +zda=ynX>NfiStzDaS7^Q=hqafhvv_xk_P>lG#_go`-!Z+gy{&l=7fEFAbZwDFHgBYj +zD9w?-2^@lD7vXwkp7XZA?C}cH6m@!lKu7^PjCsu?X|&~8-rOMOkm+idI3CLd2kp0? +zYFrTKf}l(0G~2m{X$B03qVu0 +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 +zHOvHR+$XWv`+HwI6)&J(_R{KM{h +z7#NuDE{Ki)bi9E3UKwT-!7x@#zIftAa|HoN*-xMM#8)_o7dlv&-*f5)M5gV`Mu*>z +zy!-582Hs)B8%|`USK_{UJBZO`IPb0bsI+WQSC=Pp}WE^Uv-r6 +zYmQY@t96#&Je`MQbe4-5OG|xYPa?O5V0}i76p4gy_)}_#?x__H_!47gk-=lEqoL-G +z{VBjuQRV!y0jKHU*qg?DNN5@WD$@X{X}Cb+`l-#D+}VE{A`b$dWQl>lgT$Jn2r{f- +z3$Km&*`VuGa$BDhMd#Tdo}`c@x=F@QyA5*k$TG#c?D|QWI?lqOyLH4>eqV}~p!U~<)j4CB)%Nkp +zZ^+7FZhJ4ya69=fRM$}C@Kw?2^$LRiXiWcL_au*?sW9V(ilv3A*R~|kHR)@;VL(tp +z0!Bj-9o1|n%ss~}@E+y!qi{Qq*cmH5yg0)=bm(0wHgSZ+hxn~#1H@rqJSn$cw_)t +zbc>oK%M*CUg&vcFAQZwl$viT`_9bwWs91H{VH`+1k2F4W$MDASI(nL=v6U$Q>csNOE-ewdq)Z|flEsq=@Cn(jx`1rjFFlE^ +z(28E;!u?yrJ+p1YR&d+wz>hyg +zA1&u452 +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 +zvh$1+g`N&1OYHdXvWSR=^p5*5( +z+9pU~k#)RtnglD^+UD+(MR1SFh~?u@|224x8=o7!W`w)(Yo2(l2Jjm)+Ro9K?Jg7u +z?E9W;V#w|Dwjk#iv1#z*&1>{?0m)Z#_UkU@b^;$k&eKb>av2lAF`!Ux_J(LQGVyO` +zVGL_in&WzqKKErhW5<0FsJ2Z~fvs?@*N}X?QlpIZ;dMu6d>7xiY`~!^gQl7sGHK$T +zyHN%d9d{0Ez~mn34JQ{wI$Fni>0K1t)Sws)(c#7$qu=4&_(|~^62Gigi4DfbMth7? +zS8|s2$*`U7f!v0-)w7F8vK@3rb(UW|cBS)?Z`a~Zb@wfGLc@L!7gV2^vvdADU$;lP +zpUdTz^xZd|wtEQvTHBV^b~9Kv`!hM+(bIO4nsTdlvHHaQP7qUzEzGo4iN7O}zK-b8 +zc;c%f%3&I?lgH)mmILTSr#6%f@7Ml=O=2l +z>eY@{)7|<={jc%)ANwuj#edaLKXG +zvqv>nwmt<{8OGdLXcNyMX(ZsF1~=TniDcZ +zM6DNA&f6&3bFJ}7<4I3cL4LIADO`jvBJh;E$67433vrC?I7ZOzH&FdUv8)aG4+EET +z?hlFF85#uM_WMf!}M^2W%~ +z-F_T-`yG%do)r&1m*qJ{UB}?!a8__D>lB3azFw9t9MZ{7Imi`E?V46D7vtN}Inbyb +zwJEI4HfD^oy^eb69ZNBdbF(@{&`oU|%?9D=vF|xJ=1li)Fp5dCTv04>s8=}D%(Z-dDm4j(er`{sp?zTaJhu7tKL6+fUm@w%RAe2oqV@n@HE?Z*Dq8UArA +za@-u;I{W+89j~~elbeq((qnr6-wn;5#p&Ynn5-n9>+N*UYDenU+gY`f_tcBvYU{(m +zvAU_PBl`Rwy%KkIn8xs#e1J(1cjARw75wdyCsa#iC(ZOfX_20~f4VkrO#LrvHuK37 +zDGC)NPzFw+FF!53y>fWrtJ*?ltGA(!c$qE^Fn)HUWl<4r{9>+f+F~6>eNOwzl!`NtnPMknPKq^-DA_vuYyQiY~fxENycs8=m0=()hJ7bW2o~ +zeCHGu?YMDlRuHnW`m+(nwV!0^Sg9HEUZphS>jv6UkzVBW&6j!&i@tZWy{}mOjc6B!zo!TV@?rp;7(h$RX+5hI +zPF1QA4LZ7NJ(&OVFXr6=6HfXDX>R^Ef4AU-7JJQeJ +zUw^grWlR?U{caabf1YC5ZzN8bYQI4Cw3OT2-Kx0%iGxB +zUN&cw7khFo=a`S^CxZH%-<`ik9(XICGnF1<-Sv)~Yf{&4akNjBdZ$FY{;D>`lv_i{ +z7M>HZ3^!8U{lRwG>t%9H?(-o6nuBf%44&Ly+*|FpM?{n!1>KYs!29m=1{TDL7!~k* +z@?ZbW1DYC)n1*mj58RGO=@%A5Goy<;~ +zw(aZhm1BmZGXb)BL!2W-4iJa?vFlqFq11pA=!{@GhaEgJ>O~50!ITu_uii2IBqpHe +zkxOd@O5md?GMudM&83CDZ$=bW8pimC!(f} +z9N2O^|HXE@LQb57Qknu|ToXVY$~20lt>Q!O=NlI2%&%w;aTTh7GrihgEwZPV+-{E} +zdn(j0QTbsuxBsBL(K}`#KmM&yoKM+1*RE0R(AXn6^AMZ^qsGyglwt{!Y$bBStJOKI +z&-Do9|M+#PtU2t@?+>H>@ikxC)|3}pd`z&_zu!rH@y)s%|M=f6dx38HGsgSQVzv$=+Y!M(3}i=`j`iSkiHY9&X9Z3M>cG(I +z<;*_6#>z>&x2@|W0rEd&Aa}r<>A}_A@?grl_N(tXy9ndpsr(=T@j&O>^5ot8DM2|B +zzIqoG1TT=B-LjYKud`!recas*#m_ric?Z_^JeazT`8^MbX}qu>;hI0YZ?ef`%UjEY5w|=lT +zV4DG#=|Ntq3nR^y;xVo!6Rv%2bQ^Nfc|k!LlOS!rJ)!8zbw2L5G_%n_N>aOE@nL4q +zv&m+%{ThnOQbzDDH}D*El`*(6f?+F(utwPGLu_z^{CR1Or9BVRA)G`6OFgOAaH~d$ +zBDy`8`qAH!0MQDQ9p%JeMRjIkyS09J?NB(a-y8xr<*7Ac4uH~O9FupS_B<7 +znr>$IUt{eQ!E$=pi*v#Ho<$Q|XD#BVA}co!PsarFCHTiFvy$B@ln#Z;`@_U^|ATA# +z&e{A0e!k|3R2Pmj_eDdi(BXQeC*FTwF0hPug{xCM(d2Ju6R*aSM@t7nutpP{9lQ!G +zNNleOsq-8f<#EMx%y&k*6x;&l<%0FV`6E&`pTH__hN2o(Dwo&_Q~N!o@;ULLb)&&< +z&|Kkt#jLgNcPgp>WcX;y+s^N^SH^E4Pk}i*!f-yocVq9?bggUSUz~inss=Bvz2J_H +zhUVuB-+m4FG%NPrQtq=id4>{5lw9(`?ms6-jo<9&yFEU=V}%+=8G_d?16lK5BekMS +z&pp6pM(;VYCIPO4OKzE&f-A9LPS+h}{7rPFWK`#9=VsF!vJfSHNEnnrCo#+)J98cc +zzLB4`EcpQlfzE#+OFPfP024~jy3rX(%gfS_3M9VBAQO5kEa`DJjWFj%1aEH(5sluv +zc1vrk)XdwP54I4x7kd8v-wNAwfU17jd{@Njf_bnjEcr&K*%P1~?AaVXn{8%X1-VfE +zqqlRHk9DeHxC?0)Fjm3YTP=zVn&#bfsYTz)W1(9{Hrec;bfAUBfOiIaw|Ve$+1>uc +zkN*2lA>+;FN;jc|yoOxE(e^7;V}5Skje;9ZN8k2~;3wNnqoQk&$k3g>NAazO1GeOM +zIQp9MWcxaGv#~C}sa5Z`onz9$uvQz% +zH2VjkAe%LBDjZ-t3#1D|`E$TB;0bKN>S;S6O;H6F@R%t{1_Bi|1XT +zZy*U7zy(l7zO}Zx?lk@xf`}I6OjA>&sWFC(TwiboMyF9{FKl=A{mu~Jx~t1Cy~Cv +z>KL54LtCaI{;8nZ3_Naij0)VE(1CZ}0p +z_Lv@0IPBz!mK~9IU-+~rZb1ymRNy>=*vb=fxE1&)a<4LPIUW*JdShcU|hiCpTRaG5BisTu$EB@@uH) +z@BH)bitGA$p0&J1w{BKZY~sh~)W^}DmzjGxabRV+8GE0(r5|w?;FD9KjBL}wW;K?R +z@AtrSs1nYkJ+mQ4<*TmvnGS`jV`^G2Zsxq2=|_`@demWPjR1bGlRfuYH!rtnmjQ^E +zg?YCdc(zrO)A0v__Up&Fy<8r{DVeo~c{k;LJ +z?^2;%#@AP-b9bG53}5&>*<5P72bcu(!!p5s<|1UN!=K-EUp<#oNz{&46%NtcPlr5} +zL~r@hsdyiPs}G-p_CwrJNXmE$yOgpSEh7A3MJ|>ejw(O0ps9~ +zu%=G5wy8u}@Xe?H+dXjun=yU);_SjS=A`yAA4l;kW{)yBJ|NJIJ+puT_R~$M<;J14 +zIqW3(4zO7eA!tn$syAF8yHokh6IfIM=zJjJAa)uO<~lU|MP^2SFBV^D8Khm^d%xhh +z6tm-yzyr%^5-0=OeBxF{&b0<2?XrW7E4x>-OlqB5Y%3L8Lj9KGiIf~&evGR_4^e0Y +z|3@B5g)+L#hqfx$1;Gd%D_Rf>(uxY0pyydL!%D0MmQ5Su^(n{mwiEr%-zJ98+K=EZ +ztw{u$%e|gipD`{87jT*BfNOnR-jToeXYW(td;C0ZX}c9W%vcIBfIM*+n>?;3o={$1 +zQY!KmUk5$$4_bC+=B_4N)aK4rKG!?x3?f_-zt_It?_HyKLb1>z;sCUhkMA9e^iG{Q +zwSpT=w7q^Oj%m#YcQay01ziCYAdk?gd>r@_-G7G6kt(X*x=HG9f?P8Jr@UWdVyd$< +zIydFvyhJuy6sWLWCK)p?Z(id-c)Q)Dx&Q|8N#=U9H(y@**GFrvBz5?%9)5XU;iEWh +zP8c9_Sorn@3mF{E((LxEuuxYqJ8KF*lQj6t-!=Z08*5l# +zopnNCJl-kz(&9y$T|f=O>eIE11@l_-GaZ4vrmxP!4qHds#2rJ1uV^N8r+tUb+;jRp&4|yPY|B#7%*V@1Fj)+-soyB^bTT%>B>=k|@8fn1?L=V>PCf +zPBWIgm2_Z>Q7yZqMW`@21^EhVl7E2-8@HBo=<2*w{xiOQK*e=cCX*-1wp^|j6glZl_G +zbH;*}Z>F@&=Aw9*k`Od*Y4o1lE`HGCOa_c}Q0Y7VOV8+E-rFHM&nDA7Zy-w0TNSe4 +z`9wpRM*fiHmqVI*C86exk(9GbS)=h7oWe&p%P6^YNp<42hvrME98vq`>Gf(1n8<&5 +zEhL-~Y)cf)iqAwHEciG^Q`hz%Jjrryj+0>?lN>0o-lV>id5?I@+u6C+DN> +z2C8nuIppcN*%~MGc^;+tA%u!QgMr3hi@~qkEzX)Mbi19mo^a@k+$_{?dHFrJIM_!E +zuiNqrXT6vbI#Pw+(xc~X<+X>(&AHDQ +zd{DcmYy{mt;NN0&02*K`nbMFhT+jU8FkqmbE( +zdu#YWy+q+XSEzFD7HM@Mq-WA3YBfCU|43P`-}A^@kyGVaPGBn11Vz1%{pcM_)>J?f +zq?k2)doVO=8CTV#nmT-uoRiCI`14i(J!EzF!L&-gl43+#r8>Q1JeaLr-4TcVl +z`c2Bjo?J`)L5GyY1dWe8I@{4R3?7shg30Z~wb%87kt?s)TOc8!`>WD>=SciyF&W`Q +z=#E{^H&Fed$-PAMcE+EgZ9*PCF`q?v`bD+4yQz~Y?b|&S`|BOK&NS)Z_ara*Yx3Ru +z7KTOi#a@Wh=kw>3L&KtEr7eg0;d$|NEoo)1mzeAvXUXdxUWlv- +zeD3u>xMUh*gbo(3c(3>jGlj$(UlWbO0{R!eI9$mwF_7*N29*dIH=bC+|MK&==ka^o35^wi+cch9^+bP|nNpp3#A4TH +z8q5~cc&6mWnEzZgUHq%0a+XNoyu1ZY8sZTyWHU&7O={FF#MFp7RB9G(tmjGh2k1;d +z60E2U=e)442RnA>VCd4SK9ph1XOvh!&5s7q`N_kyPdAVd;`&gXllw}s>{W|je|zE& +zytGt3-t&bO`Yh%bE_JhJ#M34r-sCRkykRw~glcDI%wGwYa3}6LM%m +zg)bFhFpq3b{y~>!2+tQ_$|jvhDH|yh?#%i}t$eh^TB<`a!Ec)G7A{AeUwI}I5w2mB +z3v3_ZNw$k)qleU1^C9#AjGkHBQzm1kAXyOpn}SEzSa-JR%K(xLgh!Cazy*Ek3_sI9 +zd)NPt2$x*K_qttc?-!?ipbN3z#bS8OMc_URJVYTP2ffR^(7MT}M*6)>+d-XK6O4H|h2K7;wcDG&MC&77x9@RS@UoTyHJhuRJ{;lQh@P3yx;bLzX +z(&x#f2*B8X%jJY7oco_?=!z(@~0tAz}m~l>C6A+aAv^{xxMS2nLDZDyVJ2R +zVbG*QpY(ZLI&|z%DzQB8gzSYomNFp3NNsb;d?3-7g#nWVyw?j7Oox$B3ECY?2~f&J +z)XDM)D~WXx-IeCcgp)HK*Dre2;08H8$pH91M0o1RX6sS^UrKz+(cy!@{n&nz#V=20 +zu*tn6G^fl@E}icEQGFhtByc_i(GE+68xbEDM9EwT9eme{?@5Pn?uVPtTjS(Nhjhr} +zF#kuGD6(y +za}P`m6f+#G#+Uw95fUp!W`rH_y@OzKYG*Mr=@BBUh^M&=dhtz^RDnp)s|CsAT8%+S +zCy7q2g#+P@LT>^t(g1_$LU5p1<>=?+9s2X%LoA@Wiwf6tMD@8GeDZMlQa?AWt-$*I +zJf*jrsNHB>1OfAF^bX`>6Y*=dIQx80ajJ>l%=9a_f4$D?80^n=WyXK|dpyweF?!DG +zE|$z%%Klsg&pt~;n0UGuO|;4RQcA?60-S{z22&TXAO<-vw<*Q|+0z3jj0&(iqV-Hh +zh#xcY*3%-}a0PokHG4{)%aj!3YEef8&J*YFx0Y}xb~X>1k|n_7^W?i|5Az1}{-Z@H +zs*Ik<`0x_pPdetEuJ7Mqqg!Hv0WyGdF`N=`{m?zB!l_ofSg`6rn=2%n<}#Gg-LYmNP^m^lx@yeEM(i| +zP1?CdH<08O#kc{^sdW7}=3REKgPt6#xx-C)uSZypE@ZT?mt6LG=h_u2=8#4lBquZ6 +zBDn-N$F21)dUlqk0ZOD3{p6BOMNSJUI&kQ12vrhldCEO;=$5_te`l@$e`XrO7iodr +z0V!P69~R5?PWH!Bm&A<+8UC4rc<|mGZU}^Fty_21y8H4tvq^coW2k>N5!uFQSJAwn +z%g68r*YBWzIA)aZYg-xqQRcXRhUHAyF +z(Nj9*TQ0eP)OX7J@=pj3*+8|sEi(8ehDV^qQ)Q~efS5O6$*nAkM7QA=g +z8)2qd`0k`n^S?@FwE3TY4Cqw{;DhCtWFiZ%qImoENAG=)*pk_iZW4-$0Jp{iL&VA!F +zTJ*f$EBFgxj_F!RB=CuV5x@6Q36%sMo99n79I4%AL`i}TwHH0qWeC%i5W9l0l0z1a=619#bdGx?o3 +zwEdij^^dU2XBDHt)OG~#&hYu~(D>QhNn7YBLHs|TPCXrs?A|zW-0YB_aT(h@F9J_L +z0!JbrtX%(b?~iB+{#IsIS)nBu%4DH;^rpK7ri74)zowW|gG&4ZjoKDDks)CyD}GXj +z1YF}m!;r}Mso;u5_3YVNN;8}wx5*so;GqZKRl#i6@XjsZ(|@Q1fJsZB@J%ma9~$Sy +zScvBappbEiBb1x2awu*U8F=s}kwYz{JBiw9huXO5F@4~;U{*Uc366>fR@J*kX0KMtYr8~Y +z2}$6{559t0mpga+S#UvM;i~T>4L7#!IS-?n)u`nR-0tfPU?VSnTXV%sOOeeJn&yRI +z7Ed?)b=xySzPG#q`be|8(_>7$B9EoSMzhHUcnN=GC0jfKF$`OT9u)ZC*yCy3QV1k9 +zQUjX{GjyWFpU_PL;4MyOr15C2=ERu>9Zz;4-({_lku +zpf|MkWqd^J)dGG_+DErjt#mp+;IF!S@UV&bIE*;j!4Mk +zC~Um6$`(wFiBbU0sfK+ODm)x4)C^qFyy`LOmTTs3%#O<*{`uQkH+f}5-w>aQDW{e7nBbj$B +zW%>LzX}7S=cvN}0MYv~SyHY9<@i0lU{_0&wITo$0qEe&II(adxAGK!g_GHVDXT5Oo +zq$>qNdkHr3?;1Qx&>6Ibia)yiKni$*)=jv9_Z%>H^-~V`-v4sbf6P8B +zcoyvB+o&;zN%JKDwlKoKEE_-e;e=aQ#CT#c&rXRG66L_52YW8{wEf);k9(Yj&*`wn +zy6C>WpJtwQu5Qlt!me5K?Dadrxg>HweLx2Px!dCY@(B9^*%PY#%YN${(^_|n#}oPt +zjsCMr{2N<0wIxwAxy<6X-z)CP%WV}t+ZE|tt1V21&==9agn{JeIH)W0Qv&vQ$685dPbdYPsP;n`E0zM#ysUOqEZh;EScv}#Ra|Iy0YJqsLlL5 +z7?f9h$R7@_$Y`B{(o^*3D5gHP+)Z$4K~8m@x(+X7)VRA{9ir6zUv2!gxf9!5PFeq= +zw?LCWYG1WsGgb{zIKP>hW`(g03G;w%jp_|WKAXp)i9c*&UhB;-xzM3dy(w}=NSzy$ +zw!EX9Xi9J-?Uq@&DFONcEK~*eUKJm}B&~At@Pj2KhfecJ$X}UHH@D}|7k8q?Pz4L( +zFQ)q{UEU2}*utS+RI-KsUffasJpU-W!$i8{){^P)W +zjytqIZec$l2S1}I`+Ogm(bbVQ-6@w^#jmA#bq^me&X(G^+Q*tt{6pQYPH+3CA&HUo +zzf}5NzolD&PQGrfKGMtd>QVVj5Wp&9ezLHks +z-lHiVapvy@pO~-v6n8thx1j{Q=rh?z$+lJPmjj7-=vPfxJUpJ*vQNoa9lc>GLGK-4 +zb@>@5>-ZVFx!uFCm`{4jZC +z>e2cJ%WaTW|J>HYGC&Er=5e$2>ZM|d{x6+Goyaj=;_iz;=Ug~^gE{Gel#Vkq)PnNO +zaF(TG2S(6S^9u)526@12_ww8Cy7wc6X5&}wt+PE%hx*FLOV0)EHZQNVyuH1c5P|gA +z*c=4rItw^{e``!^=o}zqN#@PUB_=KKUjwvYKuo}qwLRdlG>}HpOwqh^S1&U!{hfvH +zkL$V%Ra4d4hOJ9}BBDn#6A`nO%hkz(PS*pIVK3wO+wYy*+t0(ock3%EGi{ll!Q%3_ +z<5J_c)Mg6kt(E(?2VVK6@|0X3^P$yG-;a{tHgNruF6Se10Qyz*_jhA>gf}PcYR?ru +zjoy=4+;6VeX*2L)H=1nbSDqi;03n;Pq|4?j!ukzXW7l=AY-@SD)#6m{sMwUnun%{4%LmA?-u1Rs>3oL3Q8G{ +zc>9M>7n-LcCi&TykP@@Wq-T()Y{vSwxbFklT=Rqpew8|=)0B4d;d$*HAooLhPn*=5 +zAwo9%H%j=huFyNsjuc--yRQ$@a!(irmUkP`alm2=}u +z;o(~Kehm_LjUlH2s$#Z?$?>%-#iy)?#XXbP4)seoZ*FB8Z*jKHwJ7ADqRF(bMqH_B^*tb!N2=%KIO%+^#R%2H*SOzgd5+McS7XRTFzg +zrz9!WAat~Wn2ef%a7IQ3rO*t+e84D6hJCCHC<7L2#WP(+8b_;DUKN>m7nqY`Vp|o+ +z`;|2Y$&pX!ciuaR8YITo5l8pMy1J3jaRd04mrUr<0rK(52E75kw+CEsSE}ceAV-#~ +zm&`h~FrKN&OA^nhUNo2H!p@XS8l^bPgiC1$_ZPwZ^XZi_;1imoJYk+~iZtqBYYOw| +zT^1g7D#p`v|Dopb1V#W9d#YstxlR0%!2H*)eE8qg_#9NRyaI>6bke29Pg8f>`up@a +zy8mJ35{YEz84RDN;J^fSE^MGFeBB7oXA@>u0{@EXs%6N*SP-x^mEoIk)4Z;4CG_Dn +zBD~qisn572PZs#-z*B)H<=osoEJLNJ(%4H+YOii~-^`kO!g{&p0w#gJ9vG0_%B@Rm +zjD>%OAh%j~e>T9*e7VrStMg9s>-N%*o7{DUgzI;bSDxwIlziK*ntLow-B9=X`6QA4 +zFM;qp6TwgGj(dyp_0|UUIUg{a$y?#ul^(YUj_y;)&1)RCCJOtjm3>qg+p>GIN{m6jOFR#U88VYXMw! +z(kO=DzuTM@D!}A5L$&qp1(p1xraF1qzJUsp$RyA$)?A?43yV;|21iretD`79#Rwo;N)##Qt2EcjSzN2w +zORy`o_)N+7%GAXy6toPWWlK@!E;V_yH=}!jCTm74bcud98lWjgU+Wc5w&`$>MKEEF +zGba|RaC72DF05Lq;AX1-(usYx9k<(PfrhN8Kn>Kmt!hgAskF-Pd;uHHoxl5|#it~| +z>>yjff7XtKCc9}kbBRc#;VS+8JZV=yf1ktYawOhc!i}5{3OLn?mpd01VB85V0f7}K +zz5Q69*cTyU{AV*?O+QhC5kguK7e0NKV>| +z@}`6kWuc%{EaK!X%Eg~Z!i4~)g(vPY^hlR(<-v4OsFiWq>uufR!7)Cp03nR#tvd(Q +zj4@G~kex%5yDJp`a#k2YLdSIT-UU|8xUreA3W3iq)3tS7%{=^5y-w=qd!FFw?)yA1 +zj{hBtTmLeT>V1mh6C&yim~V*AU0uFae|sY9)nfaT_Sz5l&T +znP58MwJ@57T5xJJFiYkBm6MUHyrh6?1=$~7($OcYlRy*(4SJ*lZ})3%sZ=UOE!88egbpp*-| +zbNW6qYU;7(;Z~QBMSLnhhLxL6-X^Fb%BH-mtlgUxBZKU|NBL_ +zyR##qW6J)DOGJ?JXQ(v2>9)raHc*AKi%&k!BaFWLo^!``RqSM!BF*C}Z_(#CwT|)B +z^-<6Rj$oGRcl-dEIL}cp-Y)XqB7PI75>De2O6^T$OL;{gOQ36HCl0;Ds5^-`n>6bLC?3zS3!K-km$8#X-yix!KfNhIN +zUwe&v$(cOKwW)PA-+l(Wns{!ELp->iwGk{m{g2M4P2{Txtn{UY0C5Xe%&0Ka^osEb +z^D!69Y<{~O83G2aU^{We8sHiCFwJejJP3=WGCuSlewfo#_ycwGfD;^tJb>^&Pn=r+ +zVog=tIx(qBVn*!}XV*$WMxb*FP?-#2oSG3Mv&maw=V<#y#tisassTu=Y4Q>#IJcWX +zFBK3^85TvHO6?DJ&Nh=k=RjqzcCDZ^Gx`(Qs5y}8BaWTeR2-F*3T9SUu3$P-absbR +z9JJZq^9YX?^p`**!>XzC;_*&$)z|Y%dHsx)pZei~i@Q^@pqX-vFRNf@R`HWvz_GQB +zKJrH5(olNRs`ca6b~~$0e%c5w7pU4I!3qG4cTNSPYmN4}51v-*Aa`lzSD3(#s|-8H +zFoQ(jT$G@fRTrW}{;`KMuz1x#3vuy&R;_qU&;>+^y+bP}_gEHIAZlq#g5)=L8n@5v +z32WNoBdBoT*zfd@`dKJipX1@&88Hcoe#fOBp8vHb-?A1iXq=`2lfBm0@2Pq1!}z+Y +z-iC(EpLeXg4wIwzj_t3~;{1Jbx^51vu0~w5>@yuc$1hGi??)DUc5~+R_hnvjiV#Bo +zs|)K*|H<-xuj%Kvhw<|FN_M{4;~5HP{}z?~hA#Y*Q~ggY=3aJGhg%&a| +zI6$EcCKzGBH9em%fc=@P<<#LwH7~p9MQ`B +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 +zaBbT(lW$fxK%LJr_Iy9>DBrh +zWLvjk0n!tP${Awfd*uRVF#G0kP0!Y0?U-AH{E&G#XwyMXs?YZhK%b5VPXG3t!K&UL +zijiT@C=n04F4#!a$jTzfrB%$j0B^#nDNpQCr!mRrz6j=obr>!MCJ}#m_O7;zdn8sU +zqrG-G@Ke$+XY6l-JFXk0mN5R*LYwVey1p+KF~d>j03;CK#%=74Q)_d~Hf7&gde$*z +zMU(AHsvi|_)h`Ec<{F>R`OeZ6eLbbVH7pfNe&d&s=JpUQx@h1GB=Fl{yc-kbz^oq} +z)YtiC*{ik5joZ%{Zz)5mWq9Huuk}x{0(UEBZ2CD^jdahZ+20|L>JLpsT70R0#@$JS +z-{ipzr2q$p7=Z$Xu7m|g%>W<4$m0X;gHfnc-qofw$T;a=3?%4@Qycrua8urTVy#ll +z0BxUxnXfQopYRxu{1R;=ycDS2CHChHujGQx<1aDXctW`Ct-%TGQVt%cyCApA2mnVs +zb>cIQ_1eDRoq@P@l>ZaUD*0|bdNj^83Yk%a`B44g^#(yMyi1gr9VRNU=`r1OzYgA? +zjia_rT?_z(g=sgOeSUp4s=tf9rktC=hsXdvnjkn;c5o~sxMx<;Wo{npx_kG@<(^dt +zfiCugMXOB~?pF~%5YBueRzOvFhY8=MWUsjG12^w%U8ftw1xM25ct^_%LQhV8sC{qr +zL&8QBW{fnmV@?JNzzKN)bn|Tr*cvt4PEf#R+>`GnI1IA}>+q?q8P1K#oR)h&9dh)J +z5K5dq{EIuYP&PFhjDlWJDs8sekH=m{Etx&v-JcY`{#6uqhYp_9?0yGcg;TC=Iq+UW +zz&X+PdrpEb@9W9(O&Vh_0{r?l&L>O4iUgM|0!Ba@92YDe4@XUdJxC|}&;$Bhe)zNM +zZuar(c*M6qzTPvB{ePdQJas2erpCiLE?3BzPnB6v^c>MFH`(}oUk7t&mk2|& +zFGV|Xy;CUFkvsjGIulrNYV4hE|5CZ*W6I7fB%{ga`6R4HKOzSEA#-5+t6(u!ID-W+ +zHchT^*hyQ7W0e+q$jUvY)qSFlW8XOW2ig)cd>F-^l$ +zW81@D1x^|SffMk`c!z1B33oo`l8U_6q&MR|ggW^*wMByMw_mHmzp~{ieY4|@D<%Z> +z(yi|gm354lW|z~uIhlvj{-G^3rOn(Jq~8 +zB(rnM42o8N#c4vk-D~c3!|52+FHM=l%kd6~Slh)=5IQmYbfZQ*XS&>#pS87|ySwGq +zpUlk-GhpjOg9eAE6%{a7PbXpOz9nC$+r@&xu!o&YgN1+=lxI~Z +z*#tgVdgwI+oy~+-ZW{ToFYRgkJ5)@U>C8qINbqg5DSdmiecqQAmvU^HKPRq$_}vcx +zzXamI$&vxQbZ&WvS$jPm-gRU<=}GyW9{}~JXXHoq;;9Ka0uQ3e^G@@;+}P%6N00B7 +z%R6YO+lF(>(?56CqrdLv)t%hWZ}EGg^>w+jbiqX_QVBt>KYhW3Ar5n655d67gywNz=^P4yl)obY6X-1od*-0t&;Cs2_R2`tM;hX}i%kH)!!QiitAYb)AZ-0%1pO +z10Lj|wnD3Soc!Ga+x71ADOg;kMYp$>?Ql(9`aeOVr;osJH!uts;+~g#Cma<^GI++DXz>7$*c#;6L&)P3N$Kh6c8{8c+D1O)6KyMbY(3NOnB45 +z#x$L{6bqcOOoon?7MK%V;j?DwlmVs&SJ3pi-eHb$V&9@4rN4$#XOX~&_$}v2*yu5q +ze$N+Vf4=U~!;D##czOTbhhWd$l)QfFNGdm?3L%`w@k~Q*#>Rxc=>W~+cj2sqejMrb +z7Uv67Q^}h>UUSu|ror$Tw(7 +zy3GLKppaYH-vLAe2nv}Nl7tiB0^EK@&!*|Z4K_|)%^?ex-HILPLfT4hKMs_{m#7>a +z;RS=&eah8}Bb&O~h|7jeXGpPjhT5+3M{blx_E6#A?<-En7(5QHhYY&wn0s^W-S`X@ +zDPsK}DG((%B)xKAm&L=-ulTwe)X_<76jP2A84&}fb7mV7nGX^JzQSl73l60%qmdg^ +zATxOpN7%fyMetZTgLPaK>K0fX)9I>7}3s|=;Mt& +zpDX~%d*QZ>jY5-kONW!Arodmxi +z`FyVo=$9#vIi5g4`84WKKyx|X!TAfblcK6nqWD~{X{_PR85^s{gMZ*_{>%loHTL24 +z?`pi0{PyY>KP1(0_@xXU4T5ZMuCK6c{zt0-zU4=TE;}RyBqgjU +z6kg^3q-@K!BP_T;kp>-n_3_67a+CHprENTGeu4b%@sJ$#KQGILVnI4*HGZLkW9a%A +zpoZWtfYLNkG2l@ja9J>+FHunRQckb3gJQ +znVP6R4or~**wN^#^67V8TEe9@(UR4nPx823uwbLuZMx0pyoSGakHcSar+>dA1ob&R +zF!ShcBG(W{BS=x84?G^E7ZwVtQ!4NQ1t|+~!MDE#T1)*k+MuNp0~UF-Q5xm!43WV% +z$ZxAPs9`(gzS7bSdZ_z_0D +zljuKEVBUvJRZ>a}I~EEo{>dDFN!WC$`c1pOV+^;5 +z`|d9;UNC%Q?VuRJPFAhg0i$Hkw#oVzKA>~hw*IctOvMDg>4wYzg8A4P(Zg3&`@3ZK +zz5w32otJnU*J6osY|FXX6*F)*uYDB!7DquPyOQ;v+i&~({6{wCiNgRZrn)Wz!80i# +zLJMs-6Z8zgKj9>Fpk!e4VuGpID54xh&XEC--O7vtUK^!`S@7Kr_CnTiY3!B9floC5 +zswQ9&a`zH$jm9|8xk +zoGDHY)5JeApt4wX_Qn9X@ou%_kT-4C`jFoClsfnSHq-b?xXHzu@C0OGlgDO@oje#a +zA1>NihYRlhr*g`_h_}Ta@$@F_?u~I!xL()+HAtY}L-X=Klj>^I~2$ppVln@A-9Q5kc5S?-tV>|ldkj1p>zWiKEk;LCYh +z)9(EZGlqQ%+;aK-S67j*ZTs$0cUAKx!yfzJuw;}ASQTw(35ZVrwZ&a=rRW}ApZ8z8f$ysrfsFyH$xZP;Ff +zJk9QWNcLtt6eI+(Y`@?`{lvKT-sXG-ZDLd0y#$mlM^U)q9S` +z9+FiRH`1b|@e9i19OeEQ74JN=%C&Kw>+J~`e%}MbjY8-DbgGm8LI32Jc-PKkHFZK# +ze%B}9PW5e|)z_4JPsX<_#?#s&_qBDcL`OTrMKoU7sVu#L-ko@zfTaLBBW_2p%_g7r_cvI7 +zrlflRp~z7`_1k)T^dwmH;~{qcN}qEYkK;w`{)`=p6ram8-AQLNIZS%%kuDOR-*IYr +zvSow+*0juJF2^Im-n^5Kw++5O7?1aZw%g%B`pJBN_J&Q)H=H^w3h{S<8wR-Kk_W)< +zBRiW3Eg4q6;Z&0eeGyfxyfNa0arY2McO(&f)6o%fU5}{4VanNTLMI9AYU;@Q(ReWD +z*5beCxpM1d0`YinBjFd}KY|)uWqKZLQO6evEn5I3(Q91v(l<qpM7D%!b*_ +zdMo+aJrnsom&1JAD~~j-T5!3op`~EHoAxUw?fYruzz48m2n;lz}Tn`4-~H9f=f)MhnOtanr3q>bNkJV;Bj&q}$_O%L(_8jVKZ|oN5~- +z7jK!f!n2JW+L1jkfw5R-Lx&6X(2Nr1OSa_YfjO^N5U}CW+EeX% +zC(hLfIaN#N5Z(wBRPD9_@43wB@5+{*2WiY$R3g{F`se_>um0sUwMRiM~xn0H+b~*JQ3(qZm~lk_|V(e+G+`)uJfPe1_0@2YpNHl+}xEJ|xQKaI{6I*J4JHk>O*L +zMdXMbvrP^&{Mbzp%_Mml6&Z<~-z!*-H%-^w|1a_Ur%+j@d$*0E<4u{0Do2==!pXI? +zi5nz977m~P6?Cu_&qEW)!>>i<#TWE!VFF!CLukh8VEatncd~?YGWu}({Tld>UZM6{uO9!L>+90bUvEI*4g-+{ +zyiafFq-2a#*FkRq?11Hg}!vCF8Yy&ZL`LXw8_Qc|xV>QcX7~87HXmxyHNG5)-c2lF(rp-5owd +z6CHWj605gu*Bg&7{o@=QO&JsnYl|CKtYoQ~)Jqpy@1^l$HlLn8^B3Nqq4{)Y{lMS7 +zGu^L=g?Zbq_M_`r|AtdoymfCrcjntvYaYi3L#>I-4Kv3rhq;}Dad{qD)_>3)e-QEe +zUjYUQ*ma>3@yXb4?od7sZd+>gcl= +zfz)7wIzM3%I% +z0YgINoElom#S^6XF7%YYW-CU|6t*PW7z2(8!xlnKAL4 +zMEN;TvQCptn4ys1SFc32VAMS*a-19z4opb3f-1ot?KDJhw-{kfSd3;B?bk)Z;CAuZ +zAgLn8e@i=t0gu`#t9yN&?Hk1B|I)g#zPqLK58Bn?;J_@9UuSsx$Dk9h*M98o%BR$> +zGdTVcb{6*eg0miU@toN?9jEKP!K$4;zINz+4o^)Xy=!{(A|pJb>OO|=o_vb>*g$8? +ze_|2l(6anHel?zGFzC$+7iVZK>t&_5;|5Z)XREOCGawd=63?IZHw|aWL6c8dA%yJc +zyPS90mf0o3LHY2q92k9&^CN}$4YNbhpZ +zx|M_PD}(&tQm|-_HKs2XhzxbMmhyJy%Kg)IiS7i%pG?wX@(P^TOOU0UN_eeTi-{mA +zz||e4f%2YSeVbyygbnIBC#2XU@U3KP2{^Yk${yq<>_QeT`UyZKWEJ4#UUD}R85KA)7N9#Oeg4&nw4xs{~SY1 +z4L2wqn)UkZZ;6=gMUHf-Cf(?0x}rJ($t>-aS=HGNqW&#^y+<6s&)sy6Iss2tz4@0n +zlY#b1sQ<&B^jB@EbVsWeII8lH$O(3$3FW&=F=KXc*u>I^KY|A(iiKK%E7%$x}S +zZL?Wd28UYXD%CsDHqoo4>2u)QtqqQ*WIL$MSLE<}C@F91(lsb?S1-O|N)1}m)WPA5whO4iQ(Oo?Uv_m=T +zP|_mFdlx2XIP>CEj-81BkCtsg+rCU4cjZh$dP?Q0mIW(Cg<&Fh1(f#>anps72o{}mhNbo?2z810*3JnErX1|IU$9i +zPD6$)x>nPu?c&@GLx#LSQ=EX8B$x&$uh+NB$g_;THrQzgfson+cK3D`se;pyUJRC= +zYnnDJ)x>PC{>U;a)^9Wg;kZ-BK*tKrbw3^_Kcs}dot=Rt@7iv)`2dH#@T;X&2NB?8 +zDwuh;s}L!(fET0F(VUS-o@H!CEw%5=ae*QFGOINC;hT{5opm_eJuf;Px@T!GL#E(v7|dSY0+xRF +zrDyNgM(~?e3jC*g^rz!s0>0<1HlhXE`>EAJ2VGPEGkM;zGmRZo{yeyQpCU_=f8suSOM^&Hyizc0ddOZE4oF3O2lCL%=Q(A!O%g

*aaSA`m+ZowEh)+pIN +zzF@98{VL?lBR%1;WvxZ1Jkw=>`#8mQ$1NGlR7QT25YD$wWGQtQ@g-pSip<9Ct3i@a +zE)UoDod%I{+Ju?=pOH%m^KFssn4C6>oD97%=phRWmibz^MF6!V^SZryCPy|X}aV+S@lv`@sYv?3^j|mrVLq92vOS}sGF4NO=95p`fJd;RbyDD +z5t7xp80~T!)7U8mv9e7RNL=o$nc44yo>U-J$i%+|%#LLK>1wJYFKwMh?Fdv0qcF#o +z`6S8akbJZHmXl`EFI5^ys!GPtag1iE?dBG6#sc#*b`QH=^b(Do>yXFs%mBN%`pMRO +zHhw4m+BCS$$MK$^QOWt|w8gAU;ud +z%Qv*U{Tume+LZy5I(OQjOz&8~QmB&_V#x3`2gT^%h)C=f>cx?;Xfo>>mujTtT#M{2 +z>YVH0#YMm(Z_F19d(hl_ri=jz^Q>pec#|9?GX2_X&Qg~4X22BWm+*fzHSH^OduAbgYRq +ze9lCZl6-iZfnzV$i7`$(1dk{Z{xc0ICCj6W7U6#dJ`Ym^%uanat23R(G{EISz^muh +zj5#&VEr_O!>TUr5OKn^;E%%l|v$CBMPZN +zFPb+Lo-4JRvSKXP%%x=>aF6|7YQ?!YV7kL1qd3XIQTz~=(($<2!@mL(aYM(4+B1cg +zhYf+lJhWf{cfnxG?oqz-oma|@@qX%tOu7PsVg%n;YBZ`0t;LA{(?7IafcEzOkOsnl +zm6S%o5{VKY1-j5 +zY>t8~IkV#XWAs8okVPiof-+JW&3TMjx68yDdbY%kQ>$({_F6H)wi}0fWz&|8NWTn& +z;tQ*sUT{ETMBKfOQw-NBr`)J@f-`<(&N&iJp+>EZLn~)Ax>kd{cXNa0x#NH5V-MjU +zkK6Lfj!YHo&&`?ZhLB?LIiHa9EbedBUbCHPi=H$L$pm)g7+*#O@7Eq4b38u{^|o{H +z+g7480dN~l-HD9#bb5>ZKyO2i>U!TZr&eG1cl(4CL%#|y?PGU;B}F-xbOv5&dnWnq +zr|T<+=3)~W&djTtY&hA{<|Gh_LjNLBec*?poFJ5p2!qUXDTP5`5*<1wPN4%TQH4Md +zM~}99t6W6%px;l*7kolxo`qHvYct*WPWAMS%4U;z5}L1fA1`67Z0WGYWV?iV_yBs? +z|K;t-{d|?9VYch|-)HNT6a33j_(*jN#Zr)>!0YZXf!vqP4}#xiymibhLu3~86A7tW +z!A;uF6#KEB9zqU{f~-&Cf*x3B8HeX#fmi`SgQc<(!B21O5yy1Y)38ywa|s=1 +z`^L}433Q+-E<>%!4g7{M3)HYPEf>u`<`_R-5tpG%LW6jHtN`051hM*=fb~lZ87qMi +z0N&kwq?qGqUWKeqw-z9@mdf*htrHO4Q^4nt(Rd|TruUq5+I+UxPr>A_I<6WBE~S7A +zEfcF2$-pMcT5m}aB?Q6*z7YDPt4k5g8Dh|Ris(Q#l^T?o1ia5Otw;$wRw9taBbIZ{ +zF8k--l#>C*sj@Tn%aDlg{X~*xDegLlPxtrF&ZZ`o?=LGfy=f9P4J~n7k=1%OIYpMkuEPSxC<76jmMpvS#z!te!^LQmN#rnJYd@{1~vhqQ8Np!;_UAD)x +z!Z~dvfbfAmT=37NQ-MD3+vm8_W-kZ4s4QVHV1s|Gb>L6PVZ%xo3&AF%+VAI@x1LNf +ze2$BFu-Edi#z4>moo|s<{4+kD{x>En@mtda!S5{V$8o$z0!p~wy~#5@rd0;A$4BcZ +zfYPcECE%wEsCXgXE`y(F5PEa>=0Qr*+vaF3Oc>9FoLZSC?^nP=^&ncqgsK~Gn(>G# +zqicu(^vMu1;%S0cCRKSH)fz5eyS{f*j;Fz4zY;0i3m>G+ySZFNP +zH2PA_6BGy7#2ngHO-oja(1ANvBOzU{r@WR>qf#7DHL@P$6IP3Lx!>MYNrpTljy-o7 +z0vj}sI*5GZWw6s$BTQKkxs;Wn-#M2M)aRcg&-v6T&*^*mYTTS^+WrBPfx<`c8D$vnx6!TjYN(VfHo)ru +z8?2_RmGWPUgwj6Tu-17FzCbbY*N%v^s2e9W|FMvLAs&teK&Dl3|5`5g}wBfPM_`ZTkL!1+kMVbP!J}JP3 +zR{R>lcwK-L@Z57#8u$+mLCPATo&_`;ulo@Zh>}w)&t&8dmz<#Jc6wyC^bserCOsDv +z4koDNI!q@t^F^vfT&5kthQWfM4z(HrmRmM~?nyu^%O11leSo2)jLrmO@=YlqDVfA; +zLkk{XSoNnUM*j*shRY=iNo(OyGh#TcPQkxUc&XW4FsIG3(U6kFHonH=jP&CyT!O-gC!VJsjYJ +zIG$&LZ8oF)$OS;xw0>2Q} +zA#Wbqxbc=47MSGFLi~kf;$Z{9q9|tWV1(B +zbs^=ndN(kE=Cvt*bf{F`w>Da?WFgDULTC%$w+>YGENSaEs7>is8f6FIqJo +z3*Q|nClY39^$s&*dH>B^=K^sryB~P`{B!5>HWui%T5JXcbBgy_`%UO!!>qOC(D|{8 +zbI!`Ky@&OivwEpOBkWtcptHb>fQ5CG7$pc>ZyjI(i_+C<3uHq}y0RI8f>PB&ldJi^ +z(}X~i3%$0~yZ;?8oM^i4Z?ZjJcUyDD`FB10_oIn+xvAu4z4byf?PfhK&d+wc$!599 +zl!X?PrqVlYDUUYQTyvwXrVyCYl>oF51*CN;kJN=A6fShmFr`M5q|W8h +z-GOoeK);+W8PC~!WLAD0a^-Y#o4PQ`Z9q*|`b>|#-ufGl2C%i*!Uf7Ba5yz~q7D0_ +z9rA0fIG*pKLHU1phw}GG5`Wm-fdWy%i0^Rt%MlW4dC#)SVUiv%07YOH_|$Sm9R|1> +zq6B@u64run%|X{n531zUhPqA8_ya*=Hh~I6LIjfv1Q7-+DPjm4jSJ}1Fv*qW*;QgW +zKj5jRAGaimUEm|_(5MolM7~he20FZEC>TeB1nf+WO~Ii=$dYkMnb9DhD8a5=&?^s) +z7cxOA2-`N;5pBK$fe___u!b}JgwFiP7z1KF?V9QI^}}tlqhB?qW98mQo$3!*fb6Y1 +z(88r&-Q +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 +z{A;a5%Ky(Fw +z5GYv<-gzc!sGz)G%V^P*<c_DF@EL +zJ`xx_q7{iyZivMK04y_h5{p|T(z+#{{@z>7* +zV27yh^LcsxPcY+Kr+;Xi{6K#4!blt8oM3>cNQ80SEg^C*>i0*=dS6!Kbb7bg7tO5q +z9@_Wx(eXQ+oX;LrPQ%DAtD!8z{hZwxK%QC7aG8!W +z9&@Dr>SfVw2e_WVjn7g~_3 +zh{H@{`@Mmcq#sp-b&r=fNuA=BEBi`V3^kwNFvF<1ePo{BOB2NmYQe7ulfaP!9rImKD{*xGpa!q08zC%9_OW?gIG +zYolW2_Q2OEHMXWP&M?P6NHje +zUWh6l08)k}7NDtd0^OAX@^yY-qobc*gl20pV4%kqQxCBah8TP7#Ig{voHw)K#^eAp +z&^0WQ-o-DdJ@G7aNYE1M)32i4p~iEQcv!3eHISXh48oyxe$@m%0v*VKPRonui^}1m +zFDEEQ2UY=H`CeAbfGkWh5u8HimYa7HB3OVqMw^^hlmt2yhpf>xOTG3*HTtGoWVv6e +zSY>Wlfsf3MA%mlm=2|3z+aSZjRv=|iuW`PumVZEEEdvVaol1AA#TD9f`x@=p)PzDb +z*Bd8l%d>n0`CGl<_}SdJ+z?;+XZl0vTU~GBcqpuJ8&n@SkLty4Mwf|%9HhtbMYU~Z +z#s+5Q_`X%NMdWiokiiszpZE1$0{pxJF~m7h(fxRs?DcP0^9K196!Q(2^+7K9W%o;7=zj?BmZU6V3)-isoB(2Yq@- +zgJB$C{Zv{S!JN1SS8Sy9^rYBMKYz6E5_}Q!Q*Y+M8mwj%z)zn>hpr0_Anv!VCbZsf +z6IJM`yamnw%$>1B?uG`Kbo&d3#u%rXVG1hKHU&}=JF!5-Lb_O}276c=dPN85pBN!`FS^9e>mpE36;S`l=! +z`tMz>84(fmLZnj~CsG2PHaZk!L6vY@C0KJFzm;OSaKC6|#7pzaPU@vji%|j{N9D?Z +z(R;u;v0<64GSOP0+UF&30$c%o@KaQ7$CMxCWmiP~UL8!P%dr>T`VB%!G?JU5#SQtf +znC@M=p>mliws%-$Qwv%K7ZqUvzMcAj3d={*?^5mSeI>A0PY1vqKh6(D@4}WctVRmJ +z`QQtb9>))sj&M8;kktJ{!>GeX?m|;2w#hAi)$UL^dM_d9rRn5v*DHdb@hB`K`OfLRLh#=N_+II$PM9fh +zf9U`nv)M&kk+F1ZhUwjEfU8C%AaP3r5s8r4jWo>}=3W?!^d5SbPx3lybM;pCc`$y8 +zFyElYWH!#R^nqkX;Q&~5p<#e0{1%Pe^Tb@A9dle}S;cwL~mr*W6uT0D@d +zJ2<4-mx`N8@h6@7s^CQQ*VtR`u(Id0Ii5id;^*e?pht0Q6P5!7Aj9ZYm&eW8r6akB +z@;@(v9>*8PtY)n|)xqW4?Fq}z`#Y`E^N#*Pzn6c-*U5=cnt4Gqbc*MJ`sw3aRD@j{ +zZyujN6r~zH4zLPFgeNZpI1>pLPon9=B-2i1yk7)TT@|2vrs-4$cx)vupF%U6*j{3g +zbJTPButVH!fLXo)IU92VaYNj*>@yV6WNMrj+^i*jbo}Jp2tGDH;B^sGP=nL$Wfxn!uaW64La#e~9#9`FUakvT{JT?+2O&*K4A#u?y +z$#qrM8e&0I?o`tKhv;a6!|$P=`z>%Ay(OMOjKc4HjQA~$y^ECAi|beT2KVc0p8eo( +zF~xQ9@8hWaLDBk_j_yRGyqwN}{B&RHXT(oU@aP@AJI)RdfbxZ1VSKuL&R;rvS?yia +zy13c=H;$E1$ab@8{!^s(xPruXiLA#!mr&~s?A1w~=EsEHz-i!1)4qAeEu-cdWY$t! +zz4FXd9^@ztx4?@J*Hl4y+zcfrqbjd^Z@`05m=BDC_(`-$u3p$6xDRX?v~9XFT|kzL +zS2}iILWwe6NI?ojNC|fx9khYSPW?8ZPrM-hq*vm#0PV>-*fc=*Rz9@9SLpyw*^3$v?PQe+AS<1Wlu(>max +zObK~ox-glN>RW;N@ +zNUD?ou9a3fD=tG|1Uh%4n(`l#;M6kNa)I$;9oown&KK^tTYE4{&;tS07>EE&f>j&EhXR5kVyg|pSf)1QIk{}fEeSHYS;&o6h~HjN$rM}F51Q3@oFNlIHuH(QHk?|{H>DJT0{(!~fQqaJ5AF?0LSE_*X`H}hpb9D*+y5it +zAEPVnnyz7Z$F^4Kbvhq+g^XaE#TJJE2FUvGy>%!|r<)x%o__^H +z2FAXjlxMk6Go4Ma9TRGlLrIitqPrUmX^3~k5c~EyVdkJzRnXODz|(uhwwpSlN`*RM +zxs>1mC%`(_c8GgLlA083Y)j~7$py<3-mB_FD +zeU~)TU9aLmf%Ogoqyv$)sA`(@Y9!;x=w@0J+^FhHvX*M4HRnXoZ0JOSOHEQ!s>J#f +zaC_ky(BC&1cF-;uuD#JF%wm%yu-@=3wxA~)RLNK@r^W&N^cxDq-S9why{NREUx*87G1KX_!Ry +zg~@{H*{GVq4R*^8NC;IB`hj|mjN}N< +z0wfuL}r2t!Xb8o-*$LVU?Y`EJ`$>oG_8U&`Kw?jDtlgeTEQ7i4diNViQb=0Ib +z34M@_dRv*XeKLG>U3hg|t(IIG&KoFgCn=DQzueR=7*bo;_vS65V1h)KBEx|5`9Idyn({OujwAew8y{P5l*1zwniuR6>nqYKL)Ygw_A5p)H_k;*&g%nX82cx +zl{goQe)8`zjOHU+eJyOTY!Mu}L3u=m-Qvi3BhXDGPwkobR=A+)t@2L^V<1K0Nv}wl6 +ze+BqYmct$WphyE|iYUOMx5oi2Vd0Ar0oA98^=gQb0r1=Bwnj`7R&S +zmp}zTz+C_f(mF;HB^c)7R30LZ2PrBI<}BeafS#`w9=jm(a?Cnrf-0f +z;CP+zDZ*bx5c=$Rq9MmtoE)$V%H+Br4qTC$E_v(HjeCCmA`SiydS*g_q5@SAOOvg^ +z(s3pykW&cDPRK1Fx@)A6gxo2z$r;c=EsnxUj{FCE!B^rd{ +zL(V)R*zI47O(H_8ER8cAy)V=a&Cf8K|k +zok(E5`lY94^7SJ8oAu?+bMoo#vVo$3Hb-`YeqzzT@q+dH9^Y4?nh>(a1$eYJ%N +zt}||4zW0Vh{jLK=Gg@-7q<+7FT*sO3bKud>A+B)QXO3T#UBU&>&DO6|;TAQg&5#y& +zN8K8!N=oPHsw==`M;XThVHpKfJV&W +zdlc=27tA%@s6gW0Z&YL#f)b)6}` +zh&3!3HENO=UP27~wiFK`T;6n((Jrz;VaKXC<}C75^!RN;bmBEU1j*Di4LRRb6|hZ! +z$3=*ToJ>EB0~)6kz`f+O_G&k2vEo>eSRvyQ6qpeO +z0yX`Y7Gk}eakemgBa^2Jd_r9!;zKX!!U$!3x7|uqygXkTZuU4gl;a&NLeg +z^@W)x_?!~tbVdjT>W6C5x0%SCLmnE*`&^vnR?~PF(EdIFS0Dk$+l`L+*(yD_S$v*I +zRXcm>f^+?i2Y5dNb3Fyx0e}Bb<5w?Raaa4tdQ6My4H}QTVe4Q;{7K^a>eXk}2*~s= +z?r#S#hLEWU^B~c}RT8!N><7ijXxx~rlT{_~=E+OcXk=$1S7)r4wOHm;&l%=y$r&;Q +zKF>t29Z}?ctKIJn>faZ!K>uTU_Ef@g+VwGF%wNG`4YE6JopAW&qd@mFxaIcWmb3dMkMsbzO!C_A)4AwW7!KR{xWS+tBK +ziCjU8t%gXj964IAY-Bd`CK)pPf~F%W*@a@E@mI}jMsziL;?U^te*L5_M9*AOu`WVT +zn!n)XlD>2*IGr<=>Y@OMt$#Y3;=^yn&2ii|#adF6iBo={Ci8W!t1&jed4{{Ckv$Ym +z*Ymz#Xe&aflU|x0)M4?-ai|sz1k$3mChW<20pPrSUV%&cHf>9hSlE!`Z691fB-`uU +zTq)n%WYXnv{3=O{T*r*a06Z_i>y0kpwcE2Pek#@%coNSa=xS!$Arb(1t^BgzOKy5E +zSdCEn91M=%mH#@U^DLfRR6L>2^JQ$!V1)%~&E<6fg&+d{=M6r`|K?$qurM|I%2KF- +zPKmM4x%7`dC_2<8doiY*knd7HOEFwbrN?4oSngIG%T^R|)$P9~ky}e&nSDXO%=MV8 +zj%A9D0ep3?4d0Rs2qn!F!w{w4(=XF{?N`i!7Z9uky*iI&SH|GV)oS5(cIyx1ynPu_ +zr$Afykm2SA1f{E)3&^f<&W4LIJ)C|alQZ)Z=Z87KrE&i@A!R3Gnq#UiMBm!!w-Aae +z8T*In7jM{RTpPa$9o^K)wTX`dT@>MWjT7)IzmJC6L4@j0J(-fXhv!gwB({@Q)=)$e +zwj1ByTWJEwCPz%$6mzO2Fj!&u+S$Oy_THIuazX^G!$O<%fEP637uCr|JR1FA7gA|E +z{^>3U-_80jqYa5e##5;tx~6y#J)RdI2JY?p2imq-=y&I>!v;tO+*$cvXBx>~XZ7|C +zVu80ryqy96<`=1rP?lS4=sc)j@b?GR(ARW~C&vM|0D=O=Q#+|Ar!RMLC&B$o=7Bs9uS7Yk&Raa&2l*-6%; +zZeYZ^i97_Kxzu4%C2_w)JjG|Z%JWsF(Y*9=b7ELqH=K6=)+l4R|8)r;J*+)xrWi&8 +zctP7V?Yo*b7!vMyO-!B8}hasjea^x +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 +z8$t`o%tTOeHgHlb?5@ +zdJw5d>Mz153|cPAXcfRBM>4s4nai`NOB8_{r)4U0s+Zyn@Ow^G*Yos-{e5kZ)z$tf +zMgyuJ0uV>wXn-%!h5z05*kh9$` +zLv(CSvxZTma-+L3AXdj@we<&zlOo8O88>LUNk`=v3E;{S00krj1v>#nB>cBJFN=x|Zym;C~$Ok_y0S=c`#){m;Q +zk(RNpILDQQs@Xs_gKT-c9*E#G0F#+C%%q=QQ9+AS@wi2T1izwYAb4}#XwuPs$bP>? +z_?wg?X?e%cb)NAFJsHVDC;ePS@fftk(mG{iq0q96Bcc6|>4@9yRJhze_!CD?vjoRg +z6LT#E574J6KtIj=d(l_?cGf)J=D%5`+h4s=gd6O{hRsBVy*j*a$nTO4cW24ulum@q +z|5D3Kh8rpq*^4~4G%!1CS)7u2qB$jyDZnvfDC&(NjjO360W&zdlS|pbn%1e#;-=55DU@W?=Q7(CL~?AGU?; +z4yCsfA{?aix$S(Q-CuWLpK_53zLAObZvza3dZEyi=}t!}qyUxs0h7Ga!brg`QU`EZDu_GqV%#}CLp5+hUYWibKF-RC`3{h4azW;z +zjN_-CORK8B8(@?1+>;*PuhtH5J=>pur|dq1--3oEH$jPkF-;5_ +zGOifmzos#~=`;ET?fDH~97-BuLPwd8aV9gW>UIr$!9KoJFQ3#K#`K5i?csQO*rvF3 +zWj6R^c=%+r_+-|7S!?*S)B-xuip)YPGLd*m@^B{%P{5-dGD3z3aZ_#;?~9?6b0J3A +z21+#x^aKUe6U$RBMY`;7_H*Votgp8t6fsOgB;Z4yry#*W;ak;izSp0 +zr~oVxU&d}gs~`pp0bhVPz$!PAQYCBU14!2DWr6%E)Gu89=MWzSM9XmOYVeK~R^v~bfuXT@E8f|C0cXF2YM +zk{m(=FhfEM8{ba{o5xL_SrhZh9+vTnU^5$J5?=1;}*0X33xRxu< +zo&_MGA2H+|@**KyXLT8!UK2xTI|_rN$8-wTzzWLeQ?pF4$-Xc|k%7TT5}K!^=0gI8 +z+XhR^@MtZ0K(ZZ3B5QaL2xs)H_R?)O2#IqVy)kgi>X{ev9&pv8f_^3Y{&!4T*k|0d +z416B8EC +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 +z%<}z;%^3e5 +z`1BSpdVkH-bPULe2tE*lD`!uZg--_i8ay7GC +zbyL#6VtwuRl6mOO^>?m?*Z0Xaw6G$ao`U_wRIol#W*|Q+qk3VImkLJr^; +z?Lcvm>c4|8;e1!7ng)WwtdC@2pd>KR0_0NPCWg3Bd^k4aWsp4)Y)na6Of$1(fU*T_ +zpXz60!#lAkn8J=gMIjlJ0v=f_5fmz;5PJHO66TT<_8>SU2jGBi^)zhv8EZKzI51}^j2CwYyy17$O7UEj6XK~5 +z@M@AvDn3sW!NRb?Nu;k|lhsuc)Y3aU{Q)9F`6pbgt~NhTvy{h*uFxn1=Uw^PJ{A-1I~so!cdz^ +zqW@b&{O`finO-mqxW2G_W+}myNe`03yX6QzF!>oBa6?TJcRT4GTxY +z4x@IP2SBitc#C}mYze95z_m@tTL(0UHvw1uK&irwiz64VKmuVc1!VIdMkbC};;Yy>63eU{OWa*>hHBn`TaH%N++pv`1O{Udvj2C +z45|j)U~`&jEMJg2ArA})Ltu3WYU*-)e1)}Q3(~8Dn*m9j5QanoL?^A3!PURMbe&=A +z@!wHvrEM4Axfnw;(D8-^%%8VLbDboG0sC8DUwGJ1KTna7f}e&Ai?}0!eS5fZT$?3% +zm14WpGM*;%ccdIf2;Iyn4JWC8(LUVoSS%D4704(yDC@CRDqwlT+Ypji%JC&O^O;8* +zc(c%cVE%8xceDJytQ{;!eSXB2vHGCXNo3pD-vy_-&w$Q<8u-R6Aa0|=rcQ&~hmv)` +z9bi~61HZs$EocIM_p1a`6@`lG!Muk4*#pl(jxfol2vj7Y_czEHCD2(^b~N<$mgsd- +zki?2f0b+q@M^iGX+(jjQ?^L#K3g88`Os4un?%i_W)WdGm$^)ZJq+%dA@JwCt3qeFYQ`#ev9KC9M5a3D^( +zJ{}Ib);&O+v9RuHC=hne+`9Uvtf+;VFA(wyrpSO8*k}hcaUc>M>rqHNBoJ2iHV5ut}4CWo_^rHGchwU$%#lta@>B% +zd-3iAq>zLt2rpuiemivw9y2G@Ua~HG{=_1bz4r@f<{y}+>&0JK;22FO&nUX1-e`Hn +zXqVB8VLl206RWShhIiOjTOQZfbztjY3WH(@^EN2ztwp5|)K4;u-D(Q_b?AZs9U*rq|(f5iH@=`3? +z9k@Q@(8Oa4KZj!WZ$pej4|{5M))qe&Dg2g?t_^*5n)ezz +z!&hFmXWCG4DX*(Rh`d20UH~y3 +z$*Rm`>gw1UJ^bTG7w;^;-9N)#G`Zjr2g$KC~l$Wo@s7EfxqbSs@#VN*Vd=WJp3Aji{OGg&A=YnuGC7}}otk=(Zu1A(y5iX_`%-8$ +z@Wq4PXsF*JWO5zqu9pE?_Ib~^ +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 +zF1B=;JB7-{$Bz4Zo3h*%B@5e}LeL@KI$BKW +z?E`1FX)F?j?`+WA8@am@`vxq5sb; +ziKwKzg(p;|ED2%HVFy2?r12FG5a$Zc_I(BhSp5yU#HOkCRerM1|qJwtJxhwl6VvI3Og`@EU2hA8Ug +zyKrHMLR6@o^{ZCQ6~$9Ga_wG?8H{SkLyc3fQ1g2K_t7qQTj&^FQ@Y3Py%BNMvx#q7 +zzNQ!64gY(DfHE>3VHujxz8iN^zJ^x{!k-OKBUApf^zuM|gwJP4L4v{@){1Gt4)Be( +z0TnDSI0vr~)BszlUh9vC&+WBfoolpkzv6>GfHz`*HU(Uf<+cTwwC4 +zJS(O4sQzb+>ot&}-@ccf;+7EDf-j?O9Wm%J#FX+19JHxmQftCaC*T#79{&8Ck- +zi+mnAD`jyO92Rw4ucCFJ(Ub38w8`Gb|*tFSsxXegmThLz;7wviMXVr3j^> +z)-&%K_oKDw)qODc;Pc(VrFDG@x^l3n{TkZSc2|24UnEX53&TjVktwm=bAz<~GMLNT +z!;Z3Ze{(rjQp}X}Q{k2aAC{X+YUmz6k76{>H+)({cso_j3u9 +zwk1qZB3{Y>NR9GSgXEF`N9E3Mhfn$KS5RRtIE$B-IYMR*-0S&`sVjfd*W*Fiz~$$A +zBdf7+P(xGh1ZVRO*h)@hz58aFSt+XE4OkEfCkoEtoe +z!t^Rb1nXNjpde-r#t7Q^ZmRsr#r9Ma3v_c4C*`#HX2kH<#{R5mSH?X1?B*`dr3xz}>sIdecu4|vRy8{g +zeM@HkV}ZBEG>RpZP0H(%(73@p&d4Va1c%#$a!sE~_>VTZ!D=W0caWib +zgv5TEF)W9(f3Uu5Q_k!(MQyMk=A7EOF*!Yh&~SP;Bls$mP3hy=&v=MVACzXNJmHX2T_W?g^qv2cguL=c}=fpAtToJUjDM_Jc~kNFbJ2V2nCdi +z{kP2EgxDrGXolOO=iBpfRvl(WUU1yub>?dJ0m2-i@m!09wzGC|y{qkZ?(HF0M1=n| +z4|wH4G1c;&w$nvi$P<|GeI^v+)PvjK$-WK8_I2mJ$VJbQWO&>QkO1z|yi1D!$8 +zTS;-TYm>`4Ej+yq^sqAuH1c=iK$ip|wQ$Y5!t*w%1OCq>i(|fzE$_}VcdzW^Wubj_wgFSC+s)8yL>t0G;wes_(WJV0J}Ez^;WONCaP9i$m<{z5(%h+ +z8zj40gDF&$I6*49s|zwx5E@Q-0%>jwLUXS$#MJ@>@t7(wdijQx?vRj>)+wV*p3=nq1 +zlj@KVkp;IIC?*xc&aaf;i^T=qmjwr}4WcYq=s+;Xm+;|b>2Fgj +zSZy@U2CP7G?5@q1t;-n}7074n~`eWejFjB--CKVZR +z%`Vwbyul&@oEINE(}=Reh`PdRJO8~pYrQ&uddn|h7duEmC +z$WqFqND%pu`P7SoxqLYay4<3tCKn)&vWQfB+Xw>2HABV$-8g^)9H7Uh(3$bhwJs~@ +zHQftMXC-KohhEj}3h@BZ;;Zu$K-(+uIR1?teFp*Z09MH4jxcbq9>G +z)2OyG$IOBvakB{eMfb7(L)JeZOm5Gl@9F1r0*+YEsJq8n@D6#mfNIdn8JyZw2mT<{ +z#j?Zp)dlHg&#{*pFxV1&Lk8nM7Pd&0LGuO_q0aut!_y8?Ag>fLbHH4&5^^-a#2&ST +z!F_&%f+`1pR`%%WV7>z2Gyv`FC +zBcXw*hWl~%F7DH)oV`P@3+}b1!CeK?TUp5#2kJogzAEk=;NEc1{9Sz~Yz?h$SvV}F +z)4kduwz71$q-s6@aT;a21-{V*LPt9ekPPHH(;Iyaq#{m5R#-mm(q1Md1 +z)=XM{HIKrEDwK?mP9ub@lra^xOl43(3R4PNgvuplE)^MD%3|-8+~$gZSI%Ho9N-T6 +z2LaHRlqF~>ED2Wvo=1MmTF9%bEVp#6n?dh3n@0B{wdPc7CCrsaL0bweUF;aZSHU<} +z{ox87rY{7==1~WuBb_cQ4}D=(UcY*(sT@}31)LJ*IN4 +zmA>SQp1ASqz?vlrrou^UVe>T;ct!aBybIa!uHY*+`AbgZ>xN`kIp~rJv`5y~VZuv^ +z2Fg9=fYOx7uDLew+0)YOK+JF#XPMOkl~6F9D&7_X2jB}`rX_)Rw_`@21yoY$RK{|b +zRspdXH-|iyj6; +zZJqZ=NCKvmV|~Z|kJ<_VWu{uBDsi)y_y`xQ+wYkeBL|s*-I_#}ICM8KQ><3MV`ABk +zr-u$hnqM$~@k>zS=&fG|2H=I*ug&D$oFcc#@;*>Iel2v))wTiJciWam^DMJZbgxXNz +zQ@u2#cJM*;6!=kfWuYt2FwbHsX4S#DiR@BRSU#Qp+u?!sHn~6i<{xxHk!Stqtw&M_ +zdT004cW#K*Vucdn#jN}YQZRCUwiV58-f--`9zBnb((OX>Uz^`n!Cs>*S9MLghsg|m +zRS`%*h~^X}3AYB)m~kS)Bz>Aw#4WLt<@$`30u+P^BLiG8TM1Z62>Cd{;{gTYWb`G$ +z=7mOtzM}qAw^_hL$q~r)D62_ugJVFGG6}T>mDv@P5(E%aWA&G4Tk&2t?PmM@omq0? +zr~DEG>hjA4La_a&LN6LuYmoxFEVQsxz6t!bUrw!#YzYXSN;ur3u0ut~kBlV~d3V72 +z*?2~8x9d@#&+6}N{>V+M7kb_N-z(AW!-hs+n)a6=Bi8p+Ocl}eub(+0{I(5mLa?xZN%m(Z! +z?SBkQs>b;h(t+upqaX_@&*?v`tESfR%&O@Z)xs^SCYzT`C(e~Py8ce%t2T*GyHuRR +zqYV`rwWq*^CtWKn=t^~pD>_r1(}QgdEq{(I@KzHxHB?H<5HTs9W(kWI!u+Tjv*HG? +z5*kDV%44c<*Xpe+S?6*#DRG^8X*nKZ`-A;4L%*8!1sCqeSTWQ8P0!N(9=mJT +zb_<7B9_SsQ{om=>$qpz=Z-Xo)59~}vrm{!pK6xbq<*9TADJ3*eDdCL>nq^?G@BLxX +zd08>n@Zdt|v+FOn3(vlY>C6!oD6heAXjMKoDo=SOTuL#jY>*mpPO7;d#HYYrEdk_u +zSbBoTaU_(9@(?d3qxJ+i!o9^Q_}jt%VDPba8eX;qH993V>HP}SC$zNe7_9&+2B8h6 +zew#tuk9}oMFL9RFR%+FLk%?nFAJ3FQqjk}yb;*7^|KrGe(rHTXB2`%nuiQi5wP6i{ +z_tf6`r`CO~g=_wIDR|J8O)blXTjNXd5idNPnvQq>D7A`&b9UaLpfQ-V=i0}mSX>>l +z%No_>4(-h$$?Q%}lw|M8A&bvODM@gx|7KFdmZs+M4*$b1uVdCDr^u^~3mN&1N3R+` +z_BnfQ|D2&Knr}bYepG|syG>Em2)Me!8pyo}ZS!at-N-NctI;HEqJ${(tfZ8(kR!`( +z$@ZNdu+spmhuf90y#+4BEuRx?ZC>RAb3G5dc%8MZ)ikn|z4CnD1mBr+3!W`5n2%_O +zVz{fY9|~+_SOk}|{B(Mu^qd!H-nFdf8@jG>S!MNKAW@5gl~aHk>aot-9+@@sOCB;` +zdj0W!F0n{IT$|VLKkKM*kK++NEY|V(eM(($h!S&bXDIYhe!H#b3_ynFR;ue>oU +z7+dQ5clL95ZIISoHZS_#Y$U +z^KU}yIl#|OKpGN$ryj_6i}~hb3_gKhvM)z{d1|_^@8Wwb?t|aRLvh58Jfc{}9YM1j +z(6TAWI_Ib;8D0YoPPx9ZsuK%XZljR8#`{o|N-n1&x%I~jNnr@kMhLdzi-K7E67gEJ +zRxt>aDr--_TJpuVO7Vgo>sh~Kxygc`)q>xIab$msN{^`AX6$PzE#an3SmRp%4HNRR +zP_#%Fq(=9u@gZEA1aFRZLn+0?_Yqq+9cdO?@=3ra=(inSBU|;;x)FA?#ViqD|5WLS +zvKW-9OP(cWJ?kF4n0VMSF$$In73RzuO?1lribbO(OZHtIqHSQte0@UB`26$HHj`7- +zrhl>$x0&Lh`L&|EV(g8-1>?a*J7b7pMz2L8|pS`bE8hdwRJ$IFjL +z-}Q)f(6!Ly151npkrJDZJ1L(N@wJ~J{=L5qHu*)*okHMa3gptsNXB<(gv?|2j{{V` +zW#C^ioPr$%((U}nNf7pj?%9W28B9b{AA%=3ih9DBox0ZJHvpbPDPtt1%kR#iynU@f +z8Opa@73O8Qz_-&Aq+J2nYt_q_yMe&_V&PzA_-87Es+xwDxgtCFj!hb{hF`&A)O2qw +zXB)#SHQZ`0%kqGosC<6|rT>XzrlSb%NuWEb^=`0WOL|7JSVMakuzW80Cy4LFi@x^H +zg{~$Y>5jSJI$zN5J9rJ+ge$|m{p8*)y8=|5Yjp8|R8a?3=!Jt1c%DASc~QA~oxi#% +z%;GhWAPMx0l$>_-{Q{5PSR4Fg4THP)gPeL1UnAVL&tRR?=!~aE9kO%zU!jFM71-QbRz5MiVumF$$76#Y +zvX{Fm_PHsvmxh6^$CLVc5f(Ty+9^BzBs_3XB41o`i;t+DIn)^cQCeO!3ef4^l;naS +z;r+L*Gs8kEcc1TN*l_FTbPtD-bbOsAS0+pZ1+ZHea41#lto)tvhx+SRvMDy6`*4#E +zkbi6Ya9a+~U{Vu1;Ka9{-^V{5*qL~sG|JX2xK5vQKwo#0uif`uQygvVH=7K)r-(J4 +zB9oBj8dNl)W<36TKg@Vnop;C!pEHGgUEFJblbu%g$(-)zCCksBRz2t2(Bey}+bojFGg5{dgXMwEEuDZ7(vyS3H>@ze +zKKQ2x>OMK$yBGRBHR9U#F7Tgp=SIsM6uRP0TB@OG4RIOyUqNc?v6 +zgtN;^eiK;c8+2tI2S1YfQbEt4P3SaB8NVcVhzgFobqQ@B4d}4(@YsFy}TF@DTIF +z6AfoJEk}I%6tZhU2E0)G;b@E}+>DZV7Bhz^A#X6`o%Ktc;}-~pDR^`q*ru|e*SI56 +z?I4vkCET(dW_v+(re6^O*~qD1NJ!v1U=JqHyS>9_8Xq0NB1Z`9y@fr8oE;uq__dVDd+{Q0G{XIG9ha$ +z+<05FbN4Ym@yKT(V$O8t96;l+SeH=g{VQ +zeZu`lcH+M=WK}V5)y%=2d$XpWTkcG@z_fMW%}vLfaQ0x;5$d-iSnt<^-+rG8x$)F{ +z?ue_|l-&L|U!h~OPB~r7A%qpO1UV3HGGM`Yu}oMj!$nqp*;V-Y(J~7^Wp75eAFY^wtqEYlnYjXrb42k#oQ +zby6Y9vx&{5O>M~=qsV_&wW*(~tFu8UAl=We$qcZd93Vze63^2|3&;nW8G5nZ+O?>> +zp3E>Qadx|lU1p!Z^Phb-e=WNjQ@%zTV8Cxr6_?fy%j`@1f@CZ&=te_-=^u1EW&hkA +zgACZTWb^oFEymPh_3b(Ddx0GoLr-rv7&g}p%B0F1W`(fn!~i-6O72zB*^_lH|M(!F +z^*g}ZVw%ji+kjYDeI%slR7n|vsP#|4EB$5UoyU;k@lx2OF#^we`kIuMAf(P5DjTnh +zp?8_}#125M3#B7~km$jcaZbYx%K@>>WJ+d?<9ku+RX-$fIK(3KfC|QO2MO>Yf&KV@ +zV~oy;KHgD*?gwHBd%w84pTF-31KU+)pKqqG+vPsdyD|>fr2-c2Xe*hm+>u)1@~=W3 +zwuZ3WJn1Hp(mLl!z)8u1olyZU;-@YT|J-oa%&YaJJxonm2ED5#!2(L)&Tm8KA{Cqf +z7kk*?+CM4%kd+l!!GdF1OI<2VInwi9v#8WM@R^T}ga)wL`b)Wm4~?#MOy(`|VjJgC +zs=Fz=YdX46Q!mwPhT;v0lt+sFkxHqmTi6T;Qap7UOd&G3h|REz5NCO}bxZVqt*egA +zv9M>OeXCEX`duE(cla)$qqBHEeEO7AWFU~Uw}GC%G_-gDPEgo1a~Ds6jST9FyHL;T +z)|*XNn4Jl}=)QpEfqAz7`bYh7us&uan(1g;aDf@n!i0D;5V+6mKAVU4TYT|TKm;;g +zUaxOB-%g;}Q;lUg&(+K4^fs6lH9PXkvrJ=;58|fe=u9Y~0^4*}gwD&~my;)zF+t8~ +zp$FD%3kM``QNxo99Mar2ThuRs$vFc8*PBb@j+XG+HlT9$eR~5l({b9ybAj(v?skTz +zM#g83f~*CSNbiU9b6lCPcl|&*9g4LI6PU|%uery%>Sr9Bmgg4kz{Z4yIdnM|U)L0N +zflj>mJv863`IsA%`Ie4>@s^4p9f*Y}U~%@D>dq)KBm}$ur9WY;g~BK@%47<{H>WBZ +zqWa)sbFu(WO~w5ce}maBJc1$f^c?(2±ganjvGrfe$CeD2l%5J0frM*7$X6jYwXhW)=;f!(?UakEFxt&tjVo9fyM@za3 +zhOTlo1-blvU2)NYl7ti^Ygz29_t78MB2EoW)3t_h5Qib5yt2h4@WmSZA`sR{PzCrO +z2FV}Qh4YnJy+fb6oD82alpqMRR>y-0v}5n90gN;_7HxwI-pd`Z-*8*U73!W6RABta +zENbDIM(HHeUZU~*2|XU2qlr?vrOVi0XYffFaAeF%L%pY82J`bW{LXGLlee5ZG-Bt8 +zr=41fh{5zqpu|xuIW6-vk(2Lfe1d$)f(*TZYmwq-BG>D0VhEx +zpeN|ssH{vK5>SN&#JH^yZjCmgrU}rN+&9&koz<>RQ+_Od-b*xd%KVawZQdBm+-^Jj +zZ2@B`r|`i~ywCBLP4P}sZ)CPGIBkV88}5&9m;WTD{glnnFK}&q9mgo2q7G{d;P-9s +zo3CsrY5;@qq9EZN1uqcH68fgr3lF{x?-0w{`4`M8?+7398q*2Bzw$ +z^ju@H3+c1#=h?JriPfjmnh2*JJN&IEmn5QNMD4Ptrm0K%29!`*N2I6WTzD3*}hO_Q9d5U3| +z=;~czs_TYM@`IEyj5{6j*$8Cr5J)Lk(CY46wB_GD+(mGqFkIU_S=JI=_ +zDa)f&uXh?T>_t0KGLa&5vWdNXOBzlzWm?BPV&B>YuW89O6X|$jCZ#cZj#)s&^rd7y +z7kYBV2T8_!@?B=^E_3RLW{93RP$DP)7jMJQ@#ndPy%k|td15kM_&Cb;JfCm7U$tFi +z)mJY5YUuLpw$b?@-SmzdsLLgGPq6UmNvQ8?kHfPl1u0Vs!wW`OC_kn4MXgT?E|p5? +zhb$<0Bh)1Yy!~sF#ZM@3S@?@(-R60(MM19$A$stsA2^WZvVh6nduncGM~6lm^!K#D +zOao8ch*+kHldPi)uRJ};MMR}RKpf7%{_I;Cqo7UX5&<0jO62F8J(+k?W;Jd>cwEeb|RRmu= +zJ)QE&_ec*btFcP(b{~FmVDWH}1c?(8R9&Us{^)zDU@(0keNz*DSYhEAcAwL3%cqF% +zMoXJ1palJioS^fL$m*CJPg- +zRH3Tr%_m~AUfv*Fq5Nc_K8#uUa +z<$|M{50DR6m4z3_Y^jsoj@L4v8H?^(NWzVFS)Xfzdh4fWY9U1Ru?@!_PQ!0UY3E|_ +zs&(L5?ijl1GO|=Mi^5O?47%<#`8D)5GQoLgymX6ncJt&l&RY!jtXeWEoRh(Qqy!z4 +zV#Dst& +z$NQvRS*e5P#+5DBt7GBOHoOZHviuO_ +z#05@j4zydHG};>vqcV+68UuqmeeqiK=b1O%*bGQjE}&O2%oli$;=g+q#obT4UB}%M +z;vD$-B^X*X)du~4A;ra=P(7kWk%Qh9s06V&Nzf~YZ{-$5 +z8zZnX1fIl0ADR9`${M8Z8MD6I2!jhR=#exaE7gO7MuK|i<5iStpCk{0laxzH^w}12 +zT*=cFwFKhkznGln(I;~N6YWRPfAy2%6(IXpKi7Y@AsI2&5Xo9Ao^OOL1f*(WQ0PR{ +zHlgF50p0yU-wk&g7bLwNl{fwcY}_4o$iT`fsz%$ImQHrh6Hn!UdNz|xX9eyX0jTiH +zIEO8sWl)iQ>j6(sPhViRW)TBq4);m&CG*L2<9N31x+okyv3*#>8BJl)u^xY^j3)FJ +zwQXg#sk|H7B_mf=BaMyK`)QG*JFi@-X{8J+juzs|blZE#yn(e2VJ`F*s1q>?CKOm+ +zwOrghISJfRGJq$NZQ;syIxl-1 +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 +zee|&d<@T;mi4F&Q%3#6|on0~%D +zG^hsdx;h0WFGQWfAb^J-ro}@h#08ufK(W_5Is~!Prb})loO~R-sfK|i-8BT`#klMM +z$JLAv9j;9rxBn?C;YKZk^y6%q&YC}Fquzcms?I#OT86t65|UiQffew;g1`VmWku3U +zf7*?9bXBM`b6PVk_H*ibx_l-WEH`j?>0<;&CPW2?-c)E;G_!lD;JgI&Z6*i4xA*Hl +z+V~m@ALYbwsHRMoy4uz(`18jKB9y=58iRKFZcCG{N_f^^ZnpEsfr^y72CF5IEHBR; +zQ=s@r!rT&ItWtRfJyHwW6xiFrCtNAT*SZ3P0q=!Q6{?7vD)`>tTlV(hrJb74JrV}A +z!lUYavGK7gqsN(yiHjg?jh-sbI(C^YGW^=xRzDk`?>^Wpq598z<}vWs#Pw_J20fX3 +zp=;8u;4DS>UZArqRSd|^H?je5LZ5Si_Mu)jkwOhpi@OX!y8%vQmlE2C3d1sYT<24< +zj>aV#92#t?a;xK`CGTZe(f|$&-kk|-5mLtxzKEOjjIzeeGZ?bFxH;&*q!Tw!sb-l> +z2`n~~t~R5tHk0l)tDHOVO_5pxvFJy6;IPBt2rm-EbAW^Urxp4f6u)Xm +zINKx$2zV-gP#*w<$z$gj(Sj!H9kLgrv0`v=8*NV>Ae8s@TH|^16iB;XeVJ{Y`U4`b +zr5wO7dRK!RkXg^n0V_yq=^-9TR{x_3k5b-Z`9S~A?Ir+xRFo)9IGTZiiw3Idcu%+f)QT>>NU +z+B$&=tha1$fb;2nedvA#fAW6!Xh7iT@b%V3)$cpB>EZ|2B2I!)dClRN?Sk9TM+?9xr;r$EVWacfJ`o#F_osfC2PaTTqJZ*@!{YpMFKpz@cLOT2n;i +zg2fM!M&v5q_x$UmDO3uZfBm(KyaE1m3vr$J_JbH-A|e_~4Do|g6MH?0FGjKd%jPyj +z5f3|83bS{3*%_m7$eF32FdZm=B**y9=wAcB`aBoRySxrh1-~Mo<*0}ahVL0t~tWl#} +z;aGXW6*z$3ZLQp4%ob~?3`gTOr3ITZ+;iVKE1>BwcHzADf+6g5Y`=NN&OQi7 +zoXcvurZ&jaYR)DGjBjEj8su<8X +zOckn0Nx<9l>!w{lt2`}+Y{3C=-k(A|}{`B=TGv;H294xHTBj+fhUXz%m# +z5n6^z0mP=b0RiavObb_&wO?gpU)35N@??ZJ1jb_j$$s8=8UYv>^9KSG4k5Umv-CaZ +zwQTqM%JkS(Iy^N-g#s^gH?V%+PP3O0%rZvG}hi?#Oj7|SV;=PgZ5@l_+My#yu%NHF+_r)x-Gw0KBt +z&GRb->xo7-S>pquIR8_xy0N*_q38Kqx)v&Z>N$A8UJg+WB|kpePVjzTqM$dqJ$Bpv +zn~%O(0RG~ni|vBLPLd$ET)5cwourMLNn7osmtmam-1fl7#I@+ASy9+`RdV;0g*cNs +zGGkBtB7RSe+H5OmM>tUHL8IXc`zCGqSrN>cr;>NvQp5|MVTw6AGdK!jsD*EDF1H)H +z6sH2`h$OkH{bkC^fy&n+_@z;Qi)llHm}FrB-j#XlBPfXCw(3n8)2Ty(6sHvL{GziiF&YjI7(O!h(8~Ek>Px;vJmB+^xNF1U>Qd(HNp}Jt@hfb}3=*ptx9K@|_)z&2W^mT#Lg+Z8Yl`kYW;2V3V7^X!9PZ~2 +z^0rwMAVZ_pjeq9f{6BT}7gzXJGHHYSzE^AQKZhgLzVU)>BA12yNvn~Uc?KEun6$P4 +z@~Fow5l55j0w>d%FZK#!D{lWt9S^MYBSwg$y*%VNr+T|Af`2g;xyII?WZ-W^H>)8X&8&TJuj@o25GB=l#wCF8D&f`DboToBDqyE9SN-@9{W! +z)pp$ZY(tB*mp?dCXT8CjuCdcmI4xKzkKzKJQr2cDKBOu6jwH;8-FZ(ka2hUm$+#5N +zy_&CI91!q50nnMv{E^1lEG;z8p(Th~&1dJanyWRVQ0n7#LryV2?=-|Rn>1Y*9O2wQ +zRGU@Tnn)c5XOWx8L%&!WyL#$HJlRZ8nJ +znu4wP><)B&D1{cck&29=?MpM(Z=V21*DWb?=Jff&38mL5TCi5KWJd@o&|OfUMh|%t +z83qzLWJ>`I%vt0W+f;@i1;^wQjDSX8+LjvMnyb`;dpeNnBZl^D&uI-2%+jxJhf#<{ +z+^7 +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 +z#FQkO9sMncK<70;z5b{Lx +zg`eE7_gA{T!KX37>5tk0SKD7=lyBqIIBl<>JJ07_o((v!Ezr8(JXtoR3}=Trz|dm6 +zMUt)eNQjhY%T5~ZiI%ps0ied79Gnf-M`!t_@Mc+k0?I7A1q|ctYW>e%@s{leWm%+_ +z2eoskzwUH{p(F_u^NGx20W>*3|<6Zy@hS%p% +z(a8qUa3gNuFuFSn;-~FfLJ<9+0`m9X;yIGbMXxN`xowZuT`8I2a?aq{UUqUNaG}C&O%OS*W-m9M>YZ9Q<-T!Q7_xW_<0QbMf2HZnmAE@rF;5)X7BQq!pdI +zkZ-ASJ3HHx*Bx*h$1NHWtEay;34U|D@V;2dSuN7^7qBxMBK*)n=9xmm$Zohy{IBq2 +zq#=s9DiTCZhie*eZGiXS+}!EKRWaW +zKXZdCw=s|tkIs-DCDD82J8Y!a9t?&5Ri<3s`w7tMOHx|`y?$Fl#UlRNYj*2b-b6MC +zOU$`m0u9vQs5hf&4s+Y{o?H{(Nxi +z9C;Bh{szs+F`53|6}Su4aP~js%BsY-v@wvfCD3!>U#K%?Qj=7cpI`Rfx9 +z^wdRJwu26sinIF1H>gVDbQmmIHd3vbN1>BJi;(6lJ$=rMkzou+tx8R(dw%a0c~~-k +zcE9Hr>|6f&Jb1??)e=(gxujRg<_@7%LIQ9~-<{fcO*Jx|sgp2M&K8WpoE3G9!v1ZT +z!H5Dr_yW}Um_2GTDCw0{V>;}7>9lrPH!Z~I4 +z5y|$~AalcJ_Sp)Z?+(W5*-*estE3x%`nk`7%PgdTyYlb^6x)`*?4|*4J^m2s{*F#o}< +zOo9wX^I?!Y=cp(BdCa6kacg^X4|p1yr@2XHlBFvu31|#hc@X$4zKHJ-EPaQKbi2gl +zi6@G#fQA_g%OfU5-{Y*+DryZsB5X?pO4d)l6m&rLN +zP5VJ&0MN3=Am>aW6b*#KWfU~na`PynkwAumPGJU%J%T}98h%P-9{lm|H9FNR$Lw$dw1MY+6f +zI-5Qxx}x^&{$n)Qq;>BeqXy +zSu}@n4{JZz#=c-7tM=>ej(djHAUUqnwy!f>c{@{QWMRphGwTP~P3o><=WOG3gIF{B7L`KXx%{A1 +zp{==YnB0YE6JSzv0Zh5}>c5EJm4Z^o8{Rmbp$I@#oWEjPc?qlTO4hL3 +zskcL<^w{k@^vS1xzFWv0(;Ho~NvKXG_hZLo=pib0-QisA4F?Vq~Z^4(+K1ED3$h#^5#ii6G8U8 +zhN&8{z|SMHHwizS@g#uGMFc;F86<- +z7(K(U&k_8byvKarKOX&6c(fF`_JwBm6B}b6akuFoURGFN+Gyd*!JsQ5bCfugqZb=l +zKZFAH=7FJySoDz0M#RBWjl1R7>jsrf@ZOyJ8J+2-{&KP_L62(&co?na55Ee!f@?V1 +z3AaQEqka8cP=Qy8QPtI+%H)*Oz6CYlkV!+;Pa#Mh1tNXxz^^tdEIjLVvVv>CNj)w- +z1bkXp26_Po_J{fYSep2+K7gu$RFte<->^s~^=kLqzYo>VI#%HvLw0E6o7Ffe +zY&`wYRoyqFhq0d?8{7qB`v$i`EPJ2y6r`t&Nx49AHWgTdM0GHc2XNaoiD~o?eWOD{ +zCmmPb$FAeGi=mL4Sgws{; +z8O#14ldcHVmns7Qh4+17%}zdmi81lm1zT1xc~Ez&%SI^=L)c}9ar1_x>@ZNV_Nw*_!fn* +z2brZV0^zjYO$QX*)H#?AWI1BEApJOnwwH79QHEOHn|s+YlWu{?3Ot3{z`vDez(fEQ-2bjoN6o +zxdj$Sim8dj_KiPD6_lca5}4x^rP&W8OR?z-Nn) +zL~S<1Vtq<0Ph3wTiL9Z(bHKcQ@A7}2obPD?EHt()8^!fP{1YY_>(V$@oGl~g12ES; +zoJRAXkgHyE_UwMteeQa|@~t}{jr5$1osvEy&tQH;8uIdsoVqpp7aszdxavi}WD2o( +zn|Pwiw@ORavDz=`T%${8Q^yKI_iqPGs*j?&&~g-sW!Mh(m|RU!CSb6}z{v@T&Db=k +z89sUDLk)<3sxm=!C}urhg=lO9VEUU8{4UodR12qmKGyvio5?Dzs+7o-&vx7Dr1SQpyQ_gEM8VzOd%pl;(_rzm#E~)4uNegm +zAge!8zq!}U=S($P^}1c5_f}+Ec>q&DtiS8yjYO7B36eE@V2e`I>G)6S|3B0k3KvvM +z6~3?%l-b;q@mAMBbVe3;cLoUNWWf(Lbq-@*yN5J?C%M4+-k@H&naD0+d9!Yt&v?9& +zN~JcY`4@c7fq3dsFIceM8qi?V`V(8Wpu2{D>7M3Z1U$0;88O2&0>r&#NB0@c|NIww +zbHxaQl>cY=`r)7Q_zi#UCLz89b;U4wfLm~A#%{Jkf^UZ&FX;=Rfr4~^1@L9andAzq +z%l7TYkow!;fX(U=grd;jNxCY9J?6$w_3O~8PoYs0D#@Dj0a)LY@?+OMe-g4&*bf*LtZZ(k+z}ATRbB2R(JU9$kzSStclzq1hcO_ty>-H}8@58_+Y?J=Y +z`UFBPhO+i(`8~m +z9d?ifXNuXnKS^8a>p1b=kOJ%47vK(G*V(Os)GlB-NPb?j&u>e(vGt{MC7X-gfU&e- +zz=19L4?@;};^y(`)cf#hOt2)!7-*Za?qY4208er(r|Rp^G^4zf(r0a^fd&p_^Hmv- +zl5k4uYtEt$ac9#s|6l_>TV$f;&ReV{co#*{E$TOJ;S@y=RlV;UrGqS1SulVwLJTzWu6UYkicIJZ$swd`gJpjrURFbUV7FmB+QN^motKdYk;mwctAolU8*vTVQi^UY#4tcng++|sf7!}^J6 +zN2lE%LUotbJO;mgPiJGcB5B~d5^K2L~KdH6| +zQj=eAbK*s$C0Ys})^J3;#|C(}@`ML^yoZ5xHkZu^{(xHEZy4#R#vW>NDI6Yw5`UG0 +zh>pfSlm{Qk&q~Uv-aTX0!wgU?Bnq5qdlb=SH7!a)hd7GqJGOcI@<%FQ`_<`PQE*m% +zSG~&5M5uT~aeQCI*zs>mp{9f)ZYxGX@QE +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 +z?zE;B-Ne35FDj|I5*Fjb?4Mq>2_ +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 +zj9u9H7C&eNyvPB3$*+++c7Sc2V1o$>=(o +z(1Q?qfxS+o0cN=QG<_AfsqAie-RKP##ok%pM8(@jPg-;8VN9Wq&lOaqSc_23Qv&yI +zCCW${ykZ#=mc2K)S{jr-532 +zJDg7jUjWxjnV0(sP}W}@Bj1#iv-k`;*3-{S*P^edimrFk>UAh=my19DHq&Uq=sC{iQ*Xg3I+dQ+Pp76jrH0jqv)4as5NizvEJW-dnNO +zy_b+hELftoc@tzRmNG2c?xQ?%$vr-?EbBHC4ZMDMvnc6I$~(Ko*qdtvnAt?{I?$s2 +zvTND^dP-6`qqq6L@1xRFZ~+_%gWgCa%jhNM|HFcQ5dw#P>csfY9TzWy@F@atAJ7$1=b8Ya)pk6fT4!J)RK +zGkSzqbyu5bQLXaC@s$VWfMiLSo@#`QuNy3PhHOFV>D9%?foYdh{7H?7m@n0916CI& +zsgJ%B=%{ANr5#z!xdb$%1IIhd4;%Wc$5iXu-r8_8O(M#&s1qDB_pd%Aq%p#KPKo`t +zaeu!X)=$jJ@eJrf$;nZ)`V53;-2t?Ryub!~&Jdm@UQ6V=6vTG$rKSa}^JmF#-II=m +z8j_A1lur)HcjSaK&i5+MdtDd$b@fO&SJ-t*nqs8@Coj;eNU9kE@p#&tWjRMpF6Gf-O5yPOu=E8J6F^AorI?64NkR#}TNDtu-F(NX +z8g0-PkhjNhnPj1C8nN)+fRc~~1YAN1v<-{@76vlD^DyDaE3DC^W!rIwXW3=y3wZ8S +zG!&mMZqirR1YHLQ2(Pd;0~8^H&bHj~+Rhb1&rSpZsKG8g4$5a(76R2r*>kNxpOAZ1ORLYMR(Kr@ZJKwAG0j;p$*3H~=mZj9J#fU8k7$M3K%FTg*Q`ob +zy~(AW*RuyH7Rjbc62kxbcJj-(^t(VA?;<$py&)-FXC4 +zrT5nbyZI~i-G8aENd6aom8gCsy-IB}+a{bSL6dmC()lz1Q@#&Dic6KnxxkLmw* +zm;g!L1e3AF2(dde1#J?ALmGV}KpP$D;1=XZ1w8^}$Sq%%Gv*_kl$D=s)dmt#_YKP) +zhoPKlTOIqd0Mvp4HX~sx_C17uRd;8}ETOHx{PeW2g*{9L`tY}>>~|_)7z{6D1kzYj +zg;#hW%T%ZNIHz$71d0&`W;+cA#o7hrSM}g~vPefVIt|q(_B`?1=&`N;iDI!CY8?D+ +zWUg6d^fO9tE3$c!xU{RE#Mli|MGr3|Ka{?bK`~Tw@$i1&hKXkv?!*Z3~u?L(x +zx#Fc)s^SaVKiTN^X0UioB!N$djhgbO&aHqs-y7=&VW7^)YDDwKk_${^ +z$nO{;5Dz$8N`ckmD9AM~-l`Dpi8lJtlbU66q^^O%@`lWhoV?rm^+Y3!!ZzBZ?n&_M +zcXlT;bh4q?IJ>u*i0CxC{Wbjt^9J*^$GMa$uR;JCu^t=>5W5LfBwut>#mwxl1}ILa +z@&;Ik;9s-37SRmwO*#dy2((}{6k~*soetJj+!?;p9miAVn{LOMFg4xZdLkxbVqzlV +z*Y($}0;<)=qn-Hl`1+8rDYwtCjkE`X$*S{F{$%hG^nJ*KAQoAAN0 +z$kFjBGM0opkyK9Vn0Lo>(b&206~nC#=IJ~pP7}NMO5-D +zT0f_8(-fJUq}iod#)zGoLsZ47Q-?l=U$CwZCPt3nA~)pG +zaKy()(sC&vgC0o?d=irPI^uTGdKN!@+S~d7;cgg*B@=b%wBog!) +zUPZtniGa~-AYxSI>vBuZwTj2b8)E(}g!V*eO-nRq3&~?qlCj$cBWUAb&eJ=^Q1aH< +zMtRxGYL5h&;k>Hn^~mN!hI%u`Mx&*xgu`IiOp@*y462Txp3BLC6d}gipdB +zIg?|{l;)9Bm$RgY&uu;br0EP%>Xo;=e> +zDvXmX@Lhw(nemiI{7F~TQZ-DV&PV~mgyn>)es}7)>%@d(3gEqQ9zW!qs`11lo@MwX +zR$lF7N0DECva4|c|#;2tF6J0PO_o%*7X4ygzPCc}hYIr3%>(+{zxr@X4u +znt0XUeUHNEG)#!v49-g44!L5Eyrv?a!y@)0E2N^*wTjdXYv=`4H5!Bkop|XKraEqC1Z{uc3oK#p#2k5tq>rMXBYM;WVO{`wr6qPNNFY +z)|lji9Z5#W(+ACqD{M+t6MFNAZA#Vm7S+kOYKb7JWagM@Z5*coAAF@1f#*RY +zgfbyQXPO~jc_o;Z-DTVIe7Pl8GFgoT9oX#tp>+H{w|0}-kADwM!+k!z1cWIsOrF6!n|>){jnTlxdUAg7lE +z^Q;28sm_xAkFG$yKwrFimw>9jPoMjOR{9ZWu6l=%{h}>cqL3G +z#i1kDNA*VjD_wJIMmU|hNw7yW08QTaF{g|Uj1sw-Pf7Eer%|mc5!9n(S!)Pd^uR^j +zaGlfBqIT*-048-|xTXWaAN@pO;Xk_-E7halTDXt`bO{EeN*zw=sn!%#Tf>mBK>@pS +zFf;CH9$WO&i`hz#)C8g`VeSOH9$FQ6YkntblJeTA-m8a))rV~J3UG6?hSQA#TQ1(Y +z$jj<}_eKB)F!~q;*?yin#wPTX3Jb-YvRvf?n?5YFis}b8%LaVILRxX>$ZyVN%Yb;4HF=Hbu_>FET@%c(~$wf +zjTld#^98k}be4WSbe9E578J!j=x$(dxbRtxA^1Re=<&YyeyUJCI+V*9o`=8&ewJ@I +zGQJe4An(dJ%wRm)_(S +zc6Bo;&o-80mAT#4Fqim-2@q_ZI`~zCpCc5DPC2e!%}S;wWg1va#N0Cv-#nL% +zBV-V1`XPg_Vx7|NVH&#_@#vH6*2Hiaej7S +zx!a1}eR{rolp415Ui#mgBTk>Afm4F|DdQwo!1(uZ>9Gg5c&4gXrs?+ztEUF#0)|r! +z`C2|aG6Lo!y9@_P1=X>AT+M}8wGY;lyOs!ZgkG?-{~*YH-us&Lj|JWx4xIh_f^r8+ +z^ngpW;OXb>gY#y*_Y3qBtVo6X<$;=u7r-zE9{NbYi*xJrlJn4n33N3~puM+M7c2Ls +zdh4mI6K)J+oN!H}?}+yRmR0l2Y#RgZahha0&OQt(d +zSi0b|017Is4A2hRqv5W$Cy4AiOJ3uDyQR2 +ztCLE#Y(r|dr}FmqG7a=x6e$Qv(&H~g?9%Jm-;p$g0K_04zkxg)PlK0kDxa;mCn@3i +zS9#!4KP;tkXuhse_rzPTD|4LW>g%`QP`W$#nQr74B0rlHuhs|>{z@`jZmDT^iFN^{ +z#O?*w(W=@7GD^U_R9T(~GAz+vc;ofwqqVoK-0B03z#g!(%LY0`3Esk_4}d$zzGHB$ +zZ@|0jK3nv7Q#`#~OR4hP{tZzd`=IJ7b`f^Av9C+ugo +zWQL>t{jaY>mtvdd5utX!5mK2&b6W=KGNMR=Zx5IS)w`^jCV6R|T#tX`>omzCZ-AgV +zg6u81aoxDgM_xHN6&|2~R`i-k;Ef8Yuyrb_C)lx)WggAhqCdxlU3A;RrBb3$WIJns +zgly2ltDw(wSmg^NDWw5VUPG`Hp6)!BnYBlB>;j5 +zf +z%kIK20c2XcbU>U<4q@aW5lNs+qV&h?5s#dzusuk~K3i(frg-8pnzm?6#~!l~+glEM +zfBuBGt6o;fh%CS*z#JU5?o_#8IHPRPJ&zufrh@oIi!rf7B$ocBYoe9^;UB436nssd +zkn+v*@YM>-Yk}L_SrT%O0?6)?JDpD<-ybA@Yy> +zm+=1t4B$tH*Gg(H>=(nFPv3J7gjaExS9Ms|3xNNB0@63CIdY3`?O9&z%EL=(efZQ5 +z0c}f*fW43$h!q#kmFrW!eIg2>O|$ym!8*_}FekZ#gwL~bVXqmZs1{)^%{1DrWFr=1 +zayYXnuWe;w&XOK@_UP4l64SBXKF(V>M&JWFIw{sofj@#wc%JXnf>-WuNcuG+MGY%A +zOj0U+p*olx8Q~k+fVrw;3+KU`SlZYW=jCCa{kpXX!FH0-9P`MVlQBc4mT^@7uoYfdxoBQJR$S3*|H?tX!YQT+&S +zOV@o@v)+MFyHdG*bC3EAI*t92= +zC;t9`pVLvDlT25>l=r~}Y6C74SqkQu>qniM<~hd|x0l^%i@;Ut>17}+ +zXtla>6q3UbN&~c=g=OjnnOHO}7aeu_Lj1Bz#-k)|PyCIy%uCI!f%x +z(M;EMr%^~dKEwI`j#aHn*NJtm6ToJ(O~w!<6TghLNUD_fp=T^m@SI3NT6xu5!$8q) +zh%D~D!Ff+efEQG9ougRo_ah +zj7O#zn#zyj+J~Qpj)fUo!6)8Me9hq}!+-7wz+0QIGa_sYcn6;`mRPO-!0}XtM&!W43VJx)RwY=gH{ZF}X{skESS-Lm1QGlLF2iCa-+fD{Dz> +zt^7k_g)||p3%~6hP1zp)&1BCtVr=wZ^4tDXoA7T4cfp~&Fn5O+;_pa7?2uJwj6@Ko`%1a;^QRm9*g(4PF?qwQ+@K&a?uF^U&R~6b~CBa|HxSY|n5gHHFOXp>P7=7n&O1L^9%_u|94VrmW%(K|`iK%}95G!|Uhl8&a< +zk#y!HwMDh@&ptMT{og=Fk>DG1uQDxIa7Vr!%Bwugt1xWK>yP&zscdDbZ>2q5pwyVV +zx#!<^;V<~#3(*#cbGcGRcfG8G|H6-dz2$k~)%Y2|_}u@fj2n|gkjnnTKkq_rOY-X5 +zjrOh^n&jxHJ}{9}OKOB%&K4?FzbWPCqy$8hI2a)si!AAT3**PXK-Vcr=AFKytwwd( +z{^znm9n-Xhc`l=J8jg7DxQ~Z(=MW(vO>|UB7eISnYYnGP0h;M^)sb4uwuv@T4see; +z4TaKQx|!};0?r^RqPLN44l%RYB_o-QI@2&~xh@9P!+C5qUc4Se-eya1w1!BMO#2_h +zBvwjByGhie8uYVXU=1c#b1!A-`3S|C{Z2MVt2dM|^#`k8UjQQu8lL?XGc!KvbMG=j +zD>&y$#*~onydwz|wVb!KHc1y-v?_!5Js22u|HaHiX=krO07)rU9qFLzRyUUkT~p=a +z7dBoG60WqEflqX9gfMD6YQ6VSzgA{>GX89tun^o~Jxi?S@73k~z{>O8Ky~E>xqR>w +z{Gg{U{vo)VCH65}X6gs?|B*$+XLu`jYPwjbRZp^WCPuYwq1T(d|AJdIGLa +z3A``3K3txkKDtDd_3`Qi +zM{MIRr+s1;Y23W1Tihd{iJfLu>>t%pyA*qyblyplXLloI{)nO&R7r-aP$c(`3(nMDXKR$50SEzN +zCF(lPT@4JczA2z=?;Bf=R(3Vt+2iZvP)sWIf$~In1UsRBzZ+kXXOolbWc{O32;8^f +zaZ)prN2+S74h_laC40ZxKT42_-&iJDn6I^T)vR_G!hu1HM0PIBaB#53%hQVFe)4Us +z!mlT=a;yI7;3~n6G4NzXU!1plR9_7r%r`Vd_ZPtyRmx|Zy<0%tJC)VtM|0ox**jx- +zZ)E(Qwc%3P^C8jnP0T$dNQdI)-}-GE@#n9J^0#hP;y9lH{2Aa;(mtDsx00831pg;b +zMhSUPWgXdoCz3u_C>t9xU=-2VL_`T+>p2aOkiNNQwBXHe5DEF4LPckj1;9yu%?Xa>eT%)6(kc_>gEJD%a>LtYnKcFd@4(YPDs +zhSAC?&ZwPLsWwG^y;Ua&V!xVan5}RMxULA$b27#d{hKr +z=h#!Y7PR`nK59gXUWSXAz>_M&l72^v+z2@L0_RkD92`@FrvOzhqOLWw!>8cGAG4LX +zBhCfPRS}*N?SiXZAZI&B^Ujb!Nn@}$ +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 +z&oYerk?@6QXNmN_hxt;u1xkfqAsS7Vsqw^esZ +zzvl}Nk054_qXQQGqZE{5@H-9#rC+OfjC^g_<@kF;V=le2@pmDR7rf}w4sEOqVY%XS +zdz5bHJK0p1=Y@2Hf<32_XLI8q{6gh}wd4>$Fp4_8KG*@pJ +z2E3f>W1f%Cu^sdTh5Q_*M0De^!S5mN%7e15s|q*NyV}Zk8mT*qv%q7a*M0nwlUOhw +zRskWa9i^9Yph(2syD%Q)Y;+}T|C-hk_M^kA1;Fv2x6fW9NUQy-UJJGN`#Cptdu#RP +z*L@TJk;m&^9QBq4k{|^-pYArb;9AQ?YAtZ9pEubpH?mB5WSQYy2~g^GnaKGgQeFWE +z4sA`{;4IThN*?y4)jS$LVdtY|ztLLcV-uq#1Exv`T`?t1jJLt3V}7$}_bmhFjsqG4 +zW@NVTi5Q4C^1hMYNRVa9j=Ef-Z)hmgj6|o!&5nh=HQ4||1Jxp{K}=RdEFP3{Pl!N9 +z8+tDcSE$tJx9ORTmAk=Vl6u+5vhVKkRCO=smul0y(DU(d@+niMH8~`;-Mt!DDvPP4~Tivq|+_@jIn~aTORoTagNLVqLrk0*#A)7f%x;N?VINW*} +zk3mQ#axvo3W&&Q=Hz7TOJ#jXU@gh+ZF3Su)RVWKo=mqUjnk7eK-u8)0rH3w1Ok|oq +zTnr6oe5K%SSC!H|5*N~T?dp3i%SsM6$Mi{Qrf@hr(^?l7Ci{#CcX3SA_HmxoErT#k +z4*dydH_0~G@*+?|yDrX-=RclzT@7d{Y%v1s%dzJ}QcN-2dKG}ViD5>5-5ok0=i_{E +zIOw}2UrknS#PwW%!8hhFCHbF70`bUZ&s|C9Kkh$E= +z=3B0P5A8bblN-MEjh!^;T +z^2p|(<${eHK;no`-knZTC0ddzyGAEALr3j&3EYe@JH!7e+eLy8#I{oU$wdX;ABV%gS%9cWyPdt;a6r=23 +zrbEmc4tEI~aHCF;>WQe-@2LzyUEn8Y^;B?xnO}rEn!9O~_emeHy7S%NNS+5+{&B6}{GV +zb+`rxrVO%L(RlY2uN=|Vbpsj+{t*oF&Y3u`$e}dR+!-?~-dB%h-V!WdA3a6crG#jb`M4G|^b+an!0QQrHo&DI+%h0A6}vzhJM* +zDJH89%KnJjg&5;Xbz>D!75&vmrfWq3pQCZ52?^H$pckGPV0F9XL8ex*tUV?)X|uiH=9Y=H%taLAj${btb9ieftZQ}TW)z1eM87-! +z+^WaPy+pry6i!n}vmw&yBRbmL*pRrE4|~gGSAxdTsnOn(^yiTS9N~CG>Oe#nXuz(U +z$(XTz57$r*H+zKkJfzT%mjZU+%VKS;0SrsqZDHQ8jqsvKhQg&YZPl)3uvuO*jZ1<_ +zq+3j1*Z<96ZS`~1c{s47cDfM!T!*oL6ej_r!O6OllOYvGT%UW>l0_FFN+(#{=y(fwk{|PuY*@IqbRyT;+ +z_oDCTv5p#8v$PXJb_M(k +z@+MC7fDirR$;Fut&;$9lIA8tTGXc&wHCU<<^?P%BszKK2n07s6&tv>0e&H$K&9L_M +zC3)6VqF1}VFXg-2VOI1#K)B1zV=Zr5_518%7`y#L7C1L;HA~%$HUTmEt^!R<|tcv}Q`L(W{F@kRfhRhKB +zpRRxKyO)$t2qL3#{WGHORDxZ5|*Z)ZO}N;i2V{UGYv +zAq`(%98L0$inxbZP-kD+OlhnOdQ>fGn-J-uIwE&AB*{}bvG|;MOJdx+m=12*xV&lK +z0rtGEU_k+Mtj{#{WZh+o{&5@}i*u3erR=Nc +z>*=s2wQ!|C{%{%ydT4{U%Pdbm!`^r_A7jn(z;=bJnWMD9ow9*vS;a7Y;{Jo;gv{`` +zs)gwfg4%__n)&r+UtbiHomLGiHyh<296Jt469q|-u$hJong04PAwbP%L~?FntyP+= +z!#|e)cwTIR*2b1*J}h;bd)~>xv_~G^9rz!Tm@uwRGg!1b(WFv@$2h79RxS~&{Ho{n +zToXu@Oae<1ojki+S*y>d=Q~RN1@pfV0C +zj(O*AZH_m*j*|p17I;3gni;fkXuKm`i{h?6q(eYn>Q%2kYWEEqx5oXsq0TYw_^xTj +z&qbFSDiclZRWcM~Z#Fo|p3-=eJtqI#09iQ>^LuA3Uit<6V!9gwuJHl!;;*A6@)Z{e +z3FVCo>!Ks_g?RHg(Y8_LN4qQi1(o-Cki8Jk9-`Q(pdzj$v_+= +zy#QZ72pL8)(DE~K0KHFX(9j*~&4(iSRbprNj`Q^Woqs!)LsEg9(0b{TxYR}?piiu*DzMf? +z`_fR!%>kc-Kio)o?nEux@WPONulRUk{eN4P;s7(fAlM)ux{rH-0={@|iXuJIA}_HQ +zc|;GshP)e|uZ~$a7`OD_)O58lQ>oVE0wSWpiQ*TZ@}6nsy6uAY)$1mCTgz&XI0%;! +zusGR^mZpABoW8eJ1k(iqGvNYe0@O)|b|#K}f8E(E=YLqJV{vPiaO%vOgly<{S$6_7%)pQv+i#Me+&$$>TmG{yN~)g&g8F+6V1Y +zv60U=TB76OgU=?JnL38$;?5eHIgpCNZED5|Eh$I-4yHI4iZDU;RF+) +zO0X~af?GxnV5+fZnkaL^E*LeCz_}VP`S$()TU52R +zcgJ$O2V8vzyL%>j@Dw@P&{Xgb`@*)0I2L9+S5Cd_{6Wt7?PGr^Cr)fR>QYtMcPs6A +zO)8yAa)GOF2-k|sF%3=|^y#;KD+c72C3q{O}6!0+Z3twSC +z&Qp)e0cxBK5KDd991M7pit!9xW^awp(P+9xMk^vw?~`vI5S}j6#XMbzMIw7Qa;qN& +z;Dr33Ni?pN6YA-3jo#&T3x0*&T_uFm@XQSaXA&Orz&k?n;lJ|m;^lZ9Me;QPmR}n*B2y?25j@?N8IB3KF8*0+Q)u`#(PrUxw5uh3<}|Z=IkqB*vYj1 +zP|^(lKPuiS$g-_z+b-L-)n(hZZQHi1%eHOX>auOyw*TIHKkpauN34i-uuj&@k+`oM +znR7Fo*Va6DB08viLi*jwtsAShts2vO{9%_CN>=*xR!g>SbX{ykwi@l;+YGrE6*M_V +z2B1Dj +z$cWouAQXppNT??ZS6|qp3P3?z=&Vx8srIkP7el657p8U3+m4 +zx{Lh=P%%vmhy<>H`kyFSMQ-gX7x;Z>L>B-dlNO`$CHqf{& +zgdnRfw{KF~(gQhTNYpiz@PT}|8uqk7HI+pHaj#DoH?vEjUt^%h1`4R>mxX+#-Oa<9 +z8ae=X?s6d0&oK|JtcF8&=IHhcw=P1hzotzm(Am|MH;J{JfA0DOnOxQL9zkr0y-{%Z +zGx@+VPuuwv16y@Tw(bs!O_DL<9=dk9m;Co_oaLMmnGan`?jfLHO5H{|uPvt$Eo*0c-j%C-shCN8`V^NKsPCC(aLMyY +znzKpY!tdzy;QW*O%k)v;Z()$GXZ5-XWqaq0`>vM>^Nk4-9Lfy-s(mBcL%EW_`t`L?2Ze+Y5ceH +z1-U)!+YR-(RrNBx)c*GKS^C-OcR$4K)rA)Fj8k81NQj(Uud~o^zY+N8@aY+5+PXF- +z`>b@>mXN67NLa?WB#X$BJMEi(RX}1ZFR%y!2n3!a$`K(o0#Cg=fe{<-*tWjj+*xxwdW@IDnw}V&f6$ +z#&+MYICri%Y-~4y>A(vYB?I^|yYi?VThBh!=a7!?)|5LO_-MROqJ~)^8>Yqp!ZKBx +z%NgXSIRoGcuwSXcxK2dxktWPn$ytuGtXW^RAQ|5^D323b7v(c!INhkKem%m-DDMA= +zXxH9k@{V90fe#z23;f@hA_o%v2g>aSQO{o85$bL)N_;I+Ja#Ub&Ie$XhL$#1pBwK_ +z@#j$O>V6>%;&aSzP(2n0g=JSBpffmAPrN|!>jcR85XXrv$XmRiN6>CpqJgs~&rD#Q +zUwSJ55FpNj*qEUCz%ioj5mY1a=Ix1-zFK5HPH6g=in^&ez_g|WJ~<;uz{ooW6mUKx +z6U$7A0MH&e8*uI_1JlEJws7M3Fg!U{qG%z}rVuPpA1Xmy0iJ5zPB%eG0&T +zMQsynHekAAY&xAsl=p*%msoK2aL$xu<}Hg{;5wJC&GCdTtCI0MmSodj8{58ib?faL +zeO<;2U{12|5nvZ89#;O*t2s-ibDO03(iID*g_ZA9eWP@fky05ZJtBY-rI|=x)pBQ5 +z?AwRWL09MB3o#)eP6R$#N4|zBn{^BN;*42x^S|bj_dN?`*dXTzfb8ib06eQi&bhO{C!Ux-c$Q<9euf=WO(YWT(|QIAB}Zkg>{6=8C=26-FwB99PdRi;P=siJ +z{SXbSmj(Z#L*w7tb~21caJkI+d9jcRG2(eFP6RsX5zyKW74nxuRT-1!Re^&g@3gHZ +zhG~L}yr)D63yw9Mp^BwrAh=vIVJK%-K2?i(Zzk}L=?gson4dn2*bb$;`PfqS27#O* +z^^3AJ{!}somWvSR1pj`v*&#}onu2!F&R2PA*QvZizVXW1&1r#o7dGJNnm#w?$Pc_nR=7t|SQlg$*b#Y;4f7TY`Hy&jFA4Rl0{t~C>LW3k4_r}i +z+~lYRt2j0IsVb3MD)$Mp!g6YNX}8Cj^tPk>WC2y8z6A@0P5NVmeKAv_Y|)76CHo~S +zGA)HkS{o@++Ar}Hra0bbTxs*WirQw-v+$O(2I(rJ8-QlZK36AvG15(O&)Ee$;;UPx +z)Rs4`%-qny@{3fH18V)XW{4Z}%lbW8Q;AR{7>_d485?UEH7(Qdn6$(pX$v={F2TJB +zgVOjgtSFrVPBN(LI3cu}GbMHC$90^RiIG +zqsX`~pv&@)gES9YyCHm$bti|1CqPCN+(=nVqE!4pu7IEa0lY;|xpei1{quQ6be}Kx +z@co$(_PG$k2KI>!^Oq5)aZP0r#rgtkyRsG3gh0QjmV!!g!-b<661T$=zNjCB=?r@g +z@+1XavEorkj2Hh6s1b<7QD7tq`E+T~tvOd?4bxIDJc(^uxl4rQ+eX(X4oYzmAkjIJgGjVcHqVrA;>@oLHt0-*WMJ>sD7bbe>RDs5lbh1r04Wd +z0+@`%cr;nDTy`H0FMh|7kw0Zb;L8ROyY71SRA)N1b8=V_s-w-#C;0M8RwVc5%e;G* +z1NPGt*8QN_8v9Xu_fCE%1@k7wBlifRJn@jCK~*z3${fGZDZk|F<~r+I!8i(#d43Qq +z93bxYp$vX5DMEtB_0c7z2&S*kUhgdsa?SA4zOvcJ?w(~0+Se=`NdD%fIXGEC-5Jyd +z98vdxh9uiUv`6Wn)n@p(eCC1yvfCr$as10)T$j$o^4ZsV+O-n1Bpx5aKDB55*~`3Y +zooJu2WN=Rv!!AGwCgj{sUn%!^FbZJfrn^qXEi>2Ea4%U{Mpw6w<>{#Rp+_L4n}o6H +zolL^n%S?X(BhgcDYTGI4*4!x8>_ZC%$gQSY@{;9VvYQ3?K;u5UiXrksHQY*6W4B{r +z^CaYvC814Muey2m?6O#cHImZhdj5pY)3;__2xb#+g&{!nk8lB@Ng_GR&g$(x13l)yuwWG6fA?tP{?n!3(SJ~$2Y)Kxq5(72%v>L}j +zS$3zH(hq>}t16%47>RJ7f(vz2JTqQ~C2y@lp8{wyNmmvZL``e;Bmme%^yESb~l6% +zPk4oQQQ77So7~FoX<%G-f73xd|jj3{hV1PPJ2aDz=t!c{k8w&b6J=M +zh=vJ&RZeqd1+}|YB=&^SGxD{vu`%~jE#Kln>LQ?iQP8`zqf&w7=dU&A#5z`&7HMd +zq`@f}keCTx6cg|f<(u#Qx_Ase=1SCR_@=8-Y~`0sAaxvEm-dFbuT17*yHw7^V!Kb< +z@<15TElWLqQbIb5*Up`JNKY~vb*3_U0Jn9G|8FRWDBzu$#`prpTj(Ag9r%TxV0R +zXvGkV>)`(_7i@E)=_D!sz_Nnx)84KK8{c9sjrma#>gD^!#Mu>%1J=%(df|1U0X;D4 +ze?SCEXszGqK0ot0`^9TPdZR_+7$+6;PZd}>64x3-vTP-xypoea0@F_!GCZ30q +zq@94UJF9@qduc@pnQfnN&-GLw!wD8<75zQbpN3(&gQpCrHQP(4<{d(2PV6kS0Pe&# +z)jx|*Y5fI-yWZ6k*vvMLB#D}^NT;26GCR5Feo`_ePTOt_O*r^FPGug1)fqEq%l;Q` +zTrIQ*iiufKT_^z01uqkLrRKei-}{wK7HbYrF@)pa@vlIVx@zGwT%$#WBW^e4=T|=E +zIiT*{+mp2eNoiqG`WPKu>z4O+PXk?5tZ0xoztnR9U(T$^4w@Hz&rb9XdqqPbwJZne +zGvXrod0=#n{-?TVK+XtnS#l+O6eX7e+<9^=O42j4LsEOaPjSCn4nST-)$DnjS8MMnYF~ +zIU3VJn$PTjTD84w+}LP}Dx(IB*U(+@fGO7Xu0hFieZS;TkuH;)wMo>nR?DS+d-0sD0X&bW8cN&{h_*9!UWkAYjT6kUio8787E^}^BD)4 +zAbmB@oWZ9duD>N4H%|YiyHdh_A_P1j7r+&DzDEvGb?d$|#^;qrvNoUehK52IGN0YH +zmY#23S&E5b8iNRdnY1Kk<-T^w+?sNdso7xRg6U)cPqvPN^*+ozsNT+d%0w|7-@~_= +zW&+1U1`JPWGC13%TgffUmYJB3p(+n7erV`Q5LDFrm|>or3!AkfIVO%sXRO2(D_iym +zmqF+i)wv4ba#mrZHF;JF*VdhWl +z;~~EZL0OsoR%FF>B-`y*-0$a`sOW`+S1oGj4kQu78hpL+J1#@(b6MeXNY2edB4lTO +z9lMCnl#-v=DsI-ENGd_4&tF)|1f@a!N_w+?4<*1Dc+KNR+*UK%)_&qE19DXlkZ}UFUr-7^0XXk~_C1%XEDDjsO@pOPT +zUXMzrfBX`ci<;?sD!IqP;SfdzI@pfqHTR3GkQ930n@HC!0*1H5hU +zx%wKhrC)P>{ph>_*|lvQcfZ{Aa3y+jv;iK0fR_P#tMWjbkg1p%A4cpdbcsFj(gGhL~1*{XR +zAY++e;9Fr$_K5OP;%PmK*6mTh;q`J_WOuXD-l5GJBtg?hD279Z!51_!-;~@FE}j%7 +z`_ddleH?nwRjDrQ$sW|@zN6DxW$tM|bfeN@oUg$M0gj>jhV*-!FYn()FZ5YCvZ1!h +z9QqrLa(w!}+P|Jw{8Rn$xuEQGRCL=WhV|auxP8BGZijZBYu9>M`g|%AF-ZB}w@Ghy +zF++l#c=w}aL8d9DRW<%JRM!~!-CP26(M#qqD_dLXzg?nHA1&Bu0ZxH-#$*!nrYReZV-^ZQcH{z!}4lF4;Pm9D=+9Hp@7@ur3@~6U}9M;w`=K!K={vc~)u$ +zB(D^bRSwN6gXPf0b*SPrtmHIpG{ncXlitXz+mki-K+dR632%$$pM|39^ +z+jit@O%98zHW(0O!%M$(0XdgBP!p=A%AZe$lzmXCeH)}}nfdAYn^&3sA-4-g;A596 +znnO3SxU+zyp4g9Go~h*AR|@p+&KJikFJE*v?QG3!n#OLTxSO)E?nvF20XiAhZ5oPb +zVYHCwf9CtKnN!K_#++`&uaO0X#5@mt!4mNT9=B4Og{#u_$)+%XSn5+E3(&A@k*qs{ +zl0!kzibeto$MQyA4}4Y*G#dw!bq_goT}=pTcL3XJ^7DZ``@R1V=~-wiA^ften@0o3 +z7X2~?ne?ezJi=3oJ>^lE0}XVZgn#S4(3pm?f+H#iPq7RqhIZ0R9ra +z^X;ec<#?{a*hA;W>;}V;n|ucMV!NaDJO*?NMn=w=m|&G)3vN};XI#jEkT%CEf8t09 +ze;ix;ecMr;Vz*EQ!JDE31=SoCD+KL!E^ulQc8hsQXG_Hm?|k|tC(+4N_;Tli_*>9b^TKfxJ6hY}wogxmXt&&2{2_YqXY{3Od{r0m +zGfIIc6m=->ji$pQ9zXNEo~EdSA2L!OpKbUO_6z@h>f%$s)Iwrt&pW=Tf<9dt1D61q +z6sl*CbkJkbH853u?HZ${xf4_!PM;AGuCKJp{So}KKZ#zlX$Lx0sni6WUcv|N0e63H +zWC;xj{d)0Dp81HSbG!%N9w^;@qTZ5Oy>q#oa$P)RV8!pfw(IsF6{nNLnvz0bCKTt} +zId^Q&t!8_k)3yvviG3nSyO?byYT*tSPA#H^jMD}FZIG}%L?SMC<+bD5w!VI>-5a^w +zz-hre(M+aG4&)Q_H!dbgU?c_C1-U;tDMyF +zP0PZ_#8^4<#tv`QlVw>vw((|ln!bv%(ej*k*>tjYqsMZ@KwDSO=a^kxBw->bf~}{B +z?XZIsq#RO{rF4R9SGh}*y{e!{=~dZh)2;eWM)$J<&kVmj?JuNp)9bLlZa+RKcU7Ws +zpPIyf$msITG1Of6`#N`jh;og^Sxh{$Z(P>k`=hW|qX2udG{$QaO3vF=*+%+_;bEd2*%pTvWD~pj@CcXaw23I6`h|?+4Yz +z(Wj`_8LK8E(*d1T>*$`}(6dYsbenY&isL&Ar7+J(CWy#4pyavF;Skfk{_^ZEu+Otu +z?`c&xUoJ@kFs-gk*V}bN72cg#K)BN*G%#Fa=K|;a9fjpyXeIB#ZQC +zfoyRGTgakyE)q<6^KP6-?tg|kElMBNdSZ0=$o3`gx-3n +zHdP}!3+A7J18gQu*wTCFCQBtwm!g(X&@|V;13u7~m)e0ZL;<#0fcn%B$dPvK2-}N^ +zscqQP?w)v97;q1mu2t>O1Jlt3ob8Q~E-ouu;5|ur6w`wsnunZ^!`D81viq}pCGG1$DbOK~b?Di%s=W_H|~u8U3DBCjbme*H*R#S?ms#mq{y +z`!D&7)GbwCKaUUM$%$6-mbqX8onK=h;eZhVCNoC;)Dt63AmnejkyOH(vn_(%^NXz! +zF7FyUg$4JIg7wF}r(RSXH$j0{i5yrSG$&jQaefMq8}Tl_558K@ojYV5towayvfeu- +zkvrWXD@}t`R^7C9=wCfUEC`cbhPC+pe|RRcmEF#u^3O?xOhEdmjzCzBe(IF4?_PMSdQe?=J)!sBh!7QZaj)61bacIp_W&c-IWQM3Q}@f +z@8Y^a1nPF*C$m<%FHElCQZ+}R41jGC`}sM6(@tm1#1cjkdcbX0(FF786eRcW6sDa} +zLZ@sGaChK|@J!0}SS$lcjeW3Mu-oBxBe;zN5z`#?jM}!v_59kb&-PRaf@s~1n30eZ +z@AXn@IGwt(o3i3k{M5`j4kpqODtBBb(X1-i`4PpTiP%lB*h|kh;W_SE%<59a^%OR< +zF{PCZg@}Av5Dg2yXJ&S}#)~;%oDC>8ZT;Da$z}-tTA-r-hy$c5_TL`69brpyfsc%k +zM<&Bik^pxu{CVkI)#(H#I^yoD%K8Tkpq1k2?q>ep7Xe`GaJmh;gihA4GVM@;GqrRlg*%K>c! +z_s04mc#n7oXm*~Em7)tYb&XIwGXp*&|?S9W#a#Z-fn +zpoBc$N{MOi6_;I&p~F-UN44MGxnwQ%FM!h%^p{4vi1|_~)R@w^!1yBmC1&lqE+hZ5 +zAm9n@?LlAeXEy80Hp&V1H?rMVxRjOuBPt%v~9i +z=|m3MNoCXMr0S#+TB;`QXMGHJ6|yTb!-9pPwa)sI$do|3RNv4sZ46_&9QyO7Cd7QB +z?PEVwUOI?oTxI9eEDX3SdoS9p2Vx|ivHv7<^+3ow9o}4F*0pe?*Hnanr>5c%PEl-AHvDMg>S6HYP=mDj7+xpz+XqPT +zh5x$?#-qPrxuz*X0_d{Zl#z~y+%43l6OR7KO6XL-ghqodJo2SShrRkC+(o2mS>@y4 +ze-VstUlV{2{C#_~=#vI=%6G@qbyQm0;1m}U*|3eTaNt$y^7BU0$P*^uImwI;=%nGZ +zz+)YYe%v*1m?GNc4)^!}%h(wKv8-gANI;5z@|ezFL>??F_YE!6x?WD?tl#jo4nGaE +zCZx2W)So0c43K~LEx~5%JjW~xhNjGzHFpUB!tRO#(MzXs^p)|qt!`$5a#0pqUPw*h +z4%dGgs~{wUri=)jmK=O6Hj9) +zl@QFKE-a=OdTul>+pF|vfXBy_#<^K2oTQ6(Up>no@>uo9CjuWNKxPjZSSA$PPr0}% +z06alwD^;6U6h35k{a&+skd5#!Vt<(J-fkzF)EM_aK+eRTPOpD${Tu>`x8l?=x1LCQ +zYQWn3RxZl_3~^`<# +zQIv@aZT&n4e`uKPqY +z&!%9V55SUm?ActlQpL|$`zq+WYnr-+;Y%W8lr>&uDpo65zj%o3FxfL@PMApSC=?yd +zFYyMCGhZW`4o#fa8bO(kY^A-&aHRuLBdg{bUB|v1AokST-`xHdBShvDc)lvxT-j)B +zR$6P+CY*Q7EjrxepLgzb?|hQ>3x7?zUR?e~ip|L))pHempV&}k@`;6c3nNX;e89oX +z9qPKU%WQof3Y;;5e$+sWyY4&xTBbr5o*Ari~6_A +z>XXaUg~v*JFGLJHNR}DHrI9{cf6m6+$ckD^uZ}Y)@mG)XuVtbp0ALZ2{ACE*MH=36l9*JNX +z4biqpskc$Inq|=Ju2Udpn%yi;AzUCJ>+r^{Xjxn%j>tWte0RX<#!DJY=xt{qsMl>m +zt~8r+?#pjLp#5FUN$=5A+k>n0my!dRo@ld$6|L{PFi`^^(?5$KqK*I`lX})t>IAKG +zdb}e{tEw-HW~ozjgNlPQa1q=+dB{^5-Y;CVwSq5q%P*gDKu1Fy-=DrTMQbF#wMlov +zodCL&`9CFBDPD&(l^cR)3GLi#dZCJb9#UMG-l^YF2 +zak7)_U +z>W}8KEy3G2F1XaEr3cI^4hj87)G_Gvk$8e%6Vo~LId|qK|m0R +z>E!F)w +z9)tdsepOS2a^0zVZ@<~>tr7u$j-azVen{a?fNbEdzmzQ9KZ3Ek;y%4rWM9KhB={om +z9O&SRL5dgrvfe#Y(y+pEf*z@}?NsZKq;%ACw1h&WJBnq<+B}sjof@}k)tE_rCO!8~ +znhyZ0m3Y1E%4z7=5hV3(nOoa#SnsO=7c?JN(Ytd2PQz_*82;vmp=cZ{WvH;2=Bec4 +z>8?Q^%yh+>;HUXgrCG#zgn&6#8k5!a`dKvRY3aJnA?fLyBgf{R=Fg^L7z}A0p>c>4 +ztgZHK-a`7tV%JcK6mqYIUg~AGlOqabp5#%8L6DO54D^-p2WYuNQDz;wq&5t+Nb;*x +zRJ{=z6WpoxD))QPw`-P*)6*45<#F-p`yBSciG@Y?+Td!#&n7BYuW`c}SZBCv(>LsGZf6SGZ;wV>*Nq?W`##j; +zK>FMfpyQ$7g?#aL8ItAG`M$B{z_A+dEiBc6PeN^S5@SL&z6$^XC>jz)6h)Hc9>Vp{ +zI*Uhmp~P)&lkQ~O9b3{&$T6O3Oy@+QW{?(x_zY!6f=MeILR#6Zj|nvAO^$uVk{-Y@ +zrNNO~cl(r3sRE3CIKcbf>2NQ0z0>#oU3S2u@oqf(jnKrgnjqnmXKNR(9S~fsDaQjYD@2i(C(l(Nh{QcQeEZwih!E9TWR~^06Y90{gFt +zW>Tr+1T$QWAm^hK#zQ3=1{GCSC)!AWttEw_HEw{ealqmzS3Qbay`4oR9o0{I+@@HM +z^oT-}r&9*~XXG0_NUfn&hhKO*v~bFwVYy|@|MS&}%XV1r12cnD+}&P^;%W4nr%FfA +zy&#yjiQrJ}Aiqb~8t)5q2b(QGyC;k9so2{~(eG1i|950d`-fjFpVAF8Jf(ki((-13 +zeR7uwRGQtNKMd&Woy^q;C>}i_cS}*QaLPbMrO1!-W1b9FCiU7FB%UnEGa;tvQW9jV +z?&?f(2>q(9^tujYkc{b2_Qrg=l +zBXNd~{vacz9!`+%3SO!w_PfJbhf+mfwc8w1(s-@}b2>BV%N!3C0>K{8tjEZCi5az% +zIlD^en03n1XfZYcR@R8L&8`+2d`zsgPePN^xHp`r^i2Yvm*>qW{O*9`C(V&0c~7UX +z$_dUS_Xxj!t-(D!!9%HEH`!E}ha9PF+Rc2AOqD>OQ6g=cR01$)cCmuAT3KUf@WRUt +zav`C)@P8E`LJ0Ebg@|nLc_d_| +zS)=TETc!R!nlYwjvX>fVH3@v|Dw<0ZnSsR0__qrXZG8O_^p`-}=RgSUpRuuetM_n& +zllhI<5;WZc;vCE6C>=G(6CL0C +z0&o=M4FSF83BJ?xH<(mHq2knn@ +z;7cp%vR9o_9RS|4q;r&-Cxy3PyDJ#>*^seU7o#8B{btMAyL|(`J9ZDwgl)(E+hRVv +z)nF^JOy0lRr)&OdE2JWH)F%e2KrrAI2y{&^b7Jv4`Cp|;pk&!Vad^OwugOfUDffTw +z;-r7y3RL$`{1pLe98L&U)QpH^zWvZ2$|d +z%%+#e`zJx`!_=6njQtiXt^<@6mBwT~fO`4~v!IidolviEue2LlfKM5-yk}ESr{Q;a +z9k8~YSNGrBpj90-zoDmiEICJE9?91C9jPd@lpnX~sRHK*S8Jf`UE-kk(fK`9>GcDQ +zGKY4pl8?QU7sffmQ!5?e#$O|$E0IOi#vI1UdQ&8rX)-@E7Bfdi{QmTBP|9i~wVXy- +z{W|bMlh>eD{a4RkwbF6s`9Ax<0Qix-uj!QfK<1NmE3_@!-6mr23Z_~~yMLkzz2C48 +z7rKzY)A0?QsR_F2K7Lz(t;Cei9UYo6;omVz6p9G=rw7$BJ>g-6Bf*+X(~$~z=AiMc +z`OUjBOb7_)p)#FGGM>2hE+5Jw6_mSEs%{#E4 +z>P6u*wnTqMUg7)f<`1xtU3(j*6J5x?n#DfY@a8o`LG>J2=@>YG#e9U0A&RkY3P@GaIdb>(S=H&`9lkR*XqT@FAV+AgMFR6Uza?2~-~BEQ0+ +z?}(e4;!P`{)t9@IS6d7IovtYPS2@Q%9ANlH(yC2!ajzQB^SP!QSuyQr +zqA*B4Ic0nw5l7XK{d})Rdk;>GYBdZ?ce-KZSMyY9BpeY9Tos;fTvMw#<>z7)jVPj* +z0*F)lKiWc=Gd+Lk@&KiMK@i{r)f(OH>cC3V{HX%%lY-PXcRgcQQm*hL)tA?{bi?@N +z#i6knQ)AC%2++Mm%?Z{*9qV-FBl-C=8qK`#;m^LDAImMj;4!2auHg(=NLZGyJr)0) +zlwDe~%94nQvRU5j9_L!CF;pSNT6v9RpP!zK!c}kWdi5@yoM<(q1~xdN`_9?-H;@5` +z#I-;ug?yI?q@P__^_$tsJ2Z@sFyyBRN$KKQ>H5~>juvE~Xp`fQNzxwxFdT1NA_Vrm +zB;mYrT;Pc4etJ|SwErrp=8Eo?%;uS^UM*o?GGMVEg4-3g)0@nIn_qB{!mr-GD0^?2 +z-A|a#{;|AyjgZj32vHwQk94>S2UcTm+>RHURn3ta>`jQP +zKkfdVx!eVrcU3D!Y(`22HCx4P5vECq>Q>$XUjjXP^?EYK-?Q(&Ytj45h6?0N4SeIl +zSQ)TGzR@QKr`CXT_S+G@w-|Xz*rW%(9))a)4XX)>mi5`)qHdti&6EqN@w`V-+tS6o +zrdMhT#L2Q0t=q8nNVG|A%!hexf@?XLsTywuTx+5a>MtV9iLx``(&kW!P&hdh3W|6_ +z`SJixf;xXf5JdS`wH&+C8+&R$93FWdyR%(rnG@sOlRp>EOJFA%14D3Ir16FDfW5^Bb9|k!iuTY5BG*S|zF1j_JvQb%W6u2Dp4iR`_ +z)t{I&M2urq4EFxId$Kga+37ks7aM^QL@%vS`8Q#}wx$NO+O%E8MvM-q=yUDU{VZnq +z{A5EE{VZ&<_zDF6)GUf(y?YU3eHiq!Ns`Ifd{B3zi^$6reOo6as{oZ6#?>&{u4=#- +z&2z09kwMOit~L1i1DXY@ +zgf7Uzra9aE_TfT))U~rN{H^2qIfmnJHnmm6AFuJwwVu}ZRrKsXLY!db?79ya{385L~T5P%#3Sg=l}XZ&YfMc +zHhxY^P((zM<$OYE6))h+mp{1_#dzVPy)z`%N$+6053K30B>dol>h9jiXx@oLqL^P< +z`7fCA=a9{2`+R)%*aUyd?+AM3k`3RK&u=7TI%ESLL5v`FM+mlF&;V;C{kfpGOcL_Yo>`Z{RFQRE4`B&jeLgWBUoh1Bn^p}j-awdY{h@hlq +z0yryvkN2`9ZO`G4m`-**e +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 +zl~DgZ9{X*Fd@gOZ#-ntPh1)2S|%y9ExW#ioXH +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 +z+AZT62aQFE +zJ8ULSv@1Iy=8;Dp{vF-vK1D%(u`>bCz3=ZpGA9%8w4@dqEs|2aP8i9OdVZ=;nRz4A +zya@tG{8;KwmGIX!ljQ(B{lgG_MB@wSl|ycaiJ%G{{h)n$n*4oTjf_y7=$r^yz^PgD +zzu_kpEr9V}xX*2t0LPB6*gmr)ML*eJ#VZ&e9)didb%W>lK-;uL`0F>kmE>LShN*7e +zWV`8%7kb$9?;UyvG+ubioYb$rPp1GQlc&=QzCTJ#akeXM%bQSJA6+;Av*6caY-ex= +z@%c)9_yF5&-Upj=iFJZz%+9480_*;8r$Q0;cwi%dDx` +z*|UVkxT;LxI9WAM9G6i{vE6xX>zgH|TT2<9jYPAI`84~#Fcp;mO)H2Z2SuJY7BYH{ +zP{<$tNJrYP30iGTz#g_dB{5a&(#m_CvbwL?OaXd&mo9-;QLi~E5)q2aH9p_f2s@^N +zzM+!#g4eajdZZuDxMV3WH$zY#81?*8>K#AuLG{85a-svApBUE^MP!d1i7Zx2KpahR +zX&U3yl?cy~jr#xjDDbPMAj4qE6@tQ$V)5ci6~i+fuwR!y7bc(|tPwju&vw{ZjC>HPrBxlD=%?|XtQt|vGS@DLN<5>=Qov*}>jSt$p +zKCDYl_|V_=3Ecn3A`#ZlCzaUmw9s22F1e|7?1RPs^G@IW!x*UOhLh!5v--B=nH}i3 +z`}DVG+HB1YhalqI0%jg7urYoESr*Tt$WnM^0PSl=C_#5T9dtYlK+5apzspV5CMmIy +z^i5fHuQ3X1)>{>l3FSvjPqesZ31cwW#clKF^vchcdN17kN$P4c!7 +z5AOx8auv@zA)v`@HhsSd<$MlCJO+CF-#Vzh9$QNT_o|VHQUe# +zsHc5}Sa%V4fVJtF=LkKA!M-2Gv2<#tD->gOszHl9lCfhkLFQ~Ycgb-}AU(_JE(IXjAFX2$|g(je>^42tJ7#{`-PthVbDG7ti^w)Het`Qfb +z!Q?)s8@#`w8TG-7GeA$@pQ#QDw)Wj3f9>yKG6QnEZXdhb2sW+FiF!N7hMQx +z)mefRXV;&rx$W_84j9Y^$AaKkDuZp$jcAh|81#xc(8u4>YL!HoDFCNQL1z=GJ<*(UKsOVIHVieC<3Z0jSyRr8 +zGLu^47-Ih$&k3-Ear +zbol^o=Wy-imzcN-zji6876t2k(r7#r+9xBp@|qez`-LnAhObKOyVtU`Z_wEvO=s=& +z^f#C*E=kU|}^YL>e +zqlS*0NrA8!|-^&zg{BJgW`3+eFx!x<^|ox<&kA~<?xG27f-mbJFQpZP?b=+#v<+xN7O6!*gs +z@8|-t5sKf~*SAJekzs3BWRZhJh-h)~fz)p-C)KnWpsq&s=@;1~AzG3>Y3~3z^wnT? +z)tB@ft(Y1#NZ_bVZGsB*kF5h3p}>we0HS-g`z@JWaJN%Fcx-pnwFp-~vYTYtH^f-Lw3LSL +zBp2fk4qaIH*9 +zq6;6E>Q=Y^Wq1198Ku@@pH|$q@5b9&*++=Ea3SPORwK<-W7e-@ct+UH{_i%a}hjap;S_8!}EyX8z$ +zf$N&=^Zy!OAk?95@>Vu^=x7-Z{iBmTKm&%A#06F2Ts=B{V`S-A`k{rT7@IoK85Q3y +zJ{_+cjapM)QYXJ8@F-$FtdOQ31d?hXOaD;0I~MU&61JFsgR%D;28JfH3GI6#(H>zS@h)=3Nj%+5G@ZNN{e&M6LDj+Al=&x>Zx3qj| +z&wpq?b54NTV--UKnB24a52)?EU8$5;)!EIpoxx&h=Y9x~Z52 +zmW_L!U~|29?5^;} +zlN7)yjn(*?X{uEaTmm7L$0@5|@7)-I7vH`56HLmMDjCSx7cSYbCJ?H_UQuLs_vLxj +z*%3)3PjsKhpB;_JIup4w4_Y#vS#nDun?jg2vb32MxLWN>+a&2EOB;{JoVJHb;)8Hu +zZ|&Ujr*`zS4;rnwB(I6l1`8~BDH3eu;#`!&BlI$eA}v7T9Vh`$DB<4(TLpL^d+y;g +zZn&xZf;a9gQlc?CptW5phL{C;I!T#(HWyYDV99 +z)3fp%GJwtsQ779o+on+r5k4F;2ug`G^;z(r3|lN +zk%Ik>+|E8)qLRfZX1AWh*&w|x%%<2a_zd*f+q`Xlz?mq|iTM<60x7uD$dp))J=~w? +zyzH^^U +z(DM2e{s;99ZCf{XR!mgj3S-hi^-x_oh5^I{oS?__B=RRLb=I(5EG8~BMJ01R`I^(? +z6gj^Yohq!%?Ug|X-X4}Bv(CM}X0(752pF5tk`tPoMitPIQLt;)-@iploFM?^Gz?r8 +z`v!)0#n3m^H=?YbJ$K!b*}i<$cOV{_fUhNHb6>qaa~{ni1Afb@Crt;2PwJC&M^6HW +zF1Gn>=zLZunjb4A(Lv2DumdO3+0{dsxYrxS8Rp3A9^)jLd_3?*V*2vA;F6zZ{jX52 +zixO-BfB&tGp#i<{pJP!=uEYR8a(Xn?9za>WkgsP*{R16Wjv&)FXgFC4gYLbaS8(v` +z!?)?CKZ%M;+_zZh2!CyrC(O=sPS-fCk#P%zDGBo)!$EBR=gNTV!4$VBx9|kuP0 +z0Lv4xsFgSlZ(Jay7fonFU@S`!h0R#7I>USm9ZQCfS}=JvwyRHAqfRH2ah^4&m`P(T +z{%H1=yQ+vdk`ln^kZuFxd|fXIjue{Z7j&_HC?veap|{^?s)M|tE(!<+DIa<v087_1qCfRdSUWNa9CMOjeT +z76L+0#u +zhDnZG6yDe8s2D?=2c)10{ZxX_YsX;RaNKyHKh^Ig^buxs0PZ=BB<4sK4is;?Tc~uO +zxLKrrzv7Stc*XR5HECs3Kog^B6s2$p)-0deOBgq;E%topk?x?5h*6c%n6%n+nFVtG +z+Q|}lmvX{`6S;MU8LD-SmTQTptJ!Vf?W_00>6Id-Rr2T{2qlECudi@?780PlaFnyO +z3tT$Wc!9!u`1w=8W%FN!w1Hdn<4EZChPGD{_Wf>TfG=KT>YG89l!j~Ait2ldp4m$5 +zV*z@PVs|}0+m6I2#(%OhOYZyfOk;n4G^g*yG_#m$+>~zc&k1OHL77Gx115SBNTZc5VXEPRWHfZv +zh36!oRKcf(`Omw1+*16b6({n#sZo<;`;Q|z-0Fx+K +zq;PZ^x}+!Y8djecc{#`ZlL6-oUyMxl3Wa!l??0&aYQr=1{J@61hxdZo;&xRP;KbT; +z%9uZDO*!z=hYA$UU{M?#NR!=(3P?6ZMJg-SIPc7aU2pHIB6`59UURA-SFJ$03oX5k +zs8zpi&ArV~)GZ@ijvKnWlbjAB_N>6!&Onr886k8c)~U$_ZVtwT%Ka&jo}y`><+LtQ +zgB}!wTa>H+eKph4GvGYv>)y=rt7Q2>-wfakp8X1)*zV`~$s;608yHN1r1$yc-nChr +z%~P8mS5O~MYdE95Be%M-7Bn@28mS)d5gcMbXQ3)Dm$@UqQ+R!BCvlX*CT=U^N6*@( +zAS}^Knu;92ytGqYRUZopwKV;1+YfzjU!bN4N=By>-ZLYdO#F;eL$d{!OaioIqzpZ;Yu4yx(wO +zbAX9`nm~4LpQ>qDRG986NeOT6XbIxCXwB`^Aj_#KC;`iZJLl^=Tvv~J=2W$8jIIyw +z#uv~dhBqicj;a99OMo26^)0p%A2Ri+uR=QH^buCq&wnaX!n&;Nm14k*JTiD;?-Z(U +zPbt%N0PhfEYMxKS=&pab3)K^>Oz^ZqsJ&yAtN73Z_>+1s+H!&kv`ck`g(uwpnUGnn +zzOMPN96ob3{VL|{^8@7l@$c+G4|tHueE`p&rWuC0OK1F33}*)C#z)-WvW~l)1KOr$ +zR}f`SB-h&=5V8m922s$)WjSp-D@lliZBz?%Dl&oeOjppxW@{Q)gdI)uD8G6~UYQF( +zBH#t~u(`;4qUEK1=60MCMmSGzGt#-!^x2OT2c`HRr%BU+f>!28&rB05K;oug!Hf+n(MGbSk^AOLPV~~LqH-hU;-+F@fS6()5G|0#5JYW6?F#d|A7f@0 +zGZtJF!)w@xX&2LLc)|!+cLbVP3oKFusRR^ALY=w+Hf6CI?CQKjN2OauO-*G*$0?dU +z_a`hYGd{lFWLrz8b?z;PJhv;pJ_|YCgK6hs=;o8Rc&>3yd7rUe-Y`Fv-?QrH%9Ek! +zq-~4>sl5}Vzp4;&vC=g&;JrjRhS>rGUKyi2wWp==`-PO>^Kfme;)&&mUg)Bhk4N|G +zbH=LsRZlm~`5Ir-?_hTAp~AO_`1dxC&3#la66%Je4|Q+DPt_*o;}P7|0-3N^AZx>o +z(J@clW`IpFVn?w})77z;AqP57Mkw@DElCasU^4}cuI7lhqu1HbYrkL`P% +zDW63o0cLPn*Txik7pCVm6JR&CmwHNVT-W10u(m}Fk@s;=`ka{pvkzG)O{a!)D#pG1 +zYdE>*75U7p-)X+Pxj53Fwgv*}kGn*_kP?mOzYJF`4g29&;XgN>fN!H>EJQKIYxCV{ +zxcFwpbFCC18SAH{$1sS*W4$MAVltza$~Q%nBL%qOX|K5bS!Kc~qgVnTjb9quoa>piF%Mapy-nBCkwywmxd)O>+j2p=Q +zn>tN)%>6*zPcnBtkG=3c4iPVW&v5cO?f3SNKu=_L(f#T8_J#DozqM4p4ks=Xw2lAJ +z`p7o0emQvG9!{6iuClCMw_by`ZC(?iU1PjN;;N!igE+f+<;sUx6;4mWdzFDDP^O#2 +zP>t6jRNMP3=1lBT{u!FaGJEH$B8$tR?NCm!m>w6Fz8u?L+cWgjWdGGv +z(%#1 +zN)d1N^z6OEF!`>P>7kCq9O!&8bJj;ZoinZzj3eI40?5RIsD?^*K2`NRhbec{bOG)W +z6y&Vt)buV!WHJWFN=e4!>v|%5-!mpV%Z;eMAi3<)4f*2w>;wk;1{^$ZV+uxncYy{0 +z^3>0)xq0-&;WI+}V*c3cZfX{~V49kI9K2*7)l#spw$_sHLzt}G32qmZ1dnqL)G7Oe +z|64a{uXou}%_nyYvhpqy~H4|)s4l>^T@OicPyTPVRG8{qUb_!wGwNkA`w +zXI>+79STE~D +zIjS|z4C&iwYL~6;ExNPQQ2B{VOr1^BR{U9RV*w9F+Z(&)Jb7+CUC&b&R65!8hqW90 +z`>WhjY0f3#ym+fu;oSaU+n6SMPBukGP0DH+pb>v00t2W7v#!7`xOmlSY8&2TB!3FQ*E*ITK +zSyK+Lt~R=hErv~CGuD<9Udr6FtWhA(g|Gdsb^2?hHv2upfL8}1sgc4co?V%W_q|Mj +zV?8n=K0t0@Z%N_rSDAK7z9J#&8RR-Y`E8?PF*Kjk#b@$m&4Y=t4l^z)Z7b&zWIUmg +z^wr0PDUFuNWg%E%5ApXy-*6G?SODrw!2&S=_U0Ce;knA>5I5YdU5G-`0FK +zvO5#YLlfj*gfA|xQcM+cE~=PDB`ZWW%^1e~)j-edNb{_FRp?&k8Huw^NIo8`Q3f4} +z3qN2BlkG+PI!<|WqL{liY6K<<5DYNfexeQu&?_bg=@lhw^sdkB9yby#Mcq?x)~2nn +z(7cJ7_McszJtj65raqqdP++7UUyE5Y8tSuZQ*VCKwb%^Z56Q3FI|Pg&xC~EXXU6Y3 +zOR)tne^Rt3I6qvHu-h<<9r +zv;n@IHcvVYgFQpTKKC-6!)cKkCJ6Aeki_+DqTws@c^5SHI(Bk?`e_1xBkevltQ&;j +z_KqoKFKO~?Lje8)Kv2OuzpOitbz-W{$6)QefI${t@${kd+&qSFZ|zn~vw@+vc4bQ| +z3xCEu1n@+xJNn#W1*`^{PwWIX;BK6b#q-i79#0}aNx0mR4d~#5KlI2A2NtKJc*Qov +z$XN6b-S3w~EyG6<8aGXU;Dy!%NH*wiY1vnw;I~i*IBMDTJPz>8{<0YZAo;)}UolBq +z@0D`?xjDmd4Q0@9fd=C;`Km)*QKPD{+kU72_7lH;c2?rg;U0#Y#r>~NK%MYGeCGZ& +z3*fD(%GWO9<4slArwig6$Zcoe4;*(|qXqgaDWb=e%qwemUvM|D_+$Wu!sF!FRcvj` +zuv&tPoSSODm{7x0?^A};y175(w?Rp`~}kQFsG?!BQ!&p&(0qz>6X>6S&O*xw7|tGL7f$s +z9;k~YGY*LSa7_L=qmwz|glZ^N_ks=IXVa8)?^lLn{99Eo{lW|+TgOkPnPys4M{DyHN6Ofu$&KAM +z9lCMQ(*YQ)UKdJlV?+rVSr46+b0^cPy$DUA!)A?*vKXUH@(PHLhb9?J7hGg{@nb~? +zVupGLR9xL;UeUu%u(1?Q+ff1(c7f*0c#KOWq4NxX1>V*#gn_=-Hv-#VuDrj39=oKU +zh&1jv^UTYqd(_4ZEAo0F7Ar}JRqk+yq6fSWGX&8NM9VJL_6d}y|T_qZ}VB6$GZg^`N +zUn*Puj@kY^&kuXt)e?MOmLD&w8Htr+*K#gu?R(AWiG_z}^JAg)mDO;mnce3wX6i=v +z2xM_RA|oK}yWD884;F7@j7XWvdN;P$PF_~@&<5ov0Vj=XI$~msQ!&4jE?OeVkS&$D +z%j1`eMs{sJ%lc-V$kkTa7>eBXzmRY}b+J)19N?pwZwuOQ^!&q%ghY@zXpR!O8#RtO +zHSMbXhdA>v8@i6Wq|s&j^@EYjr>rI#(!9;$)=g3PhVQH(vsRLC7D4Ygg9-|s#*CNg +zzq2^`-TbfrghZzD{M+9l{?17Q*eR*F(a6K6BD&Whx}WGX+06yka{>9{1pl!{ceXhB_=$a6}*Yu5Cf~$Gr@eWJ-$&#gS8!s +zFf+6@#?BOA;MGGIV!z$<8w>(Z5dB{^@#V1h_IfBLU9g7H7jN1eq@f+)px2Yu;y4 +zAD*WF13)Lc4T<#Z!P!$e7z(D{SWmG~3D`Zi57 +zHUQZ1Zymw$V*fGRO-)N#VUK_axKUklOKQ3ZAH^0qtnN#8_rI+c+l=jU2flS8a(wMT +zNL?c_j*T43w;>$=o*yQ~wl#S3Z7HsoeZWbg4a&{tX!?*nu +zgicri;9lQ4-m*gd%|PeW8U~#;*_La(?nlPM&|Gs^Y}{U+(%5}Pu`&6npN}th*hIOM +zkOAd}S%1s#mD-HcDTXbqdxZRSdVmgWl>?TY^&(dI+_4REV4;lx6{QeGapf9D^r*$V +zoa(*vMCm`Nv4S9_75InxZd94y6YfHn!yR{L*)TdO`BF?V&)9yyhr6pITNqI~rwUZdr +zUi!*!Ww&IST9;EI(Xm2O!V^!e#*V8+j%zPi+NPC)^K=)&YJy5yRS)`$F}UEwQ4Ud| +zw6gpgmI`t!G!10ah_A;<5+En!tJ4q3O5A-GYD&T0D=`=RNU}mS33;e>I}9l*9!Rwl +zLLZ`%P0f09d3mvQV=H5q*gs1m<#tQz%HEPvVECF0?q%nRjM+FDUCX8|6_*Aq2QK7( +z%QS7wlG$F4YGzRjd0hN%dw+%|V5V;(_CB|Xc^~!UmvW;v+>66L!@|6=++kiP`p%48 +ze~F6Gle{q_KVu>@7Ijp)pRXaq&SY=Co0lS51C~LcBZ=2CIWUWjJIFcZZfFJxvUe@g +zj4rOYsE_ptWXAoigxtaghE-!7xS59i|g%g>`FSq;-LM@L7H$HNy39WXJJbm7uq +zaMEQg)c|KssI$;k+R;fu;v`GScy0^|GNqf%8rBC2Ms8QruP;dH(X%R{1&4kG&`Eh`y&bkUUl_#PJ%p +zrQ>!pyr^$Mw-zzQ`xCN_)ww3^sQ{Mk(biSlK2m;6j}DSdq2y=(SpijIA`-oS6a$iV +zWnHpd7lGZhf1a3t-PX`5xyk|)8AO9k)7#rf7{m*Y*#UxkS7?iy)CvEl|}F&;Act=x?1bgV%Q=tOpZ +z|6jNrL7Ge~VCc}>%c@GGgX<7g<<;GOy#=w*``Cp=>5k5{oR +z-TK%>?GuUJEYH$~>)q{!CPV6^nKdP4AG> +z8dRxB0v1iEs9ZAB7R|aYKYMuNibFk7_y!(kZ2ny((?-g@#BZdt54H?qZzJN3p;cXl +zeV9rS40m2l1q6#4c#mYkgOiltkVJdJ@gi`;h<-lkx=8o*6&J(uOdY)@|2d*$;rvxg +zM?|TCf`HK8zUK0a7-ca>rB)&f$Ls~yxDudg-2XfI$WHe6Ne*FDo*jgfY+F}uskfy1 +zidP9D*w49;kS{v +z4tm`~j$H7{7J%8<0t#8&$Ub{Oh?+t>y2R_gy(3b>r$bVgieTEp6}`a>#t*!rD+1Vu +zln4)Gk?g^te=}T+T-mt?k>6c+s>TW(Fdrg35FXDU|88j*S^atZ^R<{qia!m|Gki@I +z?e`@%b{1Ftm-z&=8`9fg;?|P|=mawY(7$i%PcgV)Z&VL(X9Lp$%ghXPH`nAgV$I`Ufk-$XZ3v|%1vz58hlvCB0 +zaoye5<(zxCS>);G3A&*9#aBHOt(YQ?q=-DdyKG<;*Cduhp3nwe|1VhQe}HeZCszu) +zmgc~H!CpOgX;r>%RGxtEI$9CWHdDj>;Jr&LezR4dq{uPEkVmX1Sd*c~fiVxt{`FNXyLt`sohOC8gnDfB +zap@jj=k5Z_vrUdanV0+U`90ArCkPs3MZ03Mj1WVUDlWa^qbdss)UL*=B9(coy?9lE +zk~)C5L~5sk-?(s8?5`P5;bwK(>>a8Izi|8X*uiwt0dBy)ne9U>d_yaE3o4AlBCr8} +zD0O?KyTD(SDmL~*B)>%>OQODfExt30+Hg)R?K$y@MjGVJLRisb|FRn +zVcPna&A0-D(;pd3Wwms@IDlRL>2|oeLLcF#YVp*ta=tM}P>#vGbC1jo&gG;N0%y3)RWDytj(7B^NqBkcxZ8tk#O`xG@9(q?i(_!;dD_*g9bq(q=q<<(HSEel$bi%yX +zL+|JS{nemF1Yfz4qc(jz-r<=oeRe>0;M@5XY?3WsW_`Ij4cU6YJsbgFnOJ-UM&A+K +zW5J=T2XLIA8oi)7*oGq~%dL1kz0G&;4!ci+Fqu>rSsNQA$Y4XN0l&*b8>Lfu3bW3v +z9eR5E>2FUO;*Aa*dOG{5o?Fe!vMn`X7xu}EQU;W@#yrz?c$Y8?x&AZ;C2u-;w{!>A +zkC*GSgT^Kt9M$9s*J4*brqz{3m-)+s9S2h+ZZ`t@YMvP@tx&;#ivxNZb;O3wvl0gN +z0VlU#a4>)^mg0g9`KN=QD8|vW#BZA9@#eEQeN>{l77NVCo`NO@^<1-Ncw2udJBJDg +zD8olEgrE0c6n*oqlGP|?wjGGiv9^zd=K@v@U!mTlPHLrb;l)$U^luO}y8QvmnOPDw +z>%d>@DT&o;lHs0|sEI79L3}t-Wq0#Wa8Y4F8gHSoG)u#}g=qXU)R4|8^YZauUv~s| +z{wF1D6YjH5YIZZ!km5%}rCYnXKI{|Z_9WH%f-Rs{ZD~)+l|krl2@G93hzWYH(gZX{ +zosgM{nW?t(I}FFZsLfTcMUU9?rVD&*Hwq=y#}>-9OLEG#$ywdeNAYx;Wq;;o?ZnR7 +z*oh!$fr$DA0Lawq?PcVzvgg>#=11dS+F3cuo0SC<2@Y%$6q_`ZWtNj}R#PG0NiyD-`naGq1sFY$iPzH9v=vgn)#`Q-_X7_7tdi?&R +zS)329&)1g#$RsHFk)N>J*Oee~vY29%j3*AFFkrZCkHOkqTU##@Y`?;tLe%Eb?L5Bg +zS=cNnK`!sVjtV>39ojC+tq$AXYA(n(?k!VAhlU$D;+vOnqF`$H4p@(@$_L$<3bS_v +zgV(<^ShW6+pt+f3IK75OA9Lik)?L1aGHfIXg@>{rB%mh=jW{yGe=BAr`7;}amK~h% +z?_s0H&gu3q8t%%Fy57}cK=8f{Exr~2LUX-d)LXnkhr50{2>$UJbwq7QY??ci<+ +zBQWbyn{ffMEh)w`O`r)Y>0)qGyj^c^- +zfM{rv@{sta)p#&3W{w@Lkyh3W9O$E&yZQ1_~~yyDH3~H +zLnP+CFvp~i9I=`}uWhf4s_k7C$9P7hvQ>=rG~h?x=yS;1C3cqOEb@`XZ@{Cq?Hol` +z*?4)l(%}RnjLGmCnc5ur$I+#H=yRKKm0#4}y#<+GRO5aca=V1Q) +z+@Po3HS8F$-Tq%{HG((`2=j)%_1&FFWgkQ(q8ezeJh!9UfJb~Y*sY~$|2XKwR&hB= +z(GlNcAoC{d+?>85eYOIh_85t2*GoaB0?fE}6swpH^P7 +z+Bg41_DCM>p&#Mkv|}~9fHA*dK()&O-h(w92nMr|{x4|xAyzDR80XjPtDwISNGN3_mxnx +zsd202O$#k@hk0I3Z{dpZ;mx2?$FD0|sd@)e3LE&WkT7LtU;za9J8>zb6%`>r>j +zlfI~KmLwN~`rtioNfLVe2>&l$8{!2}5-P!c;oarNm>%3vkA?;9HSk1HpXh)e^}FXe +zARR?U-A6TVo*0*BS35){$ASz?uRGC8M&16pJb%7`>z41)7kF)5Vw`9bd05)r&AsgO +zpRt~x!%Dbbn`(eGpe6qlTv*wUc)L65?NRZ1(F=lSVWUDn*atStD)sQSZ7i(!Xl?a5 +zcp*uAiC9@N?URo*6!fxG4G)cIOcXGmWPN_KJ( +zxGm+~3&A%1`~Zi-gpX|=9Aq`dGNIu4G-p!w%lYXp>PKmu2$J#vAjQTEvy_DJcd&uT +z>s=B8Q}+BC)${QKWA%Lqx~$ti>-Wx>XYit@of0v2ES0=%F`nBt`_`q5Q%+o;NPe># +zsGK1uqQ?cGplhdZqrmQO_`_!Vt?h>`tdPMqpdT3FuqHoo3&FGNrn-uYvzX00$mNdA +z`8&>L-0$OLvNkAW5I@?`>xDu!O;Uxs9GcZ9=-n0b8%lY5q6bIvrJJ^cIDNspP+*4Z +z>)tpKwoYcqLR)98J%QOA^!&l=I?u0+)rNUWW5VMB43VhVMqmw`&T(ZmyX{_snF@Df +zr}zR??F%Nshn@ijmv8}&-8iA0H9wSai+_9(<%{@4yFs90Ij2VHqnCC25&0^9)R-%_ +zsOM63ojWlz>qagH_ocV1Sr9N|^^eO4{E;U*+teSr-*BGxoWk1+AX)GHwJ}AF(o7>p +zNsMupUuoEve>-ZGEFmkLJ;L8T+wu1;m)ZU_xk|M$Mm^&OA_bFe85ze6*mh>cWwo3! +z>$?#_b!;a{65_P#cWPsO)~%mmdb}HZY=Y`Rc1aY#8*!awTvPYz|))S3x*h31A}I_&o|@hn|2}`n(=^x?qg(q;%hu3LB`NXjqoO&g7XAy|yZB +z%9&{)|G=lf2<8mKHM3&qWcOyUZOG&LN}0M`#y7cS5RC0l_B25FV!TNhs|0Q9IR_%|~z +zEN8vKZbJ4@LDCI(757=eMQ|@CR0gi2tx42PE4L%XX0YIP#r*sBWGje4u^~S$I7U}H +z`A+_^&32cl>vu)7%u^QC;_c*aS7q>IX>%l~KO{xX<>lzDY)Dd%Vot$S9Lwv&t3p(E +zRjf0FyGUtB{o%Buzs;sU4tAv0^Bk!?WYF}%+CU$X&le{CQaQnb9IOORP`~)Wve)M^ +zb4jrdtjA)Rb6?oU{L<%Bl4U_qZzqI3eMon9S1XVUw1i5vxs7z~7v!Z~CdU}qR_oe+ +zXD5e(Q=ECr%(^etmTY?EINf6A#d +zJ-p%J5>&Tdn%}gLpO+k1{ +z@7oG8Dk*E@AvtMYV6gtPZi02cfb=!?sAJu{fkmy^uZgqO&-45DUE}N|NGwHpH@BzT +z@rVL`X;DxAEpN9h^;4Uv8pB_7a!P;9D@J|xTk5xEpP4Tmy9O!G84ZyN7HGJ0Jp8mN +zqid><_rM;2H-`|TnDVrE*aekVo(3rTVgL4&ZhFuAUy14H9}(sgEEgej8{xRhVw2SS +zk~4zBOoaK1Cu)OY02c`+yEIY5hSP7-aP)}VjT^`o>p0C%voG73x~n*BGycAAz +z!?c%O0%57-u}kl|`Z%t#Ftw6%xvy}#2e5bhrDpaz1LwwogEuWO^rReVqCss~rq)cR +zGpz5;0@X2(g@^0C6sJ>YID;vE@WCgV#@4Ra8t17^>6j{%q_# +zpW1V+6_$CKEw3s^w1+Z_O_#&59v;I}=iIE>THJyS${Ihdm+ZFW{T=WPiTj_eCrr7QV%92n=l9cf}clS&)w0mdxD$C8W;2i(YxUai# +z3s$CRSl;XAu@yxm+kFz5HkGPKY%ZH?-7TE^&Sq4C=%x1cOIwb$>IkCnjFs+5K~C_h +zxDV_P0>1VQxKExr7q-k@qoOj{;4rdhm?Pu_xF#7f<|Ni(q_=XXzp|kfzWk85X=C+o +zfW7R)^hOE}IG7OebTvrmpd-e($Prn9-+wWqBVNNqupSoDb%OG0C@60suE5x|q+6!3 +zlwk#LE)_^^?pe$LPxz{kZ0*+*Dcn!}?w!e1KUo2Km>;+x`k?I$=$6*e`K(9FwqC6Q +za&)g>4#i37`V>;|H&EoKW+DM}fED=sh-BDN3{AqKGi;~26RI}U<)yuncS~EMin>;8)pPtiWZhnB +z-6>_&T@Js?HdU617*Bos&0eFnpl#`n`WxI^74|9aCsFy26|`wH9*f!VP_;gplyVsG +zof%m0-hChrx6N+5`piRA!1IhW0LSMFcyqLDur5vcLv1)wfKwXOOD!{J?0Mg#l}Msg +zNpe_Z$lnx|z$>Z0QM8+7PPbV>heIJluKdT1=uQH;Bz@FI8{cSV=xL2 +zt?3+l|Kx1;77|? +z-JFqBb;^qY+9scO{hNI!i7R!;y!--eacIcmbatrTr|e_|1q-uS7gI}s`|+(9Q*XGjF`qDHw3-^OG^rqc~(lU~2CPc-`U}u2f-M=+4B8=O| +zy`^wIy%t@7lr5;JYSCK@fy9o?ji-#kguOrRg! +zRU>sI)vJBzV~sPlBKqFe)XH26ytBdFmpN`ewcw@Vb?b(Z)+u8&)S1qj(7k1pdh=ty +znaUuUGRU>=xQ9>7Gz1>Y+s2Rf43B+u%VD?j6I~dCeE)P?{G0leKBWb_2uRO+a52UP +zzko!2k`ZgU4%3G!elznw0qRGlZVdR>p4vz1daI>?+_YKiSw4w5Ij?CwEzZ1@>3=y` +z$cspBm#STZvGMqoLu%t``Bbqlptcoa=+=5s=Rws`+vRWxMkI+RXU6HeTwUG+B3JK#$V%{dF*@{a9lcsC%sGADce8 +zAn}tyffNGKut31eH%R$K6xZ^g(rn&#>L+kFPwOHQRN~x!}n+ldT +z@-qHFW&WVe2fD;n-Dr^Ub-VnEVeh~0;T1RhK_&RQOhJkcr7z;6;^v6vINh6CZ&*MM +z^t!|4u)=YYccu4F5@y|e +zxRKrWoQIq>@gBuWuhYbOK54Ls19^@b@0rKOPp$tXH<3_Z#aAe`t|eXt8fih=kqTP> +z=i2h!Pged9Jv!;x;@c;BP{pOdFf?lQIT^^M(g&1lkH^(`n +zv+%`D(n44^k?1ofVTS%*Eq&QI{g?HH<-ZiIVj}WivfKVicCU=YlOjRFr5gDW-d0cQ +zb~u}7HTMFhS< +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 +z<2e%SKB|VKce5unX4~fWGp)@e? +z5pg8eCCB{&0ZKVl0DlKCc6^=$=Akhw3A(i^o|4aeA359d4>&NcrBYM#FQ$jrdBAp= +zPpy~iBDP5|R(#b|g1{)s@GTdx3zFw>e%(gQ(pmZC!3kttOZEg$fP~_OuCg^;y=+=N +zyiVY~*gcw4jjneuWkt?!aBe=WSFid~vx&WKlJe4(88mgeReIZC_D)w}}20vk+I_ +znArC2Y=&W+jJ{yXFcCWT(%y&N0sS?r>yHr>-uJTN|xObo__N!w@paNscHf{ +zBRE_!bY9X4C^0fjixfJ*}*_U%x!2x$sk}la;o{ +z>y}jEKE_^*x?7be7#pHq^E?0Hj`JVVp}yH4YhATcH27AKd`xhss%I+x?&S@ZNGkKr +z-s0c+Ey5+ +zlml`LGBG3Qjh^j~IC-w!n@H-r5*?r73cR;aaCS4TXqV3 +zOXn}?20Y+*3t+NTZ#ifu)9f?q<-zwQ=Tz)SbGhP8#gRH}RykCW6~~XmD1Kw5?lfM{ +zw?by6MANgmRL2jeCz1Z)MPY?kV+H(`UCL!;oOt6H?sS)FFD@;8okXR_6@mZEH^4{V +zg-Ks}^p5v@Hd7-aq1z=@UzqZ5uKaT#JD#XxAC}SE9_cpvF4kN)lQLD?s9*SM^j;#~ +z`%l2xvu5L01R=owx>BYJb?E8ituDUUl&P8?_l;o}G}mEhhT`F7E7$usWUO8mNj*Q(TaCwu-_xI=#DYh0%@P60eyZ-)&I +zdDZSmR0Oz`z$+7~Fwye9aojuSU#j)So?{LWeO$N;)Lii}nz!gL| +z22`wcZPlqFQ&;ehj9g2W4UA-W-#ji6uS?{>dDBkeV+&k>7oo>)0@fUqInr{yG +z&EM|kB~lzQw}#ev%pMvJmks89S*!-qT-9hMD=NLn2oF!~OFCUAD@aYP+t(K}OiQ4$ +zz5rH69r+Y*bEOnfY-XbOSn~gv@?sF;ny2^Wsrlbpb7aS2O{xphqWt96qfUS{rh+Ld +z{t0cpdpkF7w~zvo9KB}T03wfLy#P67LQZsb1HgJ3J*2n$DO1X})Wg^3 +zT>u@g-Su)R%#OTtX0!X>%%kHik09i$C+3UshzEQa5DbOyTZj12{^W`uCw9A67w(7) +zabKq4v%O4f9==4 +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 +zMY()E5| +z{&S6+eT?nk_TZn3&26qfg%#8>%bje~7Z7QrCer_4M@A469AmK1X7KUsj1W$vXn)_= +z!*(y(mNpTOuJO^Ducw#*HA%2`A@I8@ZKW4KP=PvfDGR0@k@IE1-TkS%(wpj+wp`IS +z)~M>t$oOwpWouh4G#uvAWS}WZAEZq|jKk9UMK9%20{U@_imNN?)G>Se)M4!aQbj`JIB{*$mVmRs)vF}Ky +z(DB*j@9BZJzYZqA$W^ddXmPOXomn|Ao~L*};9OCg`kz~HK{?DqMhFP)D!$Wh>TR+Eb3lF5 +zE#o5E9>K-*jtViOOIx7%s#U_=Jm$_Z6{`9Wv%~#<+KGIYG)upiYv1p82m;G*PbN59 +z+a?cF%*e}Xj;~zh=*?PJ9*u5l`++m-w4yt50Tjr+zgjF!5RM3v0&Z2jKtltrkk1Yi +zeVt`dvh>GYOIZraRFIhWg&Jgs6$j+)r>yI1(%y`4b}{?DW?aSRm!RP)*`e7w5xXhO*Kb(F0Sl&Mdj|qe*)UqC&Jhd +z^74jMX^+h~^{6Riyisqn_VgO3p?TOW!g_6Uuy)^LB-_$`e&gLd(}1e|yxBFb%(vM4 +z+EA)IPl7?@(Wb9nu6PUk6X +zn_HYZ_($N!@OtKewCnuc`^5o3*~`skA|w6B{gE_GE@W335~j)yp>(ii8s +zlKR#%-l2!21!>i+J&$qjIpsUwjyoTL4T^K)1b6_*u(i}IAFL36^?S5-3#)NpAD0II +z&&?%u&FJ(GL6K)z<8HT07 +zaP2o|sYY+D*4DT(m2Yf)CL=>L+PO+4*&xsKm#6FvS4ybOUXxkkyNLa1yaAd9mf^k~ +z@J-(w`({1}ePZHDiycz|2b4FM!`^}da`KM;qS%z^1`hm$E5Ml^4ztxKUIn&dJBv+B +ztrenC`R(wkvC2x2lAdp>;^+)#mD&x?Tm(W)Xd<5L4-TXQ=|6RG +zs_2_(Dhg`qz^)`9$mkWk*+-&+HP6sCs2T*Eef8h?8YW6X1CLnaWwaKILCDBId>HKT +z3i4>dvys6Y$b8=4R~~G-9ADLAg@u=*FDpA2SZLl7zYD3CsFYrv=r6z=Qi<=*^bnGh +z60!Gt>&|{K$G=+|kD8!*tX;d6u~b6nwfDc+L-@Due&x(){J!%7bIIL@dT+RxfWSxA +zetwmPwvy%`;|72!va^XyvMLu$W!P51OuIgzBW7e_=7g=3L*O&2ypc~L3qdO$R+fsE +zeGL`Pfa>~QPsqKqqjkjhaKEsoB(9}j)Su|$Z5fcdC_m%C0*15FE@EyZs0)XT6970- +zwkYZrmKxa5I~>V==;3<`3=T=54=vicH1KtF-^7RDSy_$>; +zdGy)1jHeZa;oEWn`G)!t@F!^`CfL5*DSk@<0~Mcc3rF%!;87tdnq2m6rXm0Ls{rCa +zjVp&gw-DPED@KYJKdUE^j;f7uQ45MG4s-IR%5xTZ$l@QoX~!DcZcOI&BMR_P8=lxJ +znsoO`WOA%7>Y3J{%>spG@mMk#!4nOkA%(O89p@kC0xk5ke%@v$gC?+Q{PbNMd?dC( +z_!`y&rb=xxqjT-p_Hb!fVOlHtX3XJW9)~GOuXpM(eP7^ma}?Wwb!R0Cs#~a3!l9J| +zaSoBqvVA4FFx?#PJ&b)b2K0jU!G)Up0P}@xGR-;{^_VO3Di~HC%bD8LrkMgBz^KCE +zlfDjl5#;Yn$7!O^#%4?tP?;Rh3jv(nD-q1D#bZ-sWEc03sdGiIPY4z7q#L__y@Dar +z%aJG|@%SSm*eZ7eYzD~e)Tf0#k$4i7z8l3afgagBl%BU3gs?Rh0 +zB1sYDUfey**nCG>$?jIGWS7wwF$kMw{7F%--OJ?zjhT-m(9(4e0-lVd+G9h(*;A-v +zYtBX0_V(CsJ^MQDH(41omW+zp4o{nWeDz^yHo5?Qfp>LTMp|P`FuwHx`JOSBnfswm +zdL7xzz?pVn@B~H4EfuSa4??NA@Y|zt0Yh32P@~)kVU)sZNPzmOj4uVvxczci*cUgR +z;}iA`O1%!jR`=>sSYT}cAYsZ3Mv7B|*Ippy+V;yUy)3gmkhbbPUSFvOqLEiqA?sW-fO8yx)|L4y>|VfrXIK3T*EWu;>L` +zwm$-P=$HYB3+XO#*#ppuZxwHFDwj?1w3pQ<6+5!kP00d`f}Fg(FV1iCi#iq%pT59P +zLQZDBw?U(sdg%jE)Pxqi5gz&R}^T8Sva;((P +zq;rPio8Crf?248pc`k*PeqS2;pn@I*H2w<$6AqC>Q}T$H^vU-QeL;jKpKy+vc_y32 +z`WqapGSajfX&XB3^!5O3rVJIlHzZUlj~PvGjF~xJBL=M?{Qz0;)ST!q-qA +zm9RFrJ6Y8b`CBmzq&idDLk+la +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 +zFBK{nne2Qz4CG*YqEGfpr?CX3 +zEsAaHk=GcBa~IXr{|62+9zBO5GtYv+8k@DBC$z}ncQa$^S8gO#nSvF%*oK!hH#&|V +z>YK+I&X9DWl9o^7!ok3xC+TPuo&}WdgSw5)$jq~xiUf$$9_wOwfLmK(X!5OhEiOJ{ +zK6iDr(x!Rua8XhNcTWAgh|LfkM@&zc>-j;qSOC-cVk})C9fxN$gR4nakem+D#`)6X +z$!~t9dvA|ly~50WNZlw7knkU|Ri2Lgv?`A3 +zJKzaF0SVZ#A5J$a(jw*E3(Eyi08UeFf;wEkM_~y>Vj2_YTzm9RDEIXY{5t0uQM7`P +z-z!e1nMkq}_G~M)z-N8|Z4GHZqWFW&sOl79@BIno#vwv7FhaZTej?$IT>pMJ=rmG0~q~girj^X0}DL@>2e9r>zXzI3*dxZD^ba$CL{I4Qu$=EZzNAKz?{gzGvm_-D>5O02H4a$?r!PI +z9KxG+0bE@trq)4y)P#k4J?{&6y-Ovl(T)AgF_o@|A0g~>TQpUEukwb<=*|s^}_kFOO^lNYPuCyOv=7)bgmkI0R +zvU-}A$<uLau4`>tz`b +zPn;ZkhrKu;2hunF-8G@pHoBRd)DPkEfarBokWkR~m3RMZdS}FDaO;?SMf#t3R)Lj5 +zD5L@<;msoJT1@foAY#)(Y&R{7)Q~SJ=^_#6dq-7iikYRc10}CtSY-+^;QL)sh)7#H +z1Z%_VL!Tr}+5OS>J#)qtLJS=;Z=qKp3&Pfrg2eMB&x*@qBHdSrer)$su{<2X7gaSz +zHkRiTLGi^I&KS~v52#7X+i&u=U10PcumG)jz}}}DiHu9IWCiE{M8$ss;Sjos1?tgP +zQk0SI)Ar1=9iEpGww9q9~(b#8bnJ`=;aDB +z)b~r5z(KqM;k>MKM1*VZSW-|~4Am?YjVhb143Bnc!fA5|-qRVi=0X>u1$>%3D4WgqK5 +z4f>2XR9-sNoS^ZCov)viFGLZma;2v4Dp3x2#o}){h$$ZgfY;X6!i8s2|FxPi`gjgl +z8;1KhrSk{zr6uaq0E_-jtU2>_JAxh75y)o+la8K%3_3bK-f{DIwexf+kP(&%dGG#< +zH&QuivVsN4xjZ;n?{c+)-x$o4@*6+{KpKw48aZh;BzAI%yBKrqPiji@)XR5G1 +zhoyUK6|A^$(1>-7JreMhd!43bu7#akHAyso5%3r|kowhIa{YxPU>sA)Vtkk!x(t46-n~V}+nr6wc}f{XUs-Lr^g(&iFTxRt0G)c;s7c=PlGEe*|`LE8BAr{4P-br8n}$7egetrwoybbGk1tdE6>p;hp1 +zJ*(Rwds-tynU`TztuT%dFJw6j?yP9<|DrL#GBhlch$~z&d(n!sYGBB3Seu<#DyRG# +z8S{`%VUvjaejv)9;qIrPVSm`2R{7HTsq{6e)a#g#%mKI;%f0hhMhEnE#<$I2 +z3u4I|3VB93#hZ3{E+Y25{1u4df*t6H3S=~4yUv65h4@BPm}2Dv07z3%u7WX8=0oE+WVqyRsTem;G%6cD9F +zFQvsDw)FgNJyul1UqV7$+{{zg%t+1*Qf|u);>5bnxcI|Nj;1Ax9ui=wGu+WYmpjJ` +zfYYIDhy}RoghuQxW>aIE%^kVeh&jbMH0Y`!2=;tRj(q9^5NYY1IJX14bz?zn0?!KK +ztQ_P3q{DaLmfa#U>Yw2P12Yr0u^#ej2dw=$dP@PH3BcY~I*AO7i_TyG*%UR5_`j^bu-M(RZXx*v@)GHhpHrX+AWHm57bgkg5_sX!HWATV)Ct;UbG{> +zE$GKcVsV@WA#WL|{auu8tIZq# +zBYu}sPATU;;V3Cg(Z2hr2TlX~34b{T`huwB)-M}9f=umCzO@Ud(Qj~*U`;3)Y=xWL +zMOpmG=<~xbf>(Aet=4mHLDmd?x{|UVtYkF2X8B-;3lS$<>&d_g7d)-e)DZ9TUYa?f +zZmX(G=yxo&m36-S(=Got2U_w1a|Yk(f!>k>?MvvM8C~tThFKNmjed!Xs(HG&yh(_! +zClbUxu_)`1=iu-weI5StyKA8L43%-vuQSY~O&`h9f7z2fIoLr@I#?`*D|;E;3AA%; +zL{Giuo>w+V)f))UyE(MKP0zC9_)ByDt&CGOLaO78jXwO(Jjqn%4{u9|+%-6qjT7wu +zxtz;kF(>T!2i!j#{l_SHA{LmPsnaRx1#w+eTmA{5A8piYE_akd_7|`Fk?pq!?iE*v +zfTVkZuq5;ud~E;~KU@Ko|80dc25L{pH1=~qydxTDMn^#k& +z9NP^a4?U)NaH@0etr*dZ0>%0?mt_33`^sSs-tOUVMK%5u)qNgH +z^GJ|8YjDVC@?jXVOlmg~_W{WJlq_H?nf3PK)8vXrGsyh83zWcfW`Tnqi9Tq^UE#L{ +zFI~Lol#U%q|MiwQ-n_Gut<{=2;`KbGf68atIocwW>i#r!kQv~Dt${jXw{&hN4QV|~ +zU^93d+9LzU0OR#qaPvMgqQfW_N(YOh(^BnNnLaG#uv?Bk;PETOjJ=LLW)Zhq_JGXx +zTLEouU4S!Q+r<#QAp@V*2o=~)^D22PM$wz+2H+;vHx%;h&Q(kE;*6ZHc;qfdYpO1J +zIgwJfoA&y#T2+PSZ#E>Bs>CzagL~z*KY?<-Lj63@L(EMJ#}eZ;{bfGs_4=GaAq+Y>YJ=-TNA7g4 +zA@`^pQi6>p57V7G5G>`fej`HpyI>0l`tav(w~zNY<6QPeaUmu_Z*(Y71YXToBJ-kc +zde>g}al*aMEhzjoVMM$hM}HgkBlcy1i{(AsWi9FTfict#*rnDc6~|U7VIlfoD~`+U>;iT*yoqwqm*ao&ZK!r#im4C}$?>A87tn@KqNh$<;

ldadAjaruZmXwjm9l_+9{}qs6Xz@3e0*F +zH)G~2h7=Qee;drDNK&2F(H@|e4&80H^@nGu0DVGMfL)R9E)^_QfUoZu1A`+LdRrP) +z+%~f?4mFUydDz1$=0%Faj~@(UVaM4wGGB%QKjDXve2r*y*;wF}kS!`*=#ys=I5A{T +zx=2F)9$H8)ciNsYTJTqLp@-#0Eb}-enxCM#Ym@xReMplEjRN1M-WQ9$j5F~)1Vz5}mOv){_Z +zqDf^1S|;lc`zhmER;w~|tBU>ql)M*K0e^?S6cjIDsc>TNZvw`FRf1D;Zn?g(UnY?{I;?5SU(w)tV<0jr +z?rY)Fw>IdfGUYTF0qEvV4gJNL#y&qhj1C@KldJ%b8476+liLO{YRq{cco2v!k5QCH +zlR60LYxjUX1J#jIkAZ>9K`Vezhm4k0Jit8zIq9XVaFQ0142p)sqpVFxXJ3IX{#SAJ +zhVk#|=G%vYl1-B`L}0!eV)C&!_%SS;=<;Cg9_Y4HG$O5o$hI2Dc1hgtna!y@7JT<# +z!wesW_uroSk~n}_WoF34Rq@}PICzJ;j=@ahhjV=Babr-CurRrFv-4JEU4W(r0GR26 +zp>I{V@+(yN{WG>LPd_W!kK0pzKN1rY`N=+;5DPrUlT4KNeydxBtN{l;8PBOz`v_(c +zm;QCSU&L=4r11TnXV>h{)P~i+++uM?sRA}Ye1q4O?>R)|Hr)aiVm?X8H7vaXr9mur +zL#;9UDn3A?Z6ne_=5Evlp8Dk_o}nJ9dDvj}CE4E*dhj +zyE4Ln6W3ESCjD +zr|Hyh?(>X|nz_yR6uP(5-VT<$5-?P?a8oyz_0+9g{|_8@`CN#UMrx4L;DV5O+|XrP}jEad(xY>BqsE%As+Jd@-tO7 +z&9GqX13N0Vk?DoM-O=LV=#c_ra4oUj?u1AF`2SF$|u%x;M7DCyA +z24pyJr{kIGsH7n+nngMIh^_L+tMcHn;zlO}=^cZUva17Lsym|#9UT;L7MMlHTSxF0F@wFlOT158% +z4(xASCY+wr4!<{F8sAGr9*mxm67)eXZn_}B&cV_FZYA)R5G0cW +zRFev3Mw)z>+@dgbaM&qg87@YB`=wVua|*;uC09Qx>;hQ2TAfie;BgzokT|L +z19KI!JO5=;Ty0!P9GE^YFYn0-Rl(l~>xbW83HX5Z7R*oO!%4F6Iw-VsXOB)>`m_HjX*roX-Jeo;Fd>u<-5tEQE>d0dd)v&A;zX?S?{o8Uv5A|!tg)YYL;X~xQc^X +zciMuncyPIIMfSNrgTEmM?+^rnY?8(43}mUNI$d>UGbdL3 +zmp!3^o>;n_Q$A{7*YqKLMa16s9h^kL-%(RVRk*_Je~$c-#Xide?5M}?VxDugv$@Fl +zOKTc)>85QTZu5DZJTw|agL|dEMcM`hg@_Ys&{ja*xN0CDu67X4@h>C}PnS(7P7Fcs +z=Yh&$F3P6?rm>N7`SEUFo$NDR?Lml8Cw0lM8|+T32;d0kaP{yfAC9St{`v_A<|r$W +z38WL|NB?R&1-!4Yw|v6yyULw`{$P +zmZiumFoa?_Wqi8S!3JU<26*PPIqo$5O>5qQ2dOR`xZGc?T5FYAhC+n%cHPHwhb%IO +zwT^F>_JoLoo@FdN?v+%%ajPknG!y?7xmW-}WOsP`9!h6FtjlkxPqRDsP=YZZyYjYq +zB9X9^9x$n*urKvpJHabDTtBs&ZUVktnMOH)4{UvsDdRnluV}$9+<$gMky|wu_vfmg +z#0hmWWCe&uo+a8j!5S9e9&b>&4)R|-M4i`SP=y*cehvwP`Vi!;k)5sB

Ef{jFr# +zk+?o6H;FiZoltDn1M$Rmug)N@%1FJFJUHcigK3dT@HgQML#FiRm?0x=^PQPnAD5sl +zlO|ADVlTJ=^s-KW_!O3*dU`y-CNC~67Xe$phQ<7Zi287=@qVv>-VRxRfrp98qf&7!P+md0si_s9N^Wxy62Y&-`495pw*X- +zv>+^!N?|U{!`qa|xIT7*{_1_M<8p05q`d=>Wx>-gc-!W5PusTb?rGb$ZB5&@ZQHhO +zo71+r{eK&~@!rO_@nXL{5p|+&Mck~cbMoG-%=}g6y6qhQUleD>*>gp3DQ-fi!YN5>*3I(T2}0p8ZopAu*mQaw|QC?NP)LYLqPcJQgb +zc~%dt1qbxJ&sFj4z&7MS98A~v7lilV-4j=+$=>5 +z;2d29$;sc<*SFZ!*fVHKH7g)wVCB}rzv6tN}lF?Dk%gC#9F>?`%J60G5i +z9hyQ?5NW)b$~|S+#d!r9DF+Vgerru=gGdHV=~DJ!!uldXR){M1ek#CoVEnFiMZ<}L +zeNL~-dS+u&j&O_C=i1{Vw8hP$-bMz*5kWL?D}vw#OFejZ{yHx8**Q3WG6p^38UHKV +zM6P1XmUC+RJv|umE7l&_AEWDEUIINEp1X>1hg4+VlS1n}y-gIVOdv*E@7tz8XtfH| +zaXz?RbtorZ#d?LrgDZ__7wYe)-S4BM<(nfuoAE2kqM47G^l*Rqobo~H(<4ZF#mZ+l +znqx7a6uIjVU(dU~;(gN7aYPHr7vfgLwX{x3eYj&k`7aU+?F3*0sJn(Jei^Ig^eqy{o6N-qOcz0v9>r#YGU+}J4}Y}JwT2k&ah|{ +zR*}u}X;w%USgzH;x#bA~VtSQyRb)sL_h?M(34_cgX}v+7AY6GX1%%-TH^~MEnXylr +z^AD2PxY3?*2_rzW@)GE?bPFM=z2aGfK=T<2H(2?)DY}-NYePW#pUlM>GrWuxSvpa-74yxa?eM)^ +zp6EVT%lqBSV7LeN9cv@EoCm@jtZ4@MI#*%P{t@^dBSSaTBZ(Cg-TM+re%{_4i=`kX +zlZm(s^^0WtM!Hi_=Wc;3*IGYg%~3jM3`cQ;i+w@H7}_^z5Vlev8K +zWeS|V&dQRN0o}sEO?+@mhXl0iWZkzD6Oq-ijzA#?HoctdNZ9C&oW{*-?1EQF#pfn+L +zg&(5E-pAKW)$Uz}VG8#};n2#WIRiGli%YRQdph(GNv-v|Ho3k`zk+w9f(W?yi6l$* +z=91D!Br}n~+*Lq25N!&DK4pzC_Wn(x|4x_YSuELn1Ra!>KjJEOouV_8%Yu4V?iS;t +z4yX+{!-pqj$1|q#;d#ekwuI?ZI~go$F0Jyi(u{)h+WE5+&=&|(#}&K#2mKhuzIz$Q +zknSexwvCdwp3kz)BwJ~Gf9j$K{tw4u+?JK4@`__RTQ6*k(JzFjdQ2aLeQq=+ObgZW +z#aF-J=jv#|H`u`}Zgc(txx7zHjl@Zq*Tq$OHl)Sc=49ts#nr;@Yr@N#kE{F5Sh4<6 +zqTm@_AFhp{Y`+ogDF%}?UF`>hXV02j*HQCW{r +zq2JC_+Id+BK$OYp96fE7U0EAL@Y?9|Wt!if1asjAIQlw%(PK?a=9fzz4Bx_UXu*>8 +zKY3Pg*H{~^Vj{QynfS5aL3wa*A=S0upAjl>%>VL!&e5&Q*{g;vU?OiR(>GJu*fpEV +z;Hu>qe?eMdDd=V3o^2*zRsNkxj2s9@4*%HG2BU>a%C+g&-rA5z@J{zhaqAlQbC}ld +z1x$u}5fTdQ0dNP=2W$BI3P=?j1YNDRSR$ws+Dh03Res$dW4qgI2=d2=D+b;2pdELE +z)cZlytz>*g*k&(CCyTckv|p$djc<*n_4fp@hO;$ms|B4oi>a +zP|NY4vs4l^r}+~Tl0tH(54`74eMj?D^o~R1iBsB5-eQy$Wm;3iXOSlE`6pc!X*b{L)n}Wm}?ngtXkmHd8bQzeU-( +z%6NG(-Gf=)DsTQF&!I%!jZ`UR8PKrQYb +z!1%SUYTm}L1e)$azdhjSEC@cBkni(g@+<8RDuuwGiNVg1GL=>C^++Zil(y!hFJpTg +z(iX-;MA?Fpk*9<$HZGpkY&vDEg(l5D5Noy>->4)Lo`a%(Lbr}}s$oGz6Tt+sGPzRV +zDqf|x#%2}uPnYk>W)fa(tA;h;Z+q8uj)eog9|(DghD}@U;;FxPD7{S(=#?}sOQl;x +zZWO1Q)^a?V&g%@3HV1oru%K?l$k(8RkQ~v|SmtA@l!1#;WJ%%hui(&O5&C|%L)!EE +zkg6m}{iP&pnja~rU4b)O8P0fPfC>t{05iwnqL-V?-cL*{^eTS8t8Z+4@N8nL1qzpS +z&L|8kGS^z78_sU$T%NzRqb7gPVXJ6`!)1m80;k=3stGQi6V*~V07viGnkW)t%h#t- +ze~dOr*fyQuYPC}nR2LE>3He^Df7gg@Ye}5xOmLtjVJZXS!1x>e*SmC8vxHeN)^}}V +zl#XEWG%Uo)S;RFsYmSc`w+dMid2M_+k$1{Q^X02|{0w{)^aIJVqAxD5OE>5O;6BuO +z2>NQoh4xL&LkxBzv_nKQuKHHVs8!7C06b+A=JMP_abEfn5x2uFS#z-^pa{=;KtTrj +zqIEz~5P?#>a6N}kFGGL07GbULQPkJAIL{2E +z@`N^1IMp1h+i>LwF;=vr}+CyqlU$iu4oBne73q>1h90%je5L&81)9v$wdPGk^1vxk_g +z(R@h4Bx6y}L4mDngd?^1)(Ygquh{C1TVkRMu!!2#M0%M9CC#ETOWB`Han2U~zvwYM +zNdAr4Ux}o-araL{Df>dv2UH-3fNrvf^|^B8O1HZEi{AM>s-O0X8UBL#svacOX7P4K +zQ%5*>ph!iQ@&st_{G=x(QEry6%KNxa>7Xy1L?qo1xD#($EfGw`1qb>gGQ=~aC*iRz +zsb9BeTB?xr4OCYnxva3Nf+4|*p7MTWj9JERp$1y?(GdEtxed(x-OuT-x}m;OfZd_e +zS6>o>T1y**^e!Ca4nn9vT6> +zU=jd^RAiL74F{D3Z1m^PDLX}Q$PSFCu!@JC0dj)yfQNqw>+|=V)FMhGuclxlxNIZ+ +zU+Etvu$adD)}vAIZ=e~@nsSNaE0k_YnJ2wlpeYIN-q$pn)$p*AskbA3JDb`13m}e70Xbyf@#E +zQ{OQNAKwpi-?j)Jx;Pi#+&4bXwckBRl2}UXsT-&NP706tj^lo(pj99;Kz{fDHo}a)T=$mr+SeE%kTxn2TE|5A1uYR<}$xxY$kqREnU%14Vt%FEAhH0@NDhffjrX +zj<{pAM!MH?#oGqjoBGgIJGe_PTJ%4*D(s@*@Ee&146y4@*=btz7*J{T;V?AWWa+SL +z*4_6bxSiq@!M;Z0lD-^L{yTb!7w<3FC)T`#y-cMB9H4ZmIfz{dDzz}H&`8<1VQ*Uk +zptyzX0U1|Q5N2WE322I@r;4wLMGdLEPwp^?SVGkY04oJpUDWow988dkIM2nKy~{8> +zAm>P}Kfbu)X(K;ZdwRSS`<5-3{y +zJ38F3z0%%5#WIS7szl9tWaB*W%0-&5tQZR*HgD3vY=)M3^9_$L5{^ +z>ivbGj6znvi~fnabKna#I&;67{DMeIA;P!Ar+g +z+Uy(~h_N31?oR+NhaV}s0u?4I7kc#%q&++f-!xre)+?cf9 +zT1*G`{_t}yntSR6X{2jQsL{yYF|g(ZA(u6nL77GG4r*1^g=_Jb1{7+m;2#zkL!!kn +zFDLK$zpuDH2|!rlwTlirl-tvdzP0m`qcU24FF1_ICR5$A)O#h)Mz;606)JfT^0cJR +z{?N6!3n#Xn$Lw#%1Poz|MyF0$LJ#0STVH1ff0fiAR8dMgRzdinZOQW>p;0}2*oDUg +zKZQD7W4*LcMM*aMsr+7CK|MtZCHc2e8)3@#45`z#xDv+hMksWTX~KTpyI +zE`4tb#g*tcnQ_6F48W)6F!o!u{WO@u&8)Z)7RD +zhO3L%6GsNQRgKko-=;p`>qhind(LP~qLZdOYNneR&yjx-8Jx<`wXYhcxMv_BiQp=TJKtV(|v@tT3$ +zpJ{G8U}aZ%ARH?XX->8eUGabEs@=a@g}yHY88-iIJ)_K7&pw66;V0$0C?>TBAF^SA +zvA66ckFfzk+JxMRei`}v8akLIe(!vW%v~v(oNov&a=ySmf*7hyeMWw6_GtQvs +zbkf==FhX;isf5X`OHtJP716{4&i|-2Jtubxo=Z;I>-mHxUDIZ79-5^EK~qO4f=(?y +z0@sWZL!rXtS=FbQ=h!(H*+h0du!o4dzr+R(r#BeCt9&!?t}IY^a^;M(Mm6!xmeFbM +z!n{&m?U9A(9?ywV|m +zu@P}LEZxdBH9EasG|@05_+~A<(m@@)<}OJ +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 +z{xQFm(Fr5F(U$6rhZ- +zO)$nNJyRngJvT=FysW0NlY%9=MC+e{T~rFuM36V8M}NGS-?i*TkIbRf(N(B%kM@$Q +zVjEj9ToIw2)J+U2s$9LBbl8P*M<0JQbbQU3 +zVhKVd(%6ot4-Z1uNzmdRmt9r-W1@s`WTqBQT##O)xU4ln+6FN}o)Ueqm5 +zJ?IzmOq$u8iut6s$F@ZH&3|pf0mEDKyQTx59W;v>apa{(BzxX+Tqh*j7y*_8!7SEp +zSyIz6t9Li1lU4#6Vq}h$YL9obhHQw_B1bqQjny(@ziqYfZk8{e==vwhy|yMHr6UHnZB0jZG}<4=sOP5$G*=y=lI;C`t>IaP;$j +zaE0+`YQ}VzJB+SvmrS&xOXW0gl4Y#z&Y2&S(9A5G;-mz4Odvf4d03KX1N{ziM^zg~ +zYu3X@{^RCXK>39|Qviu3p*}Wl{vB{vSE-<$J-M{&^ZhBy#FO_+KfV(V=7Z2y%Ch`M +zcBRm;xjAWx-m|doWJH;pG)ipJQR-a+7}LvPT;e_4N(Vd_m_GOwb;Ni_!ebX8+e;w3 +z)^vt0D;8{tn2jrVVg>2vaDH=$$T%GudryqSI1`Mx7)cfu>&zNBn=m-Si^nUwD8pqc +zH0qY`vd%*!D7zrjaB#>ZV8lx+M5Cly_f*RwUtNx#ptr=WgkfK!drLz+5kbY4U~Dy= +z-Iv>~sLmqV&)pQAGOQ!>9Lb$mUH(qK<4wFRNTS}$I5+?xf1oqM3-!Li1AnJq3z6Z| +zdJ2%Q`>S$R3moCK`VjDGjL?ZxV*rP538hXo+8)?xYbaM`9zSOu7V-9L7!;>fALH->p_S##_WpR?{rzc*>wcNJ +z((+kEGT}7$EMKkY!i>*|Yp|U&1Lchr~Hp +z;#E4aW*Eu}R7yn$Y%v$?Qk+T>y?v{yu3_jKuaMmlf)cZA)mRMlRU?ZdX41lhGL|%T*T!UGG-@PJlu(W_c8}%uj`EG(lmiBxqF~91f9J3p3 +z#em*rElH*a0w-6d<3k{7IL=Afivy2=jpkZ?q+R=3CZpPpG&T-{6BK$i&0{z-Kp3Zi +zCAb4I34<)79e8c;RFz>zuya9=;|`Az$TKI2-{3sRVOI(qCw%EW%opaZiI$ql8AhMVz3cjK#LW%b{rYEwS_u2PRqUR4>JE?gPhf7+>T +zXY-cFP}@!{ep?vk*Ufm^GRZfd!XKdGciM68Ca-m`d6U;_W-KIE2Dx<|Ey;|Wb#@ka)?ciD2 +zu?)-jvxOKKthMC%w${-P%qhw$o5FK>a@DV>V;@1k+;j1w$a^A3q`x;R)?{sUIAiOe_%$wB`I-kw0%gkS`_TS +z$v@TUMbW~e$=}*haDdJS4ckUgaalCuc6qhPR$CDu5C+@{*M8?*SK{9-Zo(9dN|=3MFv5XsIA6MKyc*^3igg|Bfp>grz*wwu+(>ODV8p) +zhr8gCdt#h>o!drT_!WG`6J15VTe5MwiH|*&`BlyNmPGow@9b>Oy!{gTT+GvflgjFS +zdT*46$4XwUfpOSWZj~2)ne3h##{MCHV~dTrYiVUZ@?T*$#aM)RE4RhM&h)s?X--HQ +zKN`Ebh}=wI%okD6A_ +zC|(@sKpuopq_f4O;td4?q9`WBC8zTiMvYJnOO%s(DfAm5L2HG@()PIpGg8{RrNP2S +ztIMuq3^d?MsWYF`V`<1v#^7UXzoriSK(&*`leRNonU>oK4=kt@nPd*BwCbpjhT-A2`c3R +zj2sErN@FXE^&L$vk{$Rt_$g?I{G*+`CsvVfDnwTx>Tly!YSu~|cBCT09rc)y>PqREo +zHn&ExxJb3M%_z#xA~4A;BhV}@!!sz2+)V*!Zyz0TKdEc=9)id|Px${uB_t|jd+h*(Q +zZ{I)nl{34|j~*$kCIyNPJ-Prd_ew*laar_n6~a|hlu1jPO9ki)JLnS^$`vOOUvEEO +z@7S;a&*U)AjcD|xM6#V?^s5-~t4Ox9GMJYJwuN}HiD>KX0@uedg_9_|p9}~ub2{On +zVWANT;jv-i@u~3

fekDe)1hsi~nUMJbsD$vL$_-KlALSz&oKA!SV&dBy1^4M{C+ +z1*sAFnQ6J%dBypeo#mM&r6t7`4VCpR4OJzzHFYiZ6|JqUk#RSE6~m$R6Co`NneF{S +zU03BT1C`yg&7J*CEq77<>A`&!;e)M-!=-71Z9RS6K?A+P!^`pGGf88sLBq$1(PfR?m9&Zg(<#duwubN~8N5iu*fT +z537Cm%47R`dWZTt)`n|VC)!Vj8lMk>-~LsNjEoFT&X3P6&rgo5%ujA?Y>ciPFK-^K +zZaoiPKWyy(Tf2TbT%I`GT>7`a@o=#6{l0N|d3kzqe|rD?czOKxaQ5}}m3cPf0RW(7 +zi~kW&a$CRDhI1ks@(OuQZ)7Hj8BrCRu*`sH>lK&>$1SArg7_56eRyHVC!QtEq-*sf +z;@={L^IDlbU?*GYz(z}dkc_6L=8$OlpbM6VSWUWs;yVlsVl4Kv@g#=d)q^(4T++MnAwb*Z32~dvrAD +zaONnMN+n}=l{Da@HF1)Zsc{qlA%I@e1{I}95C_B7n_dqX +z<=!1%-eg~*DUiPZw}3K+`e;4QK4R*LB7t?65MMkFJUqhJrf{+kW)j4T$4+r=AlV$< +zQ}!c>Z`a*kz)N8pFk`5*|6{fiWr9S}Q(<>jy88^)bUwA#6}|b4zs(=`e!M_p^k*(Igke&7SX_f +zOIj_==S&LJO7&U)hVweL?jhNnt#8MP7!3$rN7;J`M2?3z(4wkA(pvP-P+ft7p(`+; +z>+W6n+xE$_0sJP3Mmh +zRoPZbX>`e!v~q>LX%But({=mk2pJEAX~hBRy{PYAgp1LF(m|S%xy)k +zDESXaB0?4pINK|bn7yIJJ%UViJ#>}ecE1i&AuuGKauM4Fvdd_}+g%o+;d;LuXV`Ya +zw{_#jllc9x>X`E}%A||k{emO+0`fDt%I46BtAxr950xKwS6cq{rjctA2>IXY +zOMJKI5x$Q}9-<9eUY(oDAtb@(36udt*R1a}50PM7j_MQ32zYD)Roeq#4sspEwiJI; +zX`uz?*riq_hoj6yAgv}w^WqEKuR%I*dn31V(H$r+rvljA_3eCUJc4uEo|`-_k#2gY +zi5N%YximbzQW&IO^5Q;+uI};2_A(~ObnfRu*c)0x1L$HKc3SWrEmy41*cGew>?Q8P5H^>(U1b-1%ManUa +zbb)ng0E@A8=J+qb4R#bPj@pCyY}p^{3PnZi5=-!yWyPk=YobP{UcJLQ*$9m2& +zk-yA^C|hC8EEYrf2L&KE=1u`s4YsZu__qYsS8BJ^c#fcOY7khZWDRvVwq0^|@fhw` +zekm|1RXkETomKheoI>7eMmj6qtG=8n?5;~@8Q@F{pO2b2H9!wS#TR1Yw__R$T>i1| +zq&5biGKe-p)>S>Iy|`4N5##4S<3$D+)rM>ols!{354Bc!d$hll0`s66{Q?H0|Erv- +zxLAgQebJw|4j%Co)T$mZ`;g@^O(S{&n1C3b$LE1+CWbI16}A@ycgw%3mkg?dujfZQ +zF(#g5nhA?lOI$we_$OdC^T<%(0Fj8_`9nP*y9my +z=KpEI31cJTk_-X&o<##uy9;!&J{c0|qBpem +z$B;g>-+{Q5bjcnUH?t7zgJ+Rk=4v1zsYL?m$oSqk?K1A!m3aHE{CJX`rlTWaVv{qu +z(ZJ$zNvH^cRWwtA$Uxij;57x>^?b2RhP2}z&}@Zy`t>XVUkAjx3 +zXinhlFuUYYqQMaPdPJ{U@vTOMlPgHs>ezpf$-!!WRBTi&Mq!bw{AycpvwB2~DC73WN +zQ>h90Z6$vpBayITAwB0;xIS4bxVQy^KsyBbX8h}+8FEEgf +zJ7=i5y%E?~1BmsI74;Pt`A>k~j((zkR@k@_u~5(@Dp2mWjs^%YhW +zFQp19sCZqm89lmREXx^W>3HHlLHEYTQri=iDq1n|VF3d})&w +zZ4OIk=qv&R&MF?xF7wdgS4&5sBvr2$#tQN8!uIKMLq*+E5a2=mpme?lnOlYjdc2hw +zPXI#58psb^*c<&{JZ*sh>ozx)xH$#MRJ3@)YuG8pn`EMH(;@^m?KV|ZNzv_OFar%6 +zgATHv`42yx=^+d%PiI69OrueOCu11=cFM}*Oklab=ECDM%8vEaR+UTKj7n4gNc}*S +zVrlj;Vsq{@3%rek21c{WETb@}k;g)vvwjiF2NB-k{)WaOAj1xiOssJ5Dtn%ShRm5V +z0>ZG3-U*_u;?JG6i-o?SmS)CmELa-|#X?*_lCS{#KT10jc&OGsj-Qz^cGD9a>?I~^gi-c&X6TkZiLA+9Swf;@S4k<7BKxRhUy`kC@3`IfM$3J#`yL<8 +zna_vs@Bch=p2z=u{>xNN+dR((4DcRl96IMDcI~SWBFCKadc+*k6x??5?oGJ_v>xZ= +ztw!pBwO0IUu?RISiG3bqs6W5D;XMrv?w1oaW8_r2Atv%rp2*KcbD>4Y6sY=4N#-4x +zLetQS6XA8z`Bm7^;ZnEdvwhK?M1fF5YgJFfxMo|Vfje9DxujQ9+%w&fecn?mN5oZx +zrDM_=XLN1RU0wYXa`GWRr;<3juK6aW_bnMdc*HhXuOF9L6%iJFa;=Rc< +z_egB#?yKbJ=#RFYV+=h8yd9Wnpl4mDy4}Qbbl3y{W##gn&w$!IoFW(kUQ_o5!s>w{ +z4b96dUjkdt=$i=<$D8sZoTRU?WvFxB7WR)=4IMvUWolq##j{4&-&Np|X9E;OI&qgJ +zXT(2rSRb$w;I1ZgMhjStKV!z7HBVO|a_RU4TBZK}@l&3_nzlpD!F>SkkYs+iv=sf! +zeDi67AI@XF(|h90M~ACRpsIkp!F2Aybn6f?>bkh28YV_s`4YJR&SS0~ +zV#E-zdZGCX=oT$>$axQq8=0oqD$tG?&rfvLrQQj~Tv~nFXj)q_zP7r&J|bn+MNpsH +z@$9M2Boq-sYLGw8`>GDjvw*YxZIIxx3!D^}dE?c2$6(NuBGy}oyRX7#J!G+hNo@k} +z>usA@*tJjH*V9Z8GJA5y;4*kx3KAOuJdJ9Wi!sK;|313Z(bAWdRXIf<*O~Tl7LQHZ +zkTiWwWF4^wB9uP55_n=PsCeUd8j}uE5%1MB3SEqz>YuM8K`M`d$c2qsCe<`RZ>rx9!NR!ClhY$FCzL=#AXnwd1T~-cMTb>~;@mH$dS$Ph +z2#Y#S)FDP*j+=qRL62dd_PE^!t;DmSKh!GV}WC +zw3_#a!`Iy3-!Z&j(*y^(!5ea~KalCUotaFfLRjNkFF`;i>Nvc*p|-^~C+0(B38UV> +z0qPhYvRD3a>?jfKNa+GEp`#aOpfq3YF1A!_wFaRFw8-UCOxC*rwj7K;n~@`RPGmV? +zeMz?r6BG3A8e!T!jS=xh2Hcm82|23T)8?SDvk&^yFsp2X&{{2$qBKslc9m#fCS0eU0u(#8j +zmDB{l3N&KY6LU!PLOgU%h_}Z`Lp(4a6Jh=+89C}D5fSvW{!j^UN1HG>ViYif-Q=0O +z9{t5m+)D)BcJess15c2>LE+$D +zL8e=9DI(_5vy}F;s21Dylb#G=GGOft4sw}rm1JQ!41KCg4AGIyaVi!h&dvAXZW$h$ +zJbTho`2ye7$5ji3K+12g7htQXA*3rbmjCn<`co3=wy)x{Q|xm@Q|_BO4Gp}3M25{B +zae!JTHQUbIbzh&)#?JJMYe=Y@Cvl!(Y36#6s3YWQLXP)v0o!LM3=5Yx<}f|7P%GV~ +za*WnyVfIET7%Om`K3T$$i)DAICeo@*cXzYWLk?0_3q6_>SXd#AG%aP0R}_j#0a-&U +zUhT6rl5z4!BO`Ph7P>MOH_;%r?tvOm?2na-EFLUBskkD^*!2a8#H%Q$dl +zY;7r|WUI@@ETH^A?6cum*dV-L1NG`QqxX> +z?Aj&S!|JP7wWws1c7)nN1p{plHoT)D%w?MsjJn;=?ui#lp*;Ox&z)V&JQq>E&`rP8 +z&VFO0wR&#Oka=Kkl&?qwMM6^~hQv!mhZiC{2l8qQuB93;>>mTc(qb1n{FyZ5q{vkH +z{wYJ#>dQA7)(6uj9aL}Is)=6VAP!oSoac8A+%ucwnvHwz6so}vS;-ON+iM5-O;lVg +zeqAl=N5f|LC+$tA^6eKc+ +zQa%OV28qUHaJY>Hu+HqeOE_g~yIih6Egcq~ajOt;w%miSFX7!y%q)8uaESeES1OOs +z@Jyi)Uw^r0`zZ2=%Ilgva(f`5JzmRfSVn&&I=w7#uc5B9Bv)?(CrEudbFsQ};LC4o +zPrF@sUf45pmDCVRd3P6+!M=KYrLU{;+`PQqKK+gIJH+~JbE|jIe#q>c7Z)N_(I!Yd +zv~XlSmXgPLPTfciDqy +zV0;gdZg#%ufNKtCDfoqJv6!Ra^7X@O4W+NzeAZvqW34cC)8Z~!8LcUv9f52uykm5b +zs-dthSCNsDO0|`q)+k28+>!=UK@BbCV_Rf~nm9p=E0m&QsOZ~qpy%Vlk@}9S-l>Ge +zrlxZJ#|f)qyc6{-Bp66DxU2sVvnP=M&LN1pDsZ`o5U{TYi+_@tlkFv8I)$jyY)WL>Cmt&`6oKNAwl=9rgfh +zR7%owM>(C$Q9)&eM3)lPXlcAG%g4xdvk9c@+<8#>-C?!@@B74nb#!{CwmHzQ>QTs4Jl3w_~xT)}hHG<*INb}fZaNtRz2)0|tBT3=zFdeJX4MyRJ+{P1C +z9cWxzYWno4eb4hdW0B(E$yGpGsay2^qp~QPI@U1;NU-nc7;hoWZP?>;9ONwLyt_pu +z8S!0D3#kv(R4lhSKv#T|oJ%kH#(-ZtnHxVcs6Xa@?g}?g?5=@MC5KmU8ZPL?XWl|e +z)p^z`D*C5QDjbz}N`{4OuvCcniT$m>4aa2lIczi&W$BlGGNvcGa=T&1Ak-c7S}*)#XF%Kw1&a1h83ctIXk$UAa6%3Eg2fm`;E~v +z%K?)+DmzVZZXmbr*UgoxogfGUV6Fs*pW)~@LZ@+O*1#yEV#y37-1{I2KQnHwLMYy^m&0Of)P_rnD_asQf7hfuJt%)GJMMhxo!<`DXpCN6j*X!bSHbE9R%tH@dHnkckA`?uBx*+7;(eqGE&)KtY=P) +zr_*ZCuAVo3{pyp)Br%W5P|eozX_vo<=og|6ygDL-h`lq!%X9vITJvoit>zpQVOm?h +zUAvr(Y(D)$|M6jlTX}6@BhL`&n>^mN>>mwV;}do7piUUmHMY^8wC`4T*(+m|IoNZi +zQpJkONUPo1-zoa$ki~0HI4L36^?AkcP0Vr)t25{Os;4j0REs+cd&)9bkHB1%?~W{q +zCGza-jAm$Tg}4KINqVA}_|AdCJ~2L!R??_UnCG~ZnS=Ds{URU=FkTtq0%(GwnMENn +zxW((DKA8R5BOe5*Fx;#otRoj#wAIBD?g1lbP~0HRJr+_Tj@cn7c4^IrYcV0c0{-sQs|BT#w}ey9j3^m?-b22^ +z=jUzU(!x|*+fj8n{ss+_S#?r54&FZlpNxAzos*m7ef5*Sg;i>UU(97He-?$~BE48O +zLF6^XPXy{3{tF8ivoqVG&97LkntHdW<3Fx3{TWcD+%1umB;bv^=D){A67Z&g>K`#w +zaY_R4uhY^gfB8Lxg#!6Lm;T?8ewOIHIV=C)QMrC%-=8Ve{|-n;0U9{kcz9A0(7$G1 +zZ+p%*5PvPozqbMe7Nk5${I`hV8f5Q7DaxC$@l8t!h;JMl!R&0(#+8dBrFP!e&Cb{e +z`n4_0cbVJH3Ql}4J*)dGX*rD2AKD1GmK*|xQBcGpxr#ucS9kI8qa(ghp#&kXR%_0i~?D9qF`BL}oWF0I;T{KWu%krJwvt +zdef*8a0R#~R!LDAp`Z!FC}XxG%}{SM1<|1-SseIYnt=)Q4{kH0mI6#(5v8Dsz{o3V +zqP8RbMEPi^IFSm#hf#eu>OkXPNpBjpB1{R3l0#|AD=W*(Q|5d-(p&pBZCJ;b+cCdbF2Km3Q- +zysvMmw%WcJ?_Xjpz$B{bCt{l`ul`>?%fyd^*<6LSeLnXV`)z;1|5lOp|I*8ULjP8s +zwS7AO7Takjf1I1Gm0H_Z*g89wKT-HrwY7cv)_bS;C-lt~T-)ahZJ8gcsUPR(hib0B +z6Zusw*XGrGf+Dh|vWo)zNmbWZU*OyF-I{3k6}YjSvq`M0(9K@rcWHP3+uR?YNH&{` +z<);4T3T=Hp`8zblaLVz$FUqiGx~+MsHyi$kSG3`({nRV^Ign)w@Hz$fqpM3XbDPwy +ztLEcRsGGOPe`7b-7Q40iezf~97kK;T(`|t#Qs95NivPyet+*ZvZj)>LE9;6aL^a2v(-+1{S^S;vm + +literal 0 +HcmV?d00001 + +diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx +index 38578766934d..655673113541 100644 +--- a/sd/qa/unit/export-tests.cxx ++++ b/sd/qa/unit/export-tests.cxx +@@ -71,6 +71,7 @@ public: + void testTdf123557(); + void testTdf113822(); + void testTdf126761(); ++ void testRhbz1870501(); + + CPPUNIT_TEST_SUITE(SdExportTest); + +@@ -103,6 +104,7 @@ public: + CPPUNIT_TEST(testTdf123557); + CPPUNIT_TEST(testTdf113822); + CPPUNIT_TEST(testTdf126761); ++ CPPUNIT_TEST(testRhbz1870501); + + CPPUNIT_TEST_SUITE_END(); + +@@ -1213,6 +1215,13 @@ void SdExportTest::testTdf126761() + xDocShRef->DoClose(); + } + ++void SdExportTest::testRhbz1870501() ++{ ++ //Without the fix in place, it would crash at export time ++ ::sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc("/sd/qa/unit/data/odg/rhbz1870501.odg"), ODG); ++ xDocShRef = saveAndReload( xDocShRef.get(), ODG ); ++} ++ + CPPUNIT_TEST_SUITE_REGISTRATION(SdExportTest); + + CPPUNIT_PLUGIN_IMPLEMENT(); +diff --git a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx +index 82159e0175fc..d488fb196bab 100644 +--- a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx ++++ b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx +@@ -18,6 +18,7 @@ + */ + + #include ++#include + + using namespace ::com::sun::star; + using css::uno::Reference; +@@ -61,25 +62,41 @@ bool UnoInterfaceToUniqueIdentifierMapper::registerReference( const OUString& rI + { + return rIdentifier != (*aIter).first; + } +- else if( findIdentifier( rIdentifier, aIter ) ) ++ else if( findIdentifier( rIdentifier, aIter ) || findReserved( rIdentifier ) ) + { + return false; + } + else + { +- insertReference( rIdentifier, xRef ); ++ maEntries.insert( IdMap_t::value_type( rIdentifier, xRef ) ); ++ ++ // see if this is a reference like something we would generate in the future ++ const sal_Unicode *p = rIdentifier.getStr(); ++ sal_Int32 nLength = rIdentifier.getLength(); ++ ++ // see if the identifier is 'id' followed by a pure integer value ++ if( nLength < 2 || p[0] != 'i' || p[1] != 'd' ) ++ return true; ++ ++ nLength -= 2; ++ p += 2; ++ ++ while(nLength--) ++ { ++ if( (*p < '0') || (*p > '9') ) ++ return true; // a custom id, that will never conflict with genereated id's ++ p++; ++ } ++ ++ // the identifier is a pure integer value ++ // so we make sure we will never generate ++ // an integer value like this one ++ sal_Int32 nId = rIdentifier.copy(2).toInt32(); ++ if (nId > 0 && mnNextId <= static_cast(nId)) ++ mnNextId = nId + 1; ++ ++ return true; + } +- +- return true; +-} +- +-void UnoInterfaceToUniqueIdentifierMapper::registerReferenceAlways( const OUString& rIdentifier, const Reference< XInterface >& rInterface ) +-{ +- // Be certain that the references we store in our table are to the +- // leading / primary XInterface - cf. findReference +- uno::Reference< uno::XInterface > xRef( rInterface, uno::UNO_QUERY ); +- +- insertReference( rIdentifier, xRef ); + } + + const OUString& UnoInterfaceToUniqueIdentifierMapper::getIdentifier( const Reference< XInterface >& rInterface ) const +@@ -132,38 +149,42 @@ bool UnoInterfaceToUniqueIdentifierMapper::findIdentifier( const OUString& rIden + return rIter != maEntries.end(); + } + +-void UnoInterfaceToUniqueIdentifierMapper::insertReference( const OUString& rIdentifier, const Reference< XInterface >& rInterface ) ++bool UnoInterfaceToUniqueIdentifierMapper::reserveIdentifier( const OUString& rIdentifier ) + { +- maEntries[rIdentifier] = rInterface; ++ if ( findReserved( rIdentifier ) ) ++ return false; + +- // see if this is a reference like something we would generate in the future +- const sal_Unicode *p = rIdentifier.getStr(); +- sal_Int32 nLength = rIdentifier.getLength(); ++ maReserved.push_back( rIdentifier ); ++ return true; ++} + +- // see if the identifier is 'id' followed by a pure integer value +- if( nLength < 2 || p[0] != 'i' || p[1] != 'd' ) +- return; ++bool UnoInterfaceToUniqueIdentifierMapper::registerReservedReference( ++ const OUString& rIdentifier, ++ const css::uno::Reference< css::uno::XInterface >& rInterface ) ++{ ++ Reserved_t::const_iterator aIt; ++ if ( !findReserved( rIdentifier, aIt ) ) ++ return false; + +- nLength -= 2; +- p += 2; ++ Reserved_t::iterator aRemoveIt( maReserved.begin() + ( aIt - maReserved.begin() ) ); ++ maReserved.erase( aRemoveIt ); ++ registerReference( rIdentifier, rInterface ); + +- while(nLength--) +- { +- if( (*p < '0') || (*p > '9') ) +- return; // a custom id, that will never conflict with generated id's ++ return true; ++} + +- p++; +- } ++bool UnoInterfaceToUniqueIdentifierMapper::findReserved( const OUString& rIdentifier ) const ++{ ++ Reserved_t::const_iterator aDummy; ++ return findReserved( rIdentifier, aDummy ); ++} + +- // the identifier is a pure integer value +- // so we make sure we will never generate +- // an integer value like this one +- sal_Int32 nId = rIdentifier.copy(2).toInt32(); +- if (nId > 0 && mnNextId <= static_cast(nId)) +- { +- mnNextId = nId; +- ++mnNextId; +- } ++bool UnoInterfaceToUniqueIdentifierMapper::findReserved( ++ const OUString& rIdentifier, ++ Reserved_t::const_iterator& rIter ) const ++{ ++ rIter = std::find( maReserved.begin(), maReserved.end(), rIdentifier ); ++ return rIter != maReserved.end(); + } + + } +diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx +index 8bee4b376ba1..2e509f8f91ea 100644 +--- a/xmloff/source/draw/ximpshap.cxx ++++ b/xmloff/source/draw/ximpshap.cxx +@@ -3440,6 +3440,9 @@ SvXMLImportContextRef SdXMLFrameShapeContext::CreateChildContext( sal_uInt16 nPr + + if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get())) + { ++ if ( !maShapeId.isEmpty() ) ++ GetImport().getInterfaceToIdentifierMapper().reserveIdentifier( maShapeId ); ++ + addContent(*mxImplContext); + } + } +@@ -3552,13 +3555,11 @@ void SdXMLFrameShapeContext::EndElement() + SvXMLImportContextRef const pSelectedContext(solveMultipleImages()); + const SdXMLGraphicObjectShapeContext* pShapeContext( + dynamic_cast(pSelectedContext.get())); +- if ( pShapeContext && !maShapeId.isEmpty() ) ++ if ( pShapeContext ) + { +- // fdo#64512 and fdo#60075 - make sure *this* shape is +- // registered for given ID + assert( mxImplContext.is() ); + const uno::Reference< uno::XInterface > xShape( pShapeContext->getShape() ); +- GetImport().getInterfaceToIdentifierMapper().registerReferenceAlways( maShapeId, xShape ); ++ GetImport().getInterfaceToIdentifierMapper().registerReservedReference( maShapeId, xShape ); + } + + if( !mxImplContext.is() ) +-- +2.26.2 + diff --git a/SOURCES/0001-rhbz-1882616-move-cursor-one-step-at-a-time-in-the-d.patch b/SOURCES/0001-rhbz-1882616-move-cursor-one-step-at-a-time-in-the-d.patch new file mode 100644 index 0000000..016e653 --- /dev/null +++ b/SOURCES/0001-rhbz-1882616-move-cursor-one-step-at-a-time-in-the-d.patch @@ -0,0 +1,82 @@ +From 8bfdd84ffcffe19aa6c495a0772e1a5fcb9a5124 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 25 Sep 2020 11:22:03 +0100 +Subject: [PATCH] rhbz#1882616 move cursor one step at a time in the desired + direction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +until we get to the target position. The break iterator operates in graphemes +so we can't just move Left/Right the amount of utf-16 we want to move. + +Change-Id: I25d4e9285deae374f85dcaadbf4601bc213a89de +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103380 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit bf858622e543163a23db766912ea6b121f447e6d) +--- + sw/source/core/edit/editsh.cxx | 40 +++++++++++++++++++++++++++++----- + 1 file changed, 35 insertions(+), 5 deletions(-) + +diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx +index 8f84ce42ed75..872d92d7afcc 100644 +--- a/sw/source/core/edit/editsh.cxx ++++ b/sw/source/core/edit/editsh.cxx +@@ -988,7 +988,8 @@ OUString SwEditShell::DeleteExtTextInput( bool bInsText ) + + void SwEditShell::SetExtTextInputData( const CommandExtTextInputData& rData ) + { +- const SwPosition& rPos = *GetCursor()->GetPoint(); ++ SwPaM* pCurrentCursor = GetCursor(); ++ const SwPosition& rPos = *pCurrentCursor->GetPoint(); + SwExtTextInput* pInput = GetDoc()->GetExtTextInput( rPos.nNode.GetNode() ); + if( !pInput ) + return; +@@ -1005,10 +1006,39 @@ void SwEditShell::SetExtTextInputData( const CommandExtTextInputData& rData ) + // ugly but works + ShowCursor(); + const sal_Int32 nDiff = nNewCursorPos - rPos.nContent.GetIndex(); +- if( 0 > nDiff ) +- Left( -nDiff, CRSR_SKIP_CHARS ); +- else if( 0 < nDiff ) +- Right( nDiff, CRSR_SKIP_CHARS ); ++ if( nDiff != 0) ++ { ++ bool bLeft = nDiff < 0; ++ sal_Int32 nMaxGuard = std::abs(nDiff); ++ while (true) ++ { ++ auto nOldPos = pCurrentCursor->GetPoint()->nContent.GetIndex(); ++ if (bLeft) ++ Left(1, CRSR_SKIP_CHARS); ++ else ++ Right(1, CRSR_SKIP_CHARS); ++ auto nNewPos = pCurrentCursor->GetPoint()->nContent.GetIndex(); ++ ++ // expected success ++ if (nNewPos == nNewCursorPos) ++ break; ++ ++ if (nNewPos == nOldPos) ++ { ++ // if there was no movement, we have failed for some reason ++ SAL_WARN("sw.core", "IM cursor move failed"); ++ break; ++ } ++ ++ if (--nMaxGuard == 0) ++ { ++ // if it takes more cursor moves than there are utf-16 chars to move past ++ // something has probably gone wrong ++ SAL_WARN("sw.core", "IM abandoning cursor positioning"); ++ break; ++ } ++ } ++ } + + SetOverwriteCursor( rData.IsCursorOverwrite() ); + +-- +2.29.2 + diff --git a/SOURCES/0001-rhbz-1891326-suggest-package-install-of-the-most-app.patch b/SOURCES/0001-rhbz-1891326-suggest-package-install-of-the-most-app.patch new file mode 100644 index 0000000..88abe70 --- /dev/null +++ b/SOURCES/0001-rhbz-1891326-suggest-package-install-of-the-most-app.patch @@ -0,0 +1,27 @@ +From 3f4885f3012132e915031461036a76e693489652 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Sun, 25 Oct 2020 20:39:50 +0000 +Subject: [PATCH] rhbz#1891326 suggest package install of the most appropiate + pt langpack + +Change-Id: I87ff1a941a3a5dc0c321440a9c286ae73c9d0384 +--- + svtools/source/misc/langhelp.cxx | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/svtools/source/misc/langhelp.cxx b/svtools/source/misc/langhelp.cxx +index e64a3b869076..acaf2c6e24f3 100644 +--- a/svtools/source/misc/langhelp.cxx ++++ b/svtools/source/misc/langhelp.cxx +@@ -139,6 +139,8 @@ OUString getInstalledLocaleForSystemUILanguage(const css::uno::Sequence +Date: Tue, 13 Jul 2021 12:38:07 +0100 +Subject: [PATCH] rhbz#1980800 allow --convert-to csv to write each sheet to a + separate file + +Related: tdf#135762 except only currently implemented for command line use + +sample usage: +soffice --convert-to csv:"Text - txt - csv (StarCalc)":44,34,UTF8,1,,0,false,true,false,false,false,-1 sample.ods +where the new (11th!) final token ("-1") enables writing each sheet to a +new file based on the suggested target name so output in this example +is files sample-Sheet1.csv and sample-Sheet2.csv + +Only -1 for 'all sheets' vs 0 for existing 'current sheet only' (which +is always sheet 0 from the command line) are currently options but the +token could be expanded in the future to select specific sheets to +export. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118850 +Tested-by: Jenkins +Reviewed-by: Eike Rathke +(cherry picked from commit b8903bc106dad036acb3d117e5c4fc955697fe02) + +Related: tdf#135762 Allow --convert-to csv to specify 1-based sheet number + +Same multifile mechanism as for -1 all sheets is used, so + +soffice --convert-to csv:"Text - txt - csv (StarCalc)":44,34,UTF8,1,,0,false,true,false,false,false,2 sample.ods + +writes a file sample-Sheet2.csv + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118971 +Reviewed-by: Eike Rathke +Tested-by: Jenkins +(cherry picked from commit fda91f8be16ba760e360940ebafd6244c648cb8c) + +Related: tdf#135762 Suppress cout if not command line + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119294 +Reviewed-by: Eike Rathke +Tested-by: Jenkins +(cherry picked from commit 0cda081c9aa3b3dcb363f97bac60c845ce9a13e0) + +Change-Id: Ib99a120f1a2c8d1008a7a3c59a6b39f572fb346e +b9248c9561e4e340c88458ac5dfd159e443a4cfd +9431221aadf97739bb197871f25fa151ef4c391c + +Plus follow-up fix + +"tdf#129829 sfx2: fix handling of password to open vs modify" (which happens to +also fix saving to smb shares, in addition to the Windows-specific issue it was +originally meant to fix), plus the relevant parts of its preceding + +"sw reqif-xhtml export: add a new RTFOLEMimeType parameter" introducing +SfxMedium::SetArgs. +--- + desktop/source/app/dispatchwatcher.cxx | 50 +++++++-- + include/sfx2/docfile.hxx | 2 + + sc/source/ui/dbgui/imoptdlg.cxx | 16 ++- + sc/source/ui/docshell/docsh.cxx | 141 +++++++++++++++++++++---- + sc/source/ui/inc/docsh.hxx | 2 +- + sc/source/ui/inc/imoptdlg.hxx | 6 +- + sfx2/source/doc/docfile.cxx | 13 +++ + 7 files changed, 194 insertions(+), 36 deletions(-) + +diff --git a/desktop/source/app/dispatchwatcher.cxx b/desktop/source/app/dispatchwatcher.cxx +index 04140173c6d1..a5365da618e8 100644 +--- a/desktop/source/app/dispatchwatcher.cxx ++++ b/desktop/source/app/dispatchwatcher.cxx +@@ -30,6 +30,7 @@ + #include "dispatchwatcher.hxx" + #include + #include ++#include + #include + #include + #include +@@ -604,6 +605,8 @@ bool DispatchWatcher::executeDispatchRequests( const std::vector conversionProperties( nProps ); +- conversionProperties[0].Name = "Overwrite"; +- conversionProperties[0].Value <<= true; ++ conversionProperties[0].Name = "ConversionRequestOrigin"; ++ conversionProperties[0].Value <<= OUString("CommandLine"); ++ conversionProperties[1].Name = "Overwrite"; ++ conversionProperties[1].Value <<= true; + +- conversionProperties[1].Name = "FilterName"; ++ conversionProperties[2].Name = "FilterName"; + if( 0 < nFilterOptionsIndex ) + { +- conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex); ++ OUString sFilterName = aFilter.copy(0, nFilterOptionsIndex); ++ OUString sFilterOptions = aFilter.copy(nFilterOptionsIndex + 1); ++ ++ if (sFilterName == "Text - txt - csv (StarCalc)") ++ { ++ sal_Int32 nIdx(0); ++ // If the 11th token is '-1' then we export a file ++ // per sheet where the file name is based on the suggested ++ // output filename concatenated with the sheet name, so adjust ++ // the output and overwrite messages ++ // If the 11th token is not present or numeric 0 then the ++ // default sheet is exported with the output filename. If it ++ // is numeric >0 then that sheet (1-based) with the output ++ // filename concatenated with the sheet name. So even if ++ // that is a single file, the multi file target mechanism is ++ // used. ++ const OUString aTok(sFilterOptions.getToken(11, ',', nIdx)); ++ // Actual validity is checked in Calc, here just check for ++ // presence of numeric value at start. ++ bMultiFileTarget = (!aTok.isEmpty() && aTok.toInt32() != 0); ++ } ++ ++ conversionProperties[2].Value <<= sFilterName; + +- conversionProperties[2].Name = "FilterOptions"; +- conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1); ++ conversionProperties[3].Name = "FilterOptions"; ++ conversionProperties[3].Value <<= sFilterOptions; + } + else + { +- conversionProperties[1].Value <<= aFilter; ++ conversionProperties[2].Value <<= aFilter; + } + + if ( !aImgOut.isEmpty() ) + { ++ assert(conversionProperties[nProps-1].Name.isEmpty()); + conversionProperties[nProps-1].Name = "ImageFilter"; + conversionProperties[nProps-1].Value <<= aImgOut; + } +@@ -645,9 +673,11 @@ bool DispatchWatcher::executeDispatchRequests( const std::vector " << aTargetURL8; ++ std::cout << "convert " << aSource8; ++ if (!bMultiFileTarget) ++ std::cout << " -> " << aTargetURL8; + std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl; +- if (FStatHelper::IsDocument(aOutFile)) ++ if (!bMultiFileTarget && FStatHelper::IsDocument(aOutFile)) + std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ; + } + try +diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx +index 2019b5738c01..2886348 100644 +--- a/include/sfx2/docfile.hxx ++++ b/include/sfx2/docfile.hxx +@@ -108,6 +108,8 @@ public: + const OUString& GetOrigURL() const; + + SfxItemSet * GetItemSet() const; ++ void SetArgs(const css::uno::Sequence& rArgs); ++ css::uno::Sequence GetArgs() const; + void Close(bool bInDestruction = false); + void CloseAndRelease(); + void ReOpen(); +diff --git a/sc/source/ui/dbgui/imoptdlg.cxx b/sc/source/ui/dbgui/imoptdlg.cxx +index 26781924baac..7aa8c8acb061 100644 +--- a/sc/source/ui/dbgui/imoptdlg.cxx ++++ b/sc/source/ui/dbgui/imoptdlg.cxx +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -43,6 +44,7 @@ ScImportOptions::ScImportOptions( const OUString& rStr ) + bSaveNumberAsSuch = true; + bSaveFormulas = false; + bRemoveSpace = false; ++ nSheetToExport = 0; + sal_Int32 nTokenCount = comphelper::string::getTokenCount(rStr, ','); + if ( nTokenCount >= 3 ) + { +@@ -76,6 +78,16 @@ ScImportOptions::ScImportOptions( const OUString& rStr ) + bSaveFormulas = rStr.getToken(0, ',', nIdx) == "true"; + if ( nTokenCount >= 11 ) + bRemoveSpace = rStr.getToken(0, ',', nIdx) == "true"; ++ if ( nTokenCount >= 12 ) ++ { ++ const OUString aTok(rStr.getToken(0, ',', nIdx)); ++ if (aTok == "-1") ++ nSheetToExport = -1; // all ++ else if (aTok.isEmpty() || CharClass::isAsciiNumeric(aTok)) ++ nSheetToExport = aTok.toInt32(); ++ else ++ nSheetToExport = -23; // invalid, force error ++ } + } + } + } +@@ -99,7 +111,9 @@ OUString ScImportOptions::BuildString() const + "," + + OUString::boolean( bSaveFormulas ) + // "save formulas": not in ScAsciiOptions + "," + +- OUString::boolean( bRemoveSpace ); // same as "Remove space" in ScAsciiOptions ++ OUString::boolean( bRemoveSpace ) + // same as "Remove space" in ScAsciiOptions ++ "," + ++ OUString::number(nSheetToExport) ; // Only available for command line --convert-to + + return aResult; + } +diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx +index bd7402231333..1c544fb6fa1a 100644 +--- a/sc/source/ui/docshell/docsh.cxx ++++ b/sc/source/ui/docshell/docsh.cxx +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -120,6 +121,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1920,7 +1922,7 @@ void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr) + + } + +-void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt ) ++void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, SCTAB nTab ) + { + sal_Unicode cDelim = rAsciiOpt.nFieldSepCode; + sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode; +@@ -1966,7 +1968,6 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt + + SCCOL nStartCol = 0; + SCROW nStartRow = 0; +- SCTAB nTab = GetSaveTab(); + SCCOL nEndCol; + SCROW nEndRow; + m_aDocument.GetCellArea( nTab, nEndCol, nEndRow ); +@@ -2384,35 +2385,129 @@ bool ScDocShell::ConvertTo( SfxMedium &rMed ) + } + else if (aFltName == pFilterAscii) + { +- SvStream* pStream = rMed.GetOutStream(); +- if (pStream) ++ OUString sItStr; ++ SfxItemSet* pSet = rMed.GetItemSet(); ++ const SfxPoolItem* pItem; ++ if ( pSet && SfxItemState::SET == ++ pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) ) + { +- OUString sItStr; +- SfxItemSet* pSet = rMed.GetItemSet(); +- const SfxPoolItem* pItem; +- if ( pSet && SfxItemState::SET == +- pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) ) ++ sItStr = static_cast(pItem)->GetValue(); ++ } ++ ++ if ( sItStr.isEmpty() ) ++ { ++ // default for ascii export (from API without options): ++ // ISO8859-1/MS_1252 encoding, comma, double quotes ++ ++ ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 ); ++ sItStr = aDefOptions.BuildString(); ++ } ++ ++ weld::WaitObject aWait( GetActiveDialogParent() ); ++ ScImportOptions aOptions( sItStr ); ++ ++ if (aOptions.nSheetToExport) ++ { ++ // Only from command line --convert-to ++ bRet = true; ++ ++ // Verbose only from command line, not UI (in case we actually ++ // implement that) nor macro filter options. ++ bool bVerbose = false; ++ const css::uno::Sequence & rArgs = rMed.GetArgs(); ++ const auto pProp = std::find_if( rArgs.begin(), rArgs.end(), ++ [](const css::beans::PropertyValue& rProp) { return rProp.Name == "ConversionRequestOrigin"; }); ++ if (pProp != rArgs.end()) + { +- sItStr = static_cast(pItem)->GetValue(); ++ OUString aOrigin; ++ pProp->Value >>= aOrigin; ++ bVerbose = (aOrigin == "CommandLine"); + } + +- if ( sItStr.isEmpty() ) ++ SCTAB nStartTab; ++ SCTAB nCount = m_aDocument.GetTableCount(); ++ if (aOptions.nSheetToExport == -1) + { +- // default for ascii export (from API without options): +- // ISO8859-1/MS_1252 encoding, comma, double quotes +- +- ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 ); +- sItStr = aDefOptions.BuildString(); ++ // All sheets. ++ nStartTab = 0; ++ } ++ else if (0 < aOptions.nSheetToExport && aOptions.nSheetToExport <= nCount) ++ { ++ // One sheet, 1-based. ++ nCount = aOptions.nSheetToExport; ++ nStartTab = nCount - 1; ++ } ++ else ++ { ++ // Usage error, no export but log. ++ if (bVerbose) ++ { ++ if (aOptions.nSheetToExport < 0) ++ std::cout << "Bad sheet number string given." << std::endl; ++ else ++ std::cout << "No sheet number " << aOptions.nSheetToExport ++ << ", number of sheets is " << nCount << std::endl; ++ } ++ nStartTab = 0; ++ nCount = 0; ++ SetError(SCERR_EXPORT_DATA); ++ bRet = false; + } + +- weld::WaitObject aWait( GetActiveDialogParent() ); +- ScImportOptions aOptions( sItStr ); +- AsciiSave( *pStream, aOptions ); +- bRet = true; ++ INetURLObject aURLObject(rMed.GetURLObject()); ++ OUString sExt = aURLObject.CutExtension(); ++ OUString sBaseName = aURLObject.GetLastName(); ++ aURLObject.CutLastName(); + +- if (m_aDocument.GetTableCount() > 1) +- if (!rMed.GetError()) +- rMed.SetError(SCWARN_EXPORT_ASCII); ++ for (SCTAB i = nStartTab; i < nCount; ++i) ++ { ++ OUString sTabName; ++ if (!m_aDocument.GetName(i, sTabName)) ++ sTabName = OUString::number(i); ++ INetURLObject aSheetURLObject(aURLObject); ++ OUString sFileName = sBaseName + "-" + sTabName; ++ if (!sExt.isEmpty()) ++ sFileName = sFileName + "." + sExt; ++ aSheetURLObject.Append(sFileName); ++ ++ // log similar to DispatchWatcher::executeDispatchRequests ++ OUString aOutFile = aSheetURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE); ++ if (bVerbose) ++ { ++ OUString aDisplayedName; ++ if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(aOutFile, aDisplayedName)) ++ aDisplayedName = aOutFile; ++ std::cout << "Writing sheet " << OUStringToOString(sTabName, osl_getThreadTextEncoding()) << " -> " ++ << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) ++ << std::endl; ++ ++ if (FStatHelper::IsDocument(aOutFile)) ++ std::cout << "Overwriting: " << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) ++ << std::endl ; ++ } ++ ++ std::unique_ptr xStm = ::utl::UcbStreamHelper::CreateStream(aOutFile, StreamMode::TRUNC | StreamMode::WRITE); ++ if (!xStm) ++ { ++ SetError(ERRCODE_IO_CANTCREATE); ++ bRet = false; ++ break; ++ } ++ AsciiSave(*xStm, aOptions, i); ++ } ++ } ++ else ++ { ++ SvStream* pStream = rMed.GetOutStream(); ++ if (pStream) ++ { ++ AsciiSave(*pStream, aOptions, GetSaveTab()); ++ bRet = true; ++ ++ if (m_aDocument.GetTableCount() > 1) ++ if (!rMed.GetError()) ++ rMed.SetError(SCWARN_EXPORT_ASCII); ++ } + } + } + else if (aFltName == pFilterDBase) +diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx +index a519f4c87d04..6a075ff6dade 100644 +--- a/sc/source/ui/inc/docsh.hxx ++++ b/sc/source/ui/inc/docsh.hxx +@@ -230,7 +230,7 @@ public: + + ScDrawLayer* MakeDrawLayer(); + +- void AsciiSave( SvStream& rStream, const ScImportOptions& rOpt ); ++ void AsciiSave( SvStream& rStream, const ScImportOptions& rOpt, SCTAB nTab ); + + void Execute( SfxRequest& rReq ); + void GetState( SfxItemSet &rSet ); +diff --git a/sc/source/ui/inc/imoptdlg.hxx b/sc/source/ui/inc/imoptdlg.hxx +index bac941c2a377..382067d67813 100644 +--- a/sc/source/ui/inc/imoptdlg.hxx ++++ b/sc/source/ui/inc/imoptdlg.hxx +@@ -32,7 +32,8 @@ public: + ScImportOptions( sal_Unicode nFieldSep, sal_Unicode nTextSep, rtl_TextEncoding nEnc ) + : nFieldSepCode(nFieldSep), nTextSepCode(nTextSep), + bFixedWidth(false), bSaveAsShown(false), bQuoteAllText(false), +- bSaveNumberAsSuch(true), bSaveFormulas(false), bRemoveSpace(false) ++ bSaveNumberAsSuch(true), bSaveFormulas(false), bRemoveSpace(false), ++ nSheetToExport(0) + { SetTextEncoding( nEnc ); } + + ScImportOptions& operator=( const ScImportOptions& rCpy ) = default; +@@ -51,6 +52,9 @@ public: + bool bSaveNumberAsSuch; + bool bSaveFormulas; + bool bRemoveSpace; ++ // "0" for 'current sheet', "-1" for all sheets (each to a separate file), ++ // or 1-based specific sheet number (to a separate file). ++ sal_Int32 nSheetToExport; + }; + + #endif // INCLUDED_SC_SOURCE_UI_INC_IMOPTDLG_HXX +diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx +index 5d00d39bd837..4e4e74a 100644 +--- a/sfx2/source/doc/docfile.cxx ++++ b/sfx2/source/doc/docfile.cxx +@@ -328,6 +328,8 @@ public: + + util::DateTime m_aDateTime; + ++ uno::Sequence m_aArgs; ++ + explicit SfxMedium_Impl(); + ~SfxMedium_Impl(); + SfxMedium_Impl(const SfxMedium_Impl&) = delete; +@@ -3240,6 +3242,7 @@ SfxMedium::SfxMedium( const uno::Sequence& aArgs ) : + SfxAllItemSet *pParams = new SfxAllItemSet( SfxGetpApp()->GetPool() ); + pImpl->m_pSet.reset( pParams ); + TransformParameters( SID_OPENDOC, aArgs, *pParams ); ++ SetArgs(aArgs); + + OUString aFilterProvider, aFilterName; + { +@@ -3301,6 +3304,16 @@ SfxMedium::SfxMedium( const uno::Sequence& aArgs ) : + Init_Impl(); + } + ++void SfxMedium::SetArgs(const uno::Sequence& rArgs) ++{ ++ pImpl->m_aArgs = rArgs; ++ comphelper::SequenceAsHashMap aArgsMap(rArgs); ++ aArgsMap.erase("Stream"); ++ aArgsMap.erase("InputStream"); ++ pImpl->m_aArgs = aArgsMap.getAsConstPropertyValueList(); ++} ++ ++uno::Sequence SfxMedium::GetArgs() const { return pImpl->m_aArgs; } + + SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const OUString& rBaseURL, const std::shared_ptr& p ) : + pImpl(new SfxMedium_Impl) +-- +2.31.1 + diff --git a/SOURCES/0001-tdf-137209-unparent-widgets-in-fragment-dtor.patch b/SOURCES/0001-tdf-137209-unparent-widgets-in-fragment-dtor.patch new file mode 100644 index 0000000..991b766 --- /dev/null +++ b/SOURCES/0001-tdf-137209-unparent-widgets-in-fragment-dtor.patch @@ -0,0 +1,44 @@ +From 96fc7531331f45a314416000150b1141e5686f38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 2 Oct 2020 16:21:02 +0100 +Subject: [PATCH] tdf#137209 unparent widgets in fragment dtor + +Change-Id: I819514fd2b97e2cc8daad71a7f3b0b27afe6136d +--- + sw/source/ui/dbui/createaddresslistdialog.cxx | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sw/source/ui/dbui/createaddresslistdialog.cxx b/sw/source/ui/dbui/createaddresslistdialog.cxx +index ae4d354ea29d..994a6045cea5 100644 +--- a/sw/source/ui/dbui/createaddresslistdialog.cxx ++++ b/sw/source/ui/dbui/createaddresslistdialog.cxx +@@ -53,11 +53,13 @@ struct SwAddressFragment + std::unique_ptr m_xBuilder; + std::unique_ptr m_xLabel; + std::unique_ptr m_xEntry; ++ weld::Container* m_pGrid; + + SwAddressFragment(weld::Container* pGrid, int nLine) + : m_xBuilder(Application::CreateBuilder(pGrid, "modules/swriter/ui/addressfragment.ui")) + , m_xLabel(m_xBuilder->weld_label("label")) + , m_xEntry(m_xBuilder->weld_entry("entry")) ++ , m_pGrid(pGrid) + { + m_xLabel->set_grid_left_attach(0); + m_xLabel->set_grid_top_attach(nLine); +@@ -65,6 +67,12 @@ struct SwAddressFragment + m_xEntry->set_grid_left_attach(1); + m_xEntry->set_grid_top_attach(nLine); + } ++ ++ virtual ~SwAddressFragment() ++ { ++ m_pGrid->move(m_xEntry.get(), nullptr); ++ m_pGrid->move(m_xLabel.get(), nullptr); ++ } + }; + + class SwAddressControl_Impl +-- +2.26.2 + diff --git a/SOURCES/0001-use-gdk_wayland_window_set_application_id-when-it-be.patch b/SOURCES/0001-use-gdk_wayland_window_set_application_id-when-it-be.patch new file mode 100644 index 0000000..3467408 --- /dev/null +++ b/SOURCES/0001-use-gdk_wayland_window_set_application_id-when-it-be.patch @@ -0,0 +1,144 @@ +From f1cace2cd06b20fc1431f15892a4293fa3601b39 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 8 Jul 2020 10:13:26 +0100 +Subject: [PATCH] use gdk_wayland_window_set_application_id when it becomes + available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: I60775dcbfbc396f195a71f219668944d0bfecf31 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98325 +Tested-by: Caolán McNamara +Reviewed-by: Caolán McNamara +(cherry picked from commit 2d8e2813ddc87f7ce03b97e4d603df11613461f0) + +gdk_wayland_window_set_application_id doesn't work when called early + +after mapped it definitely works + +Change-Id: Ide0fa636ee26acea0d938aef08532b9396fe901a +--- + vcl/inc/unx/gtk/gtkframe.hxx | 3 +++ + vcl/unx/gtk3/gtk3gtkframe.cxx | 49 +++++++++++++++++++++++++++++------ + 2 files changed, 44 insertions(+), 8 deletions(-) + +diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx +index ccf9064..49b6937 100644 +--- a/vcl/inc/unx/gtk/gtkframe.hxx ++++ b/vcl/inc/unx/gtk/gtkframe.hxx +@@ -206,6 +206,7 @@ class GtkSalFrame : public SalFrame + GtkDropTarget* m_pDropTarget; + GtkDragSource* m_pDragSource; + bool m_bGeometryIsProvisional; ++ bool m_bIconSetWhileUnmapped; + + GtkSalMenu* m_pSalMenu; + +@@ -315,6 +316,8 @@ class GtkSalFrame : public SalFrame + + void SetScreen( unsigned int nNewScreen, SetType eType, tools::Rectangle const *pSize = nullptr ); + ++ void SetIcon(const char* pIcon); ++ + public: + cairo_surface_t* m_pSurface; + basegfx::B2IVector m_aFrameSize; +diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx +index 786aa40..624c75a 100644 +--- a/vcl/unx/gtk3/gtk3gtkframe.cxx ++++ b/vcl/unx/gtk3/gtk3gtkframe.cxx +@@ -55,6 +55,7 @@ + + #include + #include ++#include + + #include + #include +@@ -922,6 +923,7 @@ void GtkSalFrame::InitCommon() + m_pDropTarget = nullptr; + m_pDragSource = nullptr; + m_bGeometryIsProvisional = false; ++ m_bIconSetWhileUnmapped = false; + m_ePointerStyle = static_cast(0xffff); + m_pSalMenu = nullptr; + m_nWatcherId = 0; +@@ -1217,6 +1219,28 @@ void GtkSalFrame::SetTitle( const OUString& rTitle ) + } + } + ++void GtkSalFrame::SetIcon(const char* appicon) ++{ ++ gtk_window_set_icon_name(GTK_WINDOW(m_pWindow), appicon); ++ ++#if defined(GDK_WINDOWING_WAYLAND) ++ if (DLSYM_GDK_IS_WAYLAND_DISPLAY(getGdkDisplay())) ++ { ++ static auto set_application_id = reinterpret_cast( ++ dlsym(nullptr, "gdk_wayland_window_set_application_id")); ++ if (set_application_id) ++ { ++ GdkWindow* gdkWindow = gtk_widget_get_window(m_pWindow); ++ set_application_id(gdkWindow, appicon); ++ ++ // gdk_wayland_window_set_application_id doesn't seem to work before ++ // the window is mapped, so set this for real when/if we are mapped ++ m_bIconSetWhileUnmapped = !gtk_widget_get_mapped(m_pWindow); ++ } ++ } ++#endif ++} ++ + void GtkSalFrame::SetIcon( sal_uInt16 nIcon ) + { + if( (m_nStyle & (SalFrameStyleFlags::PLUG|SalFrameStyleFlags::SYSTEMCHILD|SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::INTRO|SalFrameStyleFlags::OWNERDRAWDECORATION)) +@@ -1240,7 +1264,8 @@ void GtkSalFrame::SetIcon( sal_uInt16 nIcon ) + else + appicon = g_strdup ("libreoffice-startcenter"); + +- gtk_window_set_icon_name (GTK_WINDOW (m_pWindow), appicon); ++ SetIcon(appicon); ++ + g_free (appicon); + } + +@@ -1309,13 +1334,18 @@ void GtkSalFrame::Show( bool bVisible, bool /*bNoActivate*/ ) + } + + #if defined(GDK_WINDOWING_WAYLAND) +- //rhbz#1334915, gnome#779143, tdf#100158 +- //gtk under wayland lacks a way to change the app_id +- //of a window, so brute force everything as a +- //startcenter when initially shown to at least get +- //the default LibreOffice icon and not the broken +- //app icon +- if (DLSYM_GDK_IS_WAYLAND_DISPLAY(getGdkDisplay())) ++ /* ++ rhbz#1334915, gnome#779143, tdf#100158 ++ https://gitlab.gnome.org/GNOME/gtk/-/issues/767 ++ ++ before gdk_wayland_window_set_application_id was available gtk ++ under wayland lacked a way to change the app_id of a window, so ++ brute force everything as a startcenter when initially shown to at ++ least get the default LibreOffice icon and not the broken app icon ++ */ ++ static bool bAppIdImmutable = DLSYM_GDK_IS_WAYLAND_DISPLAY(getGdkDisplay()) && ++ !dlsym(nullptr, "gdk_wayland_window_set_application_id"); ++ if (bAppIdImmutable) + { + OString sOrigName(g_get_prgname()); + g_set_prgname("libreoffice-startcenter"); +@@ -3039,6 +3069,9 @@ gboolean GtkSalFrame::signalMap(GtkWidget *, GdkEvent*, gpointer frame) + { + GtkSalFrame* pThis = static_cast(frame); + ++ if (pThis->m_bIconSetWhileUnmapped) ++ pThis->SetIcon(gtk_window_get_icon_name(GTK_WINDOW(pThis->m_pWindow))); ++ + pThis->CallCallbackExc( SalEvent::Resize, nullptr ); + pThis->TriggerPaintEvent(); + +-- +2.26.2 + diff --git a/SOURCES/0002-CVE-2021-25635.patch b/SOURCES/0002-CVE-2021-25635.patch new file mode 100644 index 0000000..cee888d --- /dev/null +++ b/SOURCES/0002-CVE-2021-25635.patch @@ -0,0 +1,56 @@ +From a9102a384893fd084011e8451867071452031ece Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 8 Feb 2021 17:05:28 +0000 +Subject: [PATCH 2/6] CVE-2021-25635 + +default to CertificateValidity::INVALID + +so if CertGetCertificateChain fails we don't want validity to be +css::security::CertificateValidity::VALID which is what the old default +of 0 equates to + +notably + +commit 1e0bc66d16aee28ce8bd9582ea32178c63841902 +Date: Thu Nov 5 16:55:26 2009 +0100 + + jl137: #103420# better logging + +turned the nss equivalent of SecurityEnvironment_NssImpl::verifyCertificate +from 0 to CertificateValidity::INVALID like this change does + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110561 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +(cherry picked from commit edeb164c1d8ab64116afee4e2140403a362a1358) + +Change-Id: I5350dbc22d1b9b378da2976d3b0abd728f1f4c27 +--- + .../source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx +index d9b657891b96..4031df289f44 100644 +--- a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx ++++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx +@@ -755,7 +755,7 @@ sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( + const uno::Reference< css::security::XCertificate >& aCert, + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) + { +- sal_Int32 validity = 0; ++ sal_Int32 validity = css::security::CertificateValidity::INVALID; + PCCERT_CHAIN_CONTEXT pChainContext = nullptr; + PCCERT_CONTEXT pCertContext = nullptr; + +@@ -899,7 +899,7 @@ sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( + } + else + { +- SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChaine failed."); ++ SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed."); + } + } + +-- +2.32.0 + diff --git a/SOURCES/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch b/SOURCES/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch new file mode 100644 index 0000000..4137ef1 --- /dev/null +++ b/SOURCES/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch @@ -0,0 +1,198 @@ +From 61f8673fb44150bd629d88f6626aff8d5b026449 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Mon, 21 Mar 2022 20:58:34 +0000 +Subject: [PATCH] make hash encoding match decoding + +Seeing as old versions of the hash may be in the users config, add a +StorageVersion field to the office config Passwords section which +defaults to 0 to indicate the old hash is in use. + +Try the old varient when StorageVersion is 0. When a new encoded master +password it set write StorageVersion of 1 to indicate a new hash is in +use and use the new style when StorageVersion is 1. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132080 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit e890f54dbac57f3ab5acf4fbd31222095d3e8ab6) + +svl: fix crash if user cancels/closes master password dialog + +(regression from d7ba5614d90381d68f880ca7e7c5ef8bbb1b1c43) + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133932 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit bbb8617ece6d946957c2eb96287081029bce530f) + +Change-Id: I3174c37a5891bfc849984e0ec5c2c392b9c6e7b1 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133905 +Tested-by: Michael Stahl +Reviewed-by: Michael Stahl +--- + .../schema/org/openoffice/Office/Common.xcs | 6 +++ + .../passwordcontainer/passwordcontainer.cxx | 47 ++++++++++++++++++- + .../passwordcontainer/passwordcontainer.hxx | 6 +++ + uui/source/iahndl-authentication.cxx | 5 +- + 4 files changed, 60 insertions(+), 4 deletions(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index b317f616deeb..b033b29b60d7 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -911,6 +911,12 @@ + + false + ++ ++ ++ Specifies what version of encoding scheme the password container uses. ++ ++ 0 ++ + + + Specifies if there is a valid master password. +diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx +index 02947cd3892c..ff0b40df4016 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.cxx ++++ b/svl/source/passwordcontainer/passwordcontainer.cxx +@@ -17,6 +17,8 @@ + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + ++#include ++#include + + #include "passwordcontainer.hxx" + +@@ -259,6 +261,23 @@ bool StorageItem::useStorage() + return aResult; + } + ++sal_Int32 StorageItem::getStorageVersion() ++{ ++ Sequence aNodeNames { "StorageVersion" }; ++ ++ Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); ++ ++ if( aPropertyValues.getLength() != aNodeNames.getLength() ) ++ { ++ OSL_FAIL( "Problems during reading" ); ++ return 0; ++ } ++ ++ sal_Int32 nResult = 0; ++ aPropertyValues[0] >>= nResult; ++ ++ return nResult; ++} + + bool StorageItem::getEncodedMP( OUString& aResult ) + { +@@ -291,15 +310,17 @@ bool StorageItem::getEncodedMP( OUString& aResult ) + + void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) + { +- Sequence< OUString > sendNames(2); +- Sequence< uno::Any > sendVals(2); ++ Sequence< OUString > sendNames(3); ++ Sequence< uno::Any > sendVals(3); + + sendNames[0] = "HasMaster"; + sendNames[1] = "Master"; ++ sendNames[2] = "StorageVersion"; + + bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); + sendVals[0] <<= bHasMaster; + sendVals[1] <<= aEncoded; ++ sendVals[2] <<= nCurrentStorageVersion; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); +@@ -800,6 +821,18 @@ OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, + return aResult; + } + ++// Mangle the key to match an old bug ++static OUString ReencodeAsOldHash(const OUString& rPass) ++{ ++ OUStringBuffer aBuffer; ++ for (int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ++ind) ++ { ++ unsigned char i = static_cast(rPass.copy(ind * 2, 2).toUInt32(16)); ++ aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4))); ++ aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15))); ++ } ++ return aBuffer.makeStringAndClear(); ++} + + OUString const & PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) + { +@@ -838,6 +871,9 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + } + else + { ++ if (m_pStorageFile->getStorageVersion() == 0) ++ aPass = ReencodeAsOldHash(aPass); ++ + std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) ); + if( aRM.empty() || aPass != aRM[0] ) + { +@@ -1042,6 +1078,13 @@ sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::R + + do { + aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); ++ ++ ++ if (!aPass.isEmpty() && m_pStorageFile->getStorageVersion() == 0) ++ { ++ aPass = ReencodeAsOldHash(aPass); ++ } ++ + bResult = ( !aPass.isEmpty() && aPass == m_aMasterPasswd ); + aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification + } while( !bResult && !aPass.isEmpty() ); +diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx +index 09fb7e03629d..cf5c717d0c9e 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.hxx ++++ b/svl/source/passwordcontainer/passwordcontainer.hxx +@@ -167,6 +167,10 @@ public: + typedef ::std::pair< const OUString, ::std::vector< NamePassRecord > > PairUrlRecord; + typedef ::std::map< OUString, ::std::vector< NamePassRecord > > PassMap; + ++// org.openoffice.Office.Common/Passwords/StorageVersion bump if details of ++// how password details are saved changes. Enables migration from previous ++// schemes. ++constexpr sal_Int32 nCurrentStorageVersion = 1; + + class PasswordContainer; + +@@ -195,6 +199,8 @@ public: + void remove( const OUString& url, const OUString& rec ); + void clear(); + ++ sal_Int32 getStorageVersion(); ++ + bool getEncodedMP( OUString& aResult ); + void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false ); + void setUseStorage( bool bUse ); +diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx +index 4835a485dd2a..5764e62cb1c6 100644 +--- a/uui/source/iahndl-authentication.cxx ++++ b/uui/source/iahndl-authentication.cxx +@@ -436,8 +436,9 @@ executeMasterPasswordDialog( + OUStringBuffer aBuffer; + for (sal_uInt8 i : aKey) + { +- aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4))); +- aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15))); ++ // match PasswordContainer::DecodePasswords aMasterPasswd.copy(index * 2, 2).toUInt32(16)); ++ aBuffer.append(OUString::number(i >> 4, 16)); ++ aBuffer.append(OUString::number(i & 15, 16)); + } + rInfo.SetPassword(aBuffer.makeStringAndClear()); + } +-- +2.37.1 + diff --git a/SOURCES/0002-resource-leak.patch b/SOURCES/0002-resource-leak.patch new file mode 100644 index 0000000..3823e8a --- /dev/null +++ b/SOURCES/0002-resource-leak.patch @@ -0,0 +1,25 @@ +From abaf73f99c300ffe6c38dc7d1ce93ab09043f88a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 4 Nov 2020 11:02:21 +0000 +Subject: [PATCH 2/8] resource leak + +Change-Id: I1abd8acef55d5bdb4744ecf1a62d8e1396de0e3f +--- + vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx b/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx +index 52f0a34cd3a2..483283cadab5 100644 +--- a/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx ++++ b/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx +@@ -987,6 +987,7 @@ TabStopList2String( const uno::Any& rAny, bool default_tabs ) + { + gchar * old_tab_str = ret; + ret = g_strconcat(old_tab_str, " ", tab_str, nullptr); ++ g_free( tab_str ); + g_free( old_tab_str ); + } + else +-- +2.28.0 + diff --git a/SOURCES/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch b/SOURCES/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch new file mode 100644 index 0000000..08642bf --- /dev/null +++ b/SOURCES/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch @@ -0,0 +1,586 @@ +From a3046cfa58bdfa2a1b9ea6287a021230830f056f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Tue, 22 Mar 2022 17:22:22 +0000 +Subject: [PATCH] add Initialization Vectors to password storage + +old ones default to the current all zero case and continue to work +as before + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131974 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 192fa1e3bfc6269f2ebb91716471485a56074aea) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132306 +Reviewed-by: Thorsten Behrens +(cherry picked from commit ab77587ec300f5c30084471000663c46ddf25dad) + +Change-Id: I6fe3b02fafcce1b5e7133e77e76a5118177d77af +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133907 +Tested-by: Michael Stahl +Reviewed-by: Michael Stahl +--- + .../schema/org/openoffice/Office/Common.xcs | 10 ++ + .../passwordcontainer/passwordcontainer.cxx | 127 ++++++++++++------ + .../passwordcontainer/passwordcontainer.hxx | 63 +++++++-- + 3 files changed, 151 insertions(+), 49 deletions(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index b033b29b60d7..e57d26ab3366 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -27,6 +27,11 @@ + + Contains a container for passwords. + ++ ++ ++ Contains an initialization vector for the password encryption. ++ ++ + + + Contains a password encoded with the master password. +@@ -923,6 +928,11 @@ + + false + ++ ++ ++ Contains an initialization vector for the master password encryption. ++ ++ + + + Contains the master password encrypted by itself. +diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx +index ff0b40df4016..380188ef495c 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.cxx ++++ b/svl/source/passwordcontainer/passwordcontainer.cxx +@@ -184,15 +184,18 @@ PassMap StorageItem::getInfo() + + Sequence< OUString > aNodeNames = ConfigItem::GetNodeNames( "Store" ); + sal_Int32 aNodeCount = aNodeNames.getLength(); +- Sequence< OUString > aPropNames( aNodeCount ); ++ Sequence< OUString > aPropNames( aNodeCount * 2); + + std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.begin(), + [](const OUString& rName) -> OUString { + return "Store/Passwordstorage['" + rName + "']/Password"; }); ++ std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.getArray() + aNodeCount, ++ [](const OUString& rName) -> OUString { ++ return "Store/Passwordstorage['" + rName + "']/InitializationVector"; }); + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); + +- if( aPropertyValues.getLength() != aNodeCount ) ++ if( aPropertyValues.getLength() != aNodeCount * 2) + { + OSL_FAIL( "Problems during reading" ); + return aResult; +@@ -208,14 +211,16 @@ PassMap StorageItem::getInfo() + OUString aName = aUrlUsr[1]; + + OUString aEPasswd; ++ OUString aIV; + aPropertyValues[aNodeInd] >>= aEPasswd; ++ aPropertyValues[aNodeInd + aNodeCount] >>= aIV; + + PassMap::iterator aIter = aResult.find( aUrl ); + if( aIter != aResult.end() ) +- aIter->second.emplace_back( aName, aEPasswd ); ++ aIter->second.emplace_back( aName, aEPasswd, aIV ); + else + { +- NamePassRecord aNewRecord( aName, aEPasswd ); ++ NamePassRecord aNewRecord( aName, aEPasswd, aIV ); + std::vector< NamePassRecord > listToAdd( 1, aNewRecord ); + + aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); +@@ -279,17 +284,19 @@ sal_Int32 StorageItem::getStorageVersion() + return nResult; + } + +-bool StorageItem::getEncodedMP( OUString& aResult ) ++bool StorageItem::getEncodedMP( OUString& aResult, OUString& aResultIV ) + { + if( hasEncoded ) + { + aResult = mEncoded; ++ aResultIV = mEncodedIV; + return true; + } + +- Sequence< OUString > aNodeNames( 2 ); ++ Sequence< OUString > aNodeNames( 3 ); + aNodeNames[0] = "HasMaster"; + aNodeNames[1] = "Master"; ++ aNodeNames[2] = "MasterInitializationVector"; + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); + +@@ -301,32 +308,37 @@ bool StorageItem::getEncodedMP( OUString& aResult ) + + aPropertyValues[0] >>= hasEncoded; + aPropertyValues[1] >>= mEncoded; ++ aPropertyValues[2] >>= mEncodedIV; + + aResult = mEncoded; ++ aResultIV = mEncodedIV; + + return hasEncoded; + } + + +-void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) ++void StorageItem::setEncodedMP( const OUString& aEncoded, const OUString& aEncodedIV, bool bAcceptEmpty ) + { +- Sequence< OUString > sendNames(3); +- Sequence< uno::Any > sendVals(3); ++ Sequence< OUString > sendNames(4); ++ Sequence< uno::Any > sendVals(4); + + sendNames[0] = "HasMaster"; + sendNames[1] = "Master"; +- sendNames[2] = "StorageVersion"; ++ sendNames[2] = "MasterInitializationVector"; ++ sendNames[3] = "StorageVersion"; + + bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); + sendVals[0] <<= bHasMaster; + sendVals[1] <<= aEncoded; +- sendVals[2] <<= nCurrentStorageVersion; ++ sendVals[2] <<= aEncodedIV; ++ sendVals[3] <<= nCurrentStorageVersion; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); + + hasEncoded = bHasMaster; + mEncoded = aEncoded; ++ mEncodedIV = aEncodedIV; + } + + +@@ -362,11 +374,13 @@ void StorageItem::update( const OUString& aURL, const NamePassRecord& aRecord ) + forIndex.push_back( aURL ); + forIndex.push_back( aRecord.GetUserName() ); + +- Sequence< beans::PropertyValue > sendSeq(1); ++ Sequence< beans::PropertyValue > sendSeq(2); + +- sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password"; ++ sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/InitializationVector"; ++ sendSeq[0].Value <<= aRecord.GetPersistentIV(); + +- sendSeq[0].Value <<= aRecord.GetPersPasswords(); ++ sendSeq[1].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password"; ++ sendSeq[1].Value <<= aRecord.GetPersPasswords(); + + ConfigItem::SetModified(); + ConfigItem::SetSetProperties( "Store", sendSeq ); +@@ -427,7 +441,7 @@ void SAL_CALL PasswordContainer::disposing( const EventObject& ) + } + } + +-std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) ++std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) + { + if( !aMasterPasswd.isEmpty() ) + { +@@ -442,9 +456,16 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = static_cast(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; ++ if (!aIV.isEmpty()) ++ { ++ for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) ++ iv[ ind ] = static_cast(aIV.copy( ind*2, 2 ).toUInt32(16)); ++ } ++ + rtlCipherError result = rtl_cipher_init ( + aDecoder, rtl_Cipher_DirectionDecode, +- code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); ++ code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); + + if( result == rtl_Cipher_E_None ) + { +@@ -477,7 +498,7 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin + "Can't decode!", css::uno::Reference(), mode); + } + +-OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPasswd ) ++OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPasswd) + { + if( !aMasterPasswd.isEmpty() ) + { +@@ -494,9 +515,16 @@ OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = static_cast(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; ++ if (!aIV.isEmpty()) ++ { ++ for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) ++ iv[ ind ] = static_cast(aIV.copy( ind*2, 2 ).toUInt32(16)); ++ } ++ + rtlCipherError result = rtl_cipher_init ( + aEncoder, rtl_Cipher_DirectionEncode, +- code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); ++ code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); + + if( result == rtl_Cipher_E_None ) + { +@@ -564,7 +592,7 @@ void PasswordContainer::UpdateVector( const OUString& aURL, std::vector< NamePas + + if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) + { +- aNPIter.SetPersPasswords( aRecord.GetPersPasswords() ); ++ aNPIter.SetPersPasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV() ); + + if( writeFile ) + { +@@ -597,7 +625,8 @@ UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, b + { + try + { +- ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); ++ ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV(), ++ GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); + aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); + } + catch( NoMasterException& ) +@@ -642,6 +671,19 @@ void SAL_CALL PasswordContainer::addPersistent( const OUString& Url, const OUStr + PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler ); + } + ++OUString PasswordContainer::createIV() ++{ ++ rtlRandomPool randomPool = mRandomPool.get(); ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5]; ++ rtl_random_getBytes(randomPool, iv, RTL_DIGEST_LENGTH_MD5); ++ OUStringBuffer aBuffer; ++ for (sal_uInt8 i : iv) ++ { ++ aBuffer.append(OUString::number(i >> 4, 16)); ++ aBuffer.append(OUString::number(i & 15, 16)); ++ } ++ return aBuffer.makeStringAndClear(); ++} + + void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) + { +@@ -649,7 +691,11 @@ void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserNam + ::std::vector< OUString > aStorePass = comphelper::sequenceToContainer< std::vector >( Passwords ); + + if( Mode == PERSISTENT_RECORD ) +- aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) ); ++ { ++ OUString sIV = createIV(); ++ OUString sEncodedPasswords = EncodePasswords( aStorePass, sIV, GetMasterPassword( aHandler ) ); ++ aRecord.SetPersPasswords( sEncodedPasswords, sIV ); ++ } + else if( Mode == MEMORY_RECORD ) + aRecord.SetMemPasswords( aStorePass ); + else +@@ -842,10 +888,10 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + + if( m_aMasterPasswd.isEmpty() && aHandler.is() ) + { +- OUString aEncodedMP; ++ OUString aEncodedMP, aEncodedMPIV; + bool bDefaultPassword = false; + +- if( !m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ if( !m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + aRMode = PasswordRequestMode_PASSWORD_CREATE; + else if ( aEncodedMP.isEmpty() ) + { +@@ -867,14 +913,15 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + m_aMasterPasswd = aPass; + std::vector< OUString > aMaster( 1, m_aMasterPasswd ); + +- m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); ++ OUString sIV = createIV(); ++ m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, sIV, m_aMasterPasswd ), sIV ); + } + else + { + if (m_pStorageFile->getStorageVersion() == 0) + aPass = ReencodeAsOldHash(aPass); + +- std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) ); ++ std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aEncodedMPIV, aPass, aRMode ) ); + if( aRM.empty() || aPass != aRM[0] ) + { + bAskAgain = true; +@@ -1031,7 +1078,8 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere + { + sal_Int32 oldLen = aUsers.getLength(); + aUsers.realloc( oldLen + 1 ); +- aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); ++ aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), aNP.GetPersistentIV(), ++ GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); + } + + if( aUsers.hasElements() ) +@@ -1048,12 +1096,12 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere + sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) + { + bool bResult = false; +- OUString aEncodedMP; ++ OUString aEncodedMP, aEncodedMPIV; + uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; + ::osl::MutexGuard aGuard( mMutex ); + + // the method should fail if there is no master password +- if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + { + if ( aEncodedMP.isEmpty() ) + { +@@ -1122,8 +1170,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< + + bool bCanChangePassword = true; + // if there is already a stored master password it should be entered by the user before the change happen +- OUString aEncodedMP; +- if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ OUString aEncodedMP, aEncodedMPIV; ++ if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) +@@ -1142,7 +1190,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< + // store the new master password + m_aMasterPasswd = aPass; + std::vector< OUString > aMaster( 1, m_aMasterPasswd ); +- m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); ++ OUString aIV = createIV(); ++ m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, aIV, m_aMasterPasswd ), aIV ); + + // store all the entries with the new password + for ( const auto& rURL : aPersistent ) +@@ -1167,7 +1216,7 @@ void SAL_CALL PasswordContainer::removeMasterPassword() + if ( m_pStorageFile ) + { + m_aMasterPasswd.clear(); +- m_pStorageFile->setEncodedMP( OUString() ); // let the master password be removed from configuration ++ m_pStorageFile->setEncodedMP( OUString(), OUString() ); // let the master password be removed from configuration + } + } + +@@ -1178,8 +1227,8 @@ sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( ) + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + +- OUString aEncodedMP; +- return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ); ++ OUString aEncodedMP, aEncodedMPIV; ++ return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ); + } + + sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( sal_Bool bAllow ) +@@ -1226,8 +1275,8 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere + + bool bCanChangePassword = true; + // if there is already a stored nondefault master password it should be entered by the user before the change happen +- OUString aEncodedMP; +- if( m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.isEmpty() ) ++ OUString aEncodedMP, aEncodedMPIV; ++ if( m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && !aEncodedMP.isEmpty() ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) +@@ -1244,7 +1293,7 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere + + // store the empty string to flag the default master password + m_aMasterPasswd = aPass; +- m_pStorageFile->setEncodedMP( OUString(), true ); ++ m_pStorageFile->setEncodedMP( OUString(), OUString(), true ); + + // store all the entries with the new password + for ( const auto& rURL : aPersistent ) +@@ -1268,8 +1317,8 @@ sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed() + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + +- OUString aEncodedMP; +- return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.isEmpty() ); ++ OUString aEncodedMP, aEncodedMPIV; ++ return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && aEncodedMP.isEmpty() ); + } + + +diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx +index cf5c717d0c9e..4e3a6629139e 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.hxx ++++ b/svl/source/passwordcontainer/passwordcontainer.hxx +@@ -33,6 +33,7 @@ + #include + #include + ++#include + #include + #include + +@@ -51,11 +52,12 @@ class NamePassRecord + ::std::vector< OUString > m_aMemPass; + + // persistent passwords are encrypted in one string +- bool m_bHasPersPass; ++ bool m_bHasPersPass; + OUString m_aPersPass; ++ OUString m_aPersistentIV; + + void InitArrays( bool bHasMemoryList, const ::std::vector< OUString >& aMemoryList, +- bool bHasPersistentList, const OUString& aPersistentList ) ++ bool bHasPersistentList, const OUString& aPersistentList, const OUString& aPersistentIV ) + { + m_bHasMemPass = bHasMemoryList; + if ( bHasMemoryList ) +@@ -63,7 +65,10 @@ class NamePassRecord + + m_bHasPersPass = bHasPersistentList; + if ( bHasPersistentList ) ++ { + m_aPersPass = aPersistentList; ++ m_aPersistentIV = aPersistentIV; ++ } + } + + public: +@@ -75,11 +80,12 @@ public: + { + } + +- NamePassRecord( const OUString& aName, const OUString& aPersistentList ) ++ NamePassRecord( const OUString& aName, const OUString& aPersistentList, const OUString& aPersistentIV ) + : m_aName( aName ) + , m_bHasMemPass( false ) + , m_bHasPersPass( true ) + , m_aPersPass( aPersistentList ) ++ , m_aPersistentIV( aPersistentIV ) + { + } + +@@ -88,7 +94,8 @@ public: + , m_bHasMemPass( false ) + , m_bHasPersPass( false ) + { +- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass ); ++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, ++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV ); + } + + NamePassRecord& operator=( const NamePassRecord& aRecord ) +@@ -99,7 +106,9 @@ public: + + m_aMemPass.clear(); + m_aPersPass.clear(); +- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass ); ++ m_aPersistentIV.clear(); ++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, ++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV ); + } + return *this; + } +@@ -135,15 +144,24 @@ public: + return OUString(); + } + ++ OUString GetPersistentIV() const ++ { ++ if ( m_bHasPersPass ) ++ return m_aPersistentIV; ++ ++ return OUString(); ++ } ++ + void SetMemPasswords( const ::std::vector< OUString >& aMemList ) + { + m_aMemPass = aMemList; + m_bHasMemPass = true; + } + +- void SetPersPasswords( const OUString& aPersList ) ++ void SetPersPasswords( const OUString& aPersList, const OUString& aPersIV ) + { + m_aPersPass = aPersList; ++ m_aPersistentIV = aPersIV; + m_bHasPersPass = true; + } + +@@ -158,6 +176,7 @@ public: + { + m_bHasPersPass = false; + m_aPersPass.clear(); ++ m_aPersistentIV.clear(); + } + } + +@@ -181,6 +200,7 @@ private: + PasswordContainer* mainCont; + bool hasEncoded; + OUString mEncoded; ++ OUString mEncodedIV; + + virtual void ImplCommit() override; + +@@ -201,8 +221,8 @@ public: + + sal_Int32 getStorageVersion(); + +- bool getEncodedMP( OUString& aResult ); +- void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false ); ++ bool getEncodedMP( OUString& aResult, OUString& aResultIV ); ++ void setEncodedMP( const OUString& aResult, const OUString& aResultIV, bool bAcceptEmpty = false ); + void setUseStorage( bool bUse ); + bool useStorage(); + +@@ -223,6 +243,29 @@ private: + css::uno::Reference< css::lang::XComponent > mComponent; + SysCredentialsConfig mUrlContainer; + ++ class RandomPool ++ { ++ private: ++ rtlRandomPool m_aRandomPool; ++ public: ++ RandomPool() : m_aRandomPool(rtl_random_createPool()) ++ { ++ } ++ rtlRandomPool get() ++ { ++ return m_aRandomPool; ++ } ++ ~RandomPool() ++ { ++ // Clean up random pool memory ++ rtl_random_destroyPool(m_aRandomPool); ++ } ++ }; ++ ++ RandomPool mRandomPool; ++ ++ OUString createIV(); ++ + /// @throws css::uno::RuntimeException + css::uno::Sequence< css::task::UserRecord > CopyToUserRecordSequence( + const ::std::vector< NamePassRecord >& original, +@@ -273,10 +316,10 @@ css::task::UrlRecord find( + const css::uno::Reference< css::task::XInteractionHandler >& Handler ); + + /// @throws css::uno::RuntimeException +- static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aMasterPassword, css::task::PasswordRequestMode mode ); ++ static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPassword, css::task::PasswordRequestMode mode ); + + /// @throws css::uno::RuntimeException +- static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPassword ); ++ static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPassword ); + + public: + PasswordContainer( const css::uno::Reference< css::lang::XMultiServiceFactory >& ); +-- +2.37.1 + diff --git a/SOURCES/0003-copy_paste_error-data1-looks-like-a-copy-paste-error.patch b/SOURCES/0003-copy_paste_error-data1-looks-like-a-copy-paste-error.patch new file mode 100644 index 0000000..6f00608 --- /dev/null +++ b/SOURCES/0003-copy_paste_error-data1-looks-like-a-copy-paste-error.patch @@ -0,0 +1,37 @@ +From 22eb26fe2f4ecf57bff0e1bb377f7af2e7a9e7e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 4 Nov 2020 09:28:02 +0000 +Subject: [PATCH 3/8] copy_paste_error data1 looks like a copy-paste error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change-Id: I937743f8d1789c68ed960c6a5aede0508dfa7bcd +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105282 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit 1aa5e450f065bfdae8c354344f23b897f48a166f) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105457 +Tested-by: Jean-Pierre Ledure +Reviewed-by: Jean-Pierre Ledure +(cherry picked from commit 4a6ca8920afc0bbb8e36869416745d5b0163313c) +--- + wizards/source/access2base/access2base.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/wizards/source/access2base/access2base.py b/wizards/source/access2base/access2base.py +index af14a880cb3d..3cdc758e820d 100644 +--- a/wizards/source/access2base/access2base.py ++++ b/wizards/source/access2base/access2base.py +@@ -902,7 +902,7 @@ class Basic(object, metaclass = _Singleton): + @classmethod + def DateDiff(cls, add, date1, date2, weekstart = 1, yearstart = 1): + if isinstance(date1, datetime.datetime): date1 = date1.isoformat() +- if isinstance(date2, datetime.datetime): date2 = date1.isoformat() ++ if isinstance(date2, datetime.datetime): date2 = date2.isoformat() + return cls.M('PyDateDiff', _WRAPPERMODULE, add, date1, date2, weekstart, yearstart) + + @classmethod +-- +2.28.0 + diff --git a/SOURCES/0003-xmlsecurity-replace-XSecParser-implementation.patch b/SOURCES/0003-xmlsecurity-replace-XSecParser-implementation.patch new file mode 100644 index 0000000..08266f4 --- /dev/null +++ b/SOURCES/0003-xmlsecurity-replace-XSecParser-implementation.patch @@ -0,0 +1,2172 @@ +From 4201f1be45b4567ba64655439dcc39ac403c28e0 Mon Sep 17 00:00:00 2001 +From: Michael Stahl +Date: Fri, 12 Feb 2021 16:42:51 +0100 +Subject: [PATCH 3/6] xmlsecurity: replace XSecParser implementation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement Namespaces in XML and follow xmldsig-core and XAdES schemas. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110833 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 12b15be8f4f930a04d8056b9219ac969b42a9784) + +xmlsecurity: move XSecParser state into contexts + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111158 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 59df9e70ce1a7ec797b836bda7f9642912febc53) + +xmlsecurity: move XSecParser Reference state into contexts + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111159 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit cfeb89a758b5f0ec406f0d72444e52ed2f47b85e) + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111907 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit ad5930e87e788780a255523f106deb1dde5d7b37) + +Change-Id: I03537b51bb757ecbfa63a826b38de543c70ba032 +--- + include/xmloff/xmlimp.hxx | 6 +- + include/xmloff/xmlnmspe.hxx | 7 + + include/xmloff/xmltoken.hxx | 13 + + xmloff/source/core/xmlimp.cxx | 26 +- + xmloff/source/core/xmltoken.cxx | 13 + + xmloff/source/token/tokens.txt | 10 + + xmlsecurity/source/helper/xsecparser.cxx | 1629 +++++++++++++++++----- + xmlsecurity/source/helper/xsecparser.hxx | 99 +- + 8 files changed, 1425 insertions(+), 378 deletions(-) + +diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx +index 6d0dda96596a..8d557789aa4c 100644 +--- a/include/xmloff/xmlimp.hxx ++++ b/include/xmloff/xmlimp.hxx +@@ -229,8 +229,12 @@ class XMLOFF_DLLPUBLIC SvXMLImport : public cppu::WeakImplHelper< + + static void initializeNamespaceMaps(); + void registerNamespaces(); +- std::unique_ptr processNSAttributes( ++public: ++ static std::unique_ptr processNSAttributes( ++ std::unique_ptr & rpNamespaceMap, ++ SvXMLImport *const pImport, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList); ++private: + void Characters(const OUString& aChars); + + css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator; +diff --git a/include/xmloff/xmlnmspe.hxx b/include/xmloff/xmlnmspe.hxx +index b079053c38d3..302a134f92fe 100644 +--- a/include/xmloff/xmlnmspe.hxx ++++ b/include/xmloff/xmlnmspe.hxx +@@ -66,6 +66,13 @@ XML_NAMESPACE( XML_NAMESPACE_OF, 34U ) // OpenFormula aka ODFF + XML_NAMESPACE( XML_NAMESPACE_XHTML, 35U ) + XML_NAMESPACE( XML_NAMESPACE_GRDDL, 36U ) + XML_NAMESPACE( XML_NAMESPACE_VERSIONS_LIST, 37U ) ++// OOo extension digital signatures, used in ODF 1.1 ++XML_NAMESPACE( XML_NAMESPACE_DSIG_OOO, 38U ) ++// ODF 1.2 digital signature namespaces ++XML_NAMESPACE( XML_NAMESPACE_DSIG, 39U ) ++XML_NAMESPACE( XML_NAMESPACE_DS, 40U ) ++XML_NAMESPACE( XML_NAMESPACE_XADES132, 41U ) ++XML_NAMESPACE( XML_NAMESPACE_XADES141, 42U ) + + // namespaces for odf extended formats + +diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx +index b5105e5da0f3..a0e52903060a 100644 +--- a/include/xmloff/xmltoken.hxx ++++ b/include/xmloff/xmltoken.hxx +@@ -133,6 +133,19 @@ namespace xmloff { namespace token { + XML_NP_GRDDL, + XML_N_GRDDL, + ++ // OOo extension digital signatures, used in ODF 1.1 ++ XML_NP_DSIG_OOO, ++ XML_N_DSIG_OOO, ++ // ODF 1.2 digital signatures ++ XML_NP_DSIG, ++ XML_N_DSIG, ++ XML_NP_DS, ++ XML_N_DS, ++ XML_NP_XADES132, ++ XML_N_XADES132, ++ XML_NP_XADES141, ++ XML_N_XADES141, ++ + // ODF Enhanced namespaces + XML_NP_OFFICE_EXT, + XML_N_OFFICE_EXT, +diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx +index ef63550ff2be..bfc9d3fe819a 100644 +--- a/xmloff/source/core/xmlimp.cxx ++++ b/xmloff/source/core/xmlimp.cxx +@@ -653,6 +653,8 @@ void SAL_CALL SvXMLImport::endDocument() + } + + std::unique_ptr SvXMLImport::processNSAttributes( ++ std::unique_ptr & rpNamespaceMap, ++ SvXMLImport *const pImport, // TODO??? + const uno::Reference< xml::sax::XAttributeList >& xAttrList) + { + std::unique_ptr pRewindMap; +@@ -660,12 +662,13 @@ std::unique_ptr SvXMLImport::processNSAttributes( + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); +- if ( rAttrName == "office:version" ) ++ if (pImport && rAttrName == "office:version") + { +- mpImpl->aODFVersion = xAttrList->getValueByIndex( i ); ++ pImport->mpImpl->aODFVersion = xAttrList->getValueByIndex( i ); + + // the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2 +- if ( mpImpl->mStreamName == "content.xml" && !IsODFVersionConsistent( mpImpl->aODFVersion ) ) ++ if (pImport->mpImpl->mStreamName == "content.xml" ++ && !pImport->IsODFVersionConsistent(pImport->mpImpl->aODFVersion)) + { + throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!", + uno::Reference< uno::XInterface >(), +@@ -679,8 +682,8 @@ std::unique_ptr SvXMLImport::processNSAttributes( + { + if( !pRewindMap ) + { +- pRewindMap = std::move(mpNamespaceMap); +- mpNamespaceMap.reset(new SvXMLNamespaceMap(*pRewindMap)); ++ pRewindMap = std::move(rpNamespaceMap); ++ rpNamespaceMap.reset(new SvXMLNamespaceMap(*pRewindMap)); + } + const OUString& rAttrValue = xAttrList->getValueByIndex( i ); + +@@ -688,18 +691,18 @@ std::unique_ptr SvXMLImport::processNSAttributes( + ? OUString() + : rAttrName.copy( 6 ) ); + // Add namespace, but only if it is known. +- sal_uInt16 nKey = mpNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); ++ sal_uInt16 nKey = rpNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); + // If namespace is unknown, try to match a name with similar + // TC Id and version + if( XML_NAMESPACE_UNKNOWN == nKey ) + { + OUString aTestName( rAttrValue ); + if( SvXMLNamespaceMap::NormalizeURI( aTestName ) ) +- nKey = mpNamespaceMap->AddIfKnown( aPrefix, aTestName ); ++ nKey = rpNamespaceMap->AddIfKnown( aPrefix, aTestName ); + } + // If that namespace is not known, too, add it as unknown + if( XML_NAMESPACE_UNKNOWN == nKey ) +- mpNamespaceMap->Add( aPrefix, rAttrValue ); ++ rpNamespaceMap->Add( aPrefix, rAttrValue ); + + } + } +@@ -712,7 +715,8 @@ void SAL_CALL SvXMLImport::startElement( const OUString& rName, + // SAL_INFO("svg", "startElement " << rName); + // Process namespace attributes. This must happen before creating the + // context, because namespace declaration apply to the element name itself. +- std::unique_ptr pRewindMap(processNSAttributes(xAttrList)); ++ std::unique_ptr pRewindMap( ++ processNSAttributes(mpNamespaceMap, this, xAttrList)); + + // Get element's namespace and local name. + OUString aLocalName; +@@ -885,7 +889,7 @@ void SAL_CALL SvXMLImport::startFastElement (sal_Int32 Element, + + maNamespaceHandler->addNSDeclAttributes( maNamespaceAttrList ); + std::unique_ptr pRewindMap( +- processNSAttributes( maNamespaceAttrList.get() )); ++ processNSAttributes(mpNamespaceMap, this, maNamespaceAttrList.get())); + assert( dynamic_cast( xContext.get() ) != nullptr ); + SvXMLImportContext *pContext = static_cast( xContext.get() ); + if (pRewindMap) +@@ -2231,7 +2235,7 @@ void SAL_CALL SvXMLLegacyToFastDocHandler::endDocument() + void SAL_CALL SvXMLLegacyToFastDocHandler::startElement( const OUString& rName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList ) + { +- mrImport->processNSAttributes(xAttrList); ++ SvXMLImport::processNSAttributes(mrImport->mpNamespaceMap, mrImport.get(), xAttrList); + OUString aLocalName; + sal_uInt16 nPrefix = mrImport->mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); + Sequence< sal_Int8 > aLocalNameSeq( reinterpret_cast( +diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx +index fb760c6307c5..13f1415b8cc4 100644 +--- a/xmloff/source/core/xmltoken.cxx ++++ b/xmloff/source/core/xmltoken.cxx +@@ -137,6 +137,19 @@ namespace xmloff { namespace token { + TOKEN( "grddl", XML_NP_GRDDL ), + TOKEN( "http://www.w3.org/2003/g/data-view#", XML_N_GRDDL ), + ++ // OOo extension digital signatures, used in ODF 1.1 ++ TOKEN( "dsigooo", XML_NP_DSIG_OOO ), ++ TOKEN( "http://openoffice.org/2004/documentsignatures", XML_N_DSIG_OOO ), ++ // ODF 1.2 digital signature namespaces ++ TOKEN( "dsig", XML_NP_DSIG ), ++ TOKEN( "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0", XML_N_DSIG ), ++ TOKEN( "ds", XML_NP_DS ), ++ TOKEN( "http://www.w3.org/2000/09/xmldsig#", XML_N_DS ), ++ TOKEN( "xades132", XML_NP_XADES132 ), ++ TOKEN( "http://uri.etsi.org/01903/v1.3.2#", XML_N_XADES132 ), ++ TOKEN( "xades141", XML_NP_XADES141 ), ++ TOKEN( "http://uri.etsi.org/01903/v1.4.1#", XML_N_XADES141 ), ++ + // ODF Enhanced namespaces + TOKEN( "officeooo", XML_NP_OFFICE_EXT ), + TOKEN( "http://openoffice.org/2009/office", XML_N_OFFICE_EXT ), +diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt +index 024877e8cf45..b2b95e956bd1 100644 +--- a/xmloff/source/token/tokens.txt ++++ b/xmloff/source/token/tokens.txt +@@ -72,6 +72,16 @@ xhtml + N_XHTML_DUMMY + grddl + N_GRDDL_DUMMY ++dsigooo ++N_DSIG_OOO_DUMMY ++dsig ++N_DSIG_DUMMY ++ds ++N_DS_DUMMY ++xades132 ++N_XADES132_DUMMY ++xades141 ++N_XADES141_DUMMY + officeooo + N_OFFICE_EXT_DUMMY + formx +diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx +index 82f347bff976..5c92e5efa104 100644 +--- a/xmlsecurity/source/helper/xsecparser.cxx ++++ b/xmlsecurity/source/helper/xsecparser.cxx +@@ -21,6 +21,10 @@ + #include "xsecparser.hxx" + #include + #include ++ ++#include ++#include ++ + #include + #include + #include +@@ -29,471 +33,1460 @@ namespace cssu = com::sun::star::uno; + namespace cssxc = com::sun::star::xml::crypto; + namespace cssxs = com::sun::star::xml::sax; + +-XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, +- XSecController* pXSecController) +- : m_bInX509IssuerName(false) +- , m_bInX509SerialNumber(false) +- , m_bInX509Certificate(false) +- , m_bInGpgCertificate(false) +- , m_bInGpgKeyID(false) +- , m_bInGpgOwner(false) +- , m_bInCertDigest(false) +- , m_bInEncapsulatedX509Certificate(false) +- , m_bInSigningTime(false) +- , m_bInDigestValue(false) +- , m_bInSignatureValue(false) +- , m_bInDate(false) +- , m_bInDescription(false) +- , m_bInSignatureLineId(false) +- , m_bInSignatureLineValidImage(false) +- , m_bInSignatureLineInvalidImage(false) +- , m_pXSecController(pXSecController) +- , m_bReferenceUnresolved(false) +- , m_nReferenceDigestID(cssxc::DigestID::SHA1) +- , m_rXMLSignatureHelper(rXMLSignatureHelper) ++class XSecParser::Context + { +-} ++ protected: ++ friend class XSecParser; ++ XSecParser & m_rParser; ++ private: ++ std::unique_ptr m_pOldNamespaceMap; ++ ++ public: ++ Context(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : m_rParser(rParser) ++ , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual ~Context() = default; + +-OUString XSecParser::getIdAttr(const cssu::Reference< cssxs::XAttributeList >& xAttribs ) ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) ++ { ++ } ++ ++ virtual void EndElement() ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr 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 XSecParser::UnknownContext ++ : public XSecParser::Context + { +- OUString ouIdAttr = xAttribs->getValueByName("id"); ++ public: ++ UnknownContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } + +- if (ouIdAttr.isEmpty()) +- { +- ouIdAttr = xAttribs->getValueByName("Id"); +- } ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++}; + +- return ouIdAttr; ++auto XSecParser::Context::CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) ++-> std::unique_ptr ++{ ++ // default: create new base context ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + +-/* +- * XDocumentHandler +- */ +-void SAL_CALL XSecParser::startDocument( ) ++class XSecParser::LoPGPOwnerContext ++ : public XSecParser::Context + { +- m_bInX509IssuerName = false; +- m_bInX509SerialNumber = false; +- m_bInX509Certificate = false; +- m_bInGpgCertificate = false; +- m_bInGpgKeyID = false; +- m_bInGpgOwner = false; +- m_bInSignatureValue = false; +- m_bInDigestValue = false; +- m_bInDate = false; +- m_bInDescription = false; ++ private: ++ OUString m_Value; + +- if (m_xNextHandler.is()) +- { +- m_xNextHandler->startDocument(); +- } +-} ++ public: ++ LoPGPOwnerContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } + +-void SAL_CALL XSecParser::endDocument( ) ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setGpgOwner(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsPGPKeyPacketContext ++ : public XSecParser::Context + { +- if (m_xNextHandler.is()) +- { +- m_xNextHandler->endDocument(); +- } +-} ++ private: ++ OUString m_Value; ++ ++ public: ++ DsPGPKeyPacketContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setGpgCertificate(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsPGPKeyIDContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DsPGPKeyIDContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setGpgKeyID(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsPGPDataContext ++ : public XSecParser::Context ++{ ++ public: ++ DsPGPDataContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) override ++ { ++ m_rParser.m_pXSecController->switchGpgSignature(); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::DsX509CertificateContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DsX509CertificateContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setX509Certificate(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsX509SerialNumberContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DsX509SerialNumberContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setX509SerialNumber(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsX509IssuerNameContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DsX509IssuerNameContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setX509IssuerName(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::DsX509IssuerSerialContext ++ : public XSecParser::Context ++{ ++ public: ++ DsX509IssuerSerialContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::DsX509DataContext ++ : public XSecParser::Context ++{ ++ public: ++ DsX509DataContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::DsKeyInfoContext ++ : public XSecParser::Context ++{ ++ public: ++ DsKeyInfoContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // 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 XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++ ++}; ++ ++class XSecParser::DsSignatureValueContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DsSignatureValueContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 XSecParser::DsDigestValueContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString & m_rValue; ++ ++ public: ++ DsDigestValueContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) override ++ { ++ m_rValue.clear(); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_rValue += rChars; ++ } ++}; ++ ++class XSecParser::DsDigestMethodContext ++ : public XSecParser::Context ++{ ++ private: ++ sal_Int32 & m_rReferenceDigestID; ++ ++ public: ++ DsDigestMethodContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap, ++ sal_Int32 & rReferenceDigestID) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rReferenceDigestID(rReferenceDigestID) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 XSecParser::DsTransformContext ++ : public XSecParser::Context ++{ ++ private: ++ bool & m_rIsC14N; ++ ++ public: ++ DsTransformContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap, ++ bool & rIsC14N) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rIsC14N(rIsC14N) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); ++ ++ if (ouAlgorithm == ALGO_C14N) ++ /* ++ * a xml stream ++ */ ++ { ++ m_rIsC14N = true; ++ } ++ } ++}; ++ ++class XSecParser::DsTransformsContext ++ : public XSecParser::Context ++{ ++ private: ++ bool & m_rIsC14N; ++ ++ public: ++ DsTransformsContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap, ++ bool & rIsC14N) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rIsC14N(rIsC14N) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::DsReferenceContext ++ : public XSecParser::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::SHA1; ++ ++ public: ++ DsReferenceContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::DsSignatureMethodContext ++ : public XSecParser::Context ++{ ++ public: ++ DsSignatureMethodContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 XSecParser::DsSignedInfoContext ++ : public XSecParser::Context ++{ ++ public: ++ DsSignedInfoContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setReferenceCount(); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: ds:CanonicalizationMethod ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::XadesEncapsulatedX509CertificateContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ XadesEncapsulatedX509CertificateContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->addEncapsulatedX509Certificate(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::XadesCertificateValuesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesCertificateValuesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: xades:OtherCertificate ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::XadesUnsignedSignaturePropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesUnsignedSignaturePropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: ++ // xades:CounterSignature ++ // ^ old code would read a ds:Signature inside it? ++ // xades:SignatureTimeStamp ++ // xades:CompleteCertificateRefs ++ // xades:CompleteRevocationRefs ++ // xades:AttributeCertificateRefs ++ // xades:AttributeRevocationRefs ++ // xades:SigAndRefsTimeStamp ++ // xades:RefsOnlyTimeStamp ++ // xades:RevocationValues ++ // xades:AttrAuthoritiesCertValues ++ // ^ old code: was equivalent to CertificateValues ??? ++ // xades:AttributeRevocationValues ++ // xades:ArchiveTimeStamp ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::XadesUnsignedPropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesUnsignedPropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: xades:UnsignedDataObjectProperties ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); ++ } ++}; ++ ++class XSecParser::LoSignatureLineIdContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ LoSignatureLineIdContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setSignatureLineId(m_Value); ++ } ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::LoSignatureLineValidImageContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ LoSignatureLineValidImageContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setValidSignatureImage(m_Value); ++ } + +-void SAL_CALL XSecParser::startElement( +- const OUString& aName, +- const cssu::Reference< cssxs::XAttributeList >& xAttribs ) ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::LoSignatureLineInvalidImageContext ++ : public XSecParser::Context + { +- try +- { +- OUString ouIdAttr = getIdAttr(xAttribs); +- if (!ouIdAttr.isEmpty()) ++ private: ++ OUString m_Value; ++ ++ public: ++ LoSignatureLineInvalidImageContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->collectToVerify( ouIdAttr ); + } + +- if ( aName == "Signature" ) ++ virtual void EndElement() override + { +- m_rXMLSignatureHelper.StartVerifySignatureElement(); +- m_pXSecController->addSignature(); +- if (!ouIdAttr.isEmpty()) +- { +- m_pXSecController->setId( ouIdAttr ); +- } ++ m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } +- else if (aName == "SignatureMethod") ++ ++ virtual void Characters(OUString const& rChars) override ++ { ++ m_Value += rChars; ++ } ++}; ++ ++class XSecParser::LoSignatureLineContext ++ : public XSecParser::Context ++{ ++ public: ++ LoSignatureLineContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); +- if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 +- || ouAlgorithm == ALGO_ECDSASHA512) +- m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } +- else if ( aName == "Reference" ) ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- OUString ouUri = xAttribs->getValueByName("URI"); +- SAL_WARN_IF( ouUri.isEmpty(), "xmlsecurity.helper", "URI is empty" ); +- // Remember the type of this reference. +- OUString ouType = xAttribs->getValueByName("Type"); +- if (ouUri.startsWith("#")) ++ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId") + { +- /* +- * remove the first character '#' from the attribute value +- */ +- m_pXSecController->addReference( ouUri.copy(1), m_nReferenceDigestID, ouType ); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } +- else ++ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage") + { +- /* +- * remember the uri +- */ +- m_currentReferenceURI = ouUri; +- m_bReferenceUnresolved = true; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } +- } +- else if (aName == "DigestMethod") +- { +- OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); +- +- SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); +- if (!ouAlgorithm.isEmpty()) ++ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage") + { +- 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_nReferenceDigestID = cssxc::DigestID::SHA1; +- else if (ouAlgorithm == ALGO_XMLDSIGSHA256) +- m_nReferenceDigestID = cssxc::DigestID::SHA256; +- else if (ouAlgorithm == ALGO_XMLDSIGSHA512) +- m_nReferenceDigestID = cssxc::DigestID::SHA512; +- else +- m_nReferenceDigestID = 0; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "Transform") +- { +- if ( m_bReferenceUnresolved ) +- { +- OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); ++}; + +- if (ouAlgorithm == ALGO_C14N) +- /* +- * a xml stream +- */ +- { +- m_pXSecController->addStreamReference( m_currentReferenceURI, false, m_nReferenceDigestID ); +- m_bReferenceUnresolved = false; +- } +- } ++class XSecParser::XadesCertDigestContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; ++ ++ public: ++ XadesCertDigestContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { + } +- else if (aName == "X509IssuerName") ++ ++ virtual void EndElement() override + { +- m_ouX509IssuerName.clear(); +- m_bInX509IssuerName = true; ++ m_rParser.m_pXSecController->setCertDigest(m_Value/* FIXME , m_nReferenceDigestID*/); + } +- else if (aName == "X509SerialNumber") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_ouX509SerialNumber.clear(); +- m_bInX509SerialNumber = true; ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "X509Certificate") ++}; ++ ++class XSecParser::XadesCertContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesCertContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_ouX509Certificate.clear(); +- m_bInX509Certificate = true; + } +- else if (aName == "PGPData") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_pXSecController->switchGpgSignature(); ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "PGPKeyID") ++}; ++ ++class XSecParser::XadesSigningCertificateContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesSigningCertificateContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_ouGpgKeyID.clear(); +- m_bInGpgKeyID = true; + } +- else if (aName == "PGPKeyPacket") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_ouGpgCertificate.clear(); +- m_bInGpgCertificate = true; ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "loext:PGPOwner") ++}; ++ ++class XSecParser::XadesSigningTimeContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesSigningTimeContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_ouGpgOwner.clear(); +- m_bInGpgOwner = true; + } +- else if (aName == "SignatureValue") ++ ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) override + { +- m_ouSignatureValue.clear(); +- m_bInSignatureValue = true; ++ m_rParser.m_ouDate.clear(); + } +- else if (aName == "DigestValue" && !m_bInCertDigest) ++ ++ virtual void EndElement() override + { +- m_ouDigestValue.clear(); +- m_bInDigestValue = true; ++ m_rParser.m_pXSecController->setDate( m_rParser.m_ouDate ); + } +- else if (aName == "xd:CertDigest") ++ ++ virtual void Characters(OUString const& rChars) override + { +- m_ouCertDigest.clear(); +- m_bInCertDigest = true; ++ m_rParser.m_ouDate += rChars; + } +- // FIXME: Existing code here in xmlsecurity uses "xd" as the namespace prefix for XAdES, +- // while the sample document attached to tdf#76142 uses "xades". So accept either here. Of +- // course this is idiotic and wrong, the right thing would be to use a proper way to parse +- // XML that would handle namespaces correctly. I have no idea how substantial re-plumbing of +- // this code that would require. +- else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") ++}; ++ ++class XSecParser::XadesSignedSignaturePropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesSignedSignaturePropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_ouEncapsulatedX509Certificate.clear(); +- m_bInEncapsulatedX509Certificate = true; + } +- else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_ouDate.clear(); +- m_bInSigningTime = true; ++ m_rParser.HandleIdAttr(xAttrs); + } +- else if ( aName == "SignatureProperty" ) ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- if (!ouIdAttr.isEmpty()) ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine") + { +- m_pXSecController->setPropertyId( ouIdAttr ); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } ++ // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "dc:date") ++}; ++ ++class XSecParser::XadesSignedPropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesSignedPropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- if (m_ouDate.isEmpty()) +- m_bInDate = true; + } +- else if (aName == "dc:description") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_ouDescription.clear(); +- m_bInDescription = true; ++ m_rParser.HandleIdAttr(xAttrs); + } +- else if (aName == "loext:SignatureLineId") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_ouSignatureLineId.clear(); +- m_bInSignatureLineId = true; ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: xades:SignedDataObjectProperties ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "loext:SignatureLineValidImage") ++}; ++ ++class XSecParser::XadesQualifyingPropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ XadesQualifyingPropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_ouSignatureLineValidImage.clear(); +- m_bInSignatureLineValidImage = true; + } +- else if (aName == "loext:SignatureLineInvalidImage") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_ouSignatureLineInvalidImage.clear(); +- m_bInSignatureLineInvalidImage = true; ++ m_rParser.HandleIdAttr(xAttrs); + } + +- if (m_xNextHandler.is()) ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_xNextHandler->startElement(aName, xAttribs); ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- } +- catch (cssu::Exception& ) +- {//getCaughtException MUST be the first line in the catch block +- cssu::Any exc = cppu::getCaughtException(); +- throw cssxs::SAXException( +- "xmlsecurity: Exception in XSecParser::startElement", +- nullptr, exc); +- } +- catch (...) +- { +- throw cssxs::SAXException( +- "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, +- cssu::Any()); +- } +-} ++}; + +-void SAL_CALL XSecParser::endElement( const OUString& aName ) ++class XSecParser::DcDateContext ++ : public XSecParser::Context + { +- try +- { +- if (aName == "DigestValue" && !m_bInCertDigest) ++ private: ++ bool m_isIgnore = false; ++ ++ public: ++ DcDateContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_bInDigestValue = false; + } +- else if ( aName == "Reference" ) ++ ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) override + { +- if ( m_bReferenceUnresolved ) +- /* +- * it must be an octet stream +- */ ++ m_isIgnore = !m_rParser.m_ouDate.isEmpty(); ++ } ++ ++ virtual void EndElement() override ++ { ++ if (!m_isIgnore) + { +- m_pXSecController->addStreamReference( m_currentReferenceURI, true, m_nReferenceDigestID ); +- m_bReferenceUnresolved = false; ++ m_rParser.m_pXSecController->setDate( m_rParser.m_ouDate ); + } ++ } + +- m_pXSecController->setDigestValue( m_nReferenceDigestID, m_ouDigestValue ); ++ virtual void Characters(OUString const& rChars) override ++ { ++ if (!m_isIgnore) ++ { ++ m_rParser.m_ouDate += rChars; ++ } + } +- else if ( aName == "SignedInfo" ) ++}; ++ ++class XSecParser::DcDescriptionContext ++ : public XSecParser::Context ++{ ++ private: ++ OUString m_Value; ++ ++ public: ++ DcDescriptionContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->setReferenceCount(); + } +- else if ( aName == "SignatureValue" ) ++ ++ virtual void EndElement() override + { +- m_pXSecController->setSignatureValue( m_ouSignatureValue ); +- m_bInSignatureValue = false; ++ m_rParser.m_pXSecController->setDescription(m_Value); + } +- else if (aName == "X509IssuerName") ++ ++ virtual void Characters(OUString const& rChars) override + { +- m_pXSecController->setX509IssuerName( m_ouX509IssuerName ); +- m_bInX509IssuerName = false; ++ m_Value += rChars; + } +- else if (aName == "X509SerialNumber") ++}; ++ ++class XSecParser::DsSignaturePropertyContext ++ : public XSecParser::Context ++{ ++ public: ++ DsSignaturePropertyContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber ); +- m_bInX509SerialNumber = false; + } +- else if (aName == "X509Certificate") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_pXSecController->setX509Certificate( m_ouX509Certificate ); +- m_bInX509Certificate = false; ++ OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); ++ if (!ouIdAttr.isEmpty()) ++ { ++ m_rParser.m_pXSecController->setPropertyId( ouIdAttr ); ++ } + } +- else if (aName == "PGPKeyID") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_pXSecController->setGpgKeyID( m_ouGpgKeyID ); +- m_bInGpgKeyID = false; ++ if (nNamespace == XML_NAMESPACE_DC && rName == "date") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DC && rName == "description") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "PGPKeyPacket") ++}; ++ ++class XSecParser::DsSignaturePropertiesContext ++ : public XSecParser::Context ++{ ++ public: ++ DsSignaturePropertiesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->setGpgCertificate( m_ouGpgCertificate ); +- m_bInGpgCertificate = false; + } +- else if (aName == "loext:PGPOwner") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_pXSecController->setGpgOwner( m_ouGpgOwner ); +- m_bInGpgOwner = false; ++ m_rParser.HandleIdAttr(xAttrs); + } +- else if (aName == "xd:CertDigest") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_pXSecController->setCertDigest( m_ouCertDigest ); +- m_bInCertDigest = false; ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") ++}; ++ ++class XSecParser::DsObjectContext ++ : public XSecParser::Context ++{ ++ public: ++ DsObjectContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->addEncapsulatedX509Certificate( m_ouEncapsulatedX509Certificate ); +- m_bInEncapsulatedX509Certificate = false; + } +- else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_pXSecController->setDate( m_ouDate ); +- m_bInSigningTime = false; ++ m_rParser.HandleIdAttr(xAttrs); + } +- else if (aName == "dc:date") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- if (m_bInDate) ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { +- m_pXSecController->setDate( m_ouDate ); +- m_bInDate = false; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ // missing: ds:Manifest ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "dc:description") ++}; ++ ++class XSecParser::DsSignatureContext ++ : public XSecParser::Context ++{ ++ public: ++ DsSignatureContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->setDescription( m_ouDescription ); +- m_bInDescription = false; + } +- else if (aName == "loext:SignatureLineId") ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override + { +- m_pXSecController->setSignatureLineId( m_ouSignatureLineId ); +- m_bInSignatureLineId = false; ++ 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 ); ++ } + } +- else if (aName == "loext:SignatureLineValidImage") ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_pXSecController->setValidSignatureImage( m_ouSignatureLineValidImage ); +- m_bInSignatureLineValidImage = false; ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Object") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- else if (aName == "loext:SignatureLineInvalidImage") ++}; ++ ++class XSecParser::DsigSignaturesContext ++ : public XSecParser::Context ++{ ++ public: ++ DsigSignaturesContext(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { +- m_pXSecController->setInvalidSignatureImage( m_ouSignatureLineInvalidImage ); +- m_bInSignatureLineInvalidImage = false; + } + +- if (m_xNextHandler.is()) ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override + { +- m_xNextHandler->endElement(aName); ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Signature") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +- } +- catch (cssu::Exception& ) +- {//getCaughtException MUST be the first line in the catch block +- cssu::Any exc = cppu::getCaughtException(); +- throw cssxs::SAXException( +- "xmlsecurity: Exception in XSecParser::endElement", +- nullptr, exc); +- } +- catch (...) +- { +- throw cssxs::SAXException( +- "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, +- cssu::Any()); +- } ++}; ++ ++ ++XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, ++ XSecController* pXSecController) ++ : 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( "_dsig_ooo", GetXMLToken(XML_N_DSIG_OOO), XML_NAMESPACE_DSIG_OOO ); ++ m_pNamespaceMap->Add( "_dsig", GetXMLToken(XML_N_DSIG), XML_NAMESPACE_DSIG ); ++ 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( "_office_libo", ++ GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); + } + +-void SAL_CALL XSecParser::characters( const OUString& aChars ) ++OUString XSecParser::HandleIdAttr(css::uno::Reference const& xAttrs) + { +- if (m_bInX509IssuerName) +- { +- m_ouX509IssuerName += aChars; +- } +- else if (m_bInX509SerialNumber) ++ OUString ouIdAttr = getIdAttr(xAttrs); ++ if (!ouIdAttr.isEmpty()) + { +- m_ouX509SerialNumber += aChars; ++ m_pXSecController->collectToVerify( ouIdAttr ); + } +- else if (m_bInX509Certificate) +- { +- m_ouX509Certificate += aChars; +- } +- else if (m_bInGpgCertificate) +- { +- m_ouGpgCertificate += aChars; +- } +- else if (m_bInGpgKeyID) ++ return ouIdAttr; ++} ++ ++OUString XSecParser::getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) ++{ ++ OUString ouIdAttr = xAttribs->getValueByName("id"); ++ ++ if (ouIdAttr.isEmpty()) + { +- m_ouGpgKeyID += aChars; ++ ouIdAttr = xAttribs->getValueByName("Id"); + } +- else if (m_bInGpgOwner) ++ ++ return ouIdAttr; ++} ++ ++/* ++ * XDocumentHandler ++ */ ++void SAL_CALL XSecParser::startDocument( ) ++{ ++ if (m_xNextHandler.is()) + { +- m_ouGpgOwner += aChars; ++ m_xNextHandler->startDocument(); + } +- else if (m_bInSignatureValue) ++} ++ ++void SAL_CALL XSecParser::endDocument( ) ++{ ++ if (m_xNextHandler.is()) + { +- m_ouSignatureValue += aChars; ++ m_xNextHandler->endDocument(); + } +- else if (m_bInDigestValue && !m_bInCertDigest) ++} ++ ++void SAL_CALL XSecParser::startElement( ++ const OUString& rName, ++ const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) ++{ ++ assert(m_pNamespaceMap); ++ std::unique_ptr pRewindMap( ++ SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); ++ ++ OUString localName; ++ sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); ++ ++ std::unique_ptr pContext; ++ ++ if (m_ContextStack.empty()) + { +- m_ouDigestValue += aChars; ++ if ((nPrefix == XML_NAMESPACE_DSIG || nPrefix == XML_NAMESPACE_DSIG_OOO) ++ && localName == "document-signatures") ++ { ++ pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap))); ++ } ++ else ++ { ++ throw css::xml::sax::SAXException( ++ "xmlsecurity: unexpected root element", nullptr, ++ css::uno::Any()); ++ } + } +- else if (m_bInDate) ++ else + { +- m_ouDate += aChars; ++ pContext = m_ContextStack.top()->CreateChildContext( ++ std::move(pRewindMap), nPrefix, localName); + } +- else if (m_bInDescription) ++ ++ m_ContextStack.push(std::move(pContext)); ++ assert(!pRewindMap); ++ ++ try + { +- m_ouDescription += aChars; ++ m_ContextStack.top()->StartElement(xAttribs); ++ ++ if (m_xNextHandler.is()) ++ { ++ m_xNextHandler->startElement(rName, xAttribs); ++ } + } +- else if (m_bInCertDigest) +- { +- m_ouCertDigest += aChars; ++ catch (css::uno::Exception& ) ++ {//getCaughtException MUST be the first line in the catch block ++ css::uno::Any exc = cppu::getCaughtException(); ++ throw css::xml::sax::SAXException( ++ "xmlsecurity: Exception in XSecParser::startElement", ++ nullptr, exc); + } +- else if (m_bInEncapsulatedX509Certificate) ++ catch (...) + { +- m_ouEncapsulatedX509Certificate += aChars; ++ throw css::xml::sax::SAXException( ++ "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, ++ css::uno::Any()); + } +- else if (m_bInSigningTime) ++} ++ ++void SAL_CALL XSecParser::endElement(const OUString& rName) ++{ ++ assert(!m_ContextStack.empty()); // this should be checked by sax parser? ++ ++ try + { +- m_ouDate += aChars; ++ m_ContextStack.top()->EndElement(); ++ ++ if (m_xNextHandler.is()) ++ { ++ m_xNextHandler->endElement(rName); ++ } + } +- else if (m_bInSignatureLineId) +- { +- m_ouSignatureLineId += aChars; ++ catch (css::uno::Exception& ) ++ {//getCaughtException MUST be the first line in the catch block ++ css::uno::Any exc = cppu::getCaughtException(); ++ throw css::xml::sax::SAXException( ++ "xmlsecurity: Exception in XSecParser::endElement", ++ nullptr, exc); + } +- else if (m_bInSignatureLineValidImage) ++ catch (...) + { +- m_ouSignatureLineValidImage += aChars; ++ throw css::xml::sax::SAXException( ++ "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, ++ css::uno::Any()); + } +- else if (m_bInSignatureLineInvalidImage) ++ ++ if (m_ContextStack.top()->m_pOldNamespaceMap) + { +- m_ouSignatureLineInvalidImage += aChars; ++ m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); + } ++ m_ContextStack.pop(); ++} ++ ++void SAL_CALL XSecParser::characters(const OUString& rChars) ++{ ++ assert(!m_ContextStack.empty()); // this should be checked by sax parser? ++ m_ContextStack.top()->Characters(rChars); + + if (m_xNextHandler.is()) + { +- m_xNextHandler->characters(aChars); ++ m_xNextHandler->characters(rChars); + } + } + +diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx +index d9b079aa3116..93efcb766e3e 100644 +--- a/xmlsecurity/source/helper/xsecparser.hxx ++++ b/xmlsecurity/source/helper/xsecparser.hxx +@@ -25,6 +25,10 @@ + + #include + ++#include ++ ++#include ++ + class XMLSignatureHelper; + class XSecController; + +@@ -48,47 +52,59 @@ class XSecParser: public cppu::WeakImplHelper + ******************************************************************************/ + { + friend class XSecController; ++public: ++ class Context; + private: ++ class UnknownContext; ++ class LoPGPOwnerContext; ++ class DsPGPKeyPacketContext; ++ class DsPGPKeyIDContext; ++ class DsPGPDataContext; ++ 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 LoSignatureLineIdContext; ++ class LoSignatureLineValidImageContext; ++ class LoSignatureLineInvalidImageContext; ++ class LoSignatureLineContext; ++ class XadesCertDigestContext; ++ class XadesCertContext; ++ class XadesSigningCertificateContext; ++ class XadesSigningTimeContext; ++ class XadesSignedSignaturePropertiesContext; ++ class XadesSignedPropertiesContext; ++ class XadesQualifyingPropertiesContext; ++ class DcDateContext; ++ class DcDescriptionContext; ++ class DsSignaturePropertyContext; ++ class DsSignaturePropertiesContext; ++ class DsObjectContext; ++ class DsSignatureContext; ++ class DsigSignaturesContext; ++ + /* + * the following members are used to reserve the signature information, + * including X509IssuerName, X509SerialNumber, and X509Certificate,etc. + */ +- OUString m_ouX509IssuerName; +- OUString m_ouX509SerialNumber; +- OUString m_ouX509Certificate; +- OUString m_ouGpgCertificate; +- OUString m_ouGpgKeyID; +- OUString m_ouGpgOwner; +- OUString m_ouCertDigest; +- OUString m_ouEncapsulatedX509Certificate; +- OUString m_ouDigestValue; +- OUString m_ouSignatureValue; + OUString m_ouDate; +- /// Characters of a element, as just read from XML. +- OUString m_ouDescription; +- OUString m_ouSignatureLineId; +- OUString m_ouSignatureLineValidImage; +- OUString m_ouSignatureLineInvalidImage; + +- /* +- * whether inside a particular element +- */ +- bool m_bInX509IssuerName; +- bool m_bInX509SerialNumber; +- bool m_bInX509Certificate; +- bool m_bInGpgCertificate; +- bool m_bInGpgKeyID; +- bool m_bInGpgOwner; +- bool m_bInCertDigest; +- bool m_bInEncapsulatedX509Certificate; +- bool m_bInSigningTime; +- bool m_bInDigestValue; +- bool m_bInSignatureValue; +- bool m_bInDate; +- bool m_bInDescription; +- bool m_bInSignatureLineId; +- bool m_bInSignatureLineValidImage; +- bool m_bInSignatureLineInvalidImage; ++ std::stack> m_ContextStack; ++ std::unique_ptr m_pNamespaceMap; + + /* + * the XSecController collaborating with XSecParser +@@ -101,22 +117,9 @@ private: + css::uno::Reference< + css::xml::sax::XDocumentHandler > m_xNextHandler; + +- /* +- * this string is used to remember the current handled reference's URI, +- * +- * because it can be decided whether a stream reference is xml based or binary based +- * only after the Transforms element is read in, so we have to reserve the reference's +- * URI when the startElement event is met. +- */ +- OUString m_currentReferenceURI; +- bool m_bReferenceUnresolved; +- +- // Relevant for ODF. The digest algorithm selected by the current DigestMethod element's +- // Algorithm attribute in the current Reference element. From css::xml::crypto::DigestID. +- sal_Int32 m_nReferenceDigestID; + XMLSignatureHelper& m_rXMLSignatureHelper; + +-private: ++ OUString HandleIdAttr(css::uno::Reference const& xAttrs); + static OUString getIdAttr(const css::uno::Reference< + css::xml::sax::XAttributeList >& xAttribs ); + +-- +2.32.0 + diff --git a/SOURCES/0004-CVE-2021-25634.patch b/SOURCES/0004-CVE-2021-25634.patch new file mode 100644 index 0000000..af2c9a1 --- /dev/null +++ b/SOURCES/0004-CVE-2021-25634.patch @@ -0,0 +1,397 @@ +From 9ef423d4e7c85629772131b3216b98e17d7b8d7e Mon Sep 17 00:00:00 2001 +From: Michael Stahl +Date: Thu, 18 Feb 2021 19:22:31 +0100 +Subject: [PATCH 4/6] CVE-2021-25634 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +xmlsecurity: XSecParser confused about multiple timestamps + +LO writes timestamp both to dc:date and xades:SigningTime elements. + +The parser tries to avoid reading multiple dc:date, preferring the first +one, but doesn't care about multiple xades:SigningTime, for undocumented +reasons. + +Ideally something should check all read values for consistency. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111160 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 4ab8d9c09a5873ca0aea56dafa1ab34758d52ef7) + +xmlsecurity: remove XSecController::setPropertyId() + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111252 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit d2a345e1163616fe3201ef1d6c758e2e819214e0) + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111908 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit abe77c4fcb9ea97d9fff07eaea6d8863bcba5b02) + +Change-Id: Ic018ee89797a1c8a4f870ae102af48006de930ef +--- + include/svl/sigstruct.hxx | 7 +- + xmlsecurity/inc/xsecctl.hxx | 5 +- + xmlsecurity/source/helper/ooxmlsecparser.cxx | 4 +- + xmlsecurity/source/helper/xsecctl.cxx | 2 +- + xmlsecurity/source/helper/xsecparser.cxx | 81 ++++++++++---------- + xmlsecurity/source/helper/xsecparser.hxx | 6 -- + xmlsecurity/source/helper/xsecsign.cxx | 4 +- + xmlsecurity/source/helper/xsecverify.cxx | 39 ++++------ + 8 files changed, 68 insertions(+), 80 deletions(-) + +diff --git a/include/svl/sigstruct.hxx b/include/svl/sigstruct.hxx +index f6ee242c84d1..7a0296fa9fae 100644 +--- a/include/svl/sigstruct.hxx ++++ b/include/svl/sigstruct.hxx +@@ -103,6 +103,9 @@ struct SignatureInformation + // XAdES EncapsulatedX509Certificate values + std::set maEncapsulatedX509Certificates; + ++ OUString ouSignatureId; ++ // signature may contain multiple time stamps - check they're consistent ++ bool hasInconsistentSigningTime = false; + //We also keep the date and time as string. This is done when this + //structure is created as a result of a XML signature being read. + //When then a signature is added or another removed, then the original +@@ -115,8 +118,8 @@ struct SignatureInformation + //and the converted time is written back, then the string looks different + //and the signature is broken. + OUString ouDateTime; +- OUString ouSignatureId; +- OUString ouPropertyId; ++ /// The Id attribute of the element that contains the . ++ OUString ouDateTimePropertyId; + /// Characters of the element inside the signature. + OUString ouDescription; + /// The Id attribute of the element that contains the . +diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx +index 351c94a2a3e6..7baa219fb13c 100644 +--- a/xmlsecurity/inc/xsecctl.hxx ++++ b/xmlsecurity/inc/xsecctl.hxx +@@ -271,8 +271,8 @@ private: + void setGpgCertificate( OUString const & ouGpgCert ); + void setGpgOwner( OUString const & ouGpgOwner ); + +- void setDate( OUString const & ouDate ); +- void setDescription(const OUString& rDescription); ++ void setDate(OUString const& rId, OUString const& ouDate); ++ void setDescription(OUString const& rId, OUString const& rDescription); + void setCertDigest(const OUString& rCertDigest); + void setValidSignatureImage(const OUString& rValidSigImg); + void setInvalidSignatureImage(const OUString& rInvalidSigImg); +@@ -283,7 +283,6 @@ public: + + private: + void setId( OUString const & ouId ); +- void setPropertyId( OUString const & ouPropertyId ); + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); +diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx +index c22e8c2261bf..a200de60c07a 100644 +--- a/xmlsecurity/source/helper/ooxmlsecparser.cxx ++++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx +@@ -192,12 +192,12 @@ void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) + } + else if (rName == "mdssi:Value") + { +- m_pXSecController->setDate(m_aMdssiValue); ++ m_pXSecController->setDate("", m_aMdssiValue); + m_bInMdssiValue = false; + } + else if (rName == "SignatureComments") + { +- m_pXSecController->setDescription(m_aSignatureComments); ++ m_pXSecController->setDescription("", m_aSignatureComments); + m_bInSignatureComments = false; + } + else if (rName == "X509IssuerName") +diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx +index ab108d13c224..8d5ea68c768b 100644 +--- a/xmlsecurity/source/helper/xsecctl.cxx ++++ b/xmlsecurity/source/helper/xsecctl.cxx +@@ -819,7 +819,7 @@ void XSecController::exportSignature( + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Id", +- signatureInfo.ouPropertyId); ++ signatureInfo.ouDateTimePropertyId); + pAttributeList->AddAttribute( + "Target", + "#" + signatureInfo.ouSignatureId); +diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx +index 5c92e5efa104..9cc9312b4d9f 100644 +--- a/xmlsecurity/source/helper/xsecparser.cxx ++++ b/xmlsecurity/source/helper/xsecparser.cxx +@@ -978,6 +978,9 @@ class XSecParser::XadesSigningCertificateContext + class XSecParser::XadesSigningTimeContext + : public XSecParser::Context + { ++ private: ++ OUString m_Value; ++ + public: + XadesSigningTimeContext(XSecParser & rParser, + std::unique_ptr pOldNamespaceMap) +@@ -985,20 +988,14 @@ class XSecParser::XadesSigningTimeContext + { + } + +- virtual void StartElement( +- css::uno::Reference const& /*xAttrs*/) override +- { +- m_rParser.m_ouDate.clear(); +- } +- + virtual void EndElement() override + { +- m_rParser.m_pXSecController->setDate( m_rParser.m_ouDate ); ++ m_rParser.m_pXSecController->setDate("", m_Value); + } + + virtual void Characters(OUString const& rChars) override + { +- m_rParser.m_ouDate += rChars; ++ m_Value += rChars; + } + }; + +@@ -1104,35 +1101,20 @@ class XSecParser::DcDateContext + : public XSecParser::Context + { + private: +- bool m_isIgnore = false; ++ OUString & m_rValue; + + public: + DcDateContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) + { + } + +- virtual void StartElement( +- css::uno::Reference const& /*xAttrs*/) override +- { +- m_isIgnore = !m_rParser.m_ouDate.isEmpty(); +- } +- +- virtual void EndElement() override +- { +- if (!m_isIgnore) +- { +- m_rParser.m_pXSecController->setDate( m_rParser.m_ouDate ); +- } +- } +- + virtual void Characters(OUString const& rChars) override + { +- if (!m_isIgnore) +- { +- m_rParser.m_ouDate += rChars; +- } ++ m_rValue += rChars; + } + }; + +@@ -1140,29 +1122,32 @@ class XSecParser::DcDescriptionContext + : public XSecParser::Context + { + private: +- OUString m_Value; ++ OUString & m_rValue; + + public: + DcDescriptionContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) + { + } + +- virtual void EndElement() override +- { +- m_rParser.m_pXSecController->setDescription(m_Value); +- } +- + virtual void Characters(OUString const& rChars) override + { +- m_Value += rChars; ++ m_rValue += rChars; + } + }; + + class XSecParser::DsSignaturePropertyContext + : public XSecParser::Context + { ++ private: ++ enum class SignatureProperty { Unknown, Date, Description }; ++ SignatureProperty m_Property = SignatureProperty::Unknown; ++ OUString m_Id; ++ OUString m_Value; ++ + public: + DsSignaturePropertyContext(XSecParser & rParser, + std::unique_ptr pOldNamespaceMap) +@@ -1173,10 +1158,22 @@ class XSecParser::DsSignaturePropertyContext + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); +- if (!ouIdAttr.isEmpty()) ++ m_Id = m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual void EndElement() override ++ { ++ switch (m_Property) + { +- m_rParser.m_pXSecController->setPropertyId( ouIdAttr ); ++ case SignatureProperty::Unknown: ++ SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); ++ break; ++ case SignatureProperty::Date: ++ m_rParser.m_pXSecController->setDate(m_Id, m_Value); ++ break; ++ case SignatureProperty::Description: ++ m_rParser.m_pXSecController->setDescription(m_Id, m_Value); ++ break; + } + } + +@@ -1186,11 +1183,13 @@ class XSecParser::DsSignaturePropertyContext + { + if (nNamespace == XML_NAMESPACE_DC && rName == "date") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ m_Property = SignatureProperty::Date; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_DC && rName == "description") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ m_Property = SignatureProperty::Description; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx +index 93efcb766e3e..7a0eb08bca28 100644 +--- a/xmlsecurity/source/helper/xsecparser.hxx ++++ b/xmlsecurity/source/helper/xsecparser.hxx +@@ -97,12 +97,6 @@ private: + class DsSignatureContext; + class DsigSignaturesContext; + +- /* +- * the following members are used to reserve the signature information, +- * including X509IssuerName, X509SerialNumber, and X509Certificate,etc. +- */ +- OUString m_ouDate; +- + std::stack> m_ContextStack; + std::unique_ptr m_pNamespaceMap; + +diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx +index 4d1b89949feb..5ed23281f083 100644 +--- a/xmlsecurity/source/helper/xsecsign.cxx ++++ b/xmlsecurity/source/helper/xsecsign.cxx +@@ -132,8 +132,8 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar + if (nStorageFormat != embed::StorageFormats::OFOPXML) + { + internalSignatureInfor.signatureInfor.ouSignatureId = createId(); +- internalSignatureInfor.signatureInfor.ouPropertyId = createId(); +- internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouPropertyId, -1, OUString() ); ++ internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId(); ++ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() ); + size++; + + if (bXAdESCompliantIfODF) +diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx +index 1f7fa9ac8ca8..5f5840334254 100644 +--- a/xmlsecurity/source/helper/xsecverify.cxx ++++ b/xmlsecurity/source/helper/xsecverify.cxx +@@ -321,7 +321,7 @@ void XSecController::setGpgOwner( OUString const & ouGpgOwner ) + isi.signatureInfor.ouGpgOwner = ouGpgOwner; + } + +-void XSecController::setDate( OUString const & ouDate ) ++void XSecController::setDate(OUString const& rId, OUString const& ouDate) + { + if (m_vInternalSignatureInformations.empty()) + { +@@ -329,17 +329,31 @@ void XSecController::setDate( OUString const & ouDate ) + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); ++ // there may be multiple timestamps in a signature - check them for consistency ++ if (!isi.signatureInfor.ouDateTime.isEmpty() ++ && isi.signatureInfor.ouDateTime != ouDate) ++ { ++ isi.signatureInfor.hasInconsistentSigningTime = true; ++ } + (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime); + isi.signatureInfor.ouDateTime = ouDate; ++ if (!rId.isEmpty()) ++ { ++ isi.signatureInfor.ouDateTimePropertyId = rId; ++ } + } + +-void XSecController::setDescription(const OUString& rDescription) ++void XSecController::setDescription(OUString const& rId, OUString const& rDescription) + { + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouDescription = rDescription; ++ if (!rId.isEmpty()) ++ { ++ rInformation.signatureInfor.ouDescriptionPropertyId = rId; ++ } + } + + void XSecController::setSignatureBytes(const uno::Sequence& rBytes) +@@ -433,27 +447,6 @@ void XSecController::setId( OUString const & ouId ) + isi.signatureInfor.ouSignatureId = ouId; + } + +-void XSecController::setPropertyId( OUString const & ouPropertyId ) +-{ +- if (m_vInternalSignatureInformations.empty()) +- { +- SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature"); +- return; +- } +- InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); +- +- if (isi.signatureInfor.ouPropertyId.isEmpty()) +- { +- // ID attribute is for the date. +- isi.signatureInfor.ouPropertyId = ouPropertyId; +- } +- else +- { +- // ID attribute is for the description. +- isi.signatureInfor.ouDescriptionPropertyId = ouPropertyId; +- } +-} +- + /* public: for signature verify */ + void XSecController::collectToVerify( const OUString& referenceId ) + { +-- +2.32.0 + diff --git a/SOURCES/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch b/SOURCES/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch new file mode 100644 index 0000000..c8f70ac --- /dev/null +++ b/SOURCES/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch @@ -0,0 +1,117 @@ +From 4cfd591942e4cfd3efc416bfac8e46e3580d37ba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 23 Mar 2022 13:03:30 +0000 +Subject: [PATCH] add infobar to prompt to refresh to replace old format + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131976 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit bbd196ff82bda9f66b4ba32a412f10cefe6da60e) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132307 +Reviewed-by: Sophie Gautier +Reviewed-by: Christian Lohmaier +(cherry picked from commit c5d01b11db3c83cb4a89d3b388d78e20dd3990b5) + +Change-Id: Id99cbf2b50a4ebf289dae6fc67e22e20afcda35b +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133906 +Tested-by: Michael Stahl +Reviewed-by: Michael Stahl +--- + include/sfx2/strings.hrc | 2 ++ + include/sfx2/viewfrm.hxx | 1 + + sfx2/source/view/viewfrm.cxx | 40 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 43 insertions(+) + +diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc +index 1f21f0a0f186..1db36e733c0c 100644 +--- a/include/sfx2/strings.hrc ++++ b/include/sfx2/strings.hrc +@@ -297,6 +297,8 @@ + #define STR_SIGNATURE_NOTVALIDATED_PARTIAL_OK NC_("STR_SIGNATURE_NOTVALIDATED_PARTIAL_OK", "The certificate could not be validated and the document is only partially signed.") + #define STR_SIGNATURE_OK NC_("STR_SIGNATURE_OK", "This document is digitally signed and the signature is valid.") + #define STR_SIGNATURE_SHOW NC_("STR_SIGNATURE_SHOW", "Show Signatures") ++#define STR_REFRESH_MASTER_PASSWORD NC_("STR_REFRESH_MASTER_PASSWORD", "The master password is stored in an outdated format, you should refresh it") ++#define STR_REFRESH_PASSWORD NC_("STR_REFRESH_PASSWORD", "Refresh Password") + + #define STR_CLOSE_PANE NC_("STR_CLOSE_PANE", "Close Pane") + #define STR_SFX_DOCK NC_("STR_SFX_DOCK", "Dock") +diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx +index fe336ba5f091..cc6a7dae7047 100644 +--- a/include/sfx2/viewfrm.hxx ++++ b/include/sfx2/viewfrm.hxx +@@ -61,6 +61,7 @@ protected: + DECL_LINK(WhatsNewHandler, Button*, void); + DECL_LINK(SwitchReadOnlyHandler, Button*, void); + DECL_LINK(SignDocumentHandler, Button*, void); ++ DECL_DLLPRIVATE_LINK(RefreshMasterPasswordHdl, Button*, void); + SAL_DLLPRIVATE void KillDispatcher_Impl(); + + virtual ~SfxViewFrame() override; +diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx +index 5a64599e5894..86e7d51bbfea 100644 +--- a/sfx2/source/view/viewfrm.cxx ++++ b/sfx2/source/view/viewfrm.cxx +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1390,6 +1391,24 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) + batch->commit(); + } + ++ if (officecfg::Office::Common::Passwords::HasMaster::get() && ++ officecfg::Office::Common::Passwords::StorageVersion::get() == 0) ++ { ++ // master password stored in deprecated format ++ VclPtr pOldMasterPasswordInfoBar = ++ AppendInfoBar("oldmasterpassword", "", ++ SfxResId(STR_REFRESH_MASTER_PASSWORD), InfobarType::DANGER, false); ++ if (pOldMasterPasswordInfoBar) ++ { ++ VclPtrInstance const xBtn(&GetWindow()); ++ xBtn->SetText(SfxResId(STR_REFRESH_PASSWORD)); ++ xBtn->SetSizePixel(xBtn->GetOptimalSize()); ++ xBtn->SetClickHdl(LINK(this, ++ SfxViewFrame, RefreshMasterPasswordHdl)); ++ pOldMasterPasswordInfoBar->addButton(xBtn); ++ } ++ } ++ + // read-only infobar if necessary + const SfxViewShell *pVSh; + const SfxShell *pFSh; +@@ -1565,6 +1584,27 @@ IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, Button*, void) + GetDispatcher()->Execute(SID_SIGNATURE); + } + ++IMPL_LINK_NOARG(SfxViewFrame, RefreshMasterPasswordHdl, Button*, void) ++{ ++ bool bChanged = false; ++ try ++ { ++ Reference< task::XPasswordContainer2 > xMasterPasswd( ++ task::PasswordContainer::create(comphelper::getProcessComponentContext())); ++ ++ css::uno::Reference xFrame = GetFrame().GetFrameInterface(); ++ css::uno::Reference xContainerWindow = xFrame->getContainerWindow(); ++ ++ uno::Reference xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), ++ xContainerWindow)); ++ bChanged = xMasterPasswd->changeMasterPassword(xTmpHandler); ++ } ++ catch (const Exception&) ++ {} ++ if (bChanged) ++ RemoveInfoBar(u"oldmasterpassword"); ++} ++ + void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh ) + { + m_pImpl->bResizeInToOut = true; +-- +2.37.1 + diff --git a/SOURCES/0004-Fix-use-of-uninitialized-SwFEShell-bTableCopied.patch b/SOURCES/0004-Fix-use-of-uninitialized-SwFEShell-bTableCopied.patch new file mode 100644 index 0000000..5c8a9c6 --- /dev/null +++ b/SOURCES/0004-Fix-use-of-uninitialized-SwFEShell-bTableCopied.patch @@ -0,0 +1,74 @@ +From cba3b6a12c9f0dc67a93bc3b708497a8f5eea5a5 Mon Sep 17 00:00:00 2001 +From: Stephan Bergmann +Date: Sun, 15 Dec 2019 10:03:56 +0100 +Subject: [PATCH 4/8] Fix use of uninitialized SwFEShell::bTableCopied + +...which had been introduced with 1e278d1d0cfb1d5375195aa764739f00633f21e8 +"tdf#37156 Writer menu: Paste as Nested table", during +`make CppunitTest_sw_uiwriter CPPUNIT_TEST_NAME=SwUiWriterTest::testDde +VALGRIND=memcheck`: + +> Conditional jump or move depends on uninitialised value(s) +> at 0x1EBBFAF8: SwTransferable::PrepareForCopy(bool) (sw/source/uibase/dochdl/swdtflvr.cxx:896) +> by 0x1EBC22BA: SwTransferable::Copy(bool) (sw/source/uibase/dochdl/swdtflvr.cxx:1144) +> by 0x1ECB552D: SwBaseShell::ExecClpbrd(SfxRequest&) (sw/source/uibase/shells/basesh.cxx:277) +> by 0x1C0D0BB0: SfxDispatcher::Call_Impl(SfxShell&, SfxSlot const&, SfxRequest&, bool) (include/sfx2/shell.hxx:197) +> by 0x1C0D72EB: SfxDispatcher::Execute_(SfxShell&, SfxSlot const&, SfxRequest&, SfxCallMode) (sfx2/source/control/dispatch.cxx:764) +> by 0x1C153977: SfxDispatchController_Impl::dispatch(com::sun::star::util::URL const&, com::sun::star::uno::Sequence const&, com::sun::star::uno::Reference const&) (sfx2/source/control/unoctitm.cxx:760) +> by 0x1C154916: SfxOfficeDispatch::dispatchWithNotification(com::sun::star::util::URL const&, com::sun::star::uno::Sequence const&, com::sun::star::uno::Reference const&) (sfx2/source/control/unoctitm.cxx:245) +> by 0x21FDE395: framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference const&, com::sun::star::util::URL const&, bool, com::sun::star::uno::Sequence const&) (framework/source/services/dispatchhelper.cxx:151) +> by 0x21FDEC95: framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference const&, rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence const&) (framework/source/services/dispatchhelper.cxx:109) +> by 0x19BF89C7: lcl_dispatchCommand(com::sun::star::uno::Reference const&, rtl::OUString const&, com::sun::star::uno::Sequence const&) (sw/qa/extras/uiwriter/uiwriter.cxx:4048) +> by 0x19C1F3EC: SwUiWriterTest::testDde() (sw/qa/extras/uiwriter/uiwriter.cxx:4060) +> Uninitialised value was created by a heap allocation +> at 0x4839E86: operator new(unsigned long) (/builddir/build/BUILD/valgrind-3.15.0/coregrind/m_replacemalloc/vg_replace_malloc.c:344) +> by 0x1ED6DA43: SwView::SwView(SfxViewFrame*, SfxViewShell*) (sw/source/uibase/uiview/view.cxx:864) +> by 0x1ED70065: SwView::CreateInstance(SfxViewFrame*, SfxViewShell*) (sw/source/uibase/uiview/view0.cxx:79) +> by 0x1C347941: SfxBaseModel::createViewController(rtl::OUString const&, com::sun::star::uno::Sequence const&, com::sun::star::uno::Reference const&) (sfx2/source/doc/sfxbasemodel.cxx:4233) +> by 0x1C458D81: (anonymous namespace)::SfxFrameLoader_Impl::load(com::sun::star::uno::Sequence const&, com::sun::star::uno::Reference const&) (sfx2/source/view/frmload.cxx:587) +> by 0x2401FAD0: framework::LoadEnv::impl_loadContent() (framework/source/loadenv/loadenv.cxx:1159) +> by 0x24020735: framework::LoadEnv::start() (framework/source/loadenv/loadenv.cxx:392) +> by 0x24020F89: framework::LoadEnv::startLoading(rtl::OUString const&, com::sun::star::uno::Sequence const&, com::sun::star::uno::Reference const&, rtl::OUString const&, int, LoadEnvFeatures) (framework/source/loadenv/loadenv.cxx:297) +> by 0x2402175B: framework::LoadEnv::loadComponentFromURL(com::sun::star::uno::Reference const&, com::sun::star::uno::Reference const&, rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence const&) (framework/source/loadenv/loadenv.cxx:166) +> by 0x24058172: framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence const&) (framework/source/services/desktop.cxx:610) +> by 0x1F5F7306: unotest::MacrosTest::loadFromDesktop(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Sequence const&) (unotest/source/cpp/macros_test.cxx:48) +> by 0x19C646A7: SwModelTestBase::loadURL(rtl::OUString const&, char const*, char const*) (sw/qa/inc/swmodeltestbase.hxx:764) +> by 0x19BD3792: SwUiWriterTest::createDoc(char const*) (sw/qa/extras/uiwriter/uiwriter.cxx:576) +> by 0x19C1F352: SwUiWriterTest::testDde() (sw/qa/extras/uiwriter/uiwriter.cxx:4055) + +(produced with a --enable-optimized build, so some inline frames are elided; see +also for the same issue +detected with UBSan). + +Change-Id: I080d296006bad4726942fb95a1338ea46c12bed4 +Reviewed-on: https://gerrit.libreoffice.org/85162 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann +(cherry picked from commit bcc74f619bf87ab97ffc48ab33e031d357952a70) +--- + sw/source/core/frmedt/fews.cxx | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sw/source/core/frmedt/fews.cxx b/sw/source/core/frmedt/fews.cxx +index 2ad7ec20a86f..0c4e097287c2 100644 +--- a/sw/source/core/frmedt/fews.cxx ++++ b/sw/source/core/frmedt/fews.cxx +@@ -665,6 +665,7 @@ SwFEShell::SwFEShell( SwDoc& rDoc, vcl::Window *pWindow, const SwViewOption *pOp + , m_bCheckForOLEInCaption(false) + , m_aPasteListeners(GetPasteMutex()) + , m_eTableInsertMode(SwTable::SEARCH_NONE) ++ , bTableCopied(false) + { + } + +@@ -673,6 +674,7 @@ SwFEShell::SwFEShell( SwEditShell& rShell, vcl::Window *pWindow ) + , m_bCheckForOLEInCaption(false) + , m_aPasteListeners(GetPasteMutex()) + , m_eTableInsertMode(SwTable::SEARCH_NONE) ++ , bTableCopied(false) + { + } + +-- +2.28.0 + diff --git a/SOURCES/0005-CVE-2021-25633.patch b/SOURCES/0005-CVE-2021-25633.patch new file mode 100644 index 0000000..1edc27a --- /dev/null +++ b/SOURCES/0005-CVE-2021-25633.patch @@ -0,0 +1,2120 @@ +From b970e561433f1cbeebd43c92c92c98c0468cc483 Mon Sep 17 00:00:00 2001 +From: Michael Stahl +Date: Fri, 19 Feb 2021 17:56:21 +0100 +Subject: [PATCH 5/6] CVE-2021-25633 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +xmlsecurity: ignore elements in ds:Object that aren't signed + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111253 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 2bfa00e6bf4b2a310a8b8f5060acec85b5f7a3ce) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111909 +Reviewed-by: Caolán McNamara +(cherry picked from commit 94ce59dd02fcfcaa1eb4f195b45a9a2edbd58242) + +Change-Id: I2e4411f0907b89e7ad6e0185cee8f12b600515e8 + +xmlsecurity: improve handling of multiple X509Data elements + +Combine everything related to a certificate in a new struct X509Data. + +The CertDigest is not actually written in the X509Data element but in +xades:Cert, so try to find the matching entry in +XSecController::setX509CertDigest(). + +There was a confusing interaction with PGP signatures, where ouGpgKeyID +was used for import, but export wrote the value from ouCertDigest +instead - this needed fixing. + +The main point of this is enforcing a constraint from xmldsig-core 4.5.4: + + All certificates appearing in an X509Data element MUST relate to the + validation key by either containing it or being part of a certification + chain that terminates in a certificate containing the validation key. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111254 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 9e82509b09f5fe2eb77bcdb8fd193c71923abb67) + +xmlsecurity: improve handling of multiple certificates per X509Data + +It turns out that an X509Data element can contain an arbitrary number of +each of its child elements. + +How exactly certificates of an issuer chain may or should be distributed +across multiple X509Data elements isn't terribly obvious. + +One thing that is clear is that any element that refers to or contains +one particular certificate has to be a child of the same X509Data +element, although in no particular order, so try to match the 2 such +elements that the parser supports in XSecController::setX509Data(). + +Presumably the only way it makes sense to have multiple signing +certificates is if they all contain the same key but are signed by +different CAs. This case isn't handled currently; CheckX509Data() will +complain there's not a single chain and validation of the certificates +will fail. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111500 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 5af5ea893bcb8a8eb472ac11133da10e5a604e66) + +xmlsecurity: add EqualDistinguishedNames() + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111545 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 1d3da3486d827dd5e7a3bf1c7a533f5aa9860e42) + +xmlsecurity: avoid exception in DigitalSignaturesDialog::getCertificate() + +Fallback to PGP if there's no X509 signing certificate because +CheckX509Data() failed prevents the dialog from popping up. + +To avoid confusing the user in this situation, the dialog should +show no certificate, which is already the case. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111664 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit 90b725675c2964f4a151d802d9afedd8bc2ae1a7) + +xmlsecurity: fix crash in DocumentDigitalSignatures::isAuthorTrusted() + +If the argument is null. + +This function also should use EqualDistinguishedNames(). + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111667 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit ca98e505cd69bf95d8ddb9387cf3f8e03ae4577d) + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111910 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit a1cf770c2d7ca3e153e0b1f01ddcc313bc2bed7f) + +Change-Id: I9633a980b0c18d58dfce24fc59396a833498a77d +--- + include/svl/sigstruct.hxx | 32 +- + svl/source/crypto/cryptosign.cxx | 16 +- + sw/source/core/edit/edfcol.cxx | 3 +- + xmlsecurity/inc/biginteger.hxx | 3 + + xmlsecurity/inc/xmlsignaturehelper.hxx | 12 + + xmlsecurity/inc/xsecctl.hxx | 15 +- + .../component/documentdigitalsignatures.cxx | 54 +-- + .../dialogs/digitalsignaturesdialog.cxx | 15 +- + .../source/helper/documentsignaturehelper.cxx | 63 ++-- + .../helper/documentsignaturemanager.cxx | 12 + + .../source/helper/ooxmlsecexporter.cxx | 23 +- + xmlsecurity/source/helper/ooxmlsecparser.cxx | 22 +- + .../source/helper/pdfsignaturehelper.cxx | 8 +- + .../source/helper/xmlsignaturehelper.cxx | 161 +++++++++ + xmlsecurity/source/helper/xsecctl.cxx | 84 +++-- + xmlsecurity/source/helper/xsecparser.cxx | 334 ++++++++++++------ + xmlsecurity/source/helper/xsecparser.hxx | 1 + + xmlsecurity/source/helper/xsecsign.cxx | 30 +- + xmlsecurity/source/helper/xsecverify.cxx | 143 ++++++-- + .../mscrypt/x509certificate_mscryptimpl.cxx | 47 +++ + .../mscrypt/xmlsignature_mscryptimpl.cxx | 2 + + .../xmlsec/nss/x509certificate_nssimpl.cxx | 25 ++ + .../xmlsec/nss/xmlsignature_nssimpl.cxx | 3 + + 23 files changed, 853 insertions(+), 255 deletions(-) + +diff --git a/include/svl/sigstruct.hxx b/include/svl/sigstruct.hxx +index 7a0296fa9fae..f00cbce6e4b8 100644 +--- a/include/svl/sigstruct.hxx ++++ b/include/svl/sigstruct.hxx +@@ -89,9 +89,30 @@ struct SignatureInformation + sal_Int32 nSecurityId; + css::xml::crypto::SecurityOperationStatus nStatus; + SignatureReferenceInformations vSignatureReferenceInfors; +- OUString ouX509IssuerName; +- OUString ouX509SerialNumber; +- OUString ouX509Certificate; ++ struct X509CertInfo ++ { ++ OUString X509IssuerName; ++ OUString X509SerialNumber; ++ OUString X509Certificate; ++ /// OOXML certificate SHA-256 digest, empty for ODF except when doing XAdES signature. ++ OUString CertDigest; ++ /// The certificate owner (aka subject). ++ OUString X509Subject; ++ }; ++ typedef std::vector X509Data; ++ // note: at parse time, it's unkown which one is the signing certificate; ++ // ImplVerifySignatures() figures it out and puts it at the back ++ std::vector X509Datas; ++ ++ X509CertInfo const* GetSigningCertificate() const ++ { ++ if (X509Datas.empty()) ++ { ++ return nullptr; ++ } ++ assert(!X509Datas.back().empty()); ++ return & X509Datas.back().back(); ++ } + + OUString ouGpgKeyID; + OUString ouGpgCertificate; +@@ -124,8 +145,6 @@ struct SignatureInformation + OUString ouDescription; + /// The Id attribute of the element that contains the . + OUString ouDescriptionPropertyId; +- /// OOXML certificate SHA-256 digest, empty for ODF except when doing XAdES signature. +- OUString ouCertDigest; + /// Valid and invalid signature line images + css::uno::Reference aValidSignatureImage; + css::uno::Reference aInvalidSignatureImage; +@@ -140,9 +159,6 @@ struct SignatureInformation + /// For PDF: the byte range doesn't cover the whole document. + bool bPartialDocumentSignature; + +- /// The certificate owner (aka subject). +- OUString ouSubject; +- + svl::crypto::SignatureMethodAlgorithm eAlgorithmID; + + SignatureInformation( sal_Int32 nId ) +diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx +index 5a3f0271c40d..1b882bb89deb 100644 +--- a/svl/source/crypto/cryptosign.cxx ++++ b/svl/source/crypto/cryptosign.cxx +@@ -2097,8 +2097,12 @@ bool Signing::Verify(const std::vector& aData, + aDerCert[i] = pCertificate->derCert.data[i]; + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, aDerCert); +- rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); +- rInformation.ouSubject = OUString(pCertificate->subjectName, PL_strlen(pCertificate->subjectName), RTL_TEXTENCODING_UTF8); ++ SignatureInformation::X509Data temp; ++ temp.emplace_back(); ++ temp.back().X509Certificate = aBuffer.makeStringAndClear(); ++ temp.back().X509Subject = OUString(pCertificate->subjectName, PL_strlen(pCertificate->subjectName), RTL_TEXTENCODING_UTF8); ++ rInformation.X509Datas.clear(); ++ rInformation.X509Datas.emplace_back(temp); + } + + PRTime nSigningTime; +@@ -2277,8 +2281,12 @@ bool Signing::Verify(const std::vector& aData, + aDerCert[i] = pSignerCertContext->pbCertEncoded[i]; + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, aDerCert); +- rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); +- rInformation.ouSubject = GetSubjectName(pSignerCertContext); ++ SignatureInformation::X509Data temp; ++ temp.emplace_back(); ++ temp.back().X509Certificate = aBuffer.makeStringAndClear(); ++ temp.back().X509Subject = GetSubjectName(pSignerCertContext); ++ rInformation.X509Datas.clear(); ++ rInformation.X509Datas.emplace_back(temp); + } + + if (bNonDetached) +diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx +index 2b49ee16ecc8..abbed5e40e94 100644 +--- a/sw/source/core/edit/edfcol.cxx ++++ b/sw/source/core/edit/edfcol.cxx +@@ -411,7 +411,8 @@ std::pair lcl_MakeParagraphSignatureFieldText(const SignatureDes + valid = valid + && aInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + +- msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.ouSubject + ", " + ++ assert(aInfo.GetSigningCertificate()); // it was valid ++ msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.GetSigningCertificate()->X509Subject + ", " + + aDescr.msDate; + msg += (!aDescr.msUsage.isEmpty() ? (" (" + aDescr.msUsage + "): ") : OUString(": ")); + msg += (valid ? SwResId(STR_VALID) : SwResId(STR_INVALID)); +diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx +index d07ecf45d8af..8b4d8a9143b5 100644 +--- a/xmlsecurity/inc/biginteger.hxx ++++ b/xmlsecurity/inc/biginteger.hxx +@@ -31,6 +31,9 @@ namespace xmlsecurity + { + XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString( const css::uno::Sequence< sal_Int8 >& serial ); + XSECXMLSEC_DLLPUBLIC css::uno::Sequence< sal_Int8 > numericStringToBigInteger ( const OUString& serialNumber ); ++ ++XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(OUString const& rName1, ++ OUString const& rName2); + } + + #endif +diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx +index 0fcbd665251f..2456ddd437ec 100644 +--- a/xmlsecurity/inc/xmlsignaturehelper.hxx ++++ b/xmlsecurity/inc/xmlsignaturehelper.hxx +@@ -28,6 +28,9 @@ + #include "xmlsignaturehelper.hxx" + #include "xsecctl.hxx" + ++#include ++#include ++ + class DateTime; + class UriBindingHelper; + +@@ -93,6 +96,15 @@ public: + // After signing/verifying, get information about signatures + SignatureInformation GetSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations GetSignatureInformations() const; ++ /// ImplVerifySignature calls this to figure out which X509Data is the ++ /// signing certificate and update the internal state with the result. ++ /// @return ++ /// A sequence with the signing certificate at the back on success. ++ /// An empty sequence on failure. ++ std::vector> ++ CheckAndUpdateSignatureInformation( ++ css::uno::Reference const& xSecEnv, ++ SignatureInformation const& rInfo); + + // See XSecController for documentation + void StartMission(const css::uno::Reference& xSecurityContext); +diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx +index 7baa219fb13c..7ce35cea22bf 100644 +--- a/xmlsecurity/inc/xsecctl.hxx ++++ b/xmlsecurity/inc/xsecctl.hxx +@@ -252,6 +252,7 @@ private: + /// Sets algorithm from . + void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + void switchGpgSignature(); ++ bool haveReferenceForId(OUString const& rId) const; + void addReference( + const OUString& ouUri, + sal_Int32 nDigestID, +@@ -262,9 +263,13 @@ private: + sal_Int32 nDigestID ); + void setReferenceCount() const; + +- void setX509IssuerName( OUString const & ouX509IssuerName ); +- void setX509SerialNumber( OUString const & ouX509SerialNumber ); +- void setX509Certificate( OUString const & ouX509Certificate ); ++ void setX509Data( ++ std::vector> & rX509IssuerSerials, ++ std::vector const& rX509Certificates); ++ void setX509CertDigest( ++ OUString const& rCertDigest, sal_Int32 const nReferenceDigestID, ++ OUString const& rX509IssuerName, OUString const& rX509SerialNumber); ++ + void setSignatureValue( OUString const & ouSignatureValue ); + void setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ); + void setGpgKeyID( OUString const & ouKeyID ); +@@ -273,7 +278,6 @@ private: + + void setDate(OUString const& rId, OUString const& ouDate); + void setDescription(OUString const& rId, OUString const& rDescription); +- void setCertDigest(const OUString& rCertDigest); + void setValidSignatureImage(const OUString& rValidSigImg); + void setInvalidSignatureImage(const OUString& rInvalidSigImg); + void setSignatureLineId(const OUString& rSignatureLineId); +@@ -302,6 +306,9 @@ public: + + SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations getSignatureInformations() const; ++ /// only verify can figure out which X509Data is the signing certificate ++ void UpdateSignatureInformation(sal_Int32 nSecurityId, ++ std::vector const& rDatas); + + static void exportSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, +diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx +index 52cb938a8e0a..8a5bf37a0432 100644 +--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx ++++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx +@@ -510,30 +510,36 @@ DocumentDigitalSignatures::ImplVerifySignatures( + const SignatureInformation& rInfo = aSignInfos[n]; + css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; + +- if (rInfo.ouGpgCertificate.isEmpty()) // X.509 ++ if (!rInfo.X509Datas.empty()) // X.509 + { +- if (!rInfo.ouX509Certificate.isEmpty()) +- rSigInfo.Signer = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); +- if (!rSigInfo.Signer.is()) +- rSigInfo.Signer = xSecEnv->getCertificate( +- rInfo.ouX509IssuerName, +- xmlsecurity::numericStringToBigInteger(rInfo.ouX509SerialNumber)); +- +- // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) +- // to find the parent certificate. It does not take into account that there can be several certificates +- // with the same subject name. +- try ++ std::vector> certs( ++ rSignatureHelper.CheckAndUpdateSignatureInformation( ++ xSecEnv, rInfo)); ++ if (certs.empty()) + { +- rSigInfo.CertificateStatus = xSecEnv->verifyCertificate( +- rSigInfo.Signer, Sequence>()); ++ rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } +- catch (SecurityException&) ++ else + { +- OSL_FAIL("Verification of certificate failed"); +- rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; ++ rSigInfo.Signer = certs.back(); ++ // get only intermediates ++ certs.pop_back(); ++ // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) ++ // to find the parent certificate. It does not take into account that there can be several certificates ++ // with the same subject name. ++ try ++ { ++ rSigInfo.CertificateStatus = xSecEnv->verifyCertificate( ++ rSigInfo.Signer, comphelper::containerToSequence(certs)); ++ } ++ catch (SecurityException&) ++ { ++ SAL_WARN("xmlsecurity.comp", "Verification of certificate failed"); ++ rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; ++ } + } + } +- else if (xGpgSecEnv.is()) // GPG ++ else if (!rInfo.ouGpgCertificate.isEmpty() && xGpgSecEnv.is()) // GPG + { + // TODO not ideal to retrieve cert by keyID, might + // collide, or PGPKeyID format might change - can't we +@@ -619,15 +625,19 @@ void DocumentDigitalSignatures::showCertificate( + } + + sal_Bool DocumentDigitalSignatures::isAuthorTrusted( +- const Reference< css::security::XCertificate >& Author ) ++ const Reference& xAuthor) + { +- OUString sSerialNum = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() ); ++ if (!xAuthor.is()) ++ { ++ return false; ++ } ++ OUString sSerialNum = xmlsecurity::bigIntegerToNumericString(xAuthor->getSerialNumber()); + + Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors(); + + return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(), +- [&Author, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { +- return ( rAuthor[0] == Author->getIssuerName() ) ++ [&xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { ++ return xmlsecurity::EqualDistinguishedNames(rAuthor[0], xAuthor->getIssuerName()) + && ( rAuthor[1] == sSerialNum ); + }); + } +diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +index ef67c7167c04..18ccaf2d2166 100644 +--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx ++++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +@@ -588,7 +588,7 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() + if (!rInfo.ouGpgCertificate.isEmpty()) + aType = "OpenPGP"; + // XML based: XAdES or not. +- else if (!rInfo.ouCertDigest.isEmpty()) ++ else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty()) + aType = "XAdES"; + else + aType = "XML-DSig"; +@@ -700,8 +700,8 @@ uno::Reference DigitalSignaturesDialog::getCertificate(c + uno::Reference xCert; + + //First we try to get the certificate which is embedded in the XML Signature +- if (xSecEnv.is() && !rInfo.ouX509Certificate.isEmpty()) +- xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); ++ if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty()) ++ xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate); + else { + //There must be an embedded certificate because we use it to get the + //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName +@@ -713,9 +713,12 @@ uno::Reference DigitalSignaturesDialog::getCertificate(c + } + + //In case there is no embedded certificate we try to get it from a local store +- if (!xCert.is() && xSecEnv.is()) +- xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) ); +- if (!xCert.is() && xGpgSecEnv.is()) ++ if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate()) ++ { ++ xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName, ++ xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber)); ++ } ++ if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty()) + xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") ); + + SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" ); +diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx +index 482ae6cc4126..ddff308ee52f 100644 +--- a/xmlsecurity/source/helper/documentsignaturehelper.cxx ++++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx +@@ -492,6 +492,29 @@ void DocumentSignatureHelper::writeDigestMethod( + xDocumentHandler->endElement("DigestMethod"); + } + ++static void WriteXadesCert( ++ uno::Reference const& xDocumentHandler, ++ SignatureInformation::X509CertInfo const& rCertInfo) ++{ ++ xDocumentHandler->startElement("xd:Cert", uno::Reference(new SvXMLAttributeList())); ++ xDocumentHandler->startElement("xd:CertDigest", uno::Reference(new SvXMLAttributeList())); ++ DocumentSignatureHelper::writeDigestMethod(xDocumentHandler); ++ xDocumentHandler->startElement("DigestValue", uno::Reference(new SvXMLAttributeList())); ++ assert(!rCertInfo.CertDigest.isEmpty()); ++ xDocumentHandler->characters(rCertInfo.CertDigest); ++ xDocumentHandler->endElement("DigestValue"); ++ xDocumentHandler->endElement("xd:CertDigest"); ++ xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference(new SvXMLAttributeList())); ++ xDocumentHandler->startElement("X509IssuerName", uno::Reference(new SvXMLAttributeList())); ++ xDocumentHandler->characters(rCertInfo.X509IssuerName); ++ xDocumentHandler->endElement("X509IssuerName"); ++ xDocumentHandler->startElement("X509SerialNumber", uno::Reference(new SvXMLAttributeList())); ++ xDocumentHandler->characters(rCertInfo.X509SerialNumber); ++ xDocumentHandler->endElement("X509SerialNumber"); ++ xDocumentHandler->endElement("xd:IssuerSerial"); ++ xDocumentHandler->endElement("xd:Cert"); ++} ++ + void DocumentSignatureHelper::writeSignedProperties( + const uno::Reference& xDocumentHandler, + const SignatureInformation& signatureInfo, +@@ -508,26 +531,26 @@ void DocumentSignatureHelper::writeSignedProperties( + xDocumentHandler->characters(sDate); + xDocumentHandler->endElement("xd:SigningTime"); + xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference(new SvXMLAttributeList())); +- xDocumentHandler->startElement("xd:Cert", uno::Reference(new SvXMLAttributeList())); +- xDocumentHandler->startElement("xd:CertDigest", uno::Reference(new SvXMLAttributeList())); +- writeDigestMethod(xDocumentHandler); +- +- xDocumentHandler->startElement("DigestValue", uno::Reference(new SvXMLAttributeList())); +- // TODO: this is empty for gpg signatures currently +- //assert(!signatureInfo.ouCertDigest.isEmpty()); +- xDocumentHandler->characters(signatureInfo.ouCertDigest); +- xDocumentHandler->endElement("DigestValue"); +- +- xDocumentHandler->endElement("xd:CertDigest"); +- xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference(new SvXMLAttributeList())); +- xDocumentHandler->startElement("X509IssuerName", uno::Reference(new SvXMLAttributeList())); +- xDocumentHandler->characters(signatureInfo.ouX509IssuerName); +- xDocumentHandler->endElement("X509IssuerName"); +- xDocumentHandler->startElement("X509SerialNumber", uno::Reference(new SvXMLAttributeList())); +- xDocumentHandler->characters(signatureInfo.ouX509SerialNumber); +- xDocumentHandler->endElement("X509SerialNumber"); +- xDocumentHandler->endElement("xd:IssuerSerial"); +- xDocumentHandler->endElement("xd:Cert"); ++ assert(signatureInfo.GetSigningCertificate() || !signatureInfo.ouGpgKeyID.isEmpty()); ++ if (signatureInfo.GetSigningCertificate()) ++ { ++ // how should this deal with multiple X509Data elements? ++ // for now, let's write all of the certificates ... ++ for (auto const& rData : signatureInfo.X509Datas) ++ { ++ for (auto const& it : rData) ++ { ++ WriteXadesCert(xDocumentHandler, it); ++ } ++ } ++ } ++ else ++ { ++ // for PGP, write empty mandatory X509IssuerName, X509SerialNumber ++ SignatureInformation::X509CertInfo temp; ++ temp.CertDigest = signatureInfo.ouGpgKeyID; ++ WriteXadesCert(xDocumentHandler, temp); ++ } + xDocumentHandler->endElement("xd:SigningCertificate"); + xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference(new SvXMLAttributeList())); +diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx +index a0e674c3bd1b..aa08dc5c499e 100644 +--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx ++++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx +@@ -585,6 +585,18 @@ void DocumentSignatureManager::read(bool bUseTempStream, bool bCacheLastSignatur + bCacheLastSignature); + maSignatureHelper.EndMission(); + ++ // this parses the XML independently from ImplVerifySignatures() - check ++ // certificates here too ... ++ for (auto const& it : maSignatureHelper.GetSignatureInformations()) ++ { ++ if (!it.X509Datas.empty()) ++ { ++ uno::Reference const xSecEnv( ++ getSecurityEnvironment()); ++ getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv, it); ++ } ++ } ++ + maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations(); + } + else +diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx +index cf87d6e1ad17..cae2ef3f5b16 100644 +--- a/xmlsecurity/source/helper/ooxmlsecexporter.cxx ++++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx +@@ -194,12 +194,23 @@ void OOXMLSecExporter::Impl::writeSignatureValue() + + void OOXMLSecExporter::Impl::writeKeyInfo() + { +- m_xDocumentHandler->startElement("KeyInfo", uno::Reference(new SvXMLAttributeList())); +- m_xDocumentHandler->startElement("X509Data", uno::Reference(new SvXMLAttributeList())); +- m_xDocumentHandler->startElement("X509Certificate", uno::Reference(new SvXMLAttributeList())); +- m_xDocumentHandler->characters(m_rInformation.ouX509Certificate); +- m_xDocumentHandler->endElement("X509Certificate"); +- m_xDocumentHandler->endElement("X509Data"); ++ m_xDocumentHandler->startElement( ++ "KeyInfo", uno::Reference(new SvXMLAttributeList())); ++ assert(m_rInformation.GetSigningCertificate()); ++ for (auto const& rData : m_rInformation.X509Datas) ++ { ++ m_xDocumentHandler->startElement( ++ "X509Data", uno::Reference(new SvXMLAttributeList())); ++ for (auto const& it : rData) ++ { ++ m_xDocumentHandler->startElement( ++ "X509Certificate", ++ uno::Reference(new SvXMLAttributeList())); ++ m_xDocumentHandler->characters(it.X509Certificate); ++ m_xDocumentHandler->endElement("X509Certificate"); ++ } ++ m_xDocumentHandler->endElement("X509Data"); ++ } + m_xDocumentHandler->endElement("KeyInfo"); + } + +diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx +index a200de60c07a..a25872fc057d 100644 +--- a/xmlsecurity/source/helper/ooxmlsecparser.cxx ++++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx +@@ -185,9 +185,22 @@ void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) + m_pXSecController->setSignatureValue(m_aSignatureValue); + m_bInSignatureValue = false; + } ++ else if (rName == "X509Data") ++ { ++ std::vector> X509IssuerSerials; ++ std::vector 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_pXSecController->setX509Certificate(m_aX509Certificate); + m_bInX509Certificate = false; + } + else if (rName == "mdssi:Value") +@@ -202,17 +215,18 @@ void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) + } + else if (rName == "X509IssuerName") + { +- m_pXSecController->setX509IssuerName(m_aX509IssuerName); + m_bInX509IssuerName = false; + } + else if (rName == "X509SerialNumber") + { +- m_pXSecController->setX509SerialNumber(m_aX509SerialNumber); + 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_pXSecController->setCertDigest(m_aCertDigest); + m_bInCertDigest = false; + } + else if (rName == "Object") +diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx +index f10f29c61840..8a90b73901db 100644 +--- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx ++++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx +@@ -82,8 +82,12 @@ PDFSignatureHelper::GetDocumentSignatureInformations( + security::DocumentSignatureInformation& rExternal = aRet[i]; + rExternal.SignatureIsValid + = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; +- if (!rInternal.ouX509Certificate.isEmpty()) +- rExternal.Signer = xSecEnv->createCertificateFromAscii(rInternal.ouX509Certificate); ++ if (rInternal.GetSigningCertificate() ++ && !rInternal.GetSigningCertificate()->X509Certificate.isEmpty()) ++ { ++ rExternal.Signer = xSecEnv->createCertificateFromAscii( ++ rInternal.GetSigningCertificate()->X509Certificate); ++ } + rExternal.PartialDocumentSignature = rInternal.bPartialDocumentSignature; + + // Verify certificate. +diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx +index 22c056e70da1..bcb79039e342 100644 +--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx ++++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + +@@ -45,6 +46,8 @@ + #include + #include + ++#include ++ + #define NS_DOCUMENTSIGNATURES "http://openoffice.org/2004/documentsignatures" + #define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" + #define OOXML_SIGNATURE_ORIGIN "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" +@@ -547,4 +550,162 @@ void XMLSignatureHelper::CreateAndWriteOOXMLSignature(const uno::ReferenceendDocument(); + } + ++/** check this constraint from xmldsig-core 4.5.4: ++ ++ All certificates appearing in an X509Data element MUST relate to the ++ validation key by either containing it or being part of a certification ++ chain that terminates in a certificate containing the validation key. ++ */ ++static auto CheckX509Data( ++ uno::Reference const& xSecEnv, ++ std::vector const& rX509CertInfos, ++ std::vector> & rCerts, ++ std::vector & rSorted) -> bool ++{ ++ assert(rCerts.empty()); ++ assert(rSorted.empty()); ++ if (rX509CertInfos.empty()) ++ { ++ SAL_WARN("xmlsecurity.comp", "no X509Data"); ++ return false; ++ } ++ std::vector> certs; ++ for (SignatureInformation::X509CertInfo const& it : rX509CertInfos) ++ { ++ if (!it.X509Certificate.isEmpty()) ++ { ++ certs.emplace_back(xSecEnv->createCertificateFromAscii(it.X509Certificate)); ++ } ++ else ++ { ++ certs.emplace_back(xSecEnv->getCertificate( ++ it.X509IssuerName, ++ xmlsecurity::numericStringToBigInteger(it.X509SerialNumber))); ++ } ++ if (!certs.back().is()) ++ { ++ SAL_WARN("xmlsecurity.comp", "X509Data cannot be parsed"); ++ return false; ++ } ++ } ++ ++ // first, search one whose issuer isn't in the list, or a self-signed one ++ std::optional start; ++ for (size_t i = 0; i < certs.size(); ++i) ++ { ++ for (size_t j = 0; ; ++j) ++ { ++ if (j == certs.size()) ++ { ++ if (start) ++ { ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate has no issuer but already have start of chain: " << certs[i]->getSubjectName()); ++ return false; ++ } ++ start = i; // issuer isn't in the list ++ break; ++ } ++ if (xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), certs[j]->getSubjectName())) ++ { ++ if (i == j) // self signed ++ { ++ if (start) ++ { ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate is self-signed but already have start of chain: " << certs[i]->getSubjectName()); ++ return false; ++ } ++ start = i; ++ } ++ break; ++ } ++ } ++ } ++ std::vector chain; ++ if (!start) ++ { ++ // this can only be a cycle? ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: cycle detected"); ++ return false; ++ } ++ chain.emplace_back(*start); ++ ++ // second, check that there is a chain, no tree or cycle... ++ for (size_t i = 0; i < certs.size(); ++i) ++ { ++ assert(chain.size() == i + 1); ++ for (size_t j = 0; j < certs.size(); ++j) ++ { ++ if (chain[i] != j) ++ { ++ if (xmlsecurity::EqualDistinguishedNames( ++ certs[chain[i]]->getSubjectName(), certs[j]->getIssuerName())) ++ { ++ if (chain.size() != i + 1) // already found issuee? ++ { ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 2 others: " << certs[chain[i]]->getSubjectName()); ++ return false; ++ } ++ chain.emplace_back(j); ++ } ++ } ++ } ++ if (i == certs.size() - 1) ++ { // last one: must be a leaf ++ if (chain.size() != i + 1) ++ { ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate in cycle: " << certs[chain[i]]->getSubjectName()); ++ return false; ++ } ++ } ++ else if (chain.size() != i + 2) ++ { // not issuer of another? ++ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 0 others: " << certs[chain[i]]->getSubjectName()); ++ return false; ++ } ++ } ++ ++ // success ++ assert(chain.size() == rX509CertInfos.size()); ++ for (auto const& it : chain) ++ { ++ rSorted.emplace_back(rX509CertInfos[it]); ++ rCerts.emplace_back(certs[it]); ++ } ++ return true; ++} ++ ++std::vector> ++XMLSignatureHelper::CheckAndUpdateSignatureInformation( ++ uno::Reference const& xSecEnv, ++ SignatureInformation const& rInfo) ++{ ++ // if the check fails, it's not possible to determine which X509Data ++ // contained the signing certificate - the UI cannot display something ++ // useful in this case, so prevent anything misleading by clearing the ++ // X509Datas. ++ ++ std::vector> certs; ++ std::vector datas; ++ // TODO: for now, just merge all X509Datas together for checking... ++ // (this will probably break round-trip of signature with multiple X509Data, ++ // no idea if that is a problem) ++ SignatureInformation::X509Data temp; ++ SignatureInformation::X509Data tempResult; ++ for (auto const& rData : rInfo.X509Datas) ++ { ++ for (auto const& it : rData) ++ { ++ temp.emplace_back(it); ++ } ++ } ++ if (CheckX509Data(xSecEnv, temp, certs, tempResult)) ++ { ++ datas.emplace_back(tempResult); ++ } ++ ++ // rInfo is a copy, update the original ++ mpXSecController->UpdateSignatureInformation(rInfo.nSecurityId, datas); ++ return certs; ++} ++ + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx +index 8d5ea68c768b..0901d05dbdbd 100644 +--- a/xmlsecurity/source/helper/xsecctl.cxx ++++ b/xmlsecurity/source/helper/xsecctl.cxx +@@ -737,8 +737,8 @@ void XSecController::exportSignature( + /* Write keyid element */ + xDocumentHandler->startElement( + "PGPKeyID", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); +- xDocumentHandler->characters( signatureInfo.ouCertDigest ); ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); ++ xDocumentHandler->characters(signatureInfo.ouGpgKeyID); + xDocumentHandler->endElement( "PGPKeyID" ); + + /* Write PGPKeyPacket element */ +@@ -762,43 +762,50 @@ void XSecController::exportSignature( + } + else + { +- /* Write X509Data element */ +- xDocumentHandler->startElement( +- "X509Data", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); ++ assert(signatureInfo.GetSigningCertificate()); ++ for (auto const& rData : signatureInfo.X509Datas) + { +- /* Write X509IssuerSerial element */ ++ /* Write X509Data element */ + xDocumentHandler->startElement( +- "X509IssuerSerial", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); +- { +- /* Write X509IssuerName element */ +- xDocumentHandler->startElement( +- "X509IssuerName", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); +- xDocumentHandler->characters( signatureInfo.ouX509IssuerName ); +- xDocumentHandler->endElement( "X509IssuerName" ); +- +- /* Write X509SerialNumber element */ +- xDocumentHandler->startElement( +- "X509SerialNumber", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); +- xDocumentHandler->characters( signatureInfo.ouX509SerialNumber ); +- xDocumentHandler->endElement( "X509SerialNumber" ); +- } +- xDocumentHandler->endElement( "X509IssuerSerial" ); +- +- /* Write X509Certificate element */ +- if (!signatureInfo.ouX509Certificate.isEmpty()) ++ "X509Data", ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { +- xDocumentHandler->startElement( +- "X509Certificate", +- cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); +- xDocumentHandler->characters( signatureInfo.ouX509Certificate ); +- xDocumentHandler->endElement( "X509Certificate" ); ++ for (auto const& it : rData) ++ { ++ /* Write X509IssuerSerial element */ ++ xDocumentHandler->startElement( ++ "X509IssuerSerial", ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); ++ { ++ /* Write X509IssuerName element */ ++ xDocumentHandler->startElement( ++ "X509IssuerName", ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); ++ xDocumentHandler->characters(it.X509IssuerName); ++ xDocumentHandler->endElement( "X509IssuerName" ); ++ ++ /* Write X509SerialNumber element */ ++ xDocumentHandler->startElement( ++ "X509SerialNumber", ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); ++ xDocumentHandler->characters(it.X509SerialNumber); ++ xDocumentHandler->endElement( "X509SerialNumber" ); ++ } ++ xDocumentHandler->endElement( "X509IssuerSerial" ); ++ ++ /* Write X509Certificate element */ ++ if (!it.X509Certificate.isEmpty()) ++ { ++ xDocumentHandler->startElement( ++ "X509Certificate", ++ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); ++ xDocumentHandler->characters(it.X509Certificate); ++ xDocumentHandler->endElement( "X509Certificate" ); ++ } ++ } + } ++ xDocumentHandler->endElement( "X509Data" ); + } +- xDocumentHandler->endElement( "X509Data" ); + } + } + xDocumentHandler->endElement( "KeyInfo" ); +@@ -917,6 +924,15 @@ void XSecController::exportOOXMLSignature(const uno::Reference& + aExporter.writeSignature(); + } + ++void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId, ++ std::vector const& rDatas) ++{ ++ SignatureInformation aInf( 0 ); ++ int const nIndex = findSignatureInfor(nSecurityId); ++ assert(nIndex != -1); // nothing should touch this between parsing and verify ++ m_vInternalSignatureInformations[nIndex].signatureInfor.X509Datas = rDatas; ++} ++ + SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const + { + SignatureInformation aInf( 0 ); +diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx +index 9cc9312b4d9f..595a02ed687d 100644 +--- a/xmlsecurity/source/helper/xsecparser.cxx ++++ b/xmlsecurity/source/helper/xsecparser.cxx +@@ -99,6 +99,42 @@ auto XSecParser::Context::CreateChildContext( + return std::make_unique(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 XSecParser::ReferencedContextImpl ++ : public XSecParser::Context ++{ ++ protected: ++ bool m_isReferenced; ++ ++ public: ++ ReferencedContextImpl(XSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_isReferenced(isReferenced) ++ { ++ } ++ ++ OUString CheckIdAttrReferenced(css::uno::Reference const& xAttrs) ++ { ++ OUString const id(m_rParser.HandleIdAttr(xAttrs)); ++ if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) ++ { ++ m_isReferenced = true; ++ } ++ return id; ++ } ++}; ++ + class XSecParser::LoPGPOwnerContext + : public XSecParser::Context + { +@@ -211,23 +247,20 @@ class XSecParser::DsX509CertificateContext + : public XSecParser::Context + { + private: +- OUString m_Value; ++ OUString & m_rValue; + + public: + DsX509CertificateContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) + { + } + +- virtual void EndElement() override +- { +- m_rParser.m_pXSecController->setX509Certificate(m_Value); +- } +- + virtual void Characters(OUString const& rChars) override + { +- m_Value += rChars; ++ m_rValue += rChars; + } + }; + +@@ -235,23 +268,20 @@ class XSecParser::DsX509SerialNumberContext + : public XSecParser::Context + { + private: +- OUString m_Value; ++ OUString & m_rValue; + + public: + DsX509SerialNumberContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) + { + } + +- virtual void EndElement() override +- { +- m_rParser.m_pXSecController->setX509SerialNumber(m_Value); +- } +- + virtual void Characters(OUString const& rChars) override + { +- m_Value += rChars; ++ m_rValue += rChars; + } + }; + +@@ -259,33 +289,37 @@ class XSecParser::DsX509IssuerNameContext + : public XSecParser::Context + { + private: +- OUString m_Value; ++ OUString & m_rValue; + + public: + DsX509IssuerNameContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) + { + } + +- virtual void EndElement() override +- { +- m_rParser.m_pXSecController->setX509IssuerName(m_Value); +- } +- + virtual void Characters(OUString const& rChars) override + { +- m_Value += rChars; ++ m_rValue += rChars; + } + }; + + class XSecParser::DsX509IssuerSerialContext + : public XSecParser::Context + { ++ private: ++ OUString & m_rX509IssuerName; ++ OUString & m_rX509SerialNumber; ++ + public: + DsX509IssuerSerialContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rIssuerName, OUString & rSerialNumber) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rX509IssuerName(rIssuerName) ++ , m_rX509SerialNumber(rSerialNumber) + { + } + +@@ -295,20 +329,27 @@ class XSecParser::DsX509IssuerSerialContext + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::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 XSecParser::DsX509DataContext + : public XSecParser::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> m_X509IssuerSerials; ++ std::vector m_X509Certificates; ++ + public: + DsX509DataContext(XSecParser & rParser, + std::unique_ptr pOldNamespaceMap) +@@ -316,17 +357,24 @@ class XSecParser::DsX509DataContext + { + } + ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); ++ } ++ + virtual std::unique_ptr CreateChildContext( + std::unique_ptr pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ m_X509IssuerSerials.emplace_back(); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ m_X509Certificates.emplace_back(); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); +@@ -791,21 +839,29 @@ class XSecParser::XadesUnsignedPropertiesContext + }; + + class XSecParser::LoSignatureLineIdContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + private: + OUString m_Value; + + public: + LoSignatureLineIdContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { +- m_rParser.m_pXSecController->setSignatureLineId(m_Value); ++ if (m_isReferenced) ++ { ++ m_rParser.m_pXSecController->setSignatureLineId(m_Value); ++ } ++ else ++ { ++ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineId"); ++ } + } + + virtual void Characters(OUString const& rChars) override +@@ -815,21 +871,29 @@ class XSecParser::LoSignatureLineIdContext + }; + + class XSecParser::LoSignatureLineValidImageContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + private: + OUString m_Value; + + public: + LoSignatureLineValidImageContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { +- m_rParser.m_pXSecController->setValidSignatureImage(m_Value); ++ if (m_isReferenced) ++ { ++ m_rParser.m_pXSecController->setValidSignatureImage(m_Value); ++ } ++ else ++ { ++ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); ++ } + } + + virtual void Characters(OUString const& rChars) override +@@ -839,21 +903,29 @@ class XSecParser::LoSignatureLineValidImageContext + }; + + class XSecParser::LoSignatureLineInvalidImageContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + private: + OUString m_Value; + + public: + LoSignatureLineInvalidImageContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { +- m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); ++ if (m_isReferenced) ++ { ++ m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); ++ } ++ else ++ { ++ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); ++ } + } + + virtual void Characters(OUString const& rChars) override +@@ -863,12 +935,13 @@ class XSecParser::LoSignatureLineInvalidImageContext + }; + + class XSecParser::LoSignatureLineContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + LoSignatureLineContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + +@@ -878,15 +951,15 @@ class XSecParser::LoSignatureLineContext + { + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +@@ -896,70 +969,88 @@ class XSecParser::XadesCertDigestContext + : public XSecParser::Context + { + private: +- OUString m_Value; +- sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; ++ OUString & m_rDigestValue; ++ sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) ++ std::unique_ptr pOldNamespaceMap, ++ OUString & rDigestValue, sal_Int32 & rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rDigestValue(rDigestValue) ++ , m_rReferenceDigestID(rReferenceDigestID) + { + } + +- virtual void EndElement() override +- { +- m_rParser.m_pXSecController->setCertDigest(m_Value/* FIXME , m_nReferenceDigestID*/); +- } +- + virtual std::unique_ptr CreateChildContext( + std::unique_ptr pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + }; + + class XSecParser::XadesCertContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { ++ private: ++ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; ++ OUString m_CertDigest; ++ OUString m_X509IssuerName; ++ OUString m_X509SerialNumber; ++ + public: + XadesCertContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr 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 CreateChildContext( + std::unique_ptr pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + }; + + class XSecParser::XadesSigningCertificateContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + XadesSigningCertificateContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + +@@ -969,28 +1060,36 @@ class XSecParser::XadesSigningCertificateContext + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + }; + + class XSecParser::XadesSigningTimeContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + private: + OUString m_Value; + + public: + XadesSigningTimeContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { +- m_rParser.m_pXSecController->setDate("", m_Value); ++ 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 +@@ -1000,19 +1099,20 @@ class XSecParser::XadesSigningTimeContext + }; + + class XSecParser::XadesSignedSignaturePropertiesContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + XadesSignedSignaturePropertiesContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_rParser.HandleIdAttr(xAttrs); ++ CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( +@@ -1021,15 +1121,15 @@ class XSecParser::XadesSignedSignaturePropertiesContext + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); +@@ -1037,19 +1137,20 @@ class XSecParser::XadesSignedSignaturePropertiesContext + }; + + class XSecParser::XadesSignedPropertiesContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + XadesSignedPropertiesContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_rParser.HandleIdAttr(xAttrs); ++ CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( +@@ -1058,7 +1159,7 @@ class XSecParser::XadesSignedPropertiesContext + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); +@@ -1066,19 +1167,20 @@ class XSecParser::XadesSignedPropertiesContext + }; + + class XSecParser::XadesQualifyingPropertiesContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + XadesQualifyingPropertiesContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_rParser.HandleIdAttr(xAttrs); ++ CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( +@@ -1087,7 +1189,7 @@ class XSecParser::XadesQualifyingPropertiesContext + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties") + { +@@ -1140,7 +1242,7 @@ class XSecParser::DcDescriptionContext + }; + + class XSecParser::DsSignaturePropertyContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + private: + enum class SignatureProperty { Unknown, Date, Description }; +@@ -1150,30 +1252,38 @@ class XSecParser::DsSignaturePropertyContext + + public: + DsSignaturePropertyContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_Id = m_rParser.HandleIdAttr(xAttrs); ++ m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { +- switch (m_Property) ++ if (m_isReferenced) ++ { ++ switch (m_Property) ++ { ++ case SignatureProperty::Unknown: ++ SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); ++ break; ++ case SignatureProperty::Date: ++ m_rParser.m_pXSecController->setDate(m_Id, m_Value); ++ break; ++ case SignatureProperty::Description: ++ m_rParser.m_pXSecController->setDescription(m_Id, m_Value); ++ break; ++ } ++ } ++ else + { +- case SignatureProperty::Unknown: +- SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); +- break; +- case SignatureProperty::Date: +- m_rParser.m_pXSecController->setDate(m_Id, m_Value); +- break; +- case SignatureProperty::Description: +- m_rParser.m_pXSecController->setDescription(m_Id, m_Value); +- break; ++ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + +@@ -1196,19 +1306,20 @@ class XSecParser::DsSignaturePropertyContext + }; + + class XSecParser::DsSignaturePropertiesContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + DsSignaturePropertiesContext(XSecParser & rParser, +- std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ std::unique_ptr pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_rParser.HandleIdAttr(xAttrs); ++ CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( +@@ -1217,26 +1328,27 @@ class XSecParser::DsSignaturePropertiesContext + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + }; + + class XSecParser::DsObjectContext +- : public XSecParser::Context ++ : public XSecParser::ReferencedContextImpl + { + public: + DsObjectContext(XSecParser & rParser, + std::unique_ptr pOldNamespaceMap) +- : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ // init with "false" here - the Signature element can't be referenced by its child ++ : XSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { +- m_rParser.HandleIdAttr(xAttrs); ++ CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( +@@ -1245,11 +1357,11 @@ class XSecParser::DsObjectContext + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { +- return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: ds:Manifest + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); +diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx +index 7a0eb08bca28..7674bf28b84d 100644 +--- a/xmlsecurity/source/helper/xsecparser.hxx ++++ b/xmlsecurity/source/helper/xsecparser.hxx +@@ -56,6 +56,7 @@ public: + class Context; + private: + class UnknownContext; ++ class ReferencedContextImpl; + class LoPGPOwnerContext; + class DsPGPKeyPacketContext; + class DsPGPKeyIDContext; +diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx +index 5ed23281f083..38a420a370aa 100644 +--- a/xmlsecurity/source/helper/xsecsign.cxx ++++ b/xmlsecurity/source/helper/xsecsign.cxx +@@ -197,6 +197,7 @@ void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, boo + } + } + ++// note: this is called when creating a new signature from scratch + void XSecController::setX509Certificate( + sal_Int32 nSecurityId, + const OUString& ouX509IssuerName, +@@ -210,10 +211,13 @@ void XSecController::setX509Certificate( + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, nullptr); +- isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; +- isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; +- isi.signatureInfor.ouX509Certificate = ouX509Cert; +- isi.signatureInfor.ouCertDigest = ouX509CertDigest; ++ isi.signatureInfor.X509Datas.clear(); ++ isi.signatureInfor.X509Datas.emplace_back(); ++ isi.signatureInfor.X509Datas.back().emplace_back(); ++ isi.signatureInfor.X509Datas.back().back().X509IssuerName = ouX509IssuerName; ++ isi.signatureInfor.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; ++ isi.signatureInfor.X509Datas.back().back().X509Certificate = ouX509Cert; ++ isi.signatureInfor.X509Datas.back().back().CertDigest = ouX509CertDigest; + isi.signatureInfor.eAlgorithmID = eAlgorithmID; + m_vInternalSignatureInformations.push_back( isi ); + } +@@ -221,16 +225,19 @@ void XSecController::setX509Certificate( + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; +- si.ouX509IssuerName = ouX509IssuerName; +- si.ouX509SerialNumber = ouX509SerialNumber; +- si.ouX509Certificate = ouX509Cert; +- si.ouCertDigest = ouX509CertDigest; ++ si.X509Datas.clear(); ++ si.X509Datas.emplace_back(); ++ si.X509Datas.back().emplace_back(); ++ si.X509Datas.back().back().X509IssuerName = ouX509IssuerName; ++ si.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; ++ si.X509Datas.back().back().X509Certificate = ouX509Cert; ++ si.X509Datas.back().back().CertDigest = ouX509CertDigest; + } + } + + void XSecController::setGpgCertificate( + sal_Int32 nSecurityId, +- const OUString& ouCertDigest, ++ const OUString& ouKeyDigest, + const OUString& ouCert, + const OUString& ouOwner) + { +@@ -241,16 +248,17 @@ void XSecController::setGpgCertificate( + InternalSignatureInformation isi(nSecurityId, nullptr); + isi.signatureInfor.ouGpgCertificate = ouCert; + isi.signatureInfor.ouGpgOwner = ouOwner; +- isi.signatureInfor.ouCertDigest = ouCertDigest; ++ isi.signatureInfor.ouGpgKeyID = ouKeyDigest; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; ++ si.X509Datas.clear(); // it is a PGP signature now + si.ouGpgCertificate = ouCert; + si.ouGpgOwner = ouOwner; +- si.ouCertDigest = ouCertDigest; ++ si.ouGpgKeyID = ouKeyDigest; + } + } + +diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx +index 5f5840334254..1f0445c35c14 100644 +--- a/xmlsecurity/source/helper/xsecverify.cxx ++++ b/xmlsecurity/source/helper/xsecverify.cxx +@@ -22,6 +22,7 @@ + #include + #include "xsecparser.hxx" + #include "ooxmlsecparser.hxx" ++#include + #include + #include + #include +@@ -147,6 +148,25 @@ void XSecController::switchGpgSignature() + #endif + } + ++bool XSecController::haveReferenceForId(OUString const& rId) const ++{ ++ if (m_vInternalSignatureInformations.empty()) ++ { ++ SAL_INFO("xmlsecurity.helper","XSecController::haveReferenceForId: no signature"); ++ return false; ++ } ++ InternalSignatureInformation const& rIsi(m_vInternalSignatureInformations.back()); ++ for (SignatureReferenceInformation const& rSri : rIsi.signatureInfor.vSignatureReferenceInfors) ++ { ++ if (rSri.nType == SignatureReferenceType::SAMEDOCUMENT ++ && rSri.ouURI == rId) // ouUri has # stripped ++ { ++ return true; ++ } ++ } ++ return false; ++} ++ + void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType ) + { + if (m_vInternalSignatureInformations.empty()) +@@ -225,7 +245,9 @@ void XSecController::setReferenceCount() const + } + } + +-void XSecController::setX509IssuerName( OUString const & ouX509IssuerName ) ++void XSecController::setX509Data( ++ std::vector> & rX509IssuerSerials, ++ std::vector const& rX509Certificates) + { + if (m_vInternalSignatureInformations.empty()) + { +@@ -233,29 +255,52 @@ void XSecController::setX509IssuerName( OUString const & ouX509IssuerName ) + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); +- isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; +-} +- +-void XSecController::setX509SerialNumber( OUString const & ouX509SerialNumber ) +-{ +- if (m_vInternalSignatureInformations.empty()) ++ SignatureInformation::X509Data data; ++ // due to the excessive flexibility of the spec it's possible that there ++ // is both a reference to a cert and the cert itself in one X509Data ++ for (OUString const& it : rX509Certificates) + { +- SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature"); +- return; ++ try ++ { ++ data.emplace_back(); ++ data.back().X509Certificate = it; ++ uno::Reference const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); ++ uno::Reference const xCert(xSecEnv->createCertificateFromAscii(it)); ++ if (!xCert.is()) ++ { ++ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); ++ continue; // will be handled in CheckX509Data ++ } ++ OUString const issuerName(xCert->getIssuerName()); ++ OUString const serialNumber(xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber())); ++ auto const iter = std::find_if(rX509IssuerSerials.begin(), rX509IssuerSerials.end(), ++ [&](auto const& rX509IssuerSerial) { ++ return xmlsecurity::EqualDistinguishedNames(issuerName, rX509IssuerSerial.first) ++ && serialNumber == rX509IssuerSerial.second; ++ }); ++ if (iter != rX509IssuerSerials.end()) ++ { ++ data.back().X509IssuerName = iter->first; ++ data.back().X509SerialNumber = iter->second; ++ rX509IssuerSerials.erase(iter); ++ } ++ } ++ catch (uno::Exception const&) ++ { ++ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); ++ } + } +- InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); +- isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; +-} +- +-void XSecController::setX509Certificate( OUString const & ouX509Certificate ) +-{ +- if (m_vInternalSignatureInformations.empty()) ++ // now handle any that are left... ++ for (auto const& it : rX509IssuerSerials) + { +- SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature"); +- return; ++ data.emplace_back(); ++ data.back().X509IssuerName = it.first; ++ data.back().X509SerialNumber = it.second; ++ } ++ if (!data.empty()) ++ { ++ isi.signatureInfor.X509Datas.push_back(data); + } +- InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); +- isi.signatureInfor.ouX509Certificate = ouX509Certificate; + } + + void XSecController::setSignatureValue( OUString const & ouSignatureValue ) +@@ -365,13 +410,67 @@ void XSecController::setSignatureBytes(const uno::Sequence& rBytes) + rInformation.signatureInfor.aSignatureBytes = rBytes; + } + +-void XSecController::setCertDigest(const OUString& rCertDigest) ++void XSecController::setX509CertDigest( ++ OUString const& rCertDigest, sal_Int32 const /*TODO nReferenceDigestID*/, ++ OUString const& rX509IssuerName, OUString const& rX509SerialNumber) + { + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); +- rInformation.signatureInfor.ouCertDigest = rCertDigest; ++ for (auto & rData : rInformation.signatureInfor.X509Datas) ++ { ++ for (auto & it : rData) ++ { ++ if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, rX509IssuerName) ++ && it.X509SerialNumber == rX509SerialNumber) ++ { ++ it.CertDigest = rCertDigest; ++ return; ++ } ++ } ++ } ++ // fall-back: read the actual certificates ++ for (auto & rData : rInformation.signatureInfor.X509Datas) ++ { ++ for (auto & it : rData) ++ { ++ if (!it.X509Certificate.isEmpty()) ++ { ++ try ++ { ++ uno::Reference const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); ++ uno::Reference const xCert(xSecEnv->createCertificateFromAscii(it.X509Certificate)); ++ if (!xCert.is()) ++ { ++ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); ++ } ++ else if (xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(),rX509IssuerName) ++ && xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == rX509SerialNumber) ++ { ++ it.CertDigest = rCertDigest; ++ // note: testInsertCertificate_PEM_DOCX requires these! ++ it.X509SerialNumber = rX509SerialNumber; ++ it.X509IssuerName = rX509IssuerName; ++ return; ++ } ++ } ++ catch (uno::Exception const&) ++ { ++ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); ++ } ++ } ++ } ++ } ++ if (!rInformation.signatureInfor.ouGpgCertificate.isEmpty()) ++ { ++ SAL_INFO_IF(rCertDigest != rInformation.signatureInfor.ouGpgKeyID, ++ "xmlsecurity.helper", "PGPKeyID vs CertDigest mismatch"); ++ } ++ else ++ { ++ SAL_INFO("xmlsecurity.helper", "cannot find X509Data for CertDigest"); ++ } + } + + namespace { +diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx +index 0e619b2802f8..244cd46ac564 100644 +--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx ++++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx +@@ -26,6 +26,7 @@ + #include + #include "x509certificate_mscryptimpl.hxx" + #include ++#include + #include "sanextension_mscryptimpl.hxx" + + #include "oid.hxx" +@@ -649,4 +650,50 @@ Sequence SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceName + return { OUString() }; + } + ++namespace xmlsecurity { ++ ++static bool EncodeDistinguishedName(OUString const& rName, CERT_NAME_BLOB & rBlob) ++{ ++ LPCWSTR pszError; ++ if (!CertStrToNameW(X509_ASN_ENCODING, ++ reinterpret_cast(rName.getStr()), CERT_X500_NAME_STR, ++ nullptr, nullptr, &rBlob.cbData, &pszError)) ++ { ++ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << reinterpret_cast(pszError)); ++ return false; ++ } ++ rBlob.pbData = new BYTE[rBlob.cbData]; ++ if (!CertStrToNameW(X509_ASN_ENCODING, ++ reinterpret_cast(rName.getStr()), CERT_X500_NAME_STR, ++ nullptr, rBlob.pbData, &rBlob.cbData, &pszError)) ++ { ++ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << reinterpret_cast(pszError)); ++ return false; ++ } ++ return true; ++} ++ ++bool EqualDistinguishedNames( ++ OUString const& rName1, OUString const& rName2) ++{ ++ CERT_NAME_BLOB blob1; ++ if (!EncodeDistinguishedName(rName1, blob1)) ++ { ++ return false; ++ } ++ CERT_NAME_BLOB blob2; ++ if (!EncodeDistinguishedName(rName2, blob2)) ++ { ++ delete[] blob1.pbData; ++ return false; ++ } ++ bool const ret(CertCompareCertificateName(X509_ASN_ENCODING, ++ &blob1, &blob2) == TRUE); ++ delete[] blob2.pbData; ++ delete[] blob1.pbData; ++ return ret; ++} ++ ++} // namespace xmlsecurity ++ + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx +index a0acd81786d7..db400e6f1ed9 100644 +--- a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx ++++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx +@@ -18,6 +18,7 @@ + */ + + #include ++#include + #include + + #include +@@ -250,6 +251,7 @@ SAL_CALL XMLSignature_MSCryptImpl::validate( + ++nReferenceGood; + } + } ++ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); + + if (rs == 0 && nReferenceCount == nReferenceGood) + { +diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx +index 1a323d33f32f..d6143a81883c 100644 +--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx ++++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx +@@ -31,6 +31,7 @@ + #include + #include "x509certificate_nssimpl.hxx" + ++#include + #include + + #include "sanextension_nssimpl.hxx" +@@ -533,4 +534,28 @@ sal_Bool SAL_CALL X509Certificate_NssImpl::supportsService(const OUString& servi + /* XServiceInfo */ + Sequence SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; } + ++namespace xmlsecurity { ++ ++bool EqualDistinguishedNames( ++ OUString const& rName1, OUString const& rName2) ++{ ++ CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, RTL_TEXTENCODING_UTF8).getStr())); ++ if (pName1 == nullptr) ++ { ++ return false; ++ } ++ CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, RTL_TEXTENCODING_UTF8).getStr())); ++ if (pName2 == nullptr) ++ { ++ CERT_DestroyName(pName1); ++ return false; ++ } ++ bool const ret(CERT_CompareName(pName1, pName2) == SECEqual); ++ CERT_DestroyName(pName2); ++ CERT_DestroyName(pName1); ++ return ret; ++} ++ ++} // namespace xmlsecurity ++ + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx +index c39f6cc72f76..827580bcc7d7 100644 +--- a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx ++++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx +@@ -26,6 +26,8 @@ + #include "securityenvironment_nssimpl.hxx" + + #include ++#include ++ + #include + #include + +@@ -257,6 +259,7 @@ SAL_CALL XMLSignature_NssImpl::validate( + ++nReferenceGood; + } + } ++ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); + + if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood) + { +-- +2.32.0 + diff --git a/SOURCES/0005-cid-1460969-Uninitialized-scalar-field.patch b/SOURCES/0005-cid-1460969-Uninitialized-scalar-field.patch new file mode 100644 index 0000000..7afbdff --- /dev/null +++ b/SOURCES/0005-cid-1460969-Uninitialized-scalar-field.patch @@ -0,0 +1,35 @@ +From 2ebea3e9f3504ef97ecf8af198cd803a56240fe4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 27 Mar 2020 09:03:20 +0000 +Subject: [PATCH 5/8] cid#1460969 Uninitialized scalar field +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +multiple ctor's strikes again + +Change-Id: Ieaae6d5c9e76a3ade17289ce7d1bdffad1168cc9 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91191 +Tested-by: Jenkins +Tested-by: Caolán McNamara +Reviewed-by: Caolán McNamara +(cherry picked from commit 698ecd52e4ca14b5ce633a3358a95992b0dd638c) +--- + dbaccess/source/core/dataaccess/ModelImpl.cxx | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx +index d5c3b9b3e086..1f11f3679289 100644 +--- a/dbaccess/source/core/dataaccess/ModelImpl.cxx ++++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx +@@ -407,6 +407,7 @@ ODatabaseModelImpl::ODatabaseModelImpl( + ,m_aEmbeddedMacros() + ,m_bModificationLock( false ) + ,m_bDocumentInitialized( false ) ++ ,m_nScriptingSignatureState(SignatureState::UNKNOWN) + ,m_aContext( _rxContext ) + ,m_sName(_rRegistrationName) + ,m_nLoginTimeout(0) +-- +2.28.0 + diff --git a/SOURCES/0006-tdf-137897-scRetypePassInputDlg-re-allow-password-re.patch b/SOURCES/0006-tdf-137897-scRetypePassInputDlg-re-allow-password-re.patch new file mode 100644 index 0000000..03951f7 --- /dev/null +++ b/SOURCES/0006-tdf-137897-scRetypePassInputDlg-re-allow-password-re.patch @@ -0,0 +1,45 @@ +From 81618bd69088436eb60fd07b944effb178d788ae Mon Sep 17 00:00:00 2001 +From: Justin Luth +Date: Sat, 31 Oct 2020 15:36:44 +0300 +Subject: [PATCH 6/8] tdf#137897 scRetypePassInputDlg: re-allow password + removal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This weld-conversion logic error caused a LO 6.1 regression +in commit 0e4f93e88bfae3489d2de84fc2febed100880628. + +- m_pPasswordGrid->Disable(); ++ m_xPasswordGrid->set_sensitive(false); //disable == false +- m_pBtnOk->Enable(); ++ m_xBtnOk->set_sensitive(false); //enable == true + +The result is that attempting to remove the password did not +enable the OK button, so it was impossible. + +Change-Id: I4067b2ec6b89e86b21968d33c8850cca6d067e71 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105049 +Tested-by: Jenkins +Reviewed-by: Caolán McNamara +(cherry picked from commit 9eeaff5fa9070bea685db8b6bbd2dfc1565756ac) +--- + sc/source/ui/miscdlgs/retypepassdlg.cxx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx +index 84f8ef182b54..fa31ea77e392 100644 +--- a/sc/source/ui/miscdlgs/retypepassdlg.cxx ++++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx +@@ -372,7 +372,7 @@ IMPL_LINK_NOARG(ScRetypePassInputDlg, RadioBtnHdl, weld::ToggleButton&, void) + else + { + m_xPasswordGrid->set_sensitive(false); +- m_xBtnOk->set_sensitive(false); ++ m_xBtnOk->set_sensitive(true); + } + } + +-- +2.28.0 + diff --git a/SOURCES/0006-xmlsecurity-replace-OOXMLSecParser-implementation.patch b/SOURCES/0006-xmlsecurity-replace-OOXMLSecParser-implementation.patch new file mode 100644 index 0000000..c7c1592 --- /dev/null +++ b/SOURCES/0006-xmlsecurity-replace-OOXMLSecParser-implementation.patch @@ -0,0 +1,1670 @@ +From 78f208c5aa615ccf6738d2a174564269e5f3e0ab Mon Sep 17 00:00:00 2001 +From: Michael Stahl +Date: Tue, 30 Mar 2021 17:37:31 +0200 +Subject: [PATCH] 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. + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113381 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +(cherry picked from commit cc1d19f7bbaefa5fb22ebd1344112755068b93c9) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113360 +(cherry picked from commit 5e2c137c27310e76050f2247077b1311baee4381) + +Change-Id: I56e39d9609db8fcad50ca1632ff482c1f0a30ff5 +--- + include/xmloff/xmlnmspe.hxx | 3 + + xmlsecurity/source/helper/ooxmlsecparser.cxx | 1473 +++++++++++++++--- + xmlsecurity/source/helper/ooxmlsecparser.hxx | 78 +- + 3 files changed, 1314 insertions(+), 240 deletions(-) + +diff --git a/include/xmloff/xmlnmspe.hxx b/include/xmloff/xmlnmspe.hxx +index 302a134f92fe..bebb1d656b40 100644 +--- a/include/xmloff/xmlnmspe.hxx ++++ b/include/xmloff/xmlnmspe.hxx +@@ -73,6 +73,9 @@ XML_NAMESPACE( XML_NAMESPACE_DSIG, 39U ) + XML_NAMESPACE( XML_NAMESPACE_DS, 40U ) + XML_NAMESPACE( XML_NAMESPACE_XADES132, 41U ) + XML_NAMESPACE( XML_NAMESPACE_XADES141, 42U ) ++// OOXML digital signature extension namespaces, also based on xmldsig-core ++XML_NAMESPACE( XML_NAMESPACE_MDSSI, 43U ) ++XML_NAMESPACE( XML_NAMESPACE_MSODIGSIG, 44U ) + + // namespaces for odf extended formats + +diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx +index a25872fc057d..42f226f57d14 100644 +--- a/xmlsecurity/source/helper/ooxmlsecparser.cxx ++++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx +@@ -11,32 +11,1241 @@ + #include "ooxmlsecparser.hxx" + #include + #include ++ ++#include ++#include ++ ++#include ++ + #include + +-using namespace com::sun::star; ++using namespace com::sun::star; ++ ++class OOXMLSecParser::Context ++{ ++ protected: ++ friend class OOXMLSecParser; ++ OOXMLSecParser & m_rParser; ++ private: ++ std::unique_ptr m_pOldNamespaceMap; ++ ++ public: ++ Context(OOXMLSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : m_rParser(rParser) ++ , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual ~Context() = default; ++ ++ virtual void StartElement( ++ css::uno::Reference const& /*xAttrs*/) ++ { ++ } ++ ++ virtual void EndElement() ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr 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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++}; ++ ++auto OOXMLSecParser::Context::CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) ++-> std::unique_ptr ++{ ++ // default: create new base context ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_isReferenced(isReferenced) ++ { ++ } ++ ++ OUString CheckIdAttrReferenced(css::uno::Reference 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 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 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 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 pOldNamespaceMap, ++ OUString & rIssuerName, OUString & rSerialNumber) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rX509IssuerName(rIssuerName) ++ , m_rX509SerialNumber(rSerialNumber) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") ++ { ++ return std::make_unique(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> m_X509IssuerSerials; ++ std::vector m_X509Certificates; ++ ++ public: ++ DsX509DataContext(OOXMLSecParser & rParser, ++ std::unique_ptr pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") ++ { ++ m_X509IssuerSerials.emplace_back(); ++ return std::make_unique(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(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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") ++ { ++ return std::make_unique(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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 pOldNamespaceMap, ++ OUString & rValue) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 pOldNamespaceMap, ++ sal_Int32 & rReferenceDigestID) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rReferenceDigestID(rReferenceDigestID) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 pOldNamespaceMap, ++ bool & rIsC14N) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rIsC14N(rIsC14N) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 pOldNamespaceMap, ++ bool & rIsC14N) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rIsC14N(rIsC14N) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") ++ { ++ return std::make_unique(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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") ++ { ++ return std::make_unique(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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ m_rParser.HandleIdAttr(xAttrs); ++ } ++ ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setReferenceCount(); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ OUString & rDigestValue, sal_Int32 & rReferenceDigestID) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rDigestValue(rDigestValue) ++ , m_rReferenceDigestID(rReferenceDigestID) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") ++ { ++ return std::make_unique(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 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") ++ { ++ return std::make_unique(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 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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") ++ { ++ return std::make_unique(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 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 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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_SetupID); ++ } ++ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments") ++ { ++ return std::make_unique(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 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 pOldNamespaceMap, ++ OUString & rValue) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ , m_rValue(rValue) ++ { ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime") ++ { ++ m_Property = SignatureProperty::Date; ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); ++ } ++ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") ++ { ++ return std::make_unique(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 pOldNamespaceMap, ++ bool const isReferenced) ++ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference const& xAttrs) override ++ { ++ CheckIdAttrReferenced(xAttrs); ++ } ++ ++#if 0 ++ ??? ++ virtual void EndElement() override ++ { ++ m_rParser.m_pXSecController->setReferenceCount(); ++ } ++#endif ++ ++ virtual std::unique_ptr CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") ++ { ++ return std::make_unique(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 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 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); ++ } ++ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest") ++ { ++ return std::make_unique(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 pOldNamespaceMap) ++ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) ++ { ++ } ++ ++ virtual void StartElement( ++ css::uno::Reference 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 CreateChildContext( ++ std::unique_ptr pOldNamespaceMap, ++ sal_uInt16 const nNamespace, OUString const& rName) override ++ { ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") ++ { ++ return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); ++ } ++ if (nNamespace == XML_NAMESPACE_DS && rName == "Object") ++ { ++ return std::make_unique(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 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& xAttribs) + { +- OUString aId = xAttribs->getValueByName("Id"); +- if (!aId.isEmpty()) +- m_pXSecController->collectToVerify(aId); ++ assert(m_pNamespaceMap); ++ std::unique_ptr 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 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> X509IssuerSerials; +- std::vector 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..21ff01ff26da 100644 +--- a/xmlsecurity/source/helper/ooxmlsecparser.hxx ++++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx +@@ -15,6 +15,10 @@ + + #include + ++#include ++ ++#include ++ + class XSecController; + class XMLSignatureHelper; + +@@ -25,38 +29,58 @@ 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> m_ContextStack; ++ std::unique_ptr m_pNamespaceMap; ++ + XSecController* m_pXSecController; + css::uno::Reference 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 . +- OUString m_aReferenceURI; +- /// Already called addStreamReference() for this reference. +- bool m_bReferenceUnresolved; + XMLSignatureHelper& m_rXMLSignatureHelper; + ++ OUString HandleIdAttr(css::uno::Reference const& xAttrs); ++ + public: + explicit OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); + virtual ~OOXMLSecParser() override; +-- +2.33.1 + diff --git a/SOURCES/0007-tdf-137982-m_xFrame-is-already-disposed.patch b/SOURCES/0007-tdf-137982-m_xFrame-is-already-disposed.patch new file mode 100644 index 0000000..0d1098f --- /dev/null +++ b/SOURCES/0007-tdf-137982-m_xFrame-is-already-disposed.patch @@ -0,0 +1,137 @@ +From 7efe51c401ee469ae4835994e5f11b158fd354b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Wed, 4 Nov 2020 13:01:53 +0000 +Subject: [PATCH 7/8] tdf#137982 m_xFrame is already disposed + +move the frame cleanup into a helper that listens to see if it got +disposed by the preview itself + +Change-Id: I523285268118300f18b0f0f0a10fab7a9cced9c6 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105221 +Tested-by: Jenkins +Reviewed-by: Michael Stahl +(cherry picked from commit a986db4b2d24669e502e447036851e118cc23036) +--- + sw/source/ui/dbui/dbtablepreviewdialog.cxx | 53 ++++++++++++++++++---- + sw/source/ui/dbui/dbtablepreviewdialog.hxx | 4 +- + 2 files changed, 46 insertions(+), 11 deletions(-) + +diff --git a/sw/source/ui/dbui/dbtablepreviewdialog.cxx b/sw/source/ui/dbui/dbtablepreviewdialog.cxx +index 23e7984623d8..8f2d92b1c7d5 100644 +--- a/sw/source/ui/dbui/dbtablepreviewdialog.cxx ++++ b/sw/source/ui/dbui/dbtablepreviewdialog.cxx +@@ -20,6 +20,8 @@ + #include + #include "dbtablepreviewdialog.hxx" + #include ++#include ++#include + #include + #include + +@@ -32,6 +34,34 @@ using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + ++class DBTablePreviewFrame ++ : public cppu::WeakImplHelper ++{ ++private: ++ css::uno::Reference m_xFrame; ++ ++ virtual void SAL_CALL disposing(const lang::EventObject& /*Source*/) override ++ { ++ m_xFrame.clear(); ++ } ++ ++public: ++ DBTablePreviewFrame(css::uno::Reference& rFrame) ++ : m_xFrame(rFrame) ++ { ++ } ++ ++ void cleanup() ++ { ++ if (m_xFrame.is()) ++ { ++ m_xFrame->setComponent(nullptr, nullptr); ++ m_xFrame->dispose(); ++ m_xFrame.clear(); ++ } ++ } ++}; ++ + SwDBTablePreviewDialog::SwDBTablePreviewDialog(weld::Window* pParent, uno::Sequence< beans::PropertyValue> const & rValues) + : SfxDialogController(pParent, "modules/swriter/ui/tablepreviewdialog.ui", "TablePreviewDialog") + , m_xDescriptionFI(m_xBuilder->weld_label("description")) +@@ -51,22 +81,26 @@ SwDBTablePreviewDialog::SwDBTablePreviewDialog(weld::Window* pParent, uno::Seque + m_xDescriptionFI->set_label(sDescription.replaceFirst("%1", sTemp)); + } + ++ css::uno::Reference xFrame; + try + { + // create a frame wrapper for myself +- m_xFrame = frame::Frame::create( comphelper::getProcessComponentContext() ); +- m_xFrame->initialize(m_xBeamerWIN->CreateChildFrame()); ++ xFrame = frame::Frame::create( comphelper::getProcessComponentContext() ); ++ xFrame->initialize(m_xBeamerWIN->CreateChildFrame()); + } + catch (uno::Exception const &) + { +- m_xFrame.clear(); ++ xFrame.clear(); + } +- if (m_xFrame.is()) ++ if (xFrame.is()) + { ++ m_xFrameListener.set(new DBTablePreviewFrame(xFrame)); ++ xFrame->addEventListener(m_xFrameListener.get()); ++ + util::URL aURL; + aURL.Complete = ".component:DB/DataSourceBrowser"; +- uno::Reference xD = m_xFrame->queryDispatch(aURL, "", 0x0C); +- if(xD.is()) ++ uno::Reference xD = xFrame->queryDispatch(aURL, "", 0x0C); ++ if (xD.is()) + { + xD->dispatch(aURL, rValues); + m_xBeamerWIN->show(); +@@ -76,11 +110,10 @@ SwDBTablePreviewDialog::SwDBTablePreviewDialog(weld::Window* pParent, uno::Seque + + SwDBTablePreviewDialog::~SwDBTablePreviewDialog() + { +- if(m_xFrame.is()) ++ if (m_xFrameListener) + { +- m_xFrame->setComponent(nullptr, nullptr); +- m_xFrame->dispose(); +- m_xFrame.clear(); ++ m_xFrameListener->cleanup(); ++ m_xFrameListener.clear(); + } + } + +diff --git a/sw/source/ui/dbui/dbtablepreviewdialog.hxx b/sw/source/ui/dbui/dbtablepreviewdialog.hxx +index ec2c58d92bf3..27e6e83d39ca 100644 +--- a/sw/source/ui/dbui/dbtablepreviewdialog.hxx ++++ b/sw/source/ui/dbui/dbtablepreviewdialog.hxx +@@ -27,12 +27,14 @@ namespace com{ namespace sun{ namespace star{ + namespace frame{ class XFrame2; } + }}} + ++class DBTablePreviewFrame; ++ + class SwDBTablePreviewDialog : public SfxDialogController + { + std::unique_ptr m_xDescriptionFI; + std::unique_ptr m_xBeamerWIN; + +- css::uno::Reference< css::frame::XFrame2 > m_xFrame; ++ rtl::Reference m_xFrameListener; + public: + SwDBTablePreviewDialog(weld::Window* pParent, + css::uno::Sequence< css::beans::PropertyValue> const & rValues ); +-- +2.28.0 + diff --git a/SOURCES/0008-Resolves-tdf-137215-restore-original-modality-before.patch b/SOURCES/0008-Resolves-tdf-137215-restore-original-modality-before.patch new file mode 100644 index 0000000..42f512f --- /dev/null +++ b/SOURCES/0008-Resolves-tdf-137215-restore-original-modality-before.patch @@ -0,0 +1,52 @@ +From fa0371ce0456bfe355c36df0741ff23daeccb3a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Tue, 3 Nov 2020 14:04:37 +0000 +Subject: [PATCH 8/8] Resolves: tdf#137215 restore original modality before + dialog loop ends + +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105214 +Tested-by: Jenkins +Reviewed-by: Adolfo Jayme Barrientos +(cherry picked from commit 022c11602d2101b49724b5cf104cc6c70b5a5e4b) + +Change-Id: I83467e28534b781c51b8d75a023e41f3c6a03903 +--- + sc/source/ui/dbgui/validate.cxx | 8 ++++++++ + sc/source/ui/inc/validate.hxx | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/sc/source/ui/dbgui/validate.cxx b/sc/source/ui/dbgui/validate.cxx +index 41bc913db911..73e04cc44706 100644 +--- a/sc/source/ui/dbgui/validate.cxx ++++ b/sc/source/ui/dbgui/validate.cxx +@@ -95,6 +95,14 @@ ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSe + AddTabPage("erroralert", ScTPValidationError::Create, nullptr); + } + ++void ScValidationDlg::EndDialog() ++{ ++ // tdf#137215 ensure original modalality of true is restored before dialog loop ends ++ if (m_bOwnRefHdlr) ++ RemoveRefDlg(true); ++ ScValidationDlgBase::EndDialog(); ++} ++ + ScValidationDlg::~ScValidationDlg() + { + if (m_bOwnRefHdlr) +diff --git a/sc/source/ui/inc/validate.hxx b/sc/source/ui/inc/validate.hxx +index 2c562717f921..cb88b9e8b40e 100644 +--- a/sc/source/ui/inc/validate.hxx ++++ b/sc/source/ui/inc/validate.hxx +@@ -176,6 +176,8 @@ public: + + void SetModal(bool bModal) { m_xDialog->set_modal(bModal); } + ++ virtual void EndDialog() override; ++ + virtual void SetReference( const ScRange& rRef, ScDocument* pDoc ) override + { + if ( m_pHandler && m_pSetReferenceHdl ) +-- +2.28.0 + diff --git a/SOURCES/libreoffice-6.4.7.2.tar.xz.asc b/SOURCES/libreoffice-6.4.7.2.tar.xz.asc new file mode 100644 index 0000000..f5ec3eb --- /dev/null +++ b/SOURCES/libreoffice-6.4.7.2.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEwoOeytlAj76VMcPp9DSh76/urqMFAl99uNwACgkQ9DSh76/u +rqNXhQ/9GhwXWFcV4GyBa3TReuGs+1YrzpUvp+w/MA1wN5czpPwA9CAhivCti1pU +dWwb2c/BePC+KBPthnjKNbuFIL00UuFuz4evEsNLykgwc3CCPXZDm5sxvJUAt1kf +QzlL6XQxpk47v2fRs5wY5huO5rv45o33+N1GV1OCm9Y5vo67wWHnnQJCqIKsfEoY +dWEvfFJxy9c7FiwbRZe9gZctGlOqRJpRbSwffchQ9fJQ5+10w5xhCdd5JrQheqe0 +G0JOHTbPYncv9C9+aTsye5maVEQj/Wi/SH6IzE5T5AGVEf1dguGOr//NLfuPoY0d +Hrm17tKqsV1Lc7LzSwVAdes87bIjcNkITmfyKiaH3g4gDiL2Op9nsZiSwMad4+LX +2GDQKfmqTyS1Um1SdqAMJezwlHOExT491arWwjfDeBmMDJfFNxzNRSihbqzFJs5/ +qfRjOSxpH0oRGMV4RSsLxDwjyzKAsUFQ2pZFx6A4qwp/X17+TulI3NnUHSNTMUaA +rsRgopJb2NuTP3+lTPCotFUcbmFKuCHtAHw8mntyd54JnRHlooVW+/dJ1HyGqAbD +moPg94GVKB0OPaw7D9hipG5dH1wsBz4vJXTEzJL8D/QOM7EmZDkzomPa/J10Pj4v +DXUuzAmfU4bShr1wzZvhEBIVDoS8gPGYwArYdCD18bm9NPWrO3k= +=ItCL +-----END PGP SIGNATURE----- diff --git a/SOURCES/libreoffice-help-6.4.7.2.tar.xz.asc b/SOURCES/libreoffice-help-6.4.7.2.tar.xz.asc new file mode 100644 index 0000000..9dbb363 --- /dev/null +++ b/SOURCES/libreoffice-help-6.4.7.2.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEwoOeytlAj76VMcPp9DSh76/urqMFAl99uPgACgkQ9DSh76/u +rqNc+A/+PnNAFTvU3bHl8dwQGtRxBzcBuz0mkUTHET7qOPkzHsWwiaxmVhrDPvEd +UvG5NiVzux/YnQpLfG9yFcHH78RHy3RKpYHsuUwlb8AWOpMIB4rX2IU2Kcn6jW1v +2fokIVEvu5QzbI7sAyrxfAsdTGa+NALCG7oF8HmGVv/iVHZYTFYU7461LEqNSgbB +uAO9SWV5FLDYxcg6bYHULLFylrD/YBdQrv2Jj16apwVpKNHJPj1qE00KIRl1fYQ6 +PasaGh1D6ZLKhAeOymr18eWQ0VZYmKjszddQExMbLTlxQZI+pZ8Bo6WKz7Y0IiwD +aCcZeVOYRs40Xc4Mc7+6hxO1bGFrG1CvxPE3gdrTAsPmjRko3CNTRFfPyd/e0pHV +0hpmIamL+OAE8V3gG5kSmVCtmnjhAtwnzBnqyuSU/J7thDOp0GUM+FBF6pxQPsf7 +IBZCHZALOO727A6+YR2JsBqmpDi+AxEPNaksDm+orkIG2hx5ai5LmfzgqF0gsBRN +D//oVVpDM34JF5eLD4BOzUv3KqZYSmvDUqnkDF25bMJa5v637VoC7HiPypKRiCn1 +3SLV1YUxMP0EKu2QU7Bz36CLzkxJfEcyvje5//wravbxuDopZC4703fkK1WrANzL +TviCWo1h03ClV1GEhDNB14hgzVN5kfVxaosve9U2Zyayabszj+s= +=12X5 +-----END PGP SIGNATURE----- diff --git a/SOURCES/libreoffice-multiliblauncher.sh b/SOURCES/libreoffice-multiliblauncher.sh new file mode 100644 index 0000000..05c9d3f --- /dev/null +++ b/SOURCES/libreoffice-multiliblauncher.sh @@ -0,0 +1,16 @@ +#!/bin/sh +OOO_ARCH=$(uname -m) +case $OOO_ARCH in + x86_64 | s390x | sparc64 | aarch64) + OOO_LIB_DIR="/usr/lib64" + SECONDARY_LIB_DIR="/usr/lib" + ;; + * ) + OOO_LIB_DIR="/usr/lib" + SECONDARY_LIB_DIR="/usr/lib64" + ;; +esac +if [ ! -x $OOO_LIB_DIR/BRAND/program/LAUNCHER ]; then + OOO_LIB_DIR="$SECONDARY_LIB_DIR" +fi +exec $OOO_LIB_DIR/BRAND/program/LAUNCHER "$@" diff --git a/SOURCES/libreoffice-translations-6.4.7.2.tar.xz.asc b/SOURCES/libreoffice-translations-6.4.7.2.tar.xz.asc new file mode 100644 index 0000000..318c48b --- /dev/null +++ b/SOURCES/libreoffice-translations-6.4.7.2.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEwoOeytlAj76VMcPp9DSh76/urqMFAl99uPkACgkQ9DSh76/u +rqOB9g/+OfPvMQSnfDsF4JE93HcL+z6PNa7yEIuflFSLWRxjtBRrep5FPT0mui5a +PeCkLdR5TcHEQUa4GQuk5C6VLSbyQuEVoiO89Zj+xnLQGd96QJ5hyGjRqzPeP0kr +KSq59cdT1PMETcZy4IQlqVKV7a71pBgCKXh1t3cr56rD8h97jh3lNqOU++6pmpYH +F+IA4/GuWYA22M3oP+w0zmIR4HAdQB5RhxcAMQuLy+N7QUGRU27EMq8R8niRBp8G +Hb8MqVSdy19Hz9GKc3sNHFg4GIEywf/6CY+ldaca63F0X/KWCYYY5Ql3K180LAjG +wg6apwPynkCK05YjqlS8SedZlew9pH3sIauRM99aNC742EqsNoEY1dLEFWErdrr9 +tub2bc5nYX7Ku6RXhlL5orXdU0quZH3c7n26g7VWI6rKvSh4Bs1godWs1UK5hqTt +jt/4RaMBvWzFTWbgQsWI3NLmTM/EOHAfhjDqTq5QPi+Wo3NaqBTlF1TiXJiLDWux +rBb+FcnMmeWrFLCtvKk8T5jYzv0e/HtLH4o3rWaNwzuBAgeeZrroQpTneIVqv8+L +HbE/GN1TaVIkc28RpX2PXdh918p1tmHNuKcPNQD+KIRP+FiBVfpFYm4/BtTb7nQU +Nzh0AxSSSgNcaZaj7iegb/m55BGBhMRjm2iA3bCNNG8JapOfIrs= +=Ot5W +-----END PGP SIGNATURE----- diff --git a/SPECS/libreoffice.spec b/SPECS/libreoffice.spec new file mode 100644 index 0000000..36ba2f7 --- /dev/null +++ b/SPECS/libreoffice.spec @@ -0,0 +1,4499 @@ +# This package depends on automagic byte compilation +# https://fedoraproject.org/wiki/Changes/No_more_automagic_Python_bytecompilation_phase_2 +%global _python_bytecompile_extra 1 + +# download path contains version without the last (fourth) digit +%global libo_version 6.4.7 +# Should contain .alphaX / .betaX, if this is pre-release (actually +# pre-RC) version. The pre-release string is part of tarball file names, +# so we need a way to define it easily at one place. +%global libo_prerelease %{nil} +# Should contain any suffix of release tarball name, e.g., -buildfix1. +%global libo_buildfix %{nil} +# rhbz#715152 state vendor +%if 0%{?rhel} +%global vendoroption --with-vendor="Red Hat, Inc." +%endif +%if 0%{?fedora} +%global vendoroption --with-vendor="The Fedora Project" +%endif +%global libo_python python3 +%global libo_python_executable %{__python3} +%global libo_python_sitearch %{python3_sitearch} +# rhbz#465664 jar-repacking breaks help by reordering META-INF/MANIFEST.MF +%global __jar_repack %{nil} +# make it easier to download sources from pre-release site +%if 0%{?prerelease} +%global source_url http://dev-builds.libreoffice.org/pre-releases/src +%else +%global source_url http://download.documentfoundation.org/libreoffice/src/%{libo_version} +%endif +# URL for external projects' tarballs +%global external_url http://dev-www.libreoffice.org/src +%global girapiversion 0.1 + +# get english only and no-langpacks for a faster smoketest build +# fedpkg compile/install/local/mockbuild does not handle --without ATM, +# so it is necessary to change this to bcond_with to achieve the same +# effect +%bcond_without langpacks + +# remove workdir at the end of %%build, to allow build on space-constrained machines +%ifarch s390 s390x +%bcond_without smallbuild +%else +%bcond_with smallbuild +%endif + +# generated by %%langpack definitions +%global langpack_langs %{nil} + +%global bundling_options %{nil} + +Summary: Free Software Productivity Suite +Name: libreoffice +Epoch: 1 +Version: %{libo_version}.2 +Release: 13%{?libo_prerelease}%{?dist} +License: (MPLv1.1 or LGPLv3+) and LGPLv3 and LGPLv2+ and BSD and (MPLv1.1 or GPLv2 or LGPLv2 or Netscape) and Public Domain and ASL 2.0 and MPLv2.0 and CC0 +URL: http://www.libreoffice.org/ + +Source0: %{source_url}/libreoffice-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz +Source1: %{source_url}/libreoffice-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz.asc +Source2: %{source_url}/libreoffice-help-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz +Source3: %{source_url}/libreoffice-help-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz.asc +Source4: %{source_url}/libreoffice-translations-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz +Source5: %{source_url}/libreoffice-translations-%{version}%{?libo_prerelease}%{?libo_buildfix}.tar.xz.asc +Source6: gpgkey-C2839ECAD9408FBE9531C3E9F434A1EFAFEEAEA3.gpg.asc +Source7: http://dev-www.libreoffice.org/extern/185d60944ea767075d27247c3162b3bc-unowinreg.dll +Source8: libreoffice-multiliblauncher.sh + +Source9: %{external_url}/a7983f859eafb2677d7ff386a023bc40-xsltml_2.1.2.zip +%if 0%{?fedora} +Source10: %{external_url}/798b2ffdc8bcfe7bca2cf92b62caf685-rhino1_5R5.zip +Source11: %{external_url}/35c94d2df8893241173de1d16b6034c0-swingExSrc.zip +%endif +#Unfortunately later versions of hsqldb changed the file format, so if we use a later version we loose +#backwards compatability. +Source12: %{external_url}/17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip +Source13: %{external_url}/884ed41809687c3e168fc7c19b16585149ff058eca79acbf3ee784f6630704cc-opens___.ttf +%global bundling_options %{?bundling_options} --without-system-hsqldb + +Provides: bundled(hsqldb) = 1.8.0 +%if 0%{?fedora} +Provides: bundled(rhino) = 1.5 +%endif +Provides: bundled(xsltml) = 2.1.2 + +# symbolic icons +Source42: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-base-symbolic.svg +Source43: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-calc-symbolic.svg +Source44: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-draw-symbolic.svg +Source45: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-impress-symbolic.svg +Source46: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-main-symbolic.svg +Source47: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-math-symbolic.svg +Source48: https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/libreoffice-writer-symbolic.svg + +# build tools +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: bc +BuildRequires: binutils +BuildRequires: bison +BuildRequires: desktop-file-utils +BuildRequires: doxygen +BuildRequires: findutils +BuildRequires: flex +BuildRequires: gcc-c++ +BuildRequires: gdb +BuildRequires: gettext +BuildRequires: git +BuildRequires: gnupg2 +BuildRequires: gperf +BuildRequires: icu +BuildRequires: libtool-ltdl-devel +BuildRequires: make +BuildRequires: mariadb-connector-c-devel +BuildRequires: perl(Digest::MD5) +%if 0%{?fedora} +BuildRequires: glibc-all-langpacks +BuildRequires: libappstream-glib +%endif +BuildRequires: ucpp +BuildRequires: zip + +# libs / headers - common +BuildRequires: %{libo_python}-devel +BuildRequires: boost-devel +BuildRequires: cups-devel +BuildRequires: fontpackages-devel +BuildRequires: glm-devel +BuildRequires: hyphen-devel +BuildRequires: libjpeg-turbo-devel +BuildRequires: lpsolve-devel +BuildRequires: openldap-devel +BuildRequires: pam-devel +BuildRequires: pkgconfig(bluez) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(dconf) +BuildRequires: pkgconfig(epoxy) +BuildRequires: pkgconfig(evolution-data-server-1.2) +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(freetype2) +BuildRequires: pkgconfig(gobject-introspection-1.0) +BuildRequires: pkgconfig(gstreamer-1.0) +BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) +BuildRequires: pkgconfig(gtk+-3.0) +BuildRequires: pkgconfig(hunspell) +BuildRequires: pkgconfig(ice) +BuildRequires: pkgconfig(icu-i18n) +BuildRequires: pkgconfig(lcms2) +BuildRequires: pkgconfig(libabw-0.1) +BuildRequires: pkgconfig(libcdr-0.1) +BuildRequires: pkgconfig(libclucene-core) +BuildRequires: pkgconfig(libcmis-0.5) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(libetonyek-0.1) +BuildRequires: pkgconfig(libexttextcat) +BuildRequires: pkgconfig(libfreehand-0.1) +BuildRequires: pkgconfig(libidn) +BuildRequires: pkgconfig(liblangtag) +BuildRequires: pkgconfig(libmspub-0.1) +BuildRequires: pkgconfig(libmwaw-0.3) +BuildRequires: pkgconfig(libodfgen-0.1) +BuildRequires: pkgconfig(libpagemaker-0.0) +BuildRequires: pkgconfig(libpq) +BuildRequires: pkgconfig(librevenge-0.0) +BuildRequires: pkgconfig(libstaroffice-0.0) +BuildRequires: pkgconfig(libvisio-0.1) +BuildRequires: pkgconfig(libwpd-0.10) +BuildRequires: pkgconfig(libwpg-0.3) +BuildRequires: pkgconfig(libwps-0.4) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(libxslt) +BuildRequires: pkgconfig(libzmf-0.0) +BuildRequires: pkgconfig(mythes) +BuildRequires: pkgconfig(neon) +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(poppler) +BuildRequires: pkgconfig(poppler-cpp) +BuildRequires: pkgconfig(redland) +BuildRequires: pkgconfig(sane-backends) +BuildRequires: pkgconfig(xext) +BuildRequires: pkgconfig(xinerama) +BuildRequires: pkgconfig(xmlsec1-nss) +BuildRequires: pkgconfig(xt) +BuildRequires: pkgconfig(zlib) +BuildRequires: unixODBC-devel +BuildRequires: %{libo_python_executable} + +# libs / headers - conditional +%if 0%{?fedora} +BuildRequires: pkgconfig(libe-book-0.1) +BuildRequires: qt5-qtbase-devel +BuildRequires: qt5-qtx11extras-devel +BuildRequires: kf5-kconfig-devel +BuildRequires: kf5-kcoreaddons-devel +BuildRequires: kf5-kdelibs4support-devel +BuildRequires: kf5-ki18n-devel +BuildRequires: kf5-kio-devel +BuildRequires: kf5-kwindowsystem-devel +%endif + +BuildRequires: gpgmepp-devel +BuildRequires: pkgconfig(cppunit) >= 1.14.0 +BuildRequires: pkgconfig(graphite2) +BuildRequires: pkgconfig(harfbuzz) +BuildRequires: pkgconfig(libeot) +BuildRequires: pkgconfig(libepubgen-0.1) +BuildRequires: pkgconfig(libqxp-0.0) +BuildRequires: pkgconfig(liborcus-0.15) +BuildRequires: pkgconfig(mdds-1.5) +BuildRequires: libnumbertext-devel + +# java stuff +BuildRequires: ant +%if 0%{?fedora} +BuildRequires: bsh +%endif +BuildRequires: java-devel +BuildRequires: junit +BuildRequires: pentaho-reporting-flow-engine + +# fonts needed for tests +BuildRequires: dejavu-sans-fonts +BuildRequires: google-crosextra-carlito-fonts +BuildRequires: liberation-mono-fonts +BuildRequires: liberation-sans-fonts +BuildRequires: liberation-serif-fonts + +Requires: %{name}-writer%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-calc%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-impress%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-draw%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-math%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-base%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-emailmerge%{?_isa} = %{epoch}:%{version}-%{release} + +# not upstreamed: upstream wants an automatic restart after a crash; we +# want a nice abrt report +Patch0: 0001-don-t-suppress-crashes.patch +# disable tip-of-the-day dialog by default +Patch1: 0001-disble-tip-of-the-day-dialog-by-default.patch +# rhbz#1736810 disable opencl by default again +Patch2: 0001-Resolves-rhbz-1432468-disable-opencl-by-default.patch +# backported +Patch3: 0001-replace-boost-bimap-in-sdext-pdfimport.patch +Patch4: 0001-fix-detecting-qrcodegen.patch +Patch5: 0001-Flatpak-Add-app-bin-libreoffice-app-libreoffice-prog.patch +Patch6: 0001-Restructure-solenv-bin-assemble-flatpak.sh.patch +Patch7: 0001-Related-tdf-127782-resize-the-print-dialog-to-its-op.patch +Patch8: 0001-rhbz-1870501-crash-on-reexport-of-odg.patch +Patch9: 0001-export-HYPERLINK-target-in-html-clipboard-export.patch +Patch10: 0001-use-gdk_wayland_window_set_application_id-when-it-be.patch +Patch11: 0001-tdf-137209-unparent-widgets-in-fragment-dtor.patch +Patch12: 0001-rhbz-1891326-suggest-package-install-of-the-most-app.patch +Patch13: 0001-0.5.1-is-sufficient.patch +Patch14: 0001-munge-cmis-headers-to-remove-exception-specs.patch +Patch15: 0001-1.2.25-is-sufficient.patch +Patch16: 0001-replace-Palatino-Linotype-with-Liberation-Serif.patch +Patch17: 0001-Revert-tdf-69060-lock-refreshing-font-data-when-load.patch +Patch18: 0001-Resolves-rhbz-1893846-if-last-close-had-insert-index.patch +Patch19: 0002-resource-leak.patch +Patch20: 0003-copy_paste_error-data1-looks-like-a-copy-paste-error.patch +Patch21: 0004-Fix-use-of-uninitialized-SwFEShell-bTableCopied.patch +Patch22: 0005-cid-1460969-Uninitialized-scalar-field.patch +Patch23: 0006-tdf-137897-scRetypePassInputDlg-re-allow-password-re.patch +Patch24: 0007-tdf-137982-m_xFrame-is-already-disposed.patch +Patch25: 0008-Resolves-tdf-137215-restore-original-modality-before.patch +Patch26: 0001-rhbz-1882616-move-cursor-one-step-at-a-time-in-the-d.patch +Patch27: 0001-rhbz-1980800-allow-convert-to-csv-to-write-each-shee.patch +Patch28: 0001-Resolves-tdf-132739-two-style-tags-where-there-shoul.patch +Patch29: 0001-backports-to-ease-CVE-backporting.patch +Patch30: 0002-CVE-2021-25635.patch +Patch31: 0003-xmlsecurity-replace-XSecParser-implementation.patch +Patch32: 0004-CVE-2021-25634.patch +Patch33: 0005-CVE-2021-25633.patch +Patch34: 0006-xmlsecurity-replace-OOXMLSecParser-implementation.patch +Patch35: 0001-Correctly-read-PNG-into-bitmaps-N32BitTcA.-formats-w.patch +Patch36: 0001-Read-MOSDocumentLockFile-UTF-16-string-data-with-sam.patch +Patch37: 0001-Convert-attribute-value-to-UTF-8-when-passing-it-to-.patch +Patch38: 0001-Fix-endianness-issues-in-OOX-crypto-routines.patch +Patch39: 0001-CVE-2021-25636.patch +Patch40: 0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch +Patch41: 0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch +Patch42: 0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch +Patch43: 0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch +Patch44: 0001-CVE-2022-3140.patch + +%if 0%{?rhel} +# not upstreamed +Patch500: 0001-disable-libe-book-support.patch +%endif + +%global instdir %{_libdir} +%global baseinstdir %{instdir}/libreoffice +%global sdkinstdir %{baseinstdir}/sdk +%global datadir %{_datadir}/%{name} +%global fontname opensymbol +# HACK: Get the data dir for -data subpackage. I haven't found any better +# way to do this... +%global oldname %{name} +%global name %{name}-data +%global lodatadocdir %{_pkgdocdir} +%global name %{oldname} + +%if 0%{?__isa_bits} == 64 +%global mark64 ()(64bit) +%endif + +%description +LibreOffice is an Open Source, community-developed, office productivity suite. +It includes the key desktop applications, such as a word processor, +spreadsheet, presentation manager, formula editor and drawing program, with a +user interface and feature set similar to other office suites. Sophisticated +and flexible, LibreOffice also works transparently with a variety of file +formats, including Microsoft Office File Formats. + +%package filters +Summary: All import / export filters +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-calc%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-graphicfilter%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-impress%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-writer%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-xsltfilter%{?_isa} = %{epoch}:%{version}-%{release} + +%description filters +Metapackage to pull in all subpackages that contain import or export +filters. + +%package core +Summary: Core modules for LibreOffice +Requires: %{name}-%{fontname}-fonts = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +%ifnarch s390 s390x aarch64 +Requires: %{name}-plugin%{?_isa} = %{epoch}:%{version}-%{release} +%endif +Requires: liberation-sans-fonts, liberation-serif-fonts, liberation-mono-fonts +Requires: dejavu-sans-fonts, dejavu-serif-fonts, dejavu-sans-mono-fonts +Requires: google-crosextra-caladea-fonts, google-crosextra-carlito-fonts +Requires: %{name}-langpack-en = %{epoch}:%{version}-%{release} +# rhbz#949106 libreoffice-core drags in both openjdk 1.7.0 and 1.8.0 +Requires: java-headless >= 1:1.6 +Obsoletes: libreoffice-headless < 1:4.4.0.0 +Obsoletes: libreoffice-math-debuginfo < 1:6.4.7.2 +Provides: libreoffice-headless = %{epoch}:%{version}-%{release} +Provides: libreoffice-headless%{?_isa} = %{epoch}:%{version}-%{release} +%if 0%{?rhel} +Obsoletes: libreoffice-bsh < 1:6.2.2.3 +Obsoletes: libreoffice-rhino < 1:6.2.2.3 +%endif + +%description core +The shared core libraries and support files for LibreOffice. + +%package pyuno +Summary: Python support for LibreOffice +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{libo_python_executable} + +%description pyuno +Python bindings for the LibreOffice UNO component model. Allows scripts both +external to LibreOffice and within the internal LibreOffice scripting framework +to be written in python. + +%package base +Summary: Database front-end for LibreOffice +Requires: pentaho-reporting-flow-engine +Requires: postgresql-jdbc +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-calc%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description base +GUI database front-end for LibreOffice. Allows creation and management of +databases through a GUI. + +%if 0%{?fedora} +%package bsh +Summary: BeanShell support for LibreOffice +Requires: bsh +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} + +%description bsh +Support BeanShell scripts in LibreOffice. + +%package rhino +Summary: JavaScript support for LibreOffice +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} + +%description rhino +Support JavaScript scripts in LibreOffice. +%endif + +%package officebean +Summary: JavaBean for LibreOffice Components +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-officebean-common = %{epoch}:%{version}-%{release} + +%description officebean +Allows embedding of LibreOffice documents within the Java environment. It +provides a Java AWT window into which the backend LibreOffice process draws +its visual representation + +%package officebean-common +Summary: Common JavaBean for LibreOffice Components +Requires: %{name}-data = %{epoch}:%{version}-%{release} +BuildArch: noarch + +%description officebean-common +Arch-independent part of %{name}-officebean. + +%package wiki-publisher +Summary: Create Wiki articles on MediaWiki servers with LibreOffice +Requires: %{name}-writer%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description wiki-publisher +The Wiki Publisher enables you to create Wiki articles on MediaWiki servers +without having to know the syntax of the MediaWiki markup language. Publish +your new and existing documents transparently with writer to a wiki page. + +%package nlpsolver +Summary: Non-linear solver engine for LibreOffice Calc +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-calc%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description nlpsolver +A non-linear solver engine for Calc as an alternative to the default linear +programming model when more complex, nonlinear programming is required. + +%package ogltrans +Summary: 3D OpenGL slide transitions for LibreOffice +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description ogltrans +OpenGL Transitions enable 3D slide transitions to be used in LibreOffice. +Requires good quality 3D support for your graphics card for best experience. + +%package pdfimport +Summary: PDF Importer for LibreOffice Draw +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description pdfimport +The PDF Importer imports PDF into drawing documents to preserve layout +and enable basic editing of PDF documents. + +%package %{fontname}-fonts +Summary: LibreOffice dingbats font +Requires: fontpackages-filesystem +BuildArch: noarch + +%description %{fontname}-fonts +A dingbats font, OpenSymbol, suitable for use by LibreOffice for bullets and +mathematical symbols. + +%package writer +Summary: LibreOffice Word Processor Application +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-pdfimport%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description writer +The LibreOffice Word Processor application. + +%package emailmerge +Summary: Email mail-merge component for LibreOffice +Requires: %{name}-writer%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} + +%description emailmerge +Enables the LibreOffice writer module to mail-merge to email. + +%package calc +Summary: LibreOffice Spreadsheet Application +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-pdfimport%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description calc +The LibreOffice Spreadsheet application. + +%package draw +Summary: LibreOffice Drawing Application +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-pdfimport%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-graphicfilter%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description draw +The LibreOffice Drawing Application. + +%package impress +Summary: LibreOffice Presentation Application +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-ogltrans%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pdfimport%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-graphicfilter%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description impress +The LibreOffice Presentation Application. + +%package math +Summary: LibreOffice Equation Editor Application +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pdfimport%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description math +The LibreOffice Equation Editor Application. + +%package graphicfilter +Summary: LibreOffice Extra Graphic filters +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-data = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description graphicfilter +The graphicfilter module for LibreOffice provides graphic filters, e.g. svg and +flash filters. + +%package xsltfilter +Summary: Optional xsltfilter module for LibreOffice +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} + +%description xsltfilter +The xsltfilter module for LibreOffice, provides additional docbook and +xhtml export transforms. Install this to enable docbook export. + +%package postgresql +Summary: PostgreSQL connector for LibreOffice +Requires: %{name}-base%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description postgresql +A PostgreSQL connector for the database front-end for LibreOffice. Allows +creation and management of PostgreSQL databases through a GUI. + +%package ure +Summary: UNO Runtime Environment +#rhbz#1164551 we want to ensure that a libjvm.so of this arch is available +Requires: %{name}-ure-common = %{epoch}:%{version}-%{release} +Requires: unzip%{?_isa}, libjvm.so%{?mark64} + +%description ure +UNO is the component model of LibreOffice. UNO offers interoperability between +programming languages, other components models and hardware architectures, +either in process or over process boundaries, in the Intranet as well as in the +Internet. UNO components may be implemented in and accessed from any +programming language for which a UNO implementation (AKA language binding) and +an appropriate bridge or adapter exists + +%package ure-common +Summary: Common UNO Runtime Environment +BuildArch: noarch + +%description ure-common +Arch-independent part of %{name}-ure. + +%package sdk +Summary: Software Development Kit for LibreOffice +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Requires: unzip%{?_isa}, java-devel + +%description sdk +The LibreOffice SDK is an add-on for the LibreOffice office suite. It provides +the necessary tools for programming using the LibreOffice APIs and for creating +extensions (UNO components) for LibreOffice. To set the build environment for +building against the sdk use %{sdkinstdir}/setsdkenv_unix.sh. + +%package sdk-doc +Summary: Software Development Kit documentation for LibreOffice + +%description sdk-doc +This provides documentation for programming using the LibreOffice APIs +and examples of creating extensions (UNO components) for LibreOffice. + +%package glade +Summary: Support for creating LibreOffice dialogs in glade +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} + +%description glade +%{name}-glade contains a catalog of LibreOffice-specific widgets for +glade and ui-previewer tool to check the visual appearance of dialogs. + +%package librelogo +Summary: LibreLogo scripting language +Requires: %{name}-writer%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-pyuno%{?_isa} = %{epoch}:%{version}-%{release} + +%description librelogo +Enables LibreLogo scripting in Writer. LibreLogo is a Logo-like +programming language with interactive vectorgraphics for education and +DTP. + +%package data +Summary: LibreOffice data files +BuildArch: noarch + +%description data +%{name}-data contains platform-independent data files. + +%package x11 +Summary: LibreOffice generic X11 support plug-in +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin%{?_isa} = %{epoch}:%{version}-%{release} +Supplements: (%{name}-core%{?_isa} and Xserver) + +%description x11 +A plug-in for LibreOffice that enables generic X11 support. + +%package gtk3 +Summary: LibreOffice GTK+ 3 integration plug-in +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Requires: gstreamer1(element-gtksink)%{?mark64} +Obsoletes: libreoffice-gtk2 < 1:6.2.0.0 +Obsoletes: libreoffice-gtk2-debuginfo < 1:6.2.0.0 +Supplements: (%{name}-core%{?_isa} and gtk3%{?_isa}) + +%description gtk3 +A plug-in for LibreOffice that enables integration into GTK+ 3 environment. + +%if 0%{?fedora} + +%package kde5 +Summary: LibreOffice KDE5 integration plug-in +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin%{?_isa} = %{epoch}:%{version}-%{release} +Obsoletes: libreoffice-kde4 < 1:6.3.0.0 + +%description kde5 +A plug-in for LibreOffice that enables integration into the KDE5 desktop environment. + +%package kf5 +Summary: LibreOffice KDE Frameworks 5 integration plug-in +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin = %{epoch}:%{version}-%{release} +Provides: %{name}-plugin%{?_isa} = %{epoch}:%{version}-%{release} +#Supplements: (libreoffice-core and plasma-workspace) + +%description kf5 +A plug-in for LibreOffice that enables integration into the KDE Frameworks 5. + +%endif + +%package -n libreofficekit +Summary: A library providing access to LibreOffice functionality +License: MPLv2.0 + +%description -n libreofficekit +LibreOfficeKit can be used to access LibreOffice functionality +through C/C++, without any need to use UNO. + +For now it only offers document conversion (in addition to an +experimental tiled rendering API). + +%package -n libreofficekit-devel +Summary: Development files for libreofficekit +Requires: libreofficekit%{?_isa} = %{epoch}:%{version}-%{release} +License: MPLv2.0 + +%description -n libreofficekit-devel +The libreofficekit-devel package contains libraries and header files for +developing applications that use libreofficekit. + +%if 0%{?_enable_debug_packages} + +%package gdb-debug-support +Summary: Additional support for debugging with gdb +Requires: gdb%{?_isa} +Requires: %{libo_python}-six +Requires: libreoffice-core%{?_isa} = %{epoch}:%{version}-%{release} +Supplements: libreoffice-debuginfo%{?_isa} + +%description gdb-debug-support +This package provides gdb pretty printers for package %{name}. + +%files gdb-debug-support +%{_datadir}/gdb/auto-load%{baseinstdir} +%{_datadir}/libreoffice/gdb + +%endif + +%define _langpack_common(Eg:j:l:) \ +%{!-E: \ +%{baseinstdir}/program/resource/%{-g:%{-g*}}%{!-g:%{-l*}}/LC_MESSAGES/*.mo \ +%{baseinstdir}/share/registry/res/registry_%{-l*}.xcd \ +} \ +%{baseinstdir}/share/template/%{-l*} \ +%{baseinstdir}/share/registry/Langpack-%{-l*}.xcd \ +%{baseinstdir}/share/registry/res/fcfg_langpack_%{-l*}.xcd \ +%{baseinstdir}/share/wizards/resources_%{-j:%{-j*}}%{!-j:%{-l*}}.properties \ +%{nil} + +# Defines a language pack subpackage. +# +# It's necessary to define language code (-l) and language name (-n). +# Additionally, it's possible +# * to require autocorr, hunspell, hyphen or mythes package or font for +# given language, +# * to provide libreoffice-langpack-loc package, where loc is glibc +# locale--this is necessary for yum to pick it automatically, +# * to require other, unrelated, packages, +# * to specify file serving as file list. +# For these, lower case character argument takes an argument specifying +# language, upper case character argument uses language from -l. +# +# All remaining arguments are considered to be files and added to the file +# list. +# +# Aa: autocorr dependency +# c: additional config file (just the name stem) +# E: base (US English) langpack +# Ff: font language dependency +# g: glibc/java locale +# Hh: hunspell dependency +# i: additional language added to this package +# j: java locale for the additional language +# k: glibc locale for the additional language +# L: internal (LibreOffice) language code, used in file names +# l: language code, e.g., cs +# Mm: mythes dependency +# n: language name, e.g., Czech +# p: Provides: of libreoffice-langpack +# r: comma-separated list of additional requires +# S:s: script classification (cjk, ctl). -S is only a marker, as it does +# not add any .xcd into the package (the file does not exist for at +# least one CTL-using locale, si) +# T has help files +# Xx: has autotext definitions +# Yy: hyphen dependency +# +# Example: +# libreoffice-langpack-cs: langpack for Czech lang. requiring hyphen-cs, +# autocorr-cs, mythes-cs-CZ and suitable font: +# %%langpack -l cs -n Czech -H -A -m cs-CZ +# b de q tu z BCD G IJK N PQR U Z0123456789 +%define langpack(Aa:c:EFf:g:Hh:i:j:k:L:l:Mm:n:p:r:S:s:TXx:Yy:) \ +%define lang %{-l:%{-l*}}%{!-l:%{error:Language code not defined}} \ +%define _langpack_lang %{-L:%{-L*}}%{!-L:%{lang}} \ +%define pkgname langpack-%{lang} \ +%define langname %{-n:%{-n*}}%{!-n:%{error:Language name not defined}} \ +\ +%global langpack_langs %{langpack_langs} %{_langpack_lang} %{-i:%{-i*}} \ +\ +%package %{pkgname} \ +Summary: %{langname} language pack for LibreOffice \ +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} \ +%{-a:Requires: autocorr-%{-a*}}%{!-a:%{-A:Requires: autocorr-%{lang}}} \ +%if 0%{?rhel} && 0%{?rhel} < 9 \ +%{-f:Requires: font(:lang=%{-f*})}%{!-f:%{-F:Requires: font(:lang=%{lang})}} \ +%else \ +%{-f:Recommends: langpacks-%{-f*}}%{!-f:%{-F:Recommends: langpacks-%{lang}}} \ +%endif \ +%{-h:Requires: hunspell-%{-h*}}%{!-h:%{-H:Requires: hunspell-%{lang}}} \ +%{-m:Requires: mythes-%{-m*}}%{!-m:%{-M:Requires: mythes-%{lang}}} \ +%{-y:Requires: hyphen-%{-y*}}%{!-y:%{-Y:Requires: hyphen-%{lang}}} \ +%{-r:Requires: %{-r*}} \ +%{-p:Provides: %{name}-langpack-%{-p*} = %{epoch}:%{version}-%{release}} \ +%{-p:Provides: %{name}-langpack-%{-p*}%{?_isa} = %{epoch}:%{version}-%{release}} \ +%{-p:Supplements: (%{name}-core%{?_isa} and langpacks-%{-p*})} \ +%{!-p:Supplements: (%{name}-core%{?_isa} and langpacks-%{lang})} \ +%if 0%{?rhel} \ +%{-T:Requires: %{name}-help-%{lang}} \ +%else \ +%{-T:Recommends: %{name}-help-%{lang}} \ +%endif \ +\ +%description %{pkgname} \ +Provides additional %{langname} translations and resources for LibreOffice. \ +\ +%{-T: \ +%package help-%{lang} \ +Summary: %{langname} help for LibreOffice \ +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} \ +\ +%description help-%{lang} \ +Provides %{langname} help for LibreOffice. \ +\ +%files help-%{lang} \ +%docdir %{baseinstdir}/help/%{_langpack_lang} \ +%{baseinstdir}/help/%{_langpack_lang} \ +} \ +\ +%files %{pkgname} \ +%{expand:%%_langpack_common %{-E} -l %{_langpack_lang} %{-g:-g %{-g*} -j %{-g*}}} \ +%{-x:%{baseinstdir}/share/autotext/%{-x*}}%{!-x:%{-X:%{baseinstdir}/share/autotext/%{_langpack_lang}}} \ +%{-c:%{baseinstdir}/share/registry/%{-c*}.xcd} \ +%{-s:%{baseinstdir}/share/registry/%{-s*}_%{_langpack_lang}.xcd} \ +%{-i:%{expand:%%_langpack_common %{-E} -l %{-i*} %{-k:-g %{-k*}} %{-j:-j %{-j*}}}} \ +%{nil} + +# Defines an auto-correction subpackage. +# +# i: add autocorrections from additional language +# l: language code +# n: language name +# L the filename does not contain country code +# +# All remaining arguments are considered to be files and added to the file +# list. +%define autocorr(i:Ll:n:) \ +%define lang %{-l:%{-l*}}%{!-l:%{error:Language code not defined}} \ +%define pkgname autocorr-%{lang} \ +%define langname %{-n:%{-n*}}%{!-n:%{error:Language name not defined}} \ +\ +%package -n %{pkgname} \ +Summary: %{langname} auto-correction rules \ +BuildArch: noarch \ +\ +%description -n %{pkgname} \ +Rules for auto-correcting common %{langname} typing errors. \ +\ +%files -n %{pkgname} \ +%doc instdir/LICENSE \ +%dir %{_datadir}/autocorr \ +%{-L:%{_datadir}/autocorr/acor_%{lang}.dat} \ +%{!-L:%{_datadir}/autocorr/acor_%{lang}-*.dat} \ +%{nil} + +%langpack -l en -n English -F -h en-US -Y -M -A -E -L en-US -T -X -g en_US + +%if %{with langpacks} + +%langpack -l af -n Afrikaans -F -H -Y -A -X +%langpack -l ar -n Arabic -F -H -s ctl -T -X +%langpack -l as -n Assamese -F -H -Y -X +%langpack -l bg -n Bulgarian -F -H -Y -M -A -T -X +%langpack -l bn -n Bengali -F -H -Y -T -X +%langpack -l br -n Breton -F -H -X +%langpack -l ca -n Catalan -F -H -Y -M -A -T -X +%langpack -l cs -n Czech -F -H -Y -M -A -T -X +%langpack -l cy -n Welsh -F -H -Y -X +%langpack -l da -n Danish -F -H -Y -M -A -T -X +%langpack -l de -n German -F -H -Y -M -A -T -X +%langpack -l dz -n Dzongkha -F -s ctl -T -X +%langpack -l el -n Greek -F -H -Y -M -T -X +%langpack -l es -n Spanish -F -H -Y -M -A -T -X +%langpack -l et -n Estonian -F -H -Y -T -X +%langpack -l eu -n Basque -F -H -Y -T -X +%langpack -l fa -n Farsi -A -H -Y -s ctl -X +%langpack -l fi -n Finnish -F -r libreoffice-voikko -A -T -X +%langpack -l fr -n French -F -H -Y -M -A -T -X +%langpack -l ga -n Irish -F -H -Y -M -A -X +%langpack -l gl -n Galician -F -H -Y -T -X +%langpack -l gu -n Gujarati -F -H -Y -s ctl -T -X +%langpack -l he -n Hebrew -F -H -s ctl -T -X +%langpack -l hi -n Hindi -F -H -Y -s ctl -T -X +%langpack -l hr -n Croatian -F -H -Y -A -T -X +%langpack -l hu -n Hungarian -F -H -Y -M -A -T -X +%{baseinstdir}/share/wordbook/hu_AkH11.dic +%langpack -l id -n Indonesian -F -H -Y -T -X +%langpack -l it -n Italian -F -H -Y -M -A -T -X +%langpack -l ja -n Japanese -F -A -s cjk -T -X +%langpack -l kk -n Kazakh -F -H -X +%langpack -l kn -n Kannada -F -H -Y -X +%langpack -l ko -n Korean -F -H -A -s cjk -T -X +%langpack -l lt -n Lithuanian -F -H -Y -A -T -X +%langpack -l lv -n Latvian -F -H -Y -M -T -X +%langpack -l mai -n Maithili -F -X +%langpack -l ml -n Malayalam -F -H -Y -X +%langpack -l mr -n Marathi -F -H -Y -X +%langpack -l nb -n Bokmal -F -H -Y -M -T -X +%langpack -l nl -n Dutch -F -H -Y -M -A -T -X -X +%langpack -l nn -n Nynorsk -F -H -Y -M -T +%define langpack_lang Southern Ndebele +%langpack -l nr -n %{langpack_lang} -F -H -X +%define langpack_lang Northern Sotho +%langpack -l nso -n %{langpack_lang} -F -H -X +%langpack -l or -n Odia -F -H -Y -s ctl -X +%langpack -l pa -n Punjabi -F -H -Y -s ctl -L pa-IN -g pa_IN -X +%langpack -l pl -n Polish -F -H -Y -M -A -T -X +%define langpack_lang Brazilian Portuguese +%langpack -l pt-BR -n %{langpack_lang} -f pt -h pt -y pt -m pt -a pt -p pt_BR -T -X -g pt_BR +%langpack -l pt-PT -n Portuguese -f pt -h pt -y pt -m pt -a pt -p pt_PT -T -L pt -x pt +%langpack -l ro -n Romanian -A -F -H -Y -M -T -X +%langpack -l ru -n Russian -F -H -Y -M -A -T -X +%langpack -l si -n Sinhalese -F -H -S ctl -T -X +%langpack -l sk -n Slovak -F -H -Y -M -A -T -X +%langpack -l sl -n Slovenian -F -H -Y -M -A -T -X +%{baseinstdir}/share/wordbook/sl.dic + +#rhbz#452379 clump serbian translations together +%langpack -l sr -n Serbian -F -H -Y -A -i sr-Latn -k sr@latin -j sr_Latn -x sr* +%langpack -l ss -n Swati -F -H -X +%define langpack_lang Southern Sotho +# note that langpacks-st seems to be missing as of the time of writing, so no -F here +%langpack -l st -n %{langpack_lang} -H -X +%langpack -l sv -n Swedish -F -H -Y -M -A -T -X +%langpack -l ta -n Tamil -F -H -Y -s ctl -T -X +%langpack -l te -n Telugu -F -H -Y -X +%langpack -l th -n Thai -F -H -s ctl -c ctlseqcheck_th -X +%langpack -l tn -n Tswana -F -H -X +%langpack -l tr -n Turkish -F -A -T -X +%langpack -l ts -n Tsonga -F -H -X +%langpack -l uk -n Ukrainian -F -H -Y -M -T -X +%langpack -l ve -n Venda -F -H -X +%langpack -l xh -n Xhosa -F -H -X +%define langpack_lang Simplified Chinese +%langpack -l zh-Hans -n %{langpack_lang} -f zh-cn -a zh -p zh_CN -s cjk -T -L zh-CN -x zh-CN -g zh_CN +%define langpack_lang Traditional Chinese +%langpack -l zh-Hant -n %{langpack_lang} -f zh-tw -a zh -p zh_TW -s cjk -T -L zh-TW -x zh-TW -g zh_TW +%langpack -l zu -n Zulu -F -H -Y -X +%undefine langpack_lang + +%endif + +%autocorr -l en -n English + +%if %{with langpacks} + +%autocorr -l af -n Afrikaans +%autocorr -l bg -n Bulgarian +%autocorr -l ca -n Catalan +%autocorr -l cs -n Czech +%autocorr -l da -n Danish +%autocorr -l de -n German -L +%define autocorr_lang Lower Sorbian +%autocorr -l dsb -n %{autocorr_lang} -L +%autocorr -l el -n Greek +%autocorr -l es -n Spanish -L +%autocorr -l fa -n Farsi +%autocorr -l fi -n Finnish +%autocorr -l fr -n French -L +%autocorr -l ga -n Irish +%autocorr -l hr -n Croatian +%define autocorr_lang Upper Sorbian +%autocorr -l hsb -n %{autocorr_lang} -L +%autocorr -l hu -n Hungarian +%autocorr -l is -n Icelandic +%autocorr -l it -n Italian -L +%autocorr -l ja -n Japanese +%autocorr -l ko -n Korean +%autocorr -l lb -n Luxembourgish +%autocorr -l lt -n Lithuanian +%autocorr -l mn -n Mongolian +%autocorr -l nl -n Dutch +%autocorr -l pl -n Polish +%autocorr -l pt -n Portuguese +%autocorr -l ro -n Romanian +%autocorr -l ru -n Russian +%autocorr -l sk -n Slovak +%autocorr -l sl -n Slovenian +%autocorr -l sr -n Serbian +%autocorr -l sv -n Swedish +%autocorr -l tr -n Turkish +%autocorr -l vi -n Vietnamese +%autocorr -l zh -n Chinese + +%endif + +%define make_autocorr_aliases(l:) \ +%{?-l: \ +for lang in %{*}; do \ + ln -sf acor_%{-l*}.dat acor_$lang.dat \ +done \ +} \ +%{!?-l:%{error:-l must be present}} + +%prep +# verify tarballs +gpg2 --dearmor < %{SOURCE6} > keyring.gpg +gpgv2 --keyring ./keyring.gpg %{SOURCE1} %{SOURCE0} +gpgv2 --keyring ./keyring.gpg %{SOURCE3} %{SOURCE2} +gpgv2 --keyring ./keyring.gpg %{SOURCE5} %{SOURCE4} + +%setup -q -n %{name}-%{version}%{?libo_prerelease} -b 2 -b 4 +rm -rf git-hooks */git-hooks + +# set up git repo +git init +git config user.name rpmbuild +git config user.email rpmbuild@fedoraproject.org +git config gc.auto 0 # disable auto packing +git add -A +git commit -q -a -m %{name}-%{version} + +#Customize Palette to add Red Hat colours +(head -n -1 extras/source/palettes/standard.soc && \ + echo -e ' + + + + ' && \ + tail -n 1 extras/source/palettes/standard.soc) > redhat.soc +mv -f redhat.soc extras/source/palettes/standard.soc +git commit -q -a -m 'add Red Hat colors to palette' + +# apply patches +git am %{patches} + +sed -i -e /CppunitTest_sw_ooxmlexport7/d sw/Module_sw.mk # i686 +sed -i -e /CppunitTest_sc_array_functions_test/d sc/Module_sc.mk # ppc64le +sed -i -e /CppunitTest_sw_ww8export/d sw/Module_sw.mk +sed -i -e /CppunitTest_sc_addin_functions_test/d sc/Module_sc.mk # aarch64/ppc64*/s390x +sed -i -e /CppunitTest_sc_financial_functions_test/d sc/Module_sc.mk # ppc64* +sed -i -e /CppunitTest_sc_statistical_functions_test/d sc/Module_sc.mk # aarch64/ppc64* +sed -i -e /CppunitTest_dbaccess_hsqldb_test/d dbaccess/Module_dbaccess.mk # i686 +sed -i -e s/CppunitTest_dbaccess_RowSetClones// dbaccess/Module_dbaccess.mk # i686 +sed -i -e /CppunitTest_services/d postprocess/Module_postprocess.mk # i686 +sed -i -e /CppunitTest_sd_export_ooxml2/d sd/Module_sd.mk # i686 +sed -i -e /CppunitTest_sw_ooxmlexport4/d sw/Module_sw.mk +sed -i -e /CppunitTest_xmlsecurity_signing/d xmlsecurity/Module_xmlsecurity.mk +%if 0%{?rhel} +sed -i -e /CppunitTest_desktop_lib/d desktop/Module_desktop.mk +sed -i -e s/CppunitTest_editeng_core// editeng/Module_editeng.mk +sed -i -e /CppunitTest_writerperfect_draw/d writerperfect/Module_writerperfect.mk +sed -i -e /CppunitTest_sw_ooxmlimport/d sw/Module_sw.mk +sed -i -e /CppunitTest_sw_ooxmlexport10/d sw/Module_sw.mk +sed -i -e /CppunitTest_sw_uiwriter/d sw/Module_sw.mk +sed -i -e /CppunitTest_sc_subsequent_filters_test/d sc/Module_sc.mk +%endif +sed -i -e /CppunitTest_sal_osl/d sal/Module_sal.mk +%ifarch s390x +sed -i -e /CppunitTest_dbaccess_hsqlbinary_import/d dbaccess/Module_dbaccess.mk +sed -i -e /CppunitTest_vcl_svm_test/d vcl/Module_vcl.mk +sed -i -e /CustomTarget_uno_test/d testtools/Module_testtools.mk +%endif + +git commit -q -a -m 'temporarily disable failing tests' + +# Seeing .git dir makes some of the build tools change their behavior. +# We do not want that. Note: it is still possible to use +# git --git-dir=.git-rpm +mv .git .git-rpm + +%build +# path to external tarballs +EXTSRCDIR=`dirname %{SOURCE0}` + +#use the RPM_OPT_FLAGS but remove the OOo overridden ones +for i in $RPM_OPT_FLAGS; do + case "$i" in + -pipe|-Wall|-Werror*|-fexceptions) continue;; + esac + ARCH_FLAGS="$ARCH_FLAGS $i" +done +%ifarch s390 aarch64 +# these builders typically do not have enough memory to link the big libs with -g2 +ARCH_FLAGS="$ARCH_FLAGS -g1" +%endif +export ARCH_FLAGS +export CFLAGS=$ARCH_FLAGS +export CXXFLAGS=$ARCH_FLAGS + +%if 0%{?rhel} +%define distrooptions --disable-eot --disable-scripting-beanshell --disable-scripting-javascript +%else +# fedora +%define distrooptions --enable-eot --enable-kde5 --enable-gtk3-kde5 +%endif + +%if %{with langpacks} +%define with_lang --with-lang='%{langpack_langs}' +%endif + +aclocal -I m4 +autoconf + +SMP_MFLAGS=%{?_smp_mflags} +SMP_MFLAGS=$[${SMP_MFLAGS/-j/}] + +%if 0%{?flatpak} +%define flatpakoptions --with-boost-libdir=%{_libdir} --with-beanshell-jar=/app/share/java/bsh.jar --with-commons-logging-jar=/app/share/java/commons-logging.jar --with-external-dict-dir=/app/share/myspell --with-external-hyph-dir=/app/share/hyphen --with-external-thes-dir=/app/share/mythes --with-flute-jar=/app/share/java/flute.jar --with-jdk-home=/app/lib/jvm/java-1.8.0-openjdk --with-jfreereport-jar=/app/share/java/flow-engine.jar --with-libbase-jar=/app/share/java/libbase.jar --with-libfonts-jar=/app/share/java/libfonts.jar --with-libformula-jar=/app/share/java/libformula.jar --with-liblayout-jar=/app/share/java/liblayout.jar --with-libloader-jar=/app/share/java/libloader.jar --with-librepository-jar=/app/share/java/librepository.jar --with-libserializer-jar=/app/share/java/libserializer.jar --with-libxml-jar=/app/share/java/libxml.jar --with-sac-jar=/app/share/java/sac.jar FIREBIRDCONFIG=%{_libdir}/fb_config QT4INC=%{_includedir} +%endif + +# TODO: enable coinmp? +# avoid running autogen.sh on make +touch autogen.lastrun +%configure \ + %vendoroption \ + %{?with_lang} \ + --with-parallelism=$SMP_MFLAGS \ + --disable-coinmp \ + --disable-fetch-external \ + --disable-openssl \ + --disable-firebird-sdbc \ + --disable-pdfium \ + --disable-qrcodegen \ + --enable-dconf \ + --enable-evolution2 \ + --enable-ext-nlpsolver \ + --enable-ext-wiki-publisher \ + --enable-gtk3 \ + --enable-introspection \ + --enable-release-build \ + --enable-scripting-beanshell \ + --enable-scripting-javascript \ + --enable-symbols \ + --with-build-version="%{version}-%{release}" \ + --with-external-dict-dir=/usr/share/myspell \ + --with-external-tar="$EXTSRCDIR" \ + --with-help \ + --with-system-dicts \ + --with-system-libs \ + --without-export-validation \ + --without-fonts \ + --without-lxml \ + --with-gdrive-client-secret="GYWrDtzyZQZ0_g5YoBCC6F0I" \ + --with-gdrive-client-id="457862564325.apps.googleusercontent.com" \ + --enable-python=system \ + --with-system-ucpp \ + %{distrooptions} \ + %{?bundling_options} \ + %{?archoptions} \ + %{?flatpakoptions} + +ulimit -c unlimited || true + +if ! make verbose=true build-nocheck; then + echo "build attempt 1 failed" + if ! make verbose=true build-nocheck; then + echo "build attempt 2 failed" + make verbose=true GMAKE_OPTIONS=-rj1 build-nocheck + fi +fi + +#generate the icons and mime type stuff +export DESTDIR=../output +export KDEMAINDIR=/usr +export GNOMEDIR=/usr +export GNOME_MIME_THEME=hicolor +export PREFIXDIR=/usr +# TODO use empty variables? Should make the renaming hacks in %%install +# unnecessary. +. ./bin/get_config_variables PRODUCTVERSIONSHORT PRODUCTVERSION SRCDIR WORKDIR PKG_CONFIG INSTDIR +pushd $WORKDIR/CustomTarget/sysui/share/libreoffice +./create_tree.sh +popd +mkdir $WORKDIR/os-integration +cp -pr $WORKDIR/CustomTarget/sysui/share/output/usr/share/* $WORKDIR/os-integration +cp -pr $WORKDIR/CustomTarget/sysui/share/libreoffice/LOKDocView-%{girapiversion}.* $WORKDIR/os-integration + +%if %{with smallbuild} +# remove the biggest offenders +# NOTE: not removing complete LinkTarget, as some libs are needed for smoketest +rm -rf $WORKDIR/CxxObject $WORKDIR/GenCxxObject $WORKDIR/HelpTarget $WORKDIR/LinkTarget/CppunitTest +%endif + + +%install +# TODO investigate use of make distro-pack-install +#figure out the icon version +. ./bin/get_config_variables PRODUCTVERSIONSHORT PRODUCTVERSION SRCDIR WORKDIR +export PRODUCTVERSIONSHORT PRODUCTVERSION + +# installation + +install -m 0755 -d %{buildroot}%{instdir} +if ! make instsetoo_native PKGFORMAT=installed DISABLE_STRIP=1 EPM=not-used-but-must-be-set; then + echo - ---dump log start--- + cat $WORKDIR/installation/LibreOffice/installed/logging/en-US/log_*_en-US.log + echo - ---dump log end--- + echo - ---dump log start -- SDK--- + cat $WORKDIR/installation/LibreOffice_SDK/installed/logging/en-US/log_*_en-US.log + echo - ---dump log end -- SDK--- + echo - ---dump log start -- languagepacks--- + cat $WORKDIR/installation/LibreOffice_languagepack/installed/logging/en-US/log_*_en-US.log + echo - ---dump log end -- languagepacks--- + exit 1 +fi +install -m 0755 -d %{buildroot}%{baseinstdir} +mv $WORKDIR/installation/LibreOffice/installed/install/en-US/* %{buildroot}%{baseinstdir} +%if %{with langpacks} +for langpack in $WORKDIR/installation/LibreOffice_languagepack/installed/install/*; do + [ `basename $langpack` = log ] && continue + cp -rp $langpack/* %{buildroot}%{baseinstdir} + rm -rf $langpack +done +%endif +mv $WORKDIR/installation/LibreOffice_SDK/installed/install/en-US/sdk %{buildroot}%{sdkinstdir} +chmod -R +w %{buildroot}%{baseinstdir} + +# postprocessing and tweaks + +# The installer currently sets UserInstallation to +# $ORIGIN/../libreoffice/4, which is of course total nonsense. Because I +# have no inclination to crawl through mountains of perl code to figure out +# where it comes from, I am just going to replace it by a sensible +# value here. +sed -i -e '/UserInstallation/s@\$ORIGIN/..@$SYSUSERCONFIG@' %{buildroot}%{baseinstdir}/program/bootstraprc + +#configure sdk +pushd %{buildroot}%{sdkinstdir} + sed -e "s,@OO_SDK_NAME@,sdk," \ + -e "s,@OO_SDK_HOME@,%{sdkinstdir}," \ + -e "s,@OFFICE_HOME@,%{baseinstdir}," \ + -e "s,@OO_SDK_MAKE_HOME@,/usr/bin," \ + -e "s,@OO_SDK_ZIP_HOME@,/usr/bin," \ + -e "s,@OO_SDK_CPP_HOME@,/usr/bin," \ + -e "s,@OO_SDK_CAT_HOME@,/usr/bin," \ + -e "s,@OO_SDK_SED_HOME@,/usr/bin," \ + -e "s,@OO_SDK_CC_55_OR_HIGHER@,," \ + -e "s,@OO_SDK_JAVA_HOME@,$JAVA_HOME," \ + -e "s,@OO_SDK_OUTPUT_DIR@,\$HOME," \ + -e "s,@SDK_AUTO_DEPLOYMENT@,NO," \ + setsdkenv_unix.sh.in > setsdkenv_unix.sh + # ensure no unexpanded vars sneaked in + grep '@[A_Z0-9_]\+@' setsdkenv_unix.sh && exit 1 + chmod 755 setsdkenv_unix.sh + # we don't want to install the input file + rm -f setsdkenv_unix.sh.in +# TODO: is this still necessary? +#fix permissions + find examples -type f -exec chmod -x {} \; +popd + +#ensure a template dir for each lang +pushd %{buildroot}%{baseinstdir}/share/template +for I in %{langpack_langs}; do + mkdir -p $I +done +popd + +#Set some aliases to canonical autocorrect language files for locales with matching languages +pushd %{buildroot}%{baseinstdir}/share/autocorr + +%make_autocorr_aliases -l en-GB en-AG en-AU en-BS en-BW en-BZ en-CA en-DK en-GH en-HK en-IE en-IN en-JM en-NG en-NZ en-SG en-TT +%make_autocorr_aliases -l en-US en-PH +#en-ZA exists and has a good autocorrect file with two or three extras that make sense for +#neighbouring english speaking territories +%make_autocorr_aliases -l en-ZA en-NA en-ZW +%if %{with langpacks} +%make_autocorr_aliases -l af-ZA af-NA +%make_autocorr_aliases -l nl-NL nl-AW +%make_autocorr_aliases -l sv-SE sv-FI +%else +rm -f acor_[a-df-z]*.dat acor_e[lsu]*.dat +%endif +popd +#rhbz#484055 make these shared across multiple applications +install -m 0755 -d %{buildroot}%{_datadir} +mv -f %{buildroot}%{baseinstdir}/share/autocorr %{buildroot}%{_datadir}/autocorr +chmod 755 %{buildroot}%{_datadir}/autocorr +ln -s %{_datadir}/autocorr %{buildroot}%{baseinstdir}/share/autocorr + +#remove it in case we didn't build with gcj +rm -f %{buildroot}%{baseinstdir}/program/classes/sandbox.jar +# we don't need this in the install +rm -f %{buildroot}%{baseinstdir}/program/classes/smoketest.jar + +#remove dummy .dat files +rm -f %{buildroot}%{baseinstdir}/program/root?.dat + +#set standard permissions for rpmlint +find %{buildroot}%{baseinstdir} -exec chmod +w {} \; +find %{buildroot}%{baseinstdir} -type d -exec chmod 0755 {} \; + +# move python bits into site-packages +install -m 0755 -d %{buildroot}%{libo_python_sitearch} +pushd %{buildroot}%{libo_python_sitearch} +echo "import sys, os" > uno.py +echo "sys.path.append('%{baseinstdir}/program')" >> uno.py +echo "os.putenv('URE_BOOTSTRAP', 'vnd.sun.star.pathname:%{baseinstdir}/program/fundamentalrc')" >> uno.py +cat %{buildroot}%{baseinstdir}/program/uno.py >> uno.py +rm -f %{buildroot}%{baseinstdir}/program/uno.py* +mv -f %{buildroot}%{baseinstdir}/program/unohelper.py* . +mv -f %{buildroot}%{baseinstdir}/program/officehelper.py* . +popd + +# rhbz#477435 package opensymbol separately +pushd %{buildroot}%{baseinstdir}/share/fonts/truetype +install -d -m 0755 %{buildroot}%{_fontdir} +install -p -m 0644 *.ttf %{buildroot}%{_fontdir} +popd +rm -rf %{buildroot}%{baseinstdir}/share/fonts/truetype/*.ttf + +# move platform-independent data into shared dir +install -m 0755 -d %{buildroot}%{datadir} +rm -f %{buildroot}%{baseinstdir}/CREDITS.fodt %{buildroot}%{baseinstdir}/LICENSE* %{buildroot}%{baseinstdir}/NOTICE +# rhbz#1473749 ensure display of files in license/about dialogs works +ln -sr %{buildroot}%{lodatadocdir}/CREDITS.fodt %{buildroot}%{baseinstdir}/CREDITS.fodt +ln -sr %{buildroot}%{lodatadocdir}/LICENSE.html %{buildroot}%{baseinstdir}/LICENSE.html + +#ensure that no sneaky un-prelinkable, un-fpic or non executable shared libs +#have snuck through +pic=0 +executable=0 +for foo in `find %{buildroot}%{instdir} -name "*" -exec file {} \;| grep ": ELF" | cut -d: -f 1` ; do + chmod +wx $foo + ls -asl $foo + result=`readelf -d $foo | grep TEXTREL` || true + if [ "$result" != "" ]; then + echo "TEXTREL Warning: $foo is b0rked (-fpic missing)" + pic=1 + fi + result=`readelf -l $foo | grep GNU_STACK | grep RWE` || true + if [ "$result" != "" ]; then + echo "GNU_STACK Warning: $foo is b0rked (-noexecstack missing)" + executable=1 + fi +done +if [ $pic == 1 ]; then false; fi +if [ $executable == 1 ]; then false; fi + +#make up some /usr/bin scripts +install -m 0755 -d %{buildroot}%{_bindir} + +pushd %{buildroot}%{_bindir} +echo \#\!/bin/sh > ooffice +echo exec libreoffice \"\$@\" >> ooffice +chmod a+x ooffice + +echo \#\!/bin/sh > ooviewdoc +echo exec libreoffice --view \"\$@\" >> ooviewdoc +chmod a+x ooviewdoc + +for app in base calc draw impress math writer; do + echo \#\!/bin/sh > oo$app + echo exec libreoffice --$app \"\$@\" >> oo$app + chmod a+x oo$app +done + +sed -e s/LAUNCHER/unopkg/g -e s/BRAND/libreoffice/g %{SOURCE8} > unopkg +chmod a+x unopkg + +sed -e s/LAUNCHER/soffice/g -e s/BRAND/libreoffice/g %{SOURCE8} > libreoffice +chmod a+x libreoffice + +%if 0%{?flatpak} +sed -i -e 's|/usr/lib|/app/lib|g' unopkg libreoffice +%endif + +# rhbz#499474 provide a /usr/bin/soffice for .recently-used.xbel +ln -s %{baseinstdir}/program/soffice soffice +# rhbz#499474 provide a /usr/bin/openoffice.org for backwards compat +ln -s libreoffice openoffice.org +popd + +pushd %{buildroot}%{baseinstdir}/share/xdg/ +chmod u+w *.desktop +ICONVERSION=`echo $PRODUCTVERSION | sed -e 's/\.//'` +for file in *.desktop; do + # rhbz#156677 remove the version from Name= + # rhbz#156067 don't version the icons + sed -i -e "s/ *$PRODUCTVERSION//g" \ + -e "s/$ICONVERSION//g" \ + -e "s/$PRODUCTVERSIONSHORT//g" \ + $file +done +# rhbz#186515 do not show startcenter +desktop-file-edit --set-key=NoDisplay --set-value=true startcenter.desktop +%ifarch s390 s390x aarch64 +for app in base calc draw impress math startcenter writer xsltfilter; do + desktop-file-edit --set-key=NoDisplay --set-value=true $app.desktop +done +%endif +# relocate the .desktop and icon files +install -m 0755 -d %{buildroot}%{_datadir}/applications +for app in base calc draw impress math startcenter writer xsltfilter; do + sed -i -e 's/\${UNIXBASISROOTNAME}/%{name}/' $app.desktop + desktop-file-validate $app.desktop + install -m 0644 -p $app.desktop %{buildroot}%{_datadir}/applications/libreoffice-$app.desktop +done +popd +%if 0%{?flatpak} +# Transform the libreoffice-*.desktop files into +# org.libreoffice.LibreOffice.*.desktop ones: +solenv/bin/assemble-flatpak-desktop.sh %{buildroot}%{_datadir}/applications/ \ + %{buildroot}%{_datadir}/applications/ +rm %{buildroot}%{_datadir}/applications/libreoffice-*.desktop +%endif + +pushd $WORKDIR/os-integration +#get rid of the gnome icons and other unneeded files +rm -rf icons/gnome applications application-registry + +#relocate the rest of them +# rhbz#901346 512x512 icons are not used by anything +for icon in `find icons -path '*/512x512' -prune -o -type f -print`; do + install -m 0755 -d %{buildroot}%{_datadir}/`dirname $icon` + install -m 0644 -p $icon %{buildroot}%{_datadir}/`echo $icon | sed -e s@libreoffice$ICONVERSION-@libreoffice-@ | sed -e s@libreoffice$PRODUCTVERSION-@libreoffice-@` +done +install -m 0755 -d %{buildroot}%{_datadir}/mime-info +install -m 0644 -p mime-info/libreoffice$PRODUCTVERSION.keys %{buildroot}%{_datadir}/mime-info/libreoffice.keys +install -m 0644 -p mime-info/libreoffice$PRODUCTVERSION.mime %{buildroot}%{_datadir}/mime-info/libreoffice.mime +#add our mime-types, e.g. for .oxt extensions +install -m 0755 -d %{buildroot}%{_datadir}/mime/packages +install -m 0644 -p mime/packages/libreoffice$PRODUCTVERSION.xml %{buildroot}%{_datadir}/mime/packages/libreoffice.xml + +%if 0%{?fedora} +# restrict abipkgdiff to shared objects that actually have a stable ABI +for pkg in core base officebean ogltrans pdfimport calc writer impress graphicfilter postgresql ure pyuno x11 gtk3 kde5 libreofficekit; do + cat > %{buildroot}%{baseinstdir}/program/${pkg}.abignore << _EOF +[suppress_file] +file_name_not_regexp=.*\.so\.[0-9]+ +_EOF +done +%endif + +# install LibreOfficeKit +install -m 0755 -d %{buildroot}%{_libdir}/girepository-1.0 +install -m 0644 -p LOKDocView-%{girapiversion}.typelib %{buildroot}%{_libdir}/girepository-1.0/LOKDocView-%{girapiversion}.typelib +install -m 0755 -d %{buildroot}%{_libdir}/gir-1.0 +install -m 0644 -p LOKDocView-%{girapiversion}.gir %{buildroot}%{_libdir}/gir-1.0/LOKDocView-%{girapiversion}.gir +mv %{buildroot}%{baseinstdir}/program/liblibreofficekitgtk.so %{buildroot}%{_libdir} +popd + +# install LibreOfficeKit headers +install -m 0755 -d %{buildroot}%{_includedir}/LibreOfficeKit +install -m 0644 -p include/LibreOfficeKit/* %{buildroot}%{_includedir}/LibreOfficeKit + +rm -rf %{buildroot}%{baseinstdir}/readmes +rm -rf %{buildroot}%{baseinstdir}/licenses +rm -rf %{buildroot}%{baseinstdir}/share/theme_definitions + +# to-do, remove this in libreoffice 4.4 when --without-ppds is gone, it'll do the right thing on its own then +install -m 0755 -d %{buildroot}%{baseinstdir}/share/psprint/driver +install -m 0644 -p vcl/unx/generic/printer/configuration/ppds/SGENPRT.PS %{buildroot}%{baseinstdir}/share/psprint/driver/SGENPRT.PS + +# rhbz#452385 to auto have postgres in classpath if subsequently installed +sed -i -e "s#URE_MORE_JAVA_CLASSPATH_URLS.*#& file:///usr/share/java/postgresql-jdbc.jar#" %{buildroot}%{baseinstdir}/program/fundamentalrc + +# move glade catalog to system glade dir +install -m 0755 -d %{buildroot}%{_datadir}/glade/catalogs +mv %{buildroot}%{baseinstdir}/share/glade/libreoffice-catalog.xml %{buildroot}%{_datadir}/glade/catalogs +install -m 0755 -d %{buildroot}%{_datadir}/glade3/catalogs +ln -sr %{buildroot}%{_datadir}/glade/catalogs/libreoffice-catalog.xml %{buildroot}%{_datadir}/glade3/catalogs + +# rhbz#1049543 install appdata +install -m 0755 -d %{buildroot}%{_datadir}/metainfo +install -m 0644 -p sysui/desktop/appstream-appdata/*.appdata.xml %{buildroot}%{_datadir}/metainfo + +# rhbz#1215800 install symbolic icons +install -m 0755 -d %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE42} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE43} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE44} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE45} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE46} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE47} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +install -m 0644 -p %{SOURCE48} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps + +%if 0%{?flatpak} +# Duplicate icons/*/*/apps/libreoffice-* as +# icons/*/*/apps/org.libreoffice.LibreOffice.* (so they end up "with both their +# original libreoffice-* name as well as the org.libreoffice name needed by +# Flatpak, which fixes the window icons", see +# "clean up desktop integration"): +for i in %{buildroot}%{_datadir}/icons/*/*/apps/libreoffice-*; do + cp -a "$i" \ + "$(dirname "$i")"/org.libreoffice.LibreOffice."${i##*/apps/libreoffice-}" +done +%endif + +# install man pages +install -m 0755 -d %{buildroot}%{_mandir}/man1 +install -m 0644 -p sysui/desktop/man/*.1 %{buildroot}%{_mandir}/man1 +for app in oobase oocalc oodraw ooffice ooimpress oomath ooviewdoc oowriter openoffice.org soffice; do + echo '.so man1/libreoffice.1' > $app.1 + install -m 0644 -p $app.1 %{buildroot}%{_mandir}/man1 +done + +export DESTDIR=%{buildroot} +./solenv/bin/install-gdb-printers -a %{_datadir}/gdb/auto-load%{baseinstdir} -c -i %{baseinstdir} -p %{_datadir}/libreoffice/gdb + +%if 0%{?fedora} +# Update the screenshot shown in the software center +# +# NOTE: It would be *awesome* if this file was pushed upstream. +# +# See http://people.freedesktop.org/~hughsient/appdata/#screenshots for more details. +# +appstream-util replace-screenshots %{buildroot}%{_datadir}/metainfo/libreoffice-writer.appdata.xml \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-writer/a.png \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-writer/b.png +appstream-util replace-screenshots %{buildroot}%{_datadir}/metainfo/libreoffice-calc.appdata.xml \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-calc/a.png +appstream-util replace-screenshots %{buildroot}%{_datadir}/metainfo/libreoffice-draw.appdata.xml \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-draw/a.png +appstream-util replace-screenshots %{buildroot}%{_datadir}/metainfo/libreoffice-impress.appdata.xml \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-impress/a.png +%endif +%if 0%{?flatpak} +# Assemble the libreoffice-*.appdata.xml files into a single +# org.libreoffice.LibreOffice.appdata.xml; first create the single file: +solenv/bin/assemble-flatpak-appdata-step1.sh \ + %{buildroot}%{_datadir}/metainfo/ 0 +%if 0%{?fedora} +# ...then update the screenshots in the single file (see above): +appstream-util replace-screenshots \ + %{buildroot}%{_datadir}/metainfo/org.libreoffice.LibreOffice.appdata.xml \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-writer/a.png \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-writer/b.png \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-calc/a.png \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-draw/a.png \ + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/libreoffice-impress/a.png +%endif +# ...then append the original files to the single file: +solenv/bin/assemble-flatpak-appdata-step2.sh \ + %{buildroot}%{_datadir}/metainfo/ %{buildroot}%{_datadir}/metainfo/ +rm %{buildroot}%{_datadir}/metainfo/libreoffice-*.appdata.xml +%endif + +# rhbz#1247399 - move stable API jars to noarch java location +install -m 0755 -d %{buildroot}%{_javadir}/%{name} +for jar in %{buildroot}%{baseinstdir}/program/classes/*.jar; do + j=`basename $jar` + case ${j%.jar} in + juh|jurt|ridl|unoloader|unoil|officebean) + mv $jar %{buildroot}%{_javadir}/%{name} + ln -sr %{buildroot}%{_javadir}/%{name}/$j $jar + ;; + esac +done + +%check +%ifnarch ppc64 aarch64 armv7hl +make unitcheck slowcheck +# we don't need this anymore +rm -f %{buildroot}%{baseinstdir}/program/classes/smoketest.jar +%endif + +%files + +%files filters + +%files core +%dir %{baseinstdir} +%{baseinstdir}/CREDITS.fodt +%{baseinstdir}/LICENSE.html +%dir %{baseinstdir}/help +%{baseinstdir}/help/idxcaption.xsl +%{baseinstdir}/help/idxcontent.xsl +%{baseinstdir}/help/main_transform.xsl +%{baseinstdir}/presets +%dir %{baseinstdir}/program +%if 0%{?fedora} +%{baseinstdir}/program/core.abignore +%endif +%{baseinstdir}/program/libbasprovlo.so +%{baseinstdir}/program/libcairocanvaslo.so +%{baseinstdir}/program/libcanvasfactorylo.so +%dir %{baseinstdir}/program/classes +%{baseinstdir}/program/classes/commonwizards.jar +%{baseinstdir}/program/classes/form.jar +%{baseinstdir}/program/classes/query.jar +%{baseinstdir}/program/classes/report.jar +%{baseinstdir}/program/classes/ScriptFramework.jar +%{baseinstdir}/program/classes/ScriptProviderForJava.jar +%{baseinstdir}/program/classes/table.jar +%{baseinstdir}/program/classes/unoil.jar +%{baseinstdir}/program/classes/XMergeBridge.jar +%{baseinstdir}/program/classes/xmerge.jar +%{baseinstdir}/program/libcmdmaillo.so +%{baseinstdir}/program/libdeployment.so +%{baseinstdir}/program/libdeploymentgui.so +%{baseinstdir}/program/libdlgprovlo.so +%{baseinstdir}/program/libexpwraplo.so +%{baseinstdir}/program/flat_logo.svg +%{baseinstdir}/program/libfps_officelo.so +%{baseinstdir}/program/gdbtrace +%{baseinstdir}/program/gengal +%{baseinstdir}/program/gengal.bin +%{baseinstdir}/program/libi18nsearchlo.so +%{baseinstdir}/program/libldapbe2lo.so +%{baseinstdir}/program/libacclo.so +%{baseinstdir}/program/libanimcorelo.so +%{baseinstdir}/program/libavmedia*.so +%{baseinstdir}/program/libbasctllo.so +%{baseinstdir}/program/libbiblo.so +%{baseinstdir}/program/libcached1.so +%{baseinstdir}/program/libcanvastoolslo.so +%{baseinstdir}/program/libchart*lo.so +%{baseinstdir}/program/libclewlo.so +%{baseinstdir}/program/libcollator_data.so +%{baseinstdir}/program/libcppcanvaslo.so +%{baseinstdir}/program/libctllo.so +%{baseinstdir}/program/libcuilo.so +%{baseinstdir}/program/libdbalo.so +%{baseinstdir}/program/libdbahsqllo.so +%{baseinstdir}/program/libdbaselo.so +%{baseinstdir}/program/libdbaxmllo.so +#{baseinstdir}/program/libdbmmlo.so +%{baseinstdir}/program/libdbpool2.so +%{baseinstdir}/program/libdbtoolslo.so +%{baseinstdir}/program/libdbulo.so +%{baseinstdir}/program/libdeploymentmisclo.so +%{baseinstdir}/program/libdesktop_detectorlo.so +%{baseinstdir}/program/libdict_ja.so +%{baseinstdir}/program/libdict_zh.so +%{baseinstdir}/program/libdrawinglayerlo.so +%{baseinstdir}/program/libeditenglo.so +%{baseinstdir}/program/libembobj.so +%{baseinstdir}/program/libemboleobj.so +%{baseinstdir}/program/libemfiolo.so +%{baseinstdir}/program/libevoab*.so +%{baseinstdir}/program/libevtattlo.so +%{baseinstdir}/program/libgielo.so +%{baseinstdir}/program/libicglo.so +%{baseinstdir}/program/libindex_data.so +%{baseinstdir}/program/libfilelo.so +%{baseinstdir}/program/libfilterconfiglo.so +%{baseinstdir}/program/libflatlo.so +%{baseinstdir}/program/libfrmlo.so +%{baseinstdir}/program/libguesslanglo.so +%{baseinstdir}/program/libhelplinkerlo.so +%{baseinstdir}/program/libhyphenlo.so +%{baseinstdir}/program/libjdbclo.so +%{baseinstdir}/program/liblnglo.so +%{baseinstdir}/program/libloglo.so +%{baseinstdir}/program/liblocaledata_en.so +%{baseinstdir}/program/liblocaledata_es.so +%{baseinstdir}/program/liblocaledata_euro.so +%{baseinstdir}/program/liblocaledata_others.so +%{baseinstdir}/program/libmcnttype.so +%{baseinstdir}/program/libmorklo.so +%{baseinstdir}/program/libmozbootstraplo.so +%{baseinstdir}/program/libmsfilterlo.so +%{baseinstdir}/program/libmtfrendererlo.so +%{baseinstdir}/program/libmysql_jdbclo.so +%{baseinstdir}/program/libmysqlclo.so +%{baseinstdir}/program/libodbclo.so +%{baseinstdir}/program/liboglcanvaslo.so +%{baseinstdir}/program/liboffacclo.so +%{baseinstdir}/program/libooxlo.so +%{baseinstdir}/program/libopencllo.so +%{baseinstdir}/program/libpcrlo.so +%{baseinstdir}/program/libpdffilterlo.so +%{baseinstdir}/program/libprotocolhandlerlo.so +%{baseinstdir}/program/libsaxlo.so +%{baseinstdir}/program/libscnlo.so +%{baseinstdir}/program/libscriptframe.so +%{baseinstdir}/program/libsdlo.so +%{baseinstdir}/program/libsdfiltlo.so +%{baseinstdir}/program/libsdbc2.so +%{baseinstdir}/program/libsdbtlo.so +%{baseinstdir}/program/libsddlo.so +%{baseinstdir}/program/libsduilo.so +%{baseinstdir}/program/libspelllo.so +%{baseinstdir}/program/libsrtrs1.so +%{baseinstdir}/program/libstoragefdlo.so +%{baseinstdir}/program/libsvgiolo.so +%{baseinstdir}/program/libsvxlo.so +%{baseinstdir}/program/libsvxcorelo.so +%{baseinstdir}/program/libswdlo.so +%{baseinstdir}/program/libswlo.so +%{baseinstdir}/program/libtextconv_dict.so +%{baseinstdir}/program/libtextconversiondlgslo.so +%{baseinstdir}/program/libtextfdlo.so +%{baseinstdir}/program/libodfflatxmllo.so +# TODO: shouldn't it have lo suffix? +%{baseinstdir}/program/libucbhelper.so +%{baseinstdir}/program/libucpchelp1.so +%{baseinstdir}/program/libucpdav1.so +%{baseinstdir}/program/libucpftp1.so +%{baseinstdir}/program/libucphier1.so +%{baseinstdir}/program/libucppkg1.so +%{baseinstdir}/program/libunordflo.so +%{baseinstdir}/program/libunopkgapp.so +%{baseinstdir}/program/libunoxmllo.so +%{baseinstdir}/program/libuuilo.so +%{baseinstdir}/program/libvbahelperlo.so +%{baseinstdir}/program/libxmlfalo.so +%{baseinstdir}/program/libxmlfdlo.so +%{baseinstdir}/program/libxoflo.so +%{baseinstdir}/program/libxsec_xmlsec.so +%{baseinstdir}/program/libxsltdlglo.so +%{baseinstdir}/program/libxsltfilterlo.so +%{baseinstdir}/program/libxstor.so +# TODO how useful this is in Fedora? +%{baseinstdir}/program/liblosessioninstalllo.so +%{baseinstdir}/program/libmigrationoo2lo.so +%{baseinstdir}/program/libmigrationoo3lo.so +%{baseinstdir}/program/libmsformslo.so +%{baseinstdir}/program/opencl +%dir %{baseinstdir}/program/opengl +%{baseinstdir}/program/opengl/*.glsl +%{baseinstdir}/program/types/offapi.rdb +%{baseinstdir}/program/libpasswordcontainerlo.so +%{baseinstdir}/program/pagein-common +%if %{with langpacks} +%dir %{baseinstdir}/program/resource +%endif +%{baseinstdir}/program/senddoc +%dir %{baseinstdir}/program/services +%{baseinstdir}/program/services/services.rdb +%{baseinstdir}/program/libsimplecanvaslo.so +%{baseinstdir}/program/libslideshowlo.so +%{baseinstdir}/program/libsmlo.so +%{baseinstdir}/program/libsmdlo.so +%{baseinstdir}/program/libsofficeapp.so +%{baseinstdir}/program/libstringresourcelo.so +%{baseinstdir}/program/libsysshlo.so +%{baseinstdir}/program/libucpcmis1lo.so +%{baseinstdir}/program/libucpexpand1lo.so +%{baseinstdir}/program/libucpextlo.so +%{baseinstdir}/program/libucpimagelo.so +%{baseinstdir}/program/libucptdoc1lo.so +%{baseinstdir}/program/lounorc +%{baseinstdir}/program/libupdatefeedlo.so +%{baseinstdir}/program/uri-encode +%{baseinstdir}/program/libvbaeventslo.so +%{baseinstdir}/program/libvclcanvaslo.so +%{baseinstdir}/program/versionrc +%dir %{baseinstdir}/share +%dir %{baseinstdir}/share/classification +%{baseinstdir}/share/classification/example*.xml +%dir %{baseinstdir}/share/fonts +%dir %{baseinstdir}/share/fonts/truetype +%{baseinstdir}/share/fonts/truetype/fc_local.conf +%dir %{baseinstdir}/share/Scripts +%{baseinstdir}/share/Scripts/java +%dir %{baseinstdir}/share/autotext +%dir %{_datadir}/autocorr +%{baseinstdir}/share/autocorr +%{baseinstdir}/share/basic +%dir %{baseinstdir}/share/config +%{baseinstdir}/share/config/images_breeze.zip +%{baseinstdir}/share/config/images_breeze_dark.zip +%{baseinstdir}/share/config/images_breeze_dark_svg.zip +%{baseinstdir}/share/config/images_colibre.zip +%{baseinstdir}/share/config/images_elementary.zip +%{baseinstdir}/share/config/images_helpimg.zip +%{baseinstdir}/share/config/images_karasa_jaga.zip +%{baseinstdir}/share/config/images_karasa_jaga_svg.zip +%{baseinstdir}/share/config/images_sifr.zip +%{baseinstdir}/share/config/images_sifr_dark.zip +%{baseinstdir}/share/config/images_sifr_dark_svg.zip +%{baseinstdir}/share/config/images_sifr_svg.zip +%{baseinstdir}/share/config/images_tango.zip +%{baseinstdir}/share/config/images_breeze_svg.zip +%{baseinstdir}/share/config/images_colibre_svg.zip +%{baseinstdir}/share/config/images_elementary_svg.zip +%dir %{baseinstdir}/share/tipoftheday +%{baseinstdir}/share/tipoftheday/*.png +%dir %{baseinstdir}/share/config/soffice.cfg +%{baseinstdir}/share/config/soffice.cfg/modules +%{baseinstdir}/share/config/soffice.cfg/*/ui +%dir %{baseinstdir}/share/emojiconfig +%{baseinstdir}/share/emojiconfig/emoji.json +%{baseinstdir}/share/palette +%{baseinstdir}/share/config/webcast +%{baseinstdir}/share/config/wizard +%dir %{baseinstdir}/share/dtd +%{baseinstdir}/share/dtd/officedocument +%{baseinstdir}/share/gallery +%dir %{baseinstdir}/share/labels +%{baseinstdir}/share/labels/labels.xml +%dir %{baseinstdir}/share/psprint +%config %{baseinstdir}/share/psprint/psprint.conf +%{baseinstdir}/share/psprint/driver +%dir %{baseinstdir}/share/registry +%{baseinstdir}/share/registry/draw.xcd +%{baseinstdir}/share/registry/gnome.xcd +%{baseinstdir}/share/registry/lingucomponent.xcd +%{baseinstdir}/share/registry/main.xcd +%{baseinstdir}/share/registry/math.xcd +%{baseinstdir}/share/registry/oo-ad-ldap.xcd.sample +%{baseinstdir}/share/registry/oo-ldap.xcd.sample +%dir %{baseinstdir}/share/registry/res +%dir %{baseinstdir}/share/template +%dir %{baseinstdir}/share/template/common +%{baseinstdir}/share/template/common/internal +%{baseinstdir}/share/template/common/officorr +%{baseinstdir}/share/template/common/offimisc +%{baseinstdir}/share/template/common/personal +%{baseinstdir}/share/template/common/presnt +%{baseinstdir}/share/template/common/styles +%{baseinstdir}/share/template/common/wizard +%{baseinstdir}/share/template/wizard +%dir %{baseinstdir}/share/wordbook +%{baseinstdir}/share/wordbook/en-GB.dic +%{baseinstdir}/share/wordbook/en-US.dic +%{baseinstdir}/share/wordbook/technical.dic +%{baseinstdir}/program/liblnthlo.so +%{_bindir}/unopkg +%{_mandir}/man1/unopkg.1* +%{baseinstdir}/program/libxmlsecurity.so +%{baseinstdir}/program/libconfigmgrlo.so +%{baseinstdir}/program/libdesktopbe1lo.so +%{baseinstdir}/program/libfsstoragelo.so +%{baseinstdir}/program/libi18npoollo.so +%{baseinstdir}/program/libbasegfxlo.so +# TODO: shouldn't it have lo suffix? +%{baseinstdir}/program/libcomphelper.so +%{baseinstdir}/program/libfwelo.so +%{baseinstdir}/program/libfwilo.so +%{baseinstdir}/program/libfwklo.so +%{baseinstdir}/program/libfwllo.so +%{baseinstdir}/program/libfwmlo.so +# TODO: shouldn't it have lo suffix? +%{baseinstdir}/program/libi18nutil.so +%{baseinstdir}/program/libpackage2.so +%{baseinstdir}/program/libsblo.so +%{baseinstdir}/program/libsfxlo.so +%{baseinstdir}/program/libsotlo.so +%{baseinstdir}/program/libspllo.so +%{baseinstdir}/program/libsvllo.so +%{baseinstdir}/program/libsvtlo.so +%{baseinstdir}/program/libtklo.so +%{baseinstdir}/program/libtllo.so +%{baseinstdir}/program/libucb1.so +%{baseinstdir}/program/libucpfile1.so +%{baseinstdir}/program/libutllo.so +%{baseinstdir}/program/libvcllo.so +%{baseinstdir}/program/libwriterperfectlo.so +%{baseinstdir}/program/libxmlscriptlo.so +%{baseinstdir}/program/libxolo.so +%{baseinstdir}/program/liblocalebe1lo.so +%{baseinstdir}/program/libucpgio1lo.so +%{baseinstdir}/program/types/oovbaapi.rdb +#share unopkg +%dir %{baseinstdir}/share/extensions +%{baseinstdir}/share/extensions/package.txt +%{baseinstdir}/program/unopkg +%{baseinstdir}/program/unopkg.bin +%{baseinstdir}/program/bootstraprc +%{baseinstdir}/program/fundamentalrc +%{baseinstdir}/program/setuprc +%{baseinstdir}/program/intro.png +%{baseinstdir}/program/intro-highres.png +%{baseinstdir}/program/opencltest +%{baseinstdir}/program/soffice +%{baseinstdir}/program/soffice.bin +%{baseinstdir}/program/sofficerc +%{baseinstdir}/program/unoinfo +%{baseinstdir}/program/oosplash +%{baseinstdir}/program/shell/ +%dir %{baseinstdir}/share/filter +%{baseinstdir}/share/filter/oox-drawingml-adj-names +%{baseinstdir}/share/filter/oox-drawingml-cs-presets +%{baseinstdir}/share/filter/vml-shape-types +%{baseinstdir}/share/xdg/ +%{baseinstdir}/program/redirectrc +%if 0%{?flatpak} +%{_datadir}/metainfo/org.libreoffice.LibreOffice.appdata.xml +%{_datadir}/applications/org.libreoffice.LibreOffice.desktop +%else +%{_datadir}/applications/libreoffice-startcenter.desktop +%endif +#launchers +%{_bindir}/libreoffice +%{_bindir}/openoffice.org +%{_bindir}/soffice +%{_bindir}/ooffice +%{_bindir}/ooviewdoc +%{_mandir}/man1/libreoffice.1* +%{_mandir}/man1/openoffice.org.1* +%{_mandir}/man1/soffice.1* +%{_mandir}/man1/ooffice.1* +%{_mandir}/man1/ooviewdoc.1* + +%files base +%{baseinstdir}/program/classes/hsqldb.jar +%{baseinstdir}/program/classes/reportbuilder.jar +%{baseinstdir}/program/classes/reportbuilderwizard.jar +%{baseinstdir}/program/classes/sdbc_hsqldb.jar +%{baseinstdir}/program/access2base.py +%if 0%{?fedora} +%{baseinstdir}/program/base.abignore +%endif +%{baseinstdir}/program/libabplo.so +%{baseinstdir}/program/libdbplo.so +%{baseinstdir}/program/libhsqldb.so +%{baseinstdir}/program/librptlo.so +%{baseinstdir}/program/librptuilo.so +%{baseinstdir}/program/librptxmllo.so +%{baseinstdir}/share/registry/base.xcd +%{baseinstdir}/share/registry/reportbuilder.xcd +%{baseinstdir}/program/sbase +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.base.desktop +%else +%{_datadir}/metainfo/libreoffice-base.appdata.xml +%{_datadir}/applications/libreoffice-base.desktop +%endif +%{_bindir}/oobase +%{_mandir}/man1/oobase.1* + +%if 0%{?fedora} +%files bsh +%{baseinstdir}/program/classes/ScriptProviderForBeanShell.jar +%{baseinstdir}/program/services/scriptproviderforbeanshell.rdb +%{baseinstdir}/share/Scripts/beanshell + +%files rhino +%{baseinstdir}/program/classes/js.jar +%{baseinstdir}/program/classes/ScriptProviderForJavaScript.jar +%{baseinstdir}/program/services/scriptproviderforjavascript.rdb +%{baseinstdir}/share/Scripts/javascript +%endif + +%files wiki-publisher +%docdir %{baseinstdir}/share/extensions/wiki-publisher/license +%{baseinstdir}/share/extensions/wiki-publisher + +%files nlpsolver +%docdir %{baseinstdir}/share/extensions/nlpsolver/help +%{baseinstdir}/share/extensions/nlpsolver + +%files officebean +%{baseinstdir}/program/classes/officebean.jar +%if 0%{?fedora} +%{baseinstdir}/program/officebean.abignore +%endif +%{baseinstdir}/program/libofficebean.so + +%files officebean-common +%{_javadir}/%{name}/officebean.jar + +%files ogltrans +%if 0%{?fedora} +%{baseinstdir}/program/ogltrans.abignore +%endif +%{baseinstdir}/program/libOGLTranslo.so +%{baseinstdir}/program/opengl/basicFragmentShader.glsl +%{baseinstdir}/program/opengl/basicVertexShader.glsl +%{baseinstdir}/program/opengl/dissolveFragmentShader.glsl +%{baseinstdir}/program/opengl/fadeBlackFragmentShader.glsl +%{baseinstdir}/program/opengl/fadeFragmentShader.glsl +%{baseinstdir}/program/opengl/glitterFragmentShader.glsl +%{baseinstdir}/program/opengl/glitterVertexShader.glsl +%{baseinstdir}/program/opengl/honeycombFragmentShader.glsl +%{baseinstdir}/program/opengl/honeycombGeometryShader.glsl +%{baseinstdir}/program/opengl/honeycombVertexShader.glsl +%{baseinstdir}/program/opengl/rippleFragmentShader.glsl +%{baseinstdir}/program/opengl/reflectionFragmentShader.glsl +%{baseinstdir}/program/opengl/reflectionVertexShader.glsl +%{baseinstdir}/program/opengl/staticFragmentShader.glsl +%{baseinstdir}/program/opengl/vortexFragmentShader.glsl +%{baseinstdir}/program/opengl/vortexGeometryShader.glsl +%{baseinstdir}/program/opengl/vortexVertexShader.glsl +%{baseinstdir}/share/config/soffice.cfg/simpress/transitions-ogl.xml +%{baseinstdir}/share/registry/ogltrans.xcd + +%files pdfimport +%if 0%{?fedora} +%{baseinstdir}/program/pdfimport.abignore +%endif +%{baseinstdir}/program/libpdfimportlo.so +%{baseinstdir}/program/xpdfimport +%{baseinstdir}/share/registry/pdfimport.xcd +%dir %{baseinstdir}/share/xpdfimport +%{baseinstdir}/share/xpdfimport/xpdfimport_err.pdf + +%_font_pkg -n %{fontname} opens___.ttf +%doc instdir/LICENSE + +%files calc +%if 0%{?fedora} +%{baseinstdir}/program/calc.abignore +%endif +%{baseinstdir}/program/libanalysislo.so +%{baseinstdir}/program/libcalclo.so +%{baseinstdir}/program/libdatelo.so +%{baseinstdir}/program/libforlo.so +%{baseinstdir}/program/libforuilo.so +%{baseinstdir}/program/libnumbertextlo.so +%{baseinstdir}/program/libpricinglo.so +%{baseinstdir}/program/libsclo.so +%{baseinstdir}/program/libscdlo.so +%{baseinstdir}/program/libscfiltlo.so +%{baseinstdir}/program/libscuilo.so +%{baseinstdir}/program/libsolverlo.so +%{baseinstdir}/program/libwpftcalclo.so +%{baseinstdir}/program/libvbaobjlo.so +%{baseinstdir}/share/calc/styles.xml +%{baseinstdir}/share/registry/calc.xcd +%{baseinstdir}/program/pagein-calc +%{baseinstdir}/program/scalc +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.calc.desktop +%else +%{_datadir}/metainfo/libreoffice-calc.appdata.xml +%{_datadir}/applications/libreoffice-calc.desktop +%endif +%{_bindir}/oocalc +%{_mandir}/man1/oocalc.1* + +%files draw +%{baseinstdir}/program/pagein-draw +%{baseinstdir}/program/sdraw +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.draw.desktop +%else +%{_datadir}/metainfo/libreoffice-draw.appdata.xml +%{_datadir}/applications/libreoffice-draw.desktop +%endif +%{_bindir}/oodraw +%{_mandir}/man1/oodraw.1* + +%files emailmerge +%{baseinstdir}/program/mailmerge.py* +%{baseinstdir}/program/msgbox.py* + +%files writer +%if 0%{?fedora} +%{baseinstdir}/program/writer.abignore +%endif +%{baseinstdir}/program/libhwplo.so +%{baseinstdir}/program/liblwpftlo.so +%{baseinstdir}/program/libmswordlo.so +%{baseinstdir}/program/libswuilo.so +%{baseinstdir}/program/libt602filterlo.so +%{baseinstdir}/program/libwpftwriterlo.so +%{baseinstdir}/program/libwriterfilterlo.so +%{baseinstdir}/program/libwriterlo.so +%{baseinstdir}/program/libvbaswobjlo.so +%{baseinstdir}/share/registry/writer.xcd +%{baseinstdir}/program/pagein-writer +%{baseinstdir}/program/swriter +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.writer.desktop +%else +%{_datadir}/metainfo/libreoffice-writer.appdata.xml +%{_datadir}/applications/libreoffice-writer.desktop +%endif +%{_bindir}/oowriter +%{_mandir}/man1/oowriter.1* + +%files impress +%if 0%{?fedora} +%{baseinstdir}/program/impress.abignore +%endif +%{baseinstdir}/program/libPresentationMinimizerlo.so +%{baseinstdir}/program/libPresenterScreenlo.so +%{baseinstdir}/program/libwpftimpresslo.so +%dir %{baseinstdir}/share/config/soffice.cfg/simpress +%{baseinstdir}/share/config/soffice.cfg/simpress/effects.xml +%{baseinstdir}/share/config/soffice.cfg/simpress/layoutlist.xml +%{baseinstdir}/share/config/soffice.cfg/simpress/objectlist.xml +%{baseinstdir}/share/config/soffice.cfg/simpress/transitions.xml +%{baseinstdir}/share/registry/impress.xcd +%{baseinstdir}/program/pagein-impress +%{baseinstdir}/program/simpress +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.impress.desktop +%else +%{_datadir}/metainfo/libreoffice-impress.appdata.xml +%{_datadir}/applications/libreoffice-impress.desktop +%endif +%{_bindir}/ooimpress +%{_mandir}/man1/ooimpress.1* + +%files math +%{baseinstdir}/program/smath +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.math.desktop +%else +%{_datadir}/applications/libreoffice-math.desktop +%endif +%{_bindir}/oomath +%{_mandir}/man1/oomath.1* + +%files graphicfilter +%if 0%{?fedora} +%{baseinstdir}/program/graphicfilter.abignore +%endif +%{baseinstdir}/program/libflashlo.so +%{baseinstdir}/program/libgraphicfilterlo.so +%{baseinstdir}/program/libsvgfilterlo.so +%{baseinstdir}/program/libwpftdrawlo.so +%{baseinstdir}/share/registry/graphicfilter.xcd + +%files xsltfilter +%{baseinstdir}/share/xslt +%{baseinstdir}/share/registry/xsltfilter.xcd +%if 0%{?flatpak} +%{_datadir}/applications/org.libreoffice.LibreOffice.xsltfilter.desktop +%else +%{_datadir}/applications/libreoffice-xsltfilter.desktop +%endif + +%files postgresql +%if 0%{?fedora} +%{baseinstdir}/program/postgresql.abignore +%endif +%{baseinstdir}/program/libpostgresql-sdbclo.so +%{baseinstdir}/program/libpostgresql-sdbc-impllo.so +%{baseinstdir}/program/postgresql-sdbc.ini +%{baseinstdir}/program/services/postgresql-sdbc.rdb +%{baseinstdir}/share/registry/postgresql.xcd + +%files ure +%{baseinstdir}/program/classes/java_uno.jar +%{baseinstdir}/program/classes/juh.jar +%{baseinstdir}/program/classes/jurt.jar +%{baseinstdir}/program/classes/ridl.jar +%{baseinstdir}/program/classes/unoloader.jar +%{baseinstdir}/program/javaldx +%{baseinstdir}/program/javavendors.xml +%{baseinstdir}/program/jvmfwk3rc +%{baseinstdir}/program/JREProperties.class +%if 0%{?fedora} +%{baseinstdir}/program/ure.abignore +%endif +%{baseinstdir}/program/libaffine_uno_uno.so +%{baseinstdir}/program/libbinaryurplo.so +%{baseinstdir}/program/libbootstraplo.so +%{baseinstdir}/program/libgcc3_uno.so +%{baseinstdir}/program/libi18nlangtag.so +%{baseinstdir}/program/libintrospectionlo.so +%{baseinstdir}/program/libinvocadaptlo.so +%{baseinstdir}/program/libinvocationlo.so +%{baseinstdir}/program/libiolo.so +%{baseinstdir}/program/libjava_uno.so +%{baseinstdir}/program/libjavaloaderlo.so +%{baseinstdir}/program/libjavavmlo.so +%{baseinstdir}/program/libjpipe.so +%{baseinstdir}/program/libjuh.so +%{baseinstdir}/program/libjuhx.so +%{baseinstdir}/program/libjvmaccesslo.so +%{baseinstdir}/program/libjvmfwklo.so +%{baseinstdir}/program/liblog_uno_uno.so +%{baseinstdir}/program/libnamingservicelo.so +%{baseinstdir}/program/libproxyfaclo.so +%{baseinstdir}/program/libreflectionlo.so +%{baseinstdir}/program/libreglo.so +%{baseinstdir}/program/libsal_textenclo.so +%{baseinstdir}/program/libstocserviceslo.so +%{baseinstdir}/program/libstorelo.so +%{baseinstdir}/program/libuno_cppu.so.3 +%{baseinstdir}/program/libuno_cppuhelpergcc3.so.3 +%{baseinstdir}/program/libuno_purpenvhelpergcc3.so.3 +%{baseinstdir}/program/libuno_sal.so.3 +%{baseinstdir}/program/libuno_salhelpergcc3.so.3 +%{baseinstdir}/program/libunoidllo.so +%{baseinstdir}/program/libunsafe_uno_uno.so +%{baseinstdir}/program/libuuresolverlo.so +%{baseinstdir}/program/libxmlreaderlo.so +%{baseinstdir}/program/regmerge +%{baseinstdir}/program/regview +%{baseinstdir}/program/services.rdb +%{baseinstdir}/program/types.rdb +%{baseinstdir}/program/uno +%{baseinstdir}/program/uno.bin +%{baseinstdir}/program/unorc + +%files ure-common +%dir %{_javadir}/%{name} +%{_javadir}/%{name}/juh.jar +%{_javadir}/%{name}/jurt.jar +%{_javadir}/%{name}/ridl.jar +%{_javadir}/%{name}/unoloader.jar +%license instdir/LICENSE + +%files sdk +%{sdkinstdir}/ +%exclude %{sdkinstdir}/docs/ +%exclude %{sdkinstdir}/examples/ + +%files sdk-doc +%docdir %{sdkinstdir}/docs +%license instdir/LICENSE +%{sdkinstdir}/docs/ +%{sdkinstdir}/examples/ + +%files pyuno +%if 0%{?fedora} +%{baseinstdir}/program/pyuno.abignore +%endif +%{baseinstdir}/program/libpyuno.so +%{baseinstdir}/program/pythonloader.py* +%{baseinstdir}/program/libpythonloaderlo.so +%{baseinstdir}/program/pythonloader.unorc +%{baseinstdir}/program/pythonscript.py* +%{baseinstdir}/program/pyuno.so +%{baseinstdir}/program/services/pyuno.rdb +%{baseinstdir}/program/services/scriptproviderforpython.rdb +%{baseinstdir}/program/wizards +%{baseinstdir}/share/Scripts/python +%exclude %{baseinstdir}/share/Scripts/python/LibreLogo +%{libo_python_sitearch}/uno.py* +%{libo_python_sitearch}/unohelper.py* +%{libo_python_sitearch}/officehelper.py* +%if ! 0%{?flatpak} +%{libo_python_sitearch}/__pycache__/uno.cpython-* +%{libo_python_sitearch}/__pycache__/unohelper.cpython-* +%{libo_python_sitearch}/__pycache__/officehelper.cpython-* +%endif +%{baseinstdir}/share/registry/pyuno.xcd + +%files librelogo +%{baseinstdir}/share/registry/librelogo.xcd +%{baseinstdir}/share/Scripts/python/LibreLogo + +%files glade +%{baseinstdir}/program/ui-previewer +%{_datadir}/glade +%{_datadir}/glade3 + +%files data +%{_datadir}/icons/hicolor/*/*/libreoffice* +%{_datadir}/icons/locolor/*/*/libreoffice* +%if 0%{?flatpak} +%{_datadir}/icons/hicolor/*/*/org.libreoffice.LibreOffice.* +%{_datadir}/icons/locolor/*/*/org.libreoffice.LibreOffice.* +%endif +%{_datadir}/mime-info/libreoffice.* +%{_datadir}/mime/packages/libreoffice.xml +# TODO: rename -data to -core-common? +%dir %{_javadir}/%{name} +%{_javadir}/%{name}/unoil.jar +%dir %{datadir} +%doc instdir/CREDITS.fodt +%doc instdir/LICENSE.html +%doc instdir/LICENSE +%doc instdir/NOTICE +%license instdir/LICENSE + +%post data +for theme in hicolor locolor; do + touch --no-create %{_datadir}/icons/$theme &>/dev/null || : +done + +%postun data +if [ $1 -eq 0 ] ; then + for theme in hicolor locolor; do + touch --no-create %{_datadir}/icons/$theme &>/dev/null || : + gtk-update-icon-cache -q %{_datadir}/icons/$theme &>/dev/null || : + done +fi + +%posttrans data +for theme in hicolor locolor; do + gtk-update-icon-cache -q %{_datadir}/icons/$theme &>/dev/null || : +done + +%files x11 +%if 0%{?fedora} +%{baseinstdir}/program/x11.abignore +%endif +%{baseinstdir}/program/libvclplug_genlo.so + +%files gtk3 +%if 0%{?fedora} +%{baseinstdir}/program/gtk3.abignore +%endif +%{baseinstdir}/program/libvclplug_gtk3lo.so + +%if 0%{?fedora} + +%files kde5 +%if 0%{?fedora} +%{baseinstdir}/program/kde5.abignore +%endif +%{baseinstdir}/program/libkf5be1lo.so +%{baseinstdir}/program/libvclplug_kf5lo.so +%{baseinstdir}/program/libvclplug_qt5lo.so + +%files kf5 +%{baseinstdir}/program/libvclplug_gtk3_kde5lo.so +%{baseinstdir}/program/lo_kde5filepicker + +%endif + +%files -n libreofficekit +%{baseinstdir}/share/libreofficekit +%{_libdir}/girepository-1.0/LOKDocView-%{girapiversion}.typelib +%if 0%{?fedora} +%{baseinstdir}/program/libreofficekit.abignore +%endif +%{_libdir}/liblibreofficekitgtk.so + +%files -n libreofficekit-devel +%{_libdir}/gir-1.0/LOKDocView-%{girapiversion}.gir +%{_includedir}/LibreOfficeKit + +%changelog +* Mon Nov 21 2022 Stephan Bergmann - 1:6.4.7.2-13 +- Resolves: rhbz#2031681 Failure saving to smb share + +* Fri Oct 14 2022 Caolán McNamara - 1:6.4.7.2-12 +- Resolves: rhbz#2118928 CVE-2022-26305 Untrusted Macros +- Resolves: rhbz#2118924 CVE-2022-26307 Weak Master Keys +- Resolves: rhbz#2118920 CVE-2022-26306 Static Initialization Vector +- Resolves: rhbz#2134702 CVE-2022-3140 Macro URL arbitrary script execution + +* Mon Mar 07 2022 Caolán McNamara - 1:6.4.7.2-11 +- Resolves: rhbz#2060559 CVE-2021-25636 + +* Mon Feb 07 2022 Caolán McNamara - 1:6.4.7.2-10 +- Related: rhbz#2029810 bump n-v-r + +* Mon Jan 31 2022 Caolán McNamara - 1:6.4.7.2-9 +- Related: rhbz#2029810 set NoDisplay=true for .desktop on s390x/aarch64 +- Related: rhbz#2029810 don't Require any vclplug for s390x/aarch64 + +* Tue Dec 07 2021 Caolán McNamara - 1:6.4.7.2-8 +- Resolves: rhbz#2029810 enable make check on s390x + +* Fri Oct 15 2021 Caolán McNamara - 1:6.4.7.2-7 +- Resolves: rhbz#2013858 CVE-2021-25633 +- Resolves: rhbz#2014215 CVE-2021-25634 +- Resolves: rhbz#2014209 CVE-2021-25635 + +* Mon Sep 06 2021 Caolán McNamara - 1:6.4.7.2-6 +- Resolves: rhbz#1980800 allow convert to csv to write each sheet to + separate file +- Resolves: rhbz#1992695 two style tags where there should be one + +* Wed Feb 03 2021 Caolán McNamara - 1:6.4.7.2-5 +- Resolves: rhbz#1924619 bad insertion of emoji + +* Mon Nov 09 2020 Caolán McNamara - 1:6.4.7.2-4 +- Resolves: rhbz#1889801 rebuild for poppler + +* Thu Oct 29 2020 Caolán McNamara - 1:6.4.7.2-3 +- Related: rhbz#1874234 fix upgrade dependency problems + +* Wed Oct 28 2020 Caolán McNamara - 1:6.4.7.2-2 +- Related: rhbz#1874234 hang in check + +* Wed Oct 21 2020 Caolán McNamara - 1:6.4.7.2-1 +- Resolves: rhbz#1874234 latest stable release + +* Wed Jul 08 2020 Caolán McNamara - 1:6.3.6.2-3 +- Obsoletes any libreoffice-gtk2-debuginfo along with libreoffice-gtk2 + +* Tue Jun 02 2020 Caolán McNamara - 1:6.3.6.2-2 +- Resolves: rhbz#1841907 always produce utf-8 from gettext + +* Tue Apr 28 2020 Caolán McNamara - 1:6.3.6.2-1 +- rhbz#1796893 latest stable release + +* Tue Apr 14 2020 Caolán McNamara - 1:6.3.5.2-7 +- rhbz#1796893 don't show error dialog on G_IO_ERROR_FAILED_HANDLED + +* Wed Apr 01 2020 Caolán McNamara - 1:6.3.5.2-6 +- rhbz#1819798 Start Center crash after pressing Help button before + using any topevel module + +* Fri Mar 27 2020 Caolán McNamara - 1:6.3.5.2-5 +- rhbz#1796893 spreadsheetml2ooo.xsl was not well formed xml +- rhbz#1796893 fix impress print dialog range + +* Mon Mar 23 2020 Caolán McNamara - 1:6.3.5.2-4 +- rhbz#1796893 fix help->licence info->license + +* Fri Mar 20 2020 Caolán McNamara - 1:6.3.5.2-3 +- rhbz#1796893 disable tip of the day by default + +* Thu Mar 19 2020 Caolán McNamara - 1:6.3.5.2-2 +- rhbz#1796893 improve langpack requires + +* Fri Mar 06 2020 Caolán McNamara - 1:6.3.5.2-1 +- rhbz#1796893 latest stable release + +* Mon Oct 14 2019 Caolán McNamara - 1:6.0.6.1-20 +- Resolves: rhbz#1743958 CVE-2019-9849, etc. +- Resolves: rhbz#1648281 Junk character gets added when some emojis are inserted + +* Mon Aug 19 2019 Caolán McNamara - 1:6.0.6.1-19 +- Related: rhbz#1691287 escape backslashes etc in username + +* Tue Aug 13 2019 Caolán McNamara - 1:6.0.6.1-18 +- Resolves: rhbz#1691287 improve prompt for auth-info-required + +* Fri Jun 28 2019 Marek Kasik - 1:6.0.6.1-17 +- Rebuild due to soname bump in poppler-0.66.0-21 +- Resolves: #1715842 + +* Tue Jun 04 2019 Caolán McNamara - 1:6.0.6.1-16 +- Resolves: rhbz#1715109 add 'All files' to the graphic filter list + +* Fri Apr 26 2019 Caolán McNamara - 1:6.0.6.1-15 +- Resolves: rhbz#1703375 disable bsh and rhino for rhel + +* Fri Mar 29 2019 Caolán McNamara - 1:6.0.6.1-14 +- Resolves: rhbz#1691287 prompt for auth-info-required + +* Fri Feb 08 2019 Caolán McNamara - 1:6.0.6.1-13 +- Related: rhbz#1672004 fix serbian/swedish autocorr rpm upgrade + +* Sun Feb 03 2019 Caolán McNamara - 1:6.0.6.1-12 +- Resolves: rhbz#1672004 CVE-2018-16858 + +* Thu Nov 15 2018 Caolán McNamara - 1:6.0.6.1-11 +- Resolves: rhbz#1649251 impress webpreview doesn't work without graphicfilter +- Resolves: rhbz#1648949 fix docx missing date forms + +* Thu Nov 08 2018 Caolán McNamara - 1:6.0.6.1-10 +- Resolves: rhbz#1647507 try user password for both pdf modes + +* Wed Oct 10 2018 Caolán McNamara - 1:6.0.6.1-9 +- Resolves: rhbz#1637848 enable weak-deps Supplements for langpacks + +* Tue Sep 18 2018 Tomas Orsava - 1:6.0.6.1-8 +- Resolves: rhbz#1619153 Require the Python interpreter directly instead of + relying on the package name + +* Fri Aug 31 2018 Stephan Bergmann - 1:6.0.6.1-7 +- Resolves: rhbz#1618703 Use OpenSSL instead of internal cipher functionality + +* Fri Aug 10 2018 Caolán McNamara - 1:6.0.6.1-6.3 +- Resolves: rhbz#1614376 FTBFS + +* Thu Jul 26 2018 Caolán McNamara - 1:6.0.6.1-6 +- Related: rhbz#1602589 fix/silence more covscan warnings + +* Fri Jul 20 2018 Caolán McNamara - 1:6.0.6.1-5 +- implement export of underline in outlined font for simple case + +* Wed Jul 18 2018 Caolán McNamara - 1:6.0.6.1-4 +- Resolves: rhbz#1602589 fix covscan issues + +* Tue Jul 17 2018 Eike Rathke - 1:6.0.6.1-3 +- Upgrade to ICU 61.1 +- Upgrade to ICU 62.1 + +* Tue Jul 17 2018 Caolán McNamara - 1:6.0.6.1-2 +- Resolves: rhbz#1601882 fails to build with --nocheck + +* Tue Jul 17 2018 Caolán McNamara - 1:6.0.6.1-1 +- latest 6.0 release + +* Fri Jul 13 2018 Fedora Release Engineering - 1:6.0.5.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jul 10 2018 Pete Walter - 1:6.0.5.2-2 +- Rebuild for ICU 62 + +* Fri Jun 22 2018 Caolán McNamara - 1:6.0.5.2-1 +- latest 6.0 release +- fix for ICU 61 +- fix for Python 3.7 + +* Tue Jun 19 2018 Miro Hrončok - 1:6.0.4.2-5 +- Rebuilt for Python 3.7 + +* Tue Jun 05 2018 Caolán McNamara - 1:6.0.4.2-4 +- Resolves: rhbz#1581028 endless font widget update + +* Tue Jun 05 2018 Caolán McNamara - 1:6.0.4.2-3 +- use weak deps for fedora only + +* Mon May 28 2018 Caolán McNamara - 1:6.0.4.2-2 +- Resolves: rhbz#1582324 crash after merging writer table cells + +* Fri May 25 2018 Caolán McNamara - 1:6.0.4.2-1 +- latest 6.0 release + +* Wed May 9 2018 Stephan Bergmann - 1:6.0.3.2-10 +- Fix a potential crash when using the dconf configuration backend + +* Sat May 5 2018 Caolán McNamara - 1:6.0.3.2-9 +- tdf#117413 char doubling in calc under X + +* Fri May 4 2018 Caolán McNamara - 1:6.0.3.2-8 +- rhbz#1575000 CVE-2018-10583 allow embedded links to smb resources + to be blocked + +* Thu May 3 2018 Caolán McNamara - 1:6.0.3.2-7 +- rhbz#1573845 won't start without at least Langpack-en-US.xcd + +* Mon Apr 30 2018 Pete Walter - 1:6.0.3.2-6 +- Rebuild for ICU 61.1 + +* Tue Apr 24 2018 Caolán McNamara - 1:6.0.3.2-5 +- Resolves: tdf#116951 rhbz#1569331 start is G_MAXINT + +* Thu Apr 19 2018 Stephan Bergmann - 1:6.0.3.2-4 +- Resolves: rhbz#1568579 LibreOffice --headless zombie process +- Related: rhbz#1569331 end should be in terms of unicode chars, not bytes + +* Tue Apr 17 2018 Caolán McNamara - 1:6.0.3.2-3 +- Related: rhbz#1396729 use cairo_surface_create_similar + +* Tue Apr 10 2018 Caolán McNamara - 1:6.0.3.2-2 +- finally drop bundled xmlsec1 + +* Thu Mar 29 2018 Caolán McNamara - 1:6.0.3.2-1 +- latest version + +* Thu Mar 29 2018 Caolán McNamara - 1:6.0.3.1-3 +- Related: rhbz#1066844 drop libreofficekit requires + +* Fri Mar 23 2018 Marek Kasik - 1:6.0.3.1-2 +- Rebuild for poppler-0.63.0 + +* Thu Mar 22 2018 David Tardon - 1:6.0.3.1-1 +- update to 6.0.3 rc1 + +* Fri Mar 16 2018 Caolán McNamara - 1:6.0.2.1-3 +- Resolves: rhbz#1392145 ensure titlebar close button matches 'outside' direction + +* Fri Mar 16 2018 Stephan Bergmann - 1:6.0.2.1-2 +- lib dir missing from libreoffice-sdk + +* Fri Feb 23 2018 David Tardon - 1:6.0.2.1-1 +- update to 6.0.2 rc1 + +* Wed Feb 14 2018 David Tardon - 1:6.0.1.1-2 +- rebuild for poppler 0.62.0 + +* Fri Feb 09 2018 Caolán McNamara - 1:6.0.1.1-1 +- latest stable + +* Wed Feb 07 2018 Fedora Release Engineering - 1:6.0.0.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Feb 06 2018 Stephan Bergmann - 1:6.0.0.3-2-UNBUILT +- Resolves: rhbz#1541486 Base table dialog title shown in wrong language + +* Sun Feb 04 2018 David Tardon - 1:6.0.0.3-1 +- update to 6.0.0 rc3 + +* Wed Jan 31 2018 Michael Stahl - 1:6.0.0.2-3 +- add lots of .abignore files to restrict abipkgdiff to shared objects + that actually have a stable ABI + +* Tue Jan 30 2018 Björn Esser - 1:6.0.0.2-2 +- Rebuilt for Boost 1.66.0 + +* Fri Jan 12 2018 David Tardon - 1:6.0.0.2-1 +- update to 6.0.0 rc2 + +* Tue Jan 09 2018 Caolán McNamara - 1:6.0.0.1-3 +- bump to Modify2 for app_id so install hint says 'LibreOffice wants to install' + +* Thu Dec 21 2017 Caolán McNamara - 1:6.0.0.1-2 +- request langpack for autodetected desired ui locale via packagekit + +* Wed Dec 20 2017 David Tardon - 1:6.0.0.1-1 +- update to 6.0.0 rc1 + +* Thu Dec 14 2017 David Tardon - 1:6.0.0.0-8.beta2 +- update to 6.0.0 beta2 + +* Mon Dec 04 2017 Caolán McNamara - 1:6.0.0.0-7.beta1 +- Rebuild for hunspell 1.6.2 + +* Thu Nov 30 2017 Pete Walter - 1:6.0.0.0-6.beta1 +- Rebuild for ICU 60.1 + +* Sat Nov 25 2017 David Tardon - 1:6.0.0.0-5.beta1 +- update to 6.0.0 beta1 + +* Wed Nov 22 2017 Eike Rathke - 1:6.0.0.0-4.alpha1 +- prepare for build with ICU 60.1 + +* Mon Nov 20 2017 David Tardon - 1:6.0.0.0-3.alpha1 +- rebuild for liborcus 0.13.1 + +* Wed Nov 08 2017 David Tardon - 1:6.0.0.0-2.alpha1 +- rebuild for poppler 0.61.0 + +* Thu Nov 02 2017 David Tardon - 1:6.0.0.0-1.alpha1 +- update to 6.0.0 alpha1 +- update location of appdata files +- use weak dependencies +- mark bundled packages + +* Tue Oct 17 2017 David Tardon - 1:5.4.3.1-1 +- update to 5.4.3 rc1 + +* Fri Oct 06 2017 David Tardon - 1:5.4.2.2-3 +- rebuild for poppler 0.60.1 + +* Sun Oct 01 2017 Thierry Vignaud - 1:5.4.2.2-2 +- fix libreoffice wrapper + +* Wed Sep 27 2017 David Tardon - 1:5.4.2.2-1 +- update to 5.4.2 rc2 + +* Mon Sep 18 2017 David Tardon - 1:5.4.2.1-1 +- update to 5.4.2 rc1 + +* Tue Sep 12 2017 David Tardon - 1:5.4.1.2-3 +- Resolves: rhbz#1490318 do not use versioned Supplements + +* Fri Sep 08 2017 David Tardon - 1:5.4.1.2-2 +- rebuild for poppler 0.59.0 + +* Sun Aug 27 2017 David Tardon - 1:5.4.1.2-1 +- update to 5.4.1 rc2 + +* Fri Aug 11 2017 Caolán McNamara - 1:5.4.0.3-5 +- implement char highlighting ui for graphics styles + +* Thu Aug 03 2017 David Tardon - 1:5.4.0.3-4 +- rebuild for poppler 0.57.0 + +* Mon Jul 31 2017 Kalev Lember - 1:5.4.0.3-3 +- Enable the s390x build again + +* Mon Jul 31 2017 Kalev Lember - 1:5.4.0.3-2 +- Temporarily disable the build on s390x + +* Wed Jul 26 2017 Fedora Release Engineering - 1:5.4.0.3-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Jul 21 2017 Kalev Lember - 1:5.4.0.2-2 +- Rebuilt for Boost 1.64 + +* Fri Jul 07 2017 David Tardon - 1:5.4.0.2-1 +- update to 5.4.0 rc2 + +* Fri Jun 23 2017 David Tardon - 1:5.4.0.1-1 +- update to 5.4.0 rc1 + +* Wed Jun 07 2017 David Tardon - 1:5.4.0.0-3.beta2 +- update to 5.4.0 beta2 + +* Sun May 21 2017 David Tardon - 1:5.4.0.0-2.beta1 +- update to 5.4.0 beta1 + +* Tue May 02 2017 David Tardon - 1:5.4.0.0-1.alpha1 +- update to 5.4.0 alpha1 + +* Wed Apr 19 2017 David Tardon - 1:5.3.3.1-1 +- update to 5.3.3 rc1 + +* Wed Mar 29 2017 David Tardon - 1:5.3.2.2-1 +- update to 5.3.2 rc2 + +* Tue Mar 28 2017 David Tardon - 1:5.3.2.1-3 +- rebuild for poppler 0.53.0 + +* Mon Mar 27 2017 Caolán McNamara - 1:5.3.2.1-2 +- Resolves: rhbz#1432468 disable opencl by default + +* Sun Mar 19 2017 David Tardon - 1:5.3.2.1-1 +- update to 5.3.2 rc1 + +* Mon Mar 13 2017 Caolán McNamara - 1:5.3.1.2-2 +- Resolves: rhbz#1431189 add Indonesian langpack + +* Thu Mar 09 2017 David Tardon - 1:5.3.1.2-1 +- update to 5.3.1 rc2 + +* Thu Feb 23 2017 David Tardon - 1:5.3.1.1-1 +- update to 5.3.1 rc1 + +* Tue Feb 07 2017 Björn Esser - 1:5.3.0.3-3 +- Rebuilt for Boost 1.63 + +* Thu Feb 02 2017 Caolán McNamara - 1:5.3.0.3-2 +- Resolves: rhbz#1409401 add depend on gtksink gstreamer1 element + +* Fri Jan 27 2017 David Tardon - 1:5.3.0.3-1 +- update to 5.3.0 rc3 + +* Wed Jan 18 2017 David Tardon - 1:5.3.0.2-1 +- update to 5.3.0 rc2 +- temp. disable building of help on ARM to fix build + +* Tue Jan 10 2017 David Tardon - 1:5.3.0.1-1 +- update to 5.3.0 rc1 + +* Tue Dec 27 2016 Caolán McNamara - 1:5.3.0.0-8.beta1 +- try arm build + +* Thu Dec 22 2016 Miro Hrončok - 1:5.3.0.0-7.beta2 +- Rebuild for Python 3.6 + +* Mon Dec 19 2016 Miro Hrončok - 1:5.3.0.0-6.beta2 +- Rebuild for Python 3.6 + +* Thu Dec 15 2016 David Tardon - 1:5.3.0.0-5.beta2 +- update to 5.3.0 beta2 + +* Tue Dec 13 2016 Caolán McNamara - 1:5.3.0.0-4.beta1 +- rebuild for hunspell-1.5.4 + +* Wed Nov 23 2016 David Tardon - 1:5.3.0.0-3.beta1 +- update to 5.3.0 beta1 + +* Tue Nov 08 2016 David Tardon - 1:5.3.0.0-2.alpha1 +- allow abrt to work again + +* Sat Oct 22 2016 David Tardon - 1:5.3.0.0-1.alpha1 +- update to 5.3.0 alpha1 + +* Fri Oct 21 2016 Marek Kasik - 1:5.2.3.1-2 +- Rebuild for poppler-0.48.0 + +* Sat Oct 15 2016 David Tardon - 1:5.2.3.1-1 +- update to 5.2.3 rc1 + +* Fri Oct 07 2016 Stephan Bergmann - 1:5.2.2.2-3 +- Resolves: rhbz#1382401 broken export of emojis to HTML + +* Thu Sep 29 2016 David Tardon - 1:5.2.2.2-2 +- rebuild for liborcus 0.12 + +* Wed Sep 21 2016 David Tardon - 1:5.2.2.2-1 +- update to 5.2.2 rc2 + +* Wed Sep 21 2016 Caolán McNamara - 1:5.2.2.1-5 +- Related: rhbz#1362451 apply patch + +* Tue Sep 20 2016 Caolán McNamara - 1:5.2.2.1-4 +- Related: rhbz#1362451 avoid recursive ownerchanged signal during ownerchange + +* Mon Sep 19 2016 Caolán McNamara - 1:5.2.2.1-3 +- Related: rhbz#1373933 do less on style-updated +- Related: rhbz#1353069 don't clear XATTR_FILL from in use styles + +* Fri Sep 16 2016 Caolán McNamara - 1:5.2.2.1-2 +- Resolves: rhbz#1373933 gtk 3.21 emits way too many "style-set" signals + +* Wed Sep 14 2016 David Tardon - 1:5.2.2.1-1 +- update to 5.2.2 rc1 + +* Tue Sep 13 2016 Stephan Bergmann - 1:5.2.1.2-3 +- enable dconf support for Fleet Commander + +* Mon Sep 05 2016 David Tardon - 1:5.2.1.2-2 +- Resolves: rhbz#1247399 install public jars according to packaging guidelines +- Resolves: rhbz#1363874 install LibreOfficeKit headers + +* Fri Aug 26 2016 David Tardon - 1:5.2.1.2-1 +- update to 5.2.1 rc2 + +* Thu Aug 11 2016 David Tardon - 1:5.2.1.1-1 +- update to 5.2.1 rc1 + +* Fri Jul 29 2016 David Tardon - 1:5.2.0.4-1 +- update to 5.2.0 rc4 + +* Thu Jul 21 2016 David Tardon - 1:5.2.0.3-1 +- update to 5.2.0 rc3 + +* Tue Jul 19 2016 Fedora Release Engineering - 1:5.2.0.2-4 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Mon Jul 18 2016 Marek Kasik - 1:5.2.0.2-3 +- Rebuild for poppler-0.45.0 + +* Thu Jul 07 2016 David Tardon - 1:5.2.0.2-2 +- remove obsolete wiki-publisher requires apache-commons-* + +* Thu Jul 07 2016 David Tardon - 1:5.2.0.2-1 +- update to 5.2.0 rc2 +- Resolves: rhbz#1351292 fix switching of modes in Impress + +* Tue Jun 28 2016 David Tardon - 1:5.2.0.1-2 +- Resolves: rhbz#1341064 fix test on big endian systems + +* Wed Jun 22 2016 David Tardon - 1:5.2.0.1-1 +- update to 5.1.0 rc1 +- Resolves: rhbz#1343752 wrong radiobutton and checkbutton behavior in + "view" menu +- Resolves: rhbz#1349261 do not pull in all variants of english dicts + +* Thu Jun 09 2016 David Tardon - 1:5.2.0.0-8.beta2 +- update to 5.2.0 beta2 + +* Thu May 26 2016 David Tardon - 1:5.2.0.0-7.beta1 +- update to 5.2.0 beta1 + +* Mon May 16 2016 David Tardon - 1:5.2.0.0-6.alpha1 +- Resolves: rhbz#1327847 remove multilib conflicts in .desktop files + +* Fri May 13 2016 David Tardon - 1:5.2.0.0-5.alpha1 +- rebuild for mdds 1.2.0 +- Resolves: rhbz#1325858 fix build on 64-bit secondary arches + +* Tue May 10 2016 David Tardon - 1:5.2.0.0-4.alpha1 +- Resolves: rhbz#1333899 recommended pkgs are omitted from default + installation + +* Tue May 3 2016 Marek Kasik - 1:5.2.0.0-3.alpha1 +- Rebuild for poppler-0.43.0 + +* Mon May 02 2016 David Tardon - 1:5.2.0.0-2.alpha1 +- Resolves: rhbz#1326602 leakage of removed background image set in master slide + +* Fri Apr 22 2016 David Tardon - 1:5.2.0.0-1.alpha1 +- update to 5.2.0 alpha1 + +* Thu Apr 21 2016 David Tardon - 1:5.1.3.1-1 +- update to 5.1.3 rc1 +- Resolves: tdf#91778 drawing the background over an active cursor + +* Mon Apr 18 2016 Caolán McNamara - 1:5.1.2.1-6 +- rebuild for hunspell 1.4.0 + +* Fri Apr 15 2016 David Tardon - 1:5.1.2.1-5 +- rebuild for ICU 57.1 + +* Thu Apr 07 2016 Caolán McNamara - 1:5.1.2.1-4 +- gtk3: fix combobox and listbox + +* Wed Mar 30 2016 David Tardon - 1:5.1.2.1-3 +- support both glade and glade3 + +* Mon Mar 21 2016 David Tardon - 1:5.1.2.1-2 +- Resolves: rhbz#1319458 avoid rich deps in Requires + +* Wed Mar 16 2016 David Tardon - 1:5.1.2.1-1 +- update to 5.1.2 rc1 +- split VCL plugins into subpackages +- rename libreoffice-kde to libreoffice-kde4 +- only recommend fonts +- remove hard dependency on English spell checker and auto-correction + rules +- disable quickstarter +- move icons and other system-integration stuff to a noarch subpackage +- disable browser plugin in preparation for its removal in 5.2 + +* Wed Mar 09 2016 David Tardon - 1:5.1.1.3-2 +- update for liborcus 0.11.0 + +* Thu Mar 03 2016 David Tardon - 1:5.1.1.3-1 +- update to 5.1.1 rc3 + +* Fri Feb 26 2016 David Tardon - 1:5.1.1.2-1 +- update to 5.1.1 rc2 + +* Mon Feb 22 2016 David Tardon - 1:5.1.1.1-5 +- Resolves: rhbz#1310527 add langpack deps + +* Tue Feb 16 2016 Caolán McNamara - 1:5.1.1.1-4 +- video playback under wayland with gstreamer gtksink + +* Mon Feb 15 2016 David Tardon - 1:5.1.1.1-3 +- rebuild for openCOLLADA soname change + +* Sun Feb 14 2016 David Tardon - 1:5.1.1.1-2 +- switch to mdds 1.x + +* Thu Feb 11 2016 David Tardon - 1:5.1.1.1-1 +- update to 5.1.1 rc1 +- Resolves: rhbz#1303007 add noarch Provides too + +* Thu Feb 11 2016 Caolán McNamara - 1:5.1.0.3-3 +- rework gtk3 themeing to work with latest gtk + +* Tue Feb 02 2016 Caolán McNamara - 1:5.1.0.3-2 +- Resolves: rhbz#1303619 nothing provides java-devel(x86_64) + +* Wed Jan 27 2016 David Tardon - 1:5.1.0.3-1 +- update to 5.1.0 rc3 +- Resolves: rhbz#1168757 Selecting multiple slides is not reflected in Print + dialog + +* Fri Jan 22 2016 Marek Kasik - 1:5.1.0.2-5 +- Rebuild for poppler-0.40.0 + +* Mon Jan 18 2016 Jonathan Wakely - 1:5.1.0.2-4 +- Rebuilt for Boost 1.60 + +* Sat Jan 16 2016 Mamoru TASAKA - 1:5.1.0.2-3 +- Remove arch-specific dependency for font subpackage as it is noarch + +* Thu Jan 14 2016 Adam Jackson - 1:5.1.0.2-2 +- Rebuild for glew 1.13 + +* Thu Jan 14 2016 David Tardon - 1:5.1.0.2-1 +- update to 5.1.0 rc2 + +* Thu Dec 17 2015 Bastien Nocera 1:5.1.0.1-2 +- Add GLSL files missing from the package +- Split up inclusion of latin Serbian files to avoid duplicate listing + +* Wed Dec 16 2015 David Tardon - 1:5.1.0.1-1 +- update to 5.1.0 rc1 + +* Mon Dec 14 2015 David Tardon - 1:5.1.0.0-11.beta2 +- backport more upstream fixes for libreofficekit +- fix unit test on i686 + +* Wed Dec 09 2015 David Tardon - 1:5.1.0.0-10.beta2 +- backport upstream fixes for libreofficekit + +* Fri Dec 04 2015 David Tardon - 1:5.1.0.0-9.beta2 +- update to 5.1.0 beta2 + +* Thu Dec 03 2015 Caolán McNamara - 1:5.1.0.0-8.beta1 +- enable and bundle libreofficekit introspection + +* Thu Nov 26 2015 David Tardon - 1:5.1.0.0-7.beta1 +- update to 5.1.0 beta1 + +* Tue Nov 10 2015 Fedora Release Engineering - 1:5.1.0.0-6.alpha1 +- Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 + +* Thu Nov 05 2015 David Tardon - 1:5.1.0.0-5.alpha1 +- Related: rhbz#1276061 build failure on ppc64 + +* Tue Nov 03 2015 David Tardon - 1:5.1.0.0-4.alpha1 +- Resolves: rhbz#1276061 build failure on ppc64 + +* Wed Oct 28 2015 David Tardon - 1:5.1.0.0-3.alpha1 +- rebuild for ICU 56.1 + +* Tue Oct 27 2015 Eike Rathke - 1:5.1.0.0-2.alpha1 +- prepare to enable build with ICU 56 + +* Mon Oct 19 2015 David Tardon - 1:5.1.0.0-1.alpha1 +- update to 5.1.0 alpha1 + +* Mon Oct 12 2015 David Tardon - 1:5.0.3.1-1 +- update to 5.0.3 rc1 + +* Thu Oct 08 2015 Caolán McNamara - 1:5.0.2.2-4 +- Resolves: rhbz#1269593 declare support for vnd.libreoffice.cmis:// URLs + +* Wed Sep 30 2015 Caolán McNamara - 1:5.0.2.2-3 +- implement save slide background for impress + +* Mon Sep 28 2015 Caolán McNamara - 1:5.0.2.2-2 +- Resolves: tdf#93461 captions laid out behind images + +* Thu Sep 17 2015 David Tardon - 1:5.0.2.2-1 +- update to 5.0.2 rc2 + +* Sat Sep 05 2015 David Tardon - 1:5.0.2.1-1 +- update to 5.0.2 rc1 + +* Sat Aug 22 2015 David Tardon - 1:5.0.1.2-1 +- update to 5.0.1 rc2 + +* Tue Aug 11 2015 David Tardon - 1:5.0.1.1-1 +- update to 5.0.1 rc1 + +* Wed Aug 05 2015 Jonathan Wakely 5.0.0.5-2 +- Rebuilt for Boost 1.58 + +* Mon Aug 03 2015 David Tardon - 1:5.0.0.5-1 +- update to 5.0.0 rc5 + +* Wed Jul 29 2015 Fedora Release Engineering - 1:5.0.0.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/F23Boost159 + +* Sat Jul 25 2015 David Tardon - 1:5.0.0.4-1 +- update to 5.0.0 rc4 + +* Fri Jul 24 2015 Adam Williamson - 1:5.0.0.3-3 +- rebuild for Boost 1.58 (for real this time) + +* Wed Jul 22 2015 David Tardon - 1:5.0.0.3-2 +- rebuild for Boost 1.58 + +* Fri Jul 10 2015 David Tardon - 1:5.0.0.3-1 +- update to 5.0.0 rc3 + +* Sun Jun 28 2015 David Tardon - 1:5.0.0.2-1 +- update to 5.0.0 rc2 + +* Sun Jun 21 2015 David Tardon - 1:5.0.0.1-1 +- update to 5.0.0 rc1 + +* Fri Jun 19 2015 David Tardon - 1:5.0.0.0-8.beta3 +- Resolves: rhbz#1233420 crash on auto-fill + +* Wed Jun 17 2015 Fedora Release Engineering - 1:5.0.0.0-7.beta3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed Jun 10 2015 David Tardon - 1:5.0.0.0-6.beta3 +- update to 5.0.0 beta3 + +* Tue Jun 09 2015 David Tardon - 1:5.0.0.0-5.beta2 +- update to 5.0.0 beta2 + +* Mon Jun 08 2015 David Tardon - 1:5.0.0.0-4.beta1 +- rebuild for poppler 0.33 + +* Wed May 20 2015 David Tardon - 1:5.0.0.0-3.beta1 +- update to 5.0.0 beta1 + +* Sat May 16 2015 Kalev Lember - 1:5.0.0.0-2.alpha1 +- Resolves: rhbz#1215800 install symbolic icons + +* Sun Apr 19 2015 David Tardon - 1:5.0.0.0-1.alpha1 +- update to 5.0.0 alpha1 + +* Tue Apr 14 2015 Stephan Bergmann - 1:4.4.2.2-3 +- Resolves: rhbz#1197614 crash when updating extension +- Resolves: rhbz#1134285 redundant user/password request for WebDAV access + +* Mon Mar 30 2015 Richard Hughes - 1:4.4.2.2-2 +- Use better AppData screenshots + +* Thu Mar 26 2015 David Tardon - 1:4.4.2.2-1 +- update to 4.4.2 rc2 + +* Thu Mar 12 2015 David Tardon - 1:4.4.2.1-1 +- update to 4.2.2 rc1 + +* Mon Feb 23 2015 David Tardon - 1:4.4.1.2-1 +- update to 4.4.1 rc2 + +* Tue Feb 10 2015 David Tardon - 1:4.4.1.1-1 +- update to 4.4.1 rc1 + +* Thu Jan 29 2015 David Tardon - 1:4.4.0.3-5 +- fix build on s390 + +* Wed Jan 28 2015 Petr Machata - 1:4.4.0.3-4 +- Rebuild for boost 1.57.0 + +* Wed Jan 28 2015 Petr Machata - 1:4.4.0.3-3 +- Rebuild for boost 1.57.0 + +* Fri Jan 23 2015 Stephan Bergmann - 1:4.4.0.3-2 +- Related: rhbz#1185307 get search for Hamcrest unstuck + +* Fri Jan 23 2015 David Tardon - 1:4.4.0.3-1 +- update to 4.4.0 rc3 + +* Fri Jan 23 2015 Marek Kasik - 1:4.4.0.2-4 +- Rebuild (poppler-0.30.0) + +* Thu Jan 22 2015 Stephan Bergmann - 1:4.4.0.2-3 +- Resolves: rhbz#1184582 crash in grammar checking thread + +* Mon Jan 19 2015 David Tardon - 1:4.4.0.2-2 +- Resolves: rhbz#1180114 writerfilter: don't crash on w:customXmlDelRangeStart + etc. +- Resolves: rhbz#1175027 fix life cycle of SwConnectionDisposedListener_Impl + +* Fri Jan 09 2015 David Tardon - 1:4.4.0.2-1 +- update to 4.4.0 rc2 + +* Wed Jan 07 2015 Caolán McNamara - 1:4.4.0.1-2 +- Resolves: rhbz#1177547 system autocorr files not detected + +* Sun Dec 21 2014 David Tardon - 1:4.4.0.1-1 +- update to 4.4.0 rc1 + +* Fri Dec 12 2014 David Tardon - 1:4.4.0.0-6.beta2 +- Resolves: rhbz#1116534 crash when pasting over a formula + +* Sat Dec 06 2014 David Tardon - 1:4.4.0.0-5.beta2 +- update to 4.4.0 beta2 +- move officehelper.py to pyuno package so it can be imported from python + +* Tue Dec 02 2014 David Tardon - 1:4.4.0.0-4.beta1 +- add Provides: libreoffice-headless; packages are depending on it + +* Thu Nov 27 2014 Caolán McNamara - 1:4.4.0.0-3.beta1 +- Resolves: rhbz#1165444 abrt crash with NULL pView + +* Thu Nov 27 2014 Marek Kasik - 1:4.4.0.0-2.beta1 +- Rebuild (poppler-0.28.1) + +* Sat Nov 22 2014 David Tardon - 1:4.4.0.0-1.beta1 +- update to 4.4.0 beta1 + +* Fri Nov 21 2014 Caolán McNamara - 1:4.3.4.1-6 +- Resolves: fdo#86466 Wrong background color shown in impress table + +* Thu Nov 20 2014 Caolán McNamara - 1:4.3.4.1-5 +- Resolves: rhbz#1164551 we want to ensure that a libjvm.so is available + but we have no firm interest in which one that is + +* Wed Nov 19 2014 Caolán McNamara - 1:4.3.4.1-4 +- Resolves: rhbz#1165740 arbitrarily backport some rtf crash fixes + +* Mon Nov 17 2014 Michael Stahl - 1:4.3.4.1-3 +- set VCL.WM.ShouldSwitchWorkspace to false to avoid virtual desktop switching + +* Thu Nov 13 2014 Caolán McNamara - 1:4.3.4.1-2 +- fix impress table layout cache wrt wrong table selection border + +* Tue Nov 11 2014 David Tardon - 1:4.3.4.1-1 +- update to 4.3.4 rc1 + +* Tue Nov 11 2014 Caolán McNamara - 1:4.3.3.2-6 +- strip hard coded numbering off outline master previews + +* Mon Nov 10 2014 Caolán McNamara - 1:4.3.3.2-5 +- Resolves: rhbz#1161238 sync PRESOBJ_OUTLINE para depth on load + +* Thu Nov 06 2014 Caolán McNamara - 1:4.3.3.2-4 +- Resolves: fdo#60712 Inherits cell styles in inserting rows/columns +- implement toggling off removeable master elements with delete +- Resolves: fdo#78151 change underlying style on toggling bullets on/off in master view + +* Thu Nov 06 2014 Caolán McNamara - 1:4.3.3.2-3 +- Resolves: fdo#76581 copy-and-paste -> slideshow crash in presenter console + +* Wed Nov 05 2014 Caolán McNamara - 1:4.3.3.2-2 +- Resolves: fdo#37559 revert adding extra dummy polygons + +* Tue Oct 28 2014 David Tardon - 1:4.3.3.2-1 +- update to 4.3.3 rc2 + +* Sun Oct 19 2014 David Tardon - 1:4.3.3.1-2 +- enable support for 3-D models + +* Thu Oct 09 2014 David Tardon - 1:4.3.3.1-1 +- update to 4.3.3 rc1 + +* Wed Oct 08 2014 Stephan Bergmann - 1:4.3.2.2-5 +- Resolves: rhbz#1054952 bad access of smb URLs on KDE + +* Tue Sep 23 2014 Richard Hughes - 1:4.3.2.2-4 +- move appdata files to desktop files, where the belong + +* Tue Sep 23 2014 Caolán McNamara - 1:4.3.2.2-3 +- Resolves: rhbz#1054952 cannot access smb URLs on KDE + +* Tue Sep 23 2014 Caolán McNamara - 1:4.3.2.2-2 +- make brochure printing of impress/draw work out of the box +- Resolves: rhbz#1133863 fix looping layout + +* Mon Sep 22 2014 David Tardon - 1:4.3.2.2-1 +- update to 4.3.2 rc2 + +* Wed Sep 17 2014 Caolán McNamara - 1:4.3.2.1-3 +- make n-up printing of impress notes work out of the box + +* Wed Sep 17 2014 Caolán McNamara - 1:4.3.2.1-2 +- Resolves: fdo#80911 don't swap notes page width height + +* Fri Sep 12 2014 David Tardon - 1:4.3.2.1-1 +- update to 4.3.2 rc1 + +* Wed Sep 10 2014 Caolán McNamara - 1:4.3.1.2-5 +- create a master document template type + +* Tue Sep 09 2014 Caolán McNamara - 1:4.3.1.2-4 +- Resolves: fdo#82496 Change picture option with right click in writer + +* Fri Sep 05 2014 David Tardon - 1:4.3.1.2-3 +- build for aarch64 + +* Fri Aug 29 2014 Stephan Bergmann - 1:4.3.1.2-2 +- Resolves: rhbz#1098693 AArch64 port + +* Wed Aug 27 2014 David Tardon - 1:4.3.1.2-1 +- update to 4.3.1 rc2 + +* Tue Aug 26 2014 Caolán McNamara - 1:4.3.1.1-8 +- Related: rhbz#1131425 ure only needs jre-headless + +* Tue Aug 26 2014 David Tardon - 1:4.3.1.1-7 +- rebuild for ICU 53.1 + +* Fri Aug 22 2014 Caolán McNamara - 1:4.3.1.1-6 +- Resolves: rhbz#1131425 move libjawt-using office bean into a subpackage +- Resolves: rhbz#1125588 port LibreOffice to ppc64le + +* Tue Aug 19 2014 Caolán McNamara - 1:4.3.1.1-5 +- Resolves: rhbz#1131425 try java-headless instead of java + +* Sun Aug 17 2014 Fedora Release Engineering - 1:4.3.1.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Aug 16 2014 Rex Dieter 1:4.3.1.1-3 +- update mime scriptlets + +* Fri Aug 15 2014 Caolán McNamara - 1:4.3.1.1-2 +- Related: rhbz#1130264 crash in media playback on s390x + +* Sun Aug 10 2014 David Tardon - 1:4.3.1.1-1 +- update to 4.3.1 rc1 + +* Mon Jul 28 2014 David Tardon - 1:4.3.0.4-1 +- update to 4.3.0 rc4 + +* Fri Jul 25 2014 David Tardon - 1:4.3.0.3-4 +- Resolves: rhbz#1121254 crash when using font selector after adding new font + +* Fri Jul 25 2014 Caolán McNamara - 1:4.3.0.3-3 +- Resolves: rhbz#1122868 landscape printing is broken + +* Thu Jul 24 2014 David Tardon - 1:4.3.0.3-2 +- avoid image loss in Impress after auto-save + +* Wed Jul 16 2014 David Tardon - 1:4.3.0.1-1 +- update to 4.3.0 rc3 + +* Tue Jul 08 2014 David Tardon - 1:4.3.0.2-2 +- avoid problems detecting HTML files with xls extension + +* Wed Jul 02 2014 David Tardon - 1:4.3.0.2-1 +- update to 4.3.0 rc2 + +* Tue Jun 17 2014 David Tardon - 1:4.3.0.1-1 +- update to 4.3.0 rc1 + +* Mon Jun 09 2014 David Tardon - 1:4.3.0.0-9.beta2 +- Resolves: rhbz#1105376 FlatODF import/export does not work unless + libreoffice-xsltfilter is installed + +* Wed Jun 04 2014 David Tardon - 1:4.3.0.0-8.beta2 +- update to 4.3.0 beta2 + +* Thu May 29 2014 David Tardon - 1:4.3.0.0-7.beta1 +- fix some fallout from the import libs rebase + +* Wed May 28 2014 David Tardon - 1:4.3.0.0-6.beta1 +- switch to librevenge-based import libs + +* Tue May 27 2014 Kalev Lember - 1:4.3.0.0-5.beta1 +- Rebuild for boost 1.55.0 + +* Mon May 26 2014 David Tardon - 1:4.3.0.0-4.beta1 +- unblock build on ARM + +* Fri May 23 2014 Petr Machata - 1:4.3.0.0-3.beta1 +- Rebuild for boost 1.55.0 + +* Fri May 23 2014 David Tardon - 1:4.3.0.0-2.beta1 +- rebuild for boost 1.55.0 + +* Wed May 21 2014 David Tardon - 1:4.3.0.0-1.beta1 +- update to 4.3.0 beta1 + +* Fri May 16 2014 Caolán McNamara - 1:4.2.4.2-14 +- render smart-art with a vector format so it can be scaled nicely +- fix leak on pasting metafiles into office +- fix leak on pasting draw items into office +- fix another leak on scaling metric items + +* Thu May 15 2014 David Tardon - 1:4.2.4.2-13 +- fix SDK doc generation with doxygen 1.8.7 + +* Wed May 14 2014 David Tardon - 1:4.2.4.2-12 +- rebuild for new poppler + +* Mon May 12 2014 Caolán McNamara - 1:4.2.4.2-11 +- Resolves: rhbz#1096747 format->page crash on html doc + +* Mon May 12 2014 David Tardon - 1:4.2.4.2-10 +- Resolves: fdo#78119 bad july (červenec) month name support in czech + localization + +* Mon May 12 2014 Caolán McNamara - 1:4.2.4.2-9 +- Resolves: rhbz#1096486 avoid access to nonexisting parent +- Resolves: rhbz#1096295 hard to distinguish slides in slide pane + +* Fri May 09 2014 David Tardon - 1:4.2.4.2-8 +- Resolves: rhbz#1071604 Draw depends on files from libreoffice-impress, crashes + without them + +* Fri May 09 2014 Eike Rathke - 1:4.2.4.2-7 +- Resolves: fdo#77509 memory corruption / crash in Consolidate + +* Thu May 08 2014 Caolán McNamara - 1:4.2.4.2-6 +- center current slide after changing zoom +- add a status bar icon to fit slide to window +- Related: fdo#50697 reset the cache timeout on GetGraphic + +* Thu May 08 2014 Stephan Bergmann - 1:4.2.4.2-5 +- Resolves: rhbz#1092589 Thoroughly check whether JRE is still present + +* Tue May 06 2014 Caolán McNamara - 1:4.2.4.2-4 +- clip over-long comments + +* Thu May 01 2014 Eike Rathke - 1:4.2.4.2-3 +- Resolves: fdo#78294 default null-date for document import is 1899-12-30 + +* Thu May 01 2014 Caolán McNamara - 1:4.2.4.2-2 +- better scaling of notes-using pages + +* Wed Apr 30 2014 David Tardon - 1:4.2.4.2-1 +- update to 4.2.4 rc2 + +* Fri Apr 25 2014 Caolán McNamara - 1:4.2.4.1-7 +- Related: rhbz#1032774 disable autoexit when switching monitors + +* Thu Apr 24 2014 Caolán McNamara - 1:4.2.4.1-6 +- Resolves: fdo#37130 use 10pt Default style font for comments +- Resolves: fdo#60040 crash after undoing master page +- vertically center printout when including comments + +* Wed Apr 23 2014 Caolán McNamara - 1:4.2.4.1-5 +- add a 'format all comments' feature + +* Tue Apr 22 2014 Caolán McNamara - 1:4.2.4.1-4 +- Resolves: rhbz#1089377 crash on loading a specific rtf + +* Tue Apr 22 2014 Caolán McNamara - 1:4.2.4.1-3 +- sometimes tables in impress don't resize when adding rows +- Resolves: fdo#71423 crash while editing Impress tables + +* Fri Apr 18 2014 Caolán McNamara - 1:4.2.4.1-2 +- every 2nd print job is incorrectly flagged as failed +- Related: rhbz#1088625 PresenterPaintManager seen as NULL + +* Thu Apr 17 2014 David Tardon - 1:4.2.4.1-1 +- update to 4.2.4 rc1 + +* Wed Apr 16 2014 David Tardon - 1:4.2.3.3-6 +- install man pages +- Resolves: rhbz#1086714 overlarge pixmap + +* Wed Apr 16 2014 Caolán McNamara - 1:4.2.3.3-5 +- Resolves: fdo#36815 enable printing WYSIWYG sidewindow comments + +* Sat Apr 12 2014 David Tardon - 1:4.2.3.3-4 +- drop filtering of provides again + +* Sat Apr 12 2014 Caolán McNamara - 1:4.2.3.3-3 +- Related: rhbz#1081176 don't jump to cursor pos when we don't want to + +* Fri Apr 11 2014 Caolán McNamara - 1:4.2.3.3-2 +- Resolves: rhbz#1081176 don't jump to cursor pos when we don't want to +- Related: rhbz#1085916 kde startup woes + +* Sat Apr 05 2014 David Tardon - 1:4.2.3.3-1 +- update to 4.2.3 rc3 + +* Tue Apr 01 2014 Caolán McNamara - 1:4.2.3.2-3 +- Related: rhbz#1075951 abrt crash in MSWordExportBase + +* Mon Mar 31 2014 David Tardon - 1:4.2.3.2-2 +- Resolves: rhbz#1080196 mdds/multi_type_vector_itr.hpp update_node(): + soffice.bin killed by SIGSEGV + +* Wed Mar 26 2014 David Tardon - 1:4.2.3.2-1 +- update to 4.2.3 rc2 + +* Tue Mar 25 2014 Caolán McNamara - 1:4.2.3.1-2 +- Resolves: rhbz#1077780 crash on loading a specific docx + +* Mon Mar 17 2014 David Tardon - 1:4.2.3.1-1 +- update to 4.2.3 rc1 + +* Fri Mar 14 2014 Caolán McNamara - 1:4.2.2.1-7 +- Related: rhbz#1076264 intermittent a11y crash in calc + +* Mon Mar 10 2014 Michael Stahl - 1:4.2.2.1-6 +- Resolves: rhbz#988516: DOCX import: fix context stack when importing header +- Resolves: rhbz#1072553: Fix deselection problems of template view +- Resolves: rhbz#1072607: fix crash in SvxRuler::MouseMove() +- Resolves: rhbz#1043551: sw: avoid division-by-0 in Text Grid painting code +- RTF import: import field parameters +- RTF import: fix spurious page breaks at doc end + +* Tue Mar 04 2014 Caolán McNamara - 1:4.2.2.1-5 +- Related: rhbz#1065807 wizards should find the right wizards subdir + of Template_internal, who knew this stuff was so fragile + +* Mon Mar 03 2014 Caolán McNamara - 1:4.2.2.1-4 +- Related: rhbz#1065807 wizards should look in Template_internal + +* Fri Feb 28 2014 Caolán McNamara - 1:4.2.2.1-3 +- Resolves: rhbz#1007697 Update on a Window deletes itself + +* Fri Feb 28 2014 Caolán McNamara - 1:4.2.2.1-2 +- Related: rhbz#1065807 don't throw with no "Templates" dir under KDE + +* Thu Feb 27 2014 David Tardon - 1:4.2.2.1-1 +- update to 4.2.2 rc1 + +* Thu Feb 27 2014 Stephan Bergmann - 1:4.2.1.1-4 +- Resolves: fdo#75540 spadmin does not start + +* Thu Feb 27 2014 David Tardon - 1:4.2.1.1-3 +- Resolves: rhbz#1057977 do not crash when fonts are updated + +* Tue Feb 25 2014 Caolán McNamara - 1:4.2.1.1-2 +- Resolves: rhbz#1065807 search XDG defined "Templates" dir + +* Thu Feb 13 2014 David Tardon - 1:4.2.1.1-1 +- update to 4.2.1 rc1 + +* Thu Feb 13 2014 David Tardon - 1:4.2.0.4-4 +- rebuild for new ICU + +* Thu Feb 06 2014 David Tardon - 1:4.2.0.4-3 +- Resolves: rhbz#1017379 libreoffice impress imports animated motion paths + incorrectly from powerpoint +- Resolves: fdo#33852 Custom animation (Motionpath Left) isn't being + imported correctly from .ppt + +* Thu Jan 30 2014 David Tardon - 1:4.2.0.4-2 +- split LibreLogo into a separate subpackage +- create a metapackage depending on all subpackages containing filters, + for use of packages like unoconv + +* Tue Jan 28 2014 David Tardon - 1:4.2.0.4-1 +- update to 4.2.0 rc4 + +* Fri Jan 24 2014 David Tardon - 1:4.2.0.3-3 +- enable EOT support +- fix PPC build + +* Thu Jan 23 2014 David Tardon - 1:4.2.0.3-2 +- stop showing math and startcenter in menu (again) + +* Wed Jan 22 2014 David Tardon - 1:4.2.0.3-1 +- update to 4.2.0 rc3 + +* Mon Jan 13 2014 Caolán McNamara - 1:4.2.0.2-2 +- Related: rhbz#1047871 conditional formatting doesn't fit on screen + +* Thu Jan 09 2014 David Tardon - 1:4.2.0.2-1 +- update to 4.2.0 rc2 +- Resolves: rhbz#1049543 Include AppData files in packages + +* Tue Jan 07 2014 David Tardon - 1:4.2.0.1-1 +- 4.2.0 rc1 + +* Wed Dec 11 2013 Caolán McNamara - 1:4.2.0.0-3.beta2 +- Resolves: rhbz#1040291 Change language name from "Oriya" to "Odia" + +* Wed Dec 04 2013 Caolán McNamara - 1:4.2.0.0-2.beta2 +- update to 4.2.0 beta2 +- Related: rhbz#1032774 bodge around reported NULL +- Resolves: rhbz#1035092 no shortcut key for Italian 'Tools' menu +- Resolves: rhbz#912529 Kerkis SmallCaps shown instead of Kerkis Regular +- Resolves: rhbz#1038189 refresh printer list when print dialog launched +- openssl no longer required to build + +* Thu Nov 21 2013 David Tardon - 1:4.2.0.0-1.beta1 +- switch to 4.2.0 + +* Wed Nov 20 2013 Stephan Bergmann - 1:4.1.3.2-5 +- Resolves: rhbz#1031989 Accept --pt in addition to deprecated -pt +- Related: rhbz#1014990 valgrind reports uninitialized variables + +* Sun Nov 03 2013 David Tardon - 1:4.1.3.2-4 +- adapt for libmwaw 0.2 + +* Thu Oct 31 2013 David Tardon - 1:4.1.3.2-3 +- Resolves: fdo#56209 reviving FilterFormulaParser + +* Thu Oct 31 2013 Stephan Bergmann - 1:4.1.3.2-2 +- Resolves: fdo#67725 unoidl::AggregatingCursor must wrap modules for aggregation +- Resolves: rhbz#1021915 force menubar menus to be up/down only +- Resolves: rhbz#1025201 Incorrect rendering of Devanagari short i + +* Wed Oct 23 2013 David Tardon - 1:4.1.3.2-1 +- 4.1.3 rc2 +- Resolves: rhbz#1022094 libreoffice-4.1.3.1-1 was built without + langpacks + +* Mon Oct 21 2013 Caolán McNamara - 1:4.1.3.1-2 +- Resolves: rhbz#1020712 wrong default CTL font shown in editengine +- Resolves: rhbz#919070 display -1 means span all screens + + +* Wed Oct 16 2013 David Tardon - 1:4.1.3.1-1 +- 4.1.3 rc1 + +* Mon Oct 07 2013 Caolán McNamara - 1:4.1.2.3-4 +- Resolves: rhbz#1001768: fix various a11y deadlocks and crashes +- Resolves: rhbz#1016022 fix cut from impress and paste to writer +- Resolves: rhbz#1003179 fix AUTOFMT related crashes in Writer Undo + +* Mon Oct 07 2013 Caolán McNamara - 1:4.1.2.3-3 +- Resolves: rhbz#1015281 crash on clicking custom animation +- Resolves: rhbz#996162 crash with no bullet font + +* Wed Oct 02 2013 Caolán McNamara - 1:4.1.2.3-2 +- Resolves: rhbz#1013480 crash in EditLineList::operator[] +- Resolves: rhbz#1014010 crash on start up +- Resolves: rhbz#1013844 encrypted OOo 1.0 files don't reopen + +* Mon Sep 30 2013 David Tardon - 1:4.1.2.3-1 +- 4.1.2 rc3 + +* Fri Sep 20 2013 David Tardon - 1:4.1.2.2-1 +- 4.1.2 rc2 + +* Tue Sep 17 2013 Caolán McNamara - 1:4.1.2.1-3 +- add select sheet menu to calc prev/next area +- Resolves: rhbz#988104 crash on certain pptx + +* Thu Sep 12 2013 Caolán McNamara - 1:4.1.2.1-2 +- Resolves: rhbz#1006850 crash in SwCommentRuler + +* Thu Sep 05 2013 David Tardon - 1:4.1.2.1-1 +- 4.1.2 rc1 + +* Tue Sep 03 2013 Caolán McNamara - 1:4.1.1.2-3 +- Resolves: rhbz#993963 NULL m_pWindow on firefox close plugin window + +* Fri Aug 23 2013 Stephan Bergmann - 1:4.1.1.2-2 +- Resolves: rhbz#1000150, Do not call exit upon XIOError + +* Thu Aug 22 2013 David Tardon - 1:4.1.1.2-1 +- 4.1.1 rc2 +- Related: rhbz#895690 Always try to do a mount when opening a file via GIO +- Resolves: rhbz#998136 wrong index to gWidgetData +- Resolves: rhbz#998046 store last size/position of the base windows + +* Mon Aug 19 2013 Marek Kasik - 1:4.1.1.1-2 +- Rebuild (poppler-0.24.0) + +* Fri Aug 09 2013 David Tardon - 1:4.1.1.1-1 +- 4.1.1 rc1 + +* Fri Aug 09 2013 Caolán McNamara - 1:4.1.0.4-6 +- Resolves: fdo#67743 user autocorr file not written + +* Tue Jul 30 2013 Stephan Bergmann - 1:4.1.0.4-5 +- Resolves: rhbz#989246 Honor user's JavaDriverClass override in mysql driver +- Resolves: fdo#67045 fix several nasty screen selection issues + +* Tue Jul 30 2013 Caolán McNamara - 1:4.1.0.4-4 +- Resolves: rhbz#989686 Fix crash with stripping whitespace from toc entries + +* Mon Jul 29 2013 David Tardon - 1:4.1.0.4-3 +- make libwpd-based filters work correctly with newest libwpd + +* Sun Jul 28 2013 Petr Machata - 1:4.1.0.4-2 +- Rebuild for boost 1.54.0 + +* Wed Jul 24 2013 David Tardon - 1:4.1.0.4-1 +- 4.1.0 rc4 + +* Mon Jul 22 2013 Eike Rathke - 1:4.1.0.3-2 +- force rebuild with icu-50.1.2-7 + +* Thu Jul 18 2013 David Tardon - 1:4.1.0.3-1 +- 4.1.0 rc3 +- Resolves: fdo#48835 GNOME3 app menu + +* Thu Jul 18 2013 Caolán McNamara - 1:4.1.0.2-5 +- silence scary gcc warning +- fdo#66924 switching to master view is broken + +* Tue Jul 16 2013 David Tardon - 1:4.1.0.2-4 +- bump release + +* Fri Jul 12 2013 David Tardon - 1:4.1.0.2-3 +- Resolves: rhbz#983809 libreoffice-base misses deps on needed java packages + +* Thu Jul 11 2013 David Tardon - 1:4.1.0.2-2 +- Resolves: rhbz#980387 Exporting a odg to jpg or tiff generates error + +* Thu Jul 04 2013 David Tardon - 1:4.1.0.2-1 +- 4.1.0 rc2 + +* Mon Jul 01 2013 Caolán McNamara - 1:4.1.0.1-8 +- Resolves: rhbz#979758 crash on Diagrammen in LibreOffice help page + +* Thu Jun 27 2013 David Tardon - 1:4.1.0.1-7 +- bump revision + +* Mon Jun 24 2013 Marek Kasik - 1:4.1.0.1-6 +- Rebuild (poppler-0.22.5) + +* Mon Jun 24 2013 David Tardon - 1:4.1.0.1-5 +- fix build on big endian archs + +* Mon Jun 24 2013 David Tardon - 1:4.1.0.1-4 +- put glade catalog into an extra packgae + +* Sun Jun 23 2013 Caolán McNamara - 1:4.1.0.1-3 +- Resolves: rhbz#976304 gallery elements may not insert + +* Wed Jun 19 2013 Dennis Gilmore - 1:4.1.0.1-2 +- fix _smp_mflags macro useage + +* Wed Jun 19 2013 David Tardon - 1:4.1.0.1-1 +- 4.1.0 rc1 +- Related: rhbz#971321 failing tests on ppc and s390 + +* Sun Jun 16 2013 David Tardon - 1:4.1.0.0-9.beta2 +- Resolves: rhbz#971321 failing tests on ppc and s390 +- Resolves: rhbz#974062 incorrect rendering of text in outline blocks in + Impress + +* Fri Jun 07 2013 David Tardon - 1:4.1.0.0-8.beta2 +- Related: rhbz#971795 go back to BR: harfbuzz-devel + +* Fri Jun 07 2013 David Tardon - 1:4.1.0.0-7.beta2 +- Resolves: rhbz#971230 Use BR: harfbuzz-icu-devel + +* Wed Jun 05 2013 David Tardon - 1:4.1.0.0-7.beta1 +- 4.1.0 beta2 + +* Wed Jun 05 2013 Caolán McNamara - 1:4.1.0.0-6.beta1 +- Related: rhbz#968892 discard impossible languages for Oriya script + +* Tue Jun 04 2013 Caolán McNamara - 1:4.1.0.0-5.beta1 +- Resolves: rhbz#968892 block entire grapheme together for glyph fallback +- Related: rhbz#968892 discard impossible languages for glyph fallback + +* Fri May 31 2013 Caolán McNamara - 1:4.1.0.0-4.beta1 +- Resolves: rhbz#968976 fix dropdown list autosizing + +* Thu May 30 2013 David Tardon - 1:4.1.0.0-3.beta1 +- build fix for s390 + +* Fri May 24 2013 David Tardon - 1:4.1.0.0-2.beta1 +- 4.1.0 beta1 + +* Fri May 24 2013 Stephan Bergmann - 1:4.0.3.3-3 +- Resolves: rhbz#961460 can't save WebDAV (davs) files + +* Thu May 16 2013 Caolán McNamara - 1:4.0.3.3-2 +- Resolves: rhbz#963276 font options cache crash + +* Fri May 03 2013 David Tardon - 1:4.0.3.3-1 +- 4.0.3 rc3 + +* Tue Apr 30 2013 David Tardon - 1:4.0.3.2-1 +- 4.0.3 rc2 + +* Mon Apr 22 2013 Stephan Bergmann - 1:4.0.3.1-2 +- Resolves: rhbz#954991 Avoid static data (causing trouble at exit) + +* Thu Apr 18 2013 David Tardon - 1:4.0.3.1-1 +- 4.0.3 rc1 +- Resolves: rhbz#867808 do not throw UNO exceptions by pointer in C++ + +* Tue Apr 16 2013 Caolán McNamara - 1:4.0.2.2-4 +- Resolves: rhbz#927223 syntax highlighting crash + +* Mon Apr 08 2013 Caolán McNamara - 1:4.0.2.2-3 +- Resolves: rhbz#949238 div by zero on pagedown in 0 width panel + +* Fri Apr 05 2013 Kalev Lember - 1:4.0.2.2-2 +- Resolves: rhbz#949106 libreoffice drags in both openjdk 1.7.0 and 1.8.0 + +* Thu Mar 28 2013 David Tardon - 1:4.0.2.2-1 +- 4.0.2 rc2 +- Resolves: rhbz#876742 manipulation with larger tables in impress is + very slow + +* Fri Mar 15 2013 Caolán McNamara - 1:4.0.2.1-2 +- Resolves: rhbz#906137 slide show inverts outputs + +* Fri Mar 15 2013 David Tardon - 1:4.0.2.1-1 +- 4.0.2 rc1 +- Resolves: rhbz#921716 Build Breton language pack + +* Wed Mar 13 2013 Stephan Bergmann - 1:4.0.1.2-4 +- Resolves: rhbz#895690 failure saving to gvfs mounts + +* Tue Mar 12 2013 Caolán McNamara - 1:4.0.1.2-3 +- Resolves: rhbz#920697 presentation not always full-screen + +* Thu Mar 07 2013 Caolán McNamara - 1:4.0.1.2-2 +- Related: rhbz#902884 check for NULL GetSelectedMasterPage +- Resolves: fdo#61241 force area page to size itself +- Resolves: fdo#61656 use order and orientation combobox +- Resolves: fdo#56031 RSID attr changes drop content changes + +* Thu Feb 28 2013 David Tardon - 1:4.0.1.2-1 +- 4.0.1 rc2 + +* Tue Feb 26 2013 Eike Rathke - 1:4.0.0.3-8 +- do not access vector elements beyond size, rhbz#847519 related +- Resolves: rhbz#742780 let make OPT_FLAGS=... override SDK flags +- Resolves: rhbz#907933 crash on removing second last para + +* Tue Feb 19 2013 Caolán McNamara - 1:4.0.0.3-7 +- Resolves: rhbz#895196 sc filter float a11y parent of itself + +* Tue Feb 19 2013 David Tardon - 1:4.0.0.3-6 +- Resolves: rhbz#911896 add Kazakh localization + +* Fri Feb 15 2013 Caolán McNamara - 1:4.0.0.3-5 +- make evolution 3.6 work with address book +- Resolves: rhbz#910176 cannot select directory with gtk folder picker +- fixes for building against Boost 1.53.0 + +* Fri Feb 15 2013 Stephan Bergmann - 1:4.0.0.3-4 +- Resolves: fdo#60491 missing libemboleobj.so +- Resolves: rhbz#908674 crash on start + +* Sat Feb 09 2013 Denis Arnaud - 1:4.0.0.3-3 +- Rebuild for Boost-1.53.0 + +* Wed Feb 06 2013 David Tardon - 1:4.0.0.3-2 +- fix parsing errors in translated help + +* Fri Feb 01 2013 David Tardon - 1:4.0.0.3-1 +- 4.0.0 rc3 + +* Wed Jan 23 2013 David Tardon - 1:4.0.0.2-1 +- 4.0.0 rc2 +- use ucpp again + +* Tue Jan 22 2013 David Tardon - 1:4.0.0.1-3 +- Resolves: rhbz#760765 Impress doesn't copy custom styles from one file + to another + +* Mon Jan 21 2013 David Tardon - 1:4.0.0.1-2 +- Resolves: rhbz#901346 do not install 512x512 icons + +* Tue Jan 15 2013 David Tardon - 1:4.0.0.1-1 +- 4.0.0 rc1 + +* Sat Dec 22 2012 David Tardon - 1:4.0.0.0-4.beta2 +- use system cpp instead of ucpp + +* Wed Dec 19 2012 David Tardon - 1:4.0.0.0-3.beta2 +- 4.0.0 beta2 + +* Thu Dec 06 2012 David Tardon - 1:4.0.0.0-2.beta1 +- 4.0.0 beta1 + +* Thu Nov 29 2012 David Tardon - 1:3.6.4.3-1 +- 3.6.4 rc3 + +* Wed Nov 28 2012 Caolán McNamara - 1:3.6.4.1-2 +- fix docx import on big endian + +* Sun Nov 18 2012 David Tardon - 1:3.6.4.1-1 +- 3.6.4 rc1 + +* Wed Nov 14 2012 Caolán McNamara - 1:3.6.3.2-8 +- Resolves: rhbz#872815 ogltrans effects still suboptimal + +* Tue Nov 13 2012 Caolán McNamara - 1:3.6.3.2-7 +- big endian test failure + +* Thu Nov 08 2012 Caolán McNamara - 1:3.6.3.2-6 +- Resolves: fdo#56198/rhbz#868002 honour gtk-scrollbar-warp-preference + +* Tue Nov 06 2012 Caolán McNamara - 1:3.6.3.2-5 +- bump for libexttextcat + +* Fri Nov 02 2012 David Tardon - 1:3.6.3.2-4 +- Resolves: rhbz#871929 add keywords to desktop files +- fix debuginfo + +* Wed Oct 31 2012 Eike Rathke - 1:3.6.3.2-3 +- Resolves: rhbz#865058 increase number of user-defined format codes + +* Fri Oct 26 2012 David Tardon - 1:3.6.3.2-2 +- Resolves: rhbz#824035 do not bundle saxon + +* Wed Oct 24 2012 David Tardon - 1:3.6.3.2-1 +- 3.6.3 rc2 +- drop integrated 0001-Resolves-rhbz-868479-fdo-56281-doubled-in-German-ok-.patch + +* Mon Oct 22 2012 Caolán McNamara - 1:3.6.3.1-3 +- Resolves: rhbz#868479 guard against duplicated ~ in OK/Cancel + +* Thu Oct 11 2012 David Tardon - 1:3.6.3.1-2 +- Resolves: rhbz#858641 backport gstreamer 1.0 support to F-18 + +* Thu Oct 11 2012 Caolán McNamara - 1:3.6.3.1-1 +- 3.6.3 rc1 +- drop integrated 0001-Resolves-rhbz-855972-crash-on-switching-to-outline-v.patch +- drop integrated 0001-fdo-52022-Simple-LargeControlPoints-actually-can-hav.patch +- drop integrated 0001-fdo-46071-Do-not-hide-windows-based-on-nil-Visible-p.patch + +* Fri Oct 05 2012 Stephan Bergmann - 1:3.6.2.2-3 +- Resolves: fdo#46071 Do not hide windows based on nil Visible property + +* Fri Oct 05 2012 Stephan Bergmann - 1:3.6.2.2-2 +- Resolves: fdo#52022 Part of data in userdir is lost on upgrade + +* Wed Sep 26 2012 David Tardon - 1:3.6.2.2-1 +- 3.6.2 rc2 + +* Wed Sep 12 2012 Caolán McNamara - 1:3.6.2.1-2 +- Resolves: rhbz#855541 XIOError handler multithread woes + +* Wed Sep 12 2012 David Tardon - 1:3.6.2.1-1 +- 3.6.2 rc1 + +* Tue Sep 11 2012 Caolán McNamara - 1:3.6.1.2-4 +- Resolves: rhbz#855507 large ole2 compound files fail to load + +* Mon Sep 10 2012 Caolán McNamara - 1:3.6.1.2-3 +- Resolves: rhbz#855972 crash on switching to outline view + +* Wed Aug 29 2012 Caolán McNamara - 1:3.6.1.2-2 +- Related: rhbz#850709 hunspell en-US available standalone so + make English langpack require hunspell-en and core just + bare bones hunspell-en-US + +* Sun Aug 26 2012 David Tardon - 1:3.6.1.2-1 +- 3.6.1 rc2 + +* Wed Aug 22 2012 Caolán McNamara - 1:3.6.1.1-2 +- Resolves: rhbz#846775 Clipboard must be disposed before selection +- Resolves: rhbz#842292 crash in scrolling multiselection in draw + +* Wed Aug 15 2012 David Tardon - 1:3.6.1.1-1 +- 3.6.1 rc1 + +* Sun Aug 12 2012 Kevin Fenzi - 1:3.6.0.4-3 +- Rebuild for new boost + +* Sat Jul 28 2012 David Tardon - 1:3.6.0.4-2 +- rebuilt for boost 1.50 + +* Fri Jul 27 2012 David Tardon - 1:3.6.0.4-1 +- 3.6.0 rc4 + +* Thu Jul 26 2012 David Tardon - 1:3.6.0.3-2 +- Resolves: rhbz#842552 crash in pptx import + +* Wed Jul 25 2012 David Tardon - 1:3.6.0.3-1 +- 3.6.0 rc3 + +* Tue Jul 17 2012 David Tardon - 1:3.6.0.2-1 +- 3.6.0 rc2 + +* Mon Jul 16 2012 Caolán McNamara - 1:3.6.0.1-3 +- Resolves: rhbz#836937 insanely slow with Zemberek + +* Mon Jul 16 2012 David Tardon - 1:3.6.0.1-2 +- rebuild for new libexttextcat + +* Thu Jul 12 2012 David Tardon - 3.6.0.1-1 +- 3.6.0 rc1 + +* Mon Jul 09 2012 Caolán McNamara - 3.6.0.0-4 +- Resolves: rhbz#838368 --view ignored while -view accepted + +* Thu Jul 05 2012 David Tardon - 3.6.0.0-3 +- 3.6.0 beta3 + +* Mon Jul 2 2012 Marek Kasik - 3.6.0.0-2 +- Rebuild (poppler-0.20.1) + +* Wed Jun 27 2012 David Tardon - 3.6.0.0-1 +- 3.6.0 beta2 +- drop integrated 0001-move-binfilter-mime-types-into-extra-.desktop-file.patch +- drop integrated 0001-Resolves-rhbz-788042-skip-splashscreen-with-quicksta.patch +- drop integrated libreoffice-ensure-non-broken-xml-tree.patch +- drop integrated 0001-preserve-timestamps-for-.py-files.patch +- drop integrated 0001-Resolves-rhbz-788045-swriter-help-etc-doesn-t-show-h.patch +- drop integrated 0001-Resolves-rhbz-799525-put-flat-odf-mimetypes-in-xsltf.patch +- drop integrated 0001-Resolves-rhbz-800272-complain-about-unknown-command-.patch +- drop integrated 0001-Resolves-rhbz-806663-SlideshowImpl-can-outlive-SdMod.patch +- drop integrated 0001-desktop-do-not-complain-about-soffice-command-line-o.patch +- drop integrated 0001-Resolves-fdo-48096-torn-off-popups-trigger-keyboard-.patch +- drop integrated 0001-fdo-38088-better-CSV-import-default-separators.patch +- drop integrated 0001-save-register-arguments-first.patch +- drop integrated 0001-do-not-let-gcc-use-registers-we-are-setting-ourselve.patch +- drop integrated 0001-wrong-types-used-here-breaks-64bit-bigendian.patch +- drop integrated 0001-Resolves-rhbz-805743-a11y-call-doShow-after-we-have-.patch +- drop integrated 0001-Resolves-fdo-49849-implement-Unicode-6.1-hebrew-line.patch +- drop integrated 0001-use-ure-instead-of-ure-link.patch +- drop broken 0001-fix-setting-of-paper-tray-from-print-dialog-fdo-4393.patch + +* Mon Jun 18 2012 Caolán McNamara - 3.5.5.1-2 +- Resolves: rhbz#830810 missing dependency on lucene-contrib + +* Thu Jun 14 2012 David Tardon - 3.5.5.1-1 +- 3.5.5 rc1 +- drop integrated 0001-make-hsqldb-build-with-java-1.7.patch +- drop integrated 0001-Related-rhbz-799628-crash-with-chewing-IM-with-g3g.patch +- drop integrated 0001-silence-SolarMutex-not-locked-spew.patch +- drop integrated 0001-gcc-trunk-fix-unable-to-find-string-literal-operator.patch +- drop integrated 0001-ppc-yyinput-returns-a-int-truncating-to-unsigned-cha.patch +- drop integrated 0001-Resolves-rhbz-826609-rhbz-820554-fix-smoketest-on-pp.patch + +* Mon Jun 11 2012 David Tardon - 3.5.4.2-3 +- make gdb pretty printers for URE libs usable again + +* Fri Jun 08 2012 Caolán McNamara - 3.5.4.2-2 +- Resolves: rhbz#826609, rhbz#820554 fix smoketest on ppc[64] and s390[x] + +* Wed May 23 2012 David Tardon - 3.5.4.2-1 +- 3.5.4 rc2 + +* Thu May 17 2012 Caolán McNamara - 3.5.4.1-2 +- Resolves: rhbz#811226 ARM FTBFS + +* Wed May 16 2012 David Tardon - 3.5.4.1-1 +- 3.5.4 rc1 +- drop integrated 0001-do-not-prepend-n-twice-it-confuses-KFileDialog-rhbz-.patch +- drop integrated 0001-incrementing-index-twice-in-one-run-seems-wrong.patch +- drop integrated 0001-fdo-49365-correctly-map-monitor-index-back-to-screen.patch +- drop integrated 0001-rhbz-809019-count-mirrored-monitors-as-one.patch + +* Sun May 13 2012 Caolán McNamara - 3.5.3.2-5 +- Resolves: fdo#49849 line breaking fixes for Hebrew + +* Fri May 11 2012 David Tardon - 3.5.3.2-4 +- Resolves: rhbz#820439 KDE export dialog broken for most formats +- Resolves: fdo#49365 Libreoffice fails to start on second screen with + gtk vcl plugin +- Resolves: rhbz#809019 Impress thinks a machine with 2 monitors in + clone mode is multihead + +* Wed May 09 2012 Caolán McNamara - 3.5.3.2-3 +- Resolves: rhbz#805743 a11y crash in impress/draw +- Resolves: rhbz#813202 opengl slide transitions still a bit + problematic in Fedora 17 + +* Thu May 03 2012 David Tardon - 3.5.3.2-2 +- rebuild for changed dependencies + +* Wed Apr 25 2012 David Tardon - 3.5.3.2-1 +- 3.5.3 rc2 +- fix broken test on 64bit big endian + +* Mon Apr 23 2012 David Tardon - 3.5.3.1-2 +- rebuild for icu +- fix UNO bridges for ppc and ppc64 + +* Thu Apr 19 2012 David Tardon - 3.5.3.1-1 +- 3.5.3 rc1 +- drop integrated 0001-Introduced-SystemShellExecuteFlags-URIS_ONLY.patch +- drop integrated 0001-Simplify-code-and-use-proper-register-names-for-linu.patch +- drop integrated 0001-resolved-rhbz-813280-the-current-document-is-not-alw.patch + +* Wed Apr 18 2012 Eike Rathke - 3.5.2.1-7 +- Resolves: rhbz#813280 sheets cannot be moved in Calc + +* Wed Apr 11 2012 Eike Rathke - 3.5.2.1-6 +- Resolves: fdo#38088 rhbz#810267 better CSV import default separators + +* Tue Apr 10 2012 Caolán McNamara - 3.5.2.1-5 +- Resolves: rhbz#811226 FTBFS ARM + +* Thu Apr 05 2012 Stephan Bergmann - 3.5.2.1-4 +- Fix URIS_ONLY flag issue +- rebuild for db4 + +* Mon Apr 02 2012 Caolán McNamara - 3.5.2.1-3 +- Resolves: rhbz#708041 focus problems with tearable menus + +* Mon Mar 26 2012 Caolán McNamara - 3.5.2.1-2 +- Resolves: rhbz#806663 SlideshowImpl can outlive SdModule + +* Sun Mar 25 2012 David Tardon - 3.5.2.1-1 +- 3.5.2 rc1 +-drop integrated 0001-yet-another-clash-with-macro-name.patch + +* Wed Mar 14 2012 David Tardon - 3.5.1.2-2 +- Resolves: rhbz#770209 can't change paper tray setting while printing + +* Thu Mar 08 2012 David Tardon - 3.5.1.2-1 +- 3.5.1 rc2 + +* Tue Mar 06 2012 Caolán McNamara - 3.5.1.1-3 +- Resolves: rhbz#799628 crash with chewing IM with g3g +- Resolves: rhbz#799525 put flat odf mimetypes into xsltfilter.desktop +- Resolves: rhbz#800272 complain about unknown commandline options + +* Wed Feb 29 2012 Caolán McNamara - 3.5.1.1-2 +- Resolves: rhbz#788045 swriter --help doesn't show help +- Resolves: rhbz#798667 missing .desktop icons + +* Sun Feb 26 2012 David Tardon - 3.5.1.1-1 +- 3.5.1 rc1 +- drop 0001-Resolves-fdo-43644-survive-registered-but-unavailabl.patch +- drop 0001-Resolves-rhbz-789622-Adapt-SDK-to-changed-paths-in-L.patch +- drop 0001-Fix-fdo-45177-avoid-linked-undo-for-the-while.patch +- drop 0001-Fix-some-apparent-misuses-of-RTL_CONSTASCII_USTRINGP.patch +- drop binfilter-Fix-some-apparent-misuses-of-RTL_CONSTASCII_USTRINGP.patch +- Resolves: fdo#45177 avoid linked undo crash +- Fix some apparent misuses of RTL_CONSTASCII_USTRINGPARAM (cherry-picked from + upstream libreoffice-3-5 branch) + +* Tue Feb 14 2012 Stephan Bergmann - 3.5.0.3-5 +- Resolves rhbz#789622: Adapt SDK to changed paths in LO installation + +* Mon Feb 13 2012 Caolán McNamara - 3.5.0.3-4 +- ensure gdb .py files have the same timstamps so that multilib + .pyc's and .pyo's have the same content (timestamp in binary cache) + +* Sat Feb 11 2012 Caolán McNamara - 3.5.0.3-3 +- make sure .tree files don't get busted again + +* Tue Feb 07 2012 Stephan Bergmann - 3.5.0.3-2 +- junit4 -> junit +- Resolves: rhbz#788042 skip splashscreen with quickstarter +- with split binfilter we need fix for fdo#43644 + +* Thu Feb 02 2012 David Tardon - 3.5.0.3-1 +- 3.5.0 rc3 +- Resolves: rhbz#786328 add nlpsolver subpackage +- split legacy binary filters into subpackage + +* Thu Jan 26 2012 Stephan Bergmann - 3.5.0.2-2 +- add libreoffice-postgresql subpackage + +* Wed Jan 25 2012 David Tardon - 3.5.0.2-1 +- 3.5.0 rc2 + +* Thu Jan 19 2012 David Tardon - 3.5.0.1-1 +- 3.5.0 rc1 +- drop integrated 0001-workaround-internal-compiler-error-with-gcc-4.7.patch +- drop integrated 0001-fix-for-gcc-4.7-C-11-these-are-not-string-literal-op.patch +- drop integrated 0001-fix-for-gcc-4.7-C-11-this-is-not-string-literal-oper.patch +- drop integrated 0001-Revert-fast_merge-fix-mis-merge-of-first-module-s-st.patch +- drop integrated 0001-fix-writing-of-strings-from-the-first-module.patch +- drop integrated 0001-refactor-slightly-to-avoid-link-problems-with-gcc-4..patch + +* Fri Jan 13 2012 David Tardon - 3.4.99.3-1 +- 3.5.0 beta3 +- drop integrated 0001-fix-syntactic-error.patch +- drop integrated 0001-gcc-trunk-fix-error-unable-to-find-string-literal-op.patch +- drop integrated 0001-gcc-trunk-avoid-confusion.patch +- drop integrated 0001-workaround-for-LO-namespace-pollution-breaking-KDE4-.patch +- drop integrated 0001-smath-does-not-handle-accents-in-MathML.patch +- Resolves: rhbz#533318 smath does not handle accents in MathML +- Resolves: rhbz#771108 English menu in writer despite installation of + libreoffice-langpack-de + +* Fri Jan 06 2012 David Tardon - 3.4.99.2-2 +- rebuild with gcc 4.7 + +* Wed Dec 21 2011 David Tardon - 3.4.99.2-1 +- 3.5.0 beta2 +- drop integrated 0001-Resolves-rhbz-761009-IFSD_Equal-is-asymmetrical.patch +- drop integrated 0001-Resolves-rhbz-767708-avoid-SIGBUS-writing-to-overcom.patch +- drop integrated 0001-force-gbuild-stage-for-CustomTargets.patch +- drop integrated 0001-these-translations-do-already-exist-in-translations-.patch +- drop integrated 0001-Fix-typo-and-clean-up.patch +- use system mysql-connector-c++ + +* Sun Dec 18 2011 David Tardon - 3.4.99.1-1 +- 3.5.0 beta1 +- drop integrated 0001-Related-fdo-37195-migrationoo3-not-registered.patch +- drop integrated 0001-Related-i58612-don-t-crash-anyway.patch +- drop integrated 0001-Related-rhbz-652604-better-survive-exceptions-thrown.patch +- drop integrated 0001-Related-rhbz-702833-addEventListener-without-removeE.patch +- drop integrated 0001-Related-rhbz-711087-band-aid.patch +- drop integrated 0001-Related-rhbz-718976-crash-in-SwTxtSizeInfo-GetMultiC.patch +- drop integrated 0001-Related-rhbz-730225-avoid-segv-in-ld-this-was-set-to.patch +- drop integrated 0001-Related-rhbz-753201-fedora-ant-java-1.5.0-gcj-won-t-.patch +- drop integrated 0001-Resolves-fdo-32665-handle-that-FreeSerif-lacks-some-.patch +- drop integrated 0001-Resolves-rhbz-693265-fix-crash-from-unhandled-except.patch +- drop integrated 0001-Resolves-rhbz-695509-crash-in-RefreshDocumentLB.patch +- drop integrated 0001-Resolves-rhbz-713154-pdf-export-dialog-too-tall-to-f.patch +- drop integrated 0001-Resolves-rhbz-715549-use-fontconfig-s-detected-forma.patch +- drop integrated 0001-Resolves-rhbz-738255-avoid-crash-on-NULL-pointer.patch +- drop integrated 0001-Resolves-rhbz-751290-KDE-black-on-dark-tooltips.patch +- drop integrated 0001-add-Oracle-Java-1.7.0-recognition.patch +- drop integrated 0001-avoid-using-com.sun.org-apis.patch +- drop integrated 0001-bubble-down-configure-test-findings-on-visibility.patch +- drop integrated 0001-fix-horizontal-scrollbars-with-KDE-oxygen-style-bnc-.patch +- drop integrated 0001-gtk3-fix-cairo-canvas-crash-for-non-X-or-svp-backend.patch +- drop integrated 0001-helgrind-Related-rhbz-655686-get-order-of-shutdown-c.patch +- drop integrated 0001-rhbz-667082-do-not-crash-importing-section-containin.patch +- drop integrated 0001-rhbz-702635-set-correct-page-number-when-exporting-s.patch +- drop integrated Backport-reading-AES-encrypted-ODF-1.2-documents.patch +- drop integrated gdb-pretty-printers.patch +- drop integrated kde4configure.patch +- drop integrated libreoffice-ppc64.patch +- drop integrated openoffice.org-3.3.0.ooo108637.sfx2.uisavedir.patch +- drop integrated openoffice.org-3.3.0.ooo113273.desktop.resolvelinks.patch +- drop integrated vbahelper.visibility.patch +- drop libreoffice-testtools subpackage, because testtool has been + removed by upstream + +* Thu Dec 15 2011 Caolán McNamara - 3.4.4.2-6 +- Resolves: rhbz#761009 IFSD_Equal is asymmetrical +- Resolves: rhbz#767708 write to mmap'ed file w/o disk space: SIGBUS + +* Tue Nov 29 2011 Caolán McNamara - 3.4.4.2-5 +- Resolves: rhbz#757653 fix headless crash with cairo canvas + +* Tue Nov 22 2011 Lukas Tinkl - 3.4.4.2-4 +- Resolves: rhbz#751290 - [kde] LibreOffice has black on dark-grey tooltip-texts + +* Fri Nov 11 2011 Caolán McNamara - 3.4.4.2-3 +- Related: fdo#42534 0001-Related-i58612-don-t-crash-anyway.patch +- Resolves: fdo#42749 KDE oxygen theme and scrollbars + +* Thu Nov 10 2011 Stephan Bergmann - 3.4.4.2-2 +- Patch to backport reading AES-encrypted ODF 1.2 documents + +* Thu Nov 03 2011 David Tardon - 3.4.4.2-1 +- 3.4.4 rc2 + +* Fri Oct 28 2011 Rex Dieter - 1:3.4.4.1-4 +- rebuild(poppler) + +* Thu Oct 27 2011 Caolán McNamara - 3.4.4.1-3 +- Resolves: rhbz#665800 missing glyph symbol shown when toggling bold/italic + for Sinhala text + +* Thu Oct 27 2011 Caolán McNamara - 3.4.4.1-2 +- possible fix for java 1.7.0 detection + + +* Wed Oct 26 2011 David Tardon - 3.4.4.1-1 +- 3.4.4 rc1 + +* Tue Oct 25 2011 Caolán McNamara - 3.4.3.2-16 +- allow building with gcj + +* Fri Oct 21 2011 Caolán McNamara - 3.4.3.2-15 +- Resolves: rhbz#747356 let Qt call XInitThreads +- fix .sdw import + +* Wed Oct 19 2011 Caolán McNamara - 3.4.3.2-14 +- Related: rhbz#743750 addXineramaScreenUnique issue + +* Fri Oct 07 2011 Stephan Bergmann - 3.4.3.2-13 +- Patches to build with GCC 6.4.1 + +* Fri Sep 30 2011 Marek Kasik - 3.4.3.2-12 +- Rebuild (poppler-0.18.0) + +* Tue Sep 20 2011 Caolán McNamara - 3.4.3.2-11 +- Resolves: rhbz#738133 fix bn discard string +- Resolves: fdo#35513 avoid crash while processing incorrect print range + +* Mon Sep 19 2011 Marek Kasik - 3.4.3.2-10 +- Rebuild (poppler-0.17.3) + +* Thu Sep 15 2011 Caolán McNamara - 3.4.3.2-9 +- Resolves: rhbz#738255 avoid crash on sc inputhdl + +* Tue Sep 13 2011 Caolán McNamara - 3.4.3.2-8 +- Resolves: rhbz#274631 remove NoDisplay from -math.desktop + +* Thu Sep 08 2011 David Tardon - 3.4.3.2-7 +- rebuild for new icu + +* Tue Sep 06 2011 David Tardon - 3.4.3.2-6 +- Resolves: rhbz#734976 libreoffice-langpack-*-* not pulled in by + yum install libreoffice + +* Fri Sep 02 2011 Caolán McNamara - 3.4.3.2-5 +- Resolves: rhbz#735182 be able to rebuild against poppler 0.17.3 + +* Tue Aug 30 2011 David Tardon - 3.4.3.2-4 +- Resolves: rhbz#734432 openoffice.org symlink broken + +* Mon Aug 29 2011 David Tardon - 3.4.3.2-3 +- add Latvian langpack + +* Fri Aug 26 2011 Caolán McNamara - 3.4.3.2-2 +- Resolves: rhbz#733564 graphite2 now packaged into fedora +- Related: fdo#37195 migrationoo3 not registered + +* Thu Aug 25 2011 David Tardon - 3.4.3.2-1 +- 3.4.3 rc2 + +* Mon Aug 22 2011 David Tardon - 3.4.3.1-2 +- add gdb pretty printers + +* Tue Aug 16 2011 David Tardon - 3.4.3.1-1 +- 3.4.3 rc1 +- drop integrated 0001-Resolves-rhbz-725144-wrong-csh-syntax.patch + +* Fri Aug 12 2011 Caolán McNamara - 3.4.2.3-3 +- Related: rhbz#730225 avoid segv in ld + +* Tue Aug 02 2011 Caolán McNamara - 3.4.2.3-2 +- Resolves: rhbz#693265 fix crash from unhandled exception + +* Fri Jul 29 2011 David Tardon - 3.4.2.3-1 +- 3.4.2 rc3 + +* Mon Jul 25 2011 Caolán McNamara - 3.4.2.2-2 +- Resolves: rhbz#725144 wrong csh syntax + +* Wed Jul 20 2011 David Tardon - 3.4.2.2-1 +- 3.4.2 rc2 +- fix breakage in KDE4 plugin + +* Tue Jul 19 2011 Caolán McNamara - 3.4.2.1-3 +- Resolves: rhbz#715549 use fontconfig's detected format + +* Mon Jul 18 2011 Caolán McNamara - 3.4.2.1-2 +- Rebuild (poppler-0.17.0), add libreoffice-poppler-0.17.0.patch + seeing as the API changed for some reason or other + +* Wed Jul 13 2011 David Tardon - 3.4.2.1-1 +- 3.4.2 rc1 +- drop 0001-bad-merge-fix-to-enable-extensions-to-build-again.patch +- drop 0001-fix-regression-in-SvGlobalName-operator.patch + +* Tue Jul 12 2011 Caolán McNamara - 3.4.1.3-3 +- fix regression in SvGlobalName operator + +* Tue Jul 05 2011 Caolán McNamara - 3.4.1.3-2 +- Related: rhbz#718976 crash in SwTxtSizeInfo::GetMultiCreator + +* Fri Jul 01 2011 David Tardon - 3.4.1.3-1 +- 3.4.1 rc3 + +* Thu Jun 23 2011 Caolán McNamara - 3.4.1.2-1 +- 3.4.1 rc2 +- drop integrated 0001-correctly-build-GTK-systray-icon.patch + +* Tue Jun 21 2011 David Tardon - 3.4.1.1-5 +- Resolves: rhbz#714781 add Persian langpack +- Resolves: rhbz#667082 do not crash importing section containing just + an empty paragraph + +* Mon Jun 20 2011 Caolán McNamara - 3.4.1.1-4 +- Related: rhbz#711087 band aid for crash in sc undo +- Resolves: rhbz#714338 add a metapackage to install standard bits + +* Fri Jun 17 2011 Caolán McNamara - 3.4.1.1-3 +- Related: rhbz#702833 addEventListener without removeEventListener + +* Thu Jun 16 2011 Caolán McNamara - 3.4.1.1-2 +- Resolves: rhbz#713154 pdf export dialog too tall to fit + +* Wed Jun 15 2011 David Tardon - 3.4.1.1-1 +- 3.4.1 RC1 +- drop integrated 0001-Resolves-rhbz-707317-avoid-crash-in-getRowSpan.patch +- drop integrated 0001-Resolves-rhbz-710004-band-aid-for-immediate-crash-in.patch +- drop integrated 0001-Resolves-rhbz-710556-don-t-crash-on-missing-graphics.patch +- drop integrated 0001-Resolves-rhbz-699909-crash-in-export-of-.doc-in-lcl_.patch +- drop integrated 0001-fdo-37584-Make-a-real-copy-of-the-text-where-to-coun.patch +- drop integrated 0001-Resolves-fdo-37668-bitwise-operations-on-signed-numb.patch + +* Thu Jun 09 2011 Caolán McNamara - 3.4.0.2-5 +- Resolves: rhbz#699909 crash in export of .doc in lcl_getField +- Resolves: fdo#37584 Make a real copy of the text +- Resolves: rhbz#709503/fdo#37668 bitwise operations on signed values + +* Tue Jun 07 2011 Caolán McNamara - 3.4.0.2-4 +- Resolves: rhbz#710556 't crash on missing graphics .pptx export +- Resolves: rhbz#652604 better survive exceptions in autorecovery + +* Thu Jun 02 2011 Caolán McNamara - 3.4.0.2-3 +- Resolves: rhbz#710004 band aid for crash + +* Mon May 30 2011 Caolán McNamara - 3.4.0.2-2 +- Resolves: rhbz#707317 avoid crash in getRowSpan + +* Fri May 27 2011 David Tardon - 3.4.0.2-1 +- 3.4.0 RC2 +- drop integrated 0001-fix-build-with-system-bsh.patch + +* Wed May 25 2011 Caolán McNamara - 3.4.0.1-3 +- rebuild for new hunspell + +* Tue May 24 2011 David Tardon - 3.4.0.1-2 +- Resolves: rhbz#706110 oosplash.bin segfault on every login + +* Fri May 20 2011 David Tardon - 3.4.0.1-1 +- 3.4 RC1 +- Resolves: rhbz#702635 set correct page number when exporting selected + pages + +* Sat May 07 2011 Christopher Aillon - 3.3.99.4-2 +- Update icon cache scriptlet + +* Sat May 07 2011 David Tardon 3.3.99.4-1 +- 3.4 beta4 +- drop integrated 0001-Removed-duplicate-code-block-mis-merge-prolly.patch +- drop integrated 7de0b88ce2dd932915894385b54be1897d5ee053.zip + +* Mon Apr 18 2011 Caolán McNamara 3.3.99.1-2 +- Resolves: rhbz#695509 crash in RefreshDocumentLB +- bubble down configure test findings on visibility + +* Mon Apr 11 2011 Caolán McNamara 3.3.99.1-1 +- 3.4 beta1 +- drop openoffice.org-1.9.123.ooo53397.prelinkoptimize.desktop.patch + in favour of ooosplash +- drop openoffice.org-2.2.0.gccXXXXX.solenv.javaregistration.patch + because components are passively registered now +- drop integrated openoffice.org-3.1.0.ooo102061.sc.cellanchoring.patch +- drop integrated turn-script-providers-into-extensions.patch +- drop integrated 0001-tidy-this-up-and-don-t-bail-out-on-mislength-records.patch +- drop integrated 0001-free-ctxt-after-taking-lastError-details.patch +- drop integrated 0001-Removed-suspect-hack.-Cursor-on-post-it-now-scrolls-.patch +- drop integrated libreoffice-gcc4.6.0.patch +- drop integrated 0001-fexceptions-fexceptions.patch +- drop integrated 0001-Related-rhbz-672872-cancel-gtk-file-dialog-on-deskto.patch +- drop vbahelper.visibility.patch +- drop integrated 0001-Resolves-fdo-33509-i62414-out-by-one-breaks-CTL-spel.patch +- drop integrated 0001-Resolves-rhbz-670020-crash-in-slidesorting.patch +- drop integrated 0001-Resolves-rhbz-676539-handle-missing-pWindows-from-xW.patch +- drop integrated 0001-Resolves-fdo-33750-i94623-use-optimal-border-width-w.patch +- drop integrated 0001-rhbz-649310-don-t-crash-deregistering-diff.-platform.patch +- drop integrated 0001-Resolves-rhbz-674330-dereference-of-NULL-mpBase.patch +- drop integrated 0001-rhbz-678284-Get-correct-current-position-when-shift-page-up-and-.patch +- drop integrated 0001-Resolves-rhbz-681159-bandaid-for-crash.patch +- drop integrated 0001-Resolves-rhbz-672818-bandaid-for-crash-in-SwTxtNode-.patch +- drop integrated 0001-install-high-resolution-icons.patch +- drop integrated 0001-Resolves-rhbz-682716-pa-IN-isn-t-handled-by-fontconf.patch +- drop integrated 0001-Related-rhbz-684477-make-sure-this-is-thread-safe.patch +- drop integrated 0001-Resolves-rhbz-682621-better-resizing-of-overtall-gly.patch +- drop integrated 0001-Resolves-rhbz-684620-crash-with-NULL-pTableBox.patch +- drop integrated libreoffice-fdo33947.sd.print.crash.patch +- drop integrated 0001-add-cairo_ft_font_face_create_for_pattern-wrapper.patch +- drop integrated 0001-Related-rhbz-680460-reorganize-this-to-make-it-inher.patch +- drop integrated 0001-Related-rhbz-680460-don-t-bother-with-an-interim-Fon.patch +- drop integrated 0001-Resolves-rhbz-680460-honour-lcdfilter-subpixeling-et.patch +- drop integrated 0001-Cut-Gordian-Knot-of-who-owns-the-font-options.patch +- drop integrated 0001-beware-of-invalidated-iterator.patch +- drop integrated rhbz680766.fix-mdds-crash.patch +- drop integrated 0001-Resolves-rhbz-684580-X-and-strike-through-escapes-ra.patch +- drop integrated 0001-set-mime-types-on-flat-xml-filters.patch +- drop integrated 0001-add-flat-xml-types-to-.desktop-files-etc.patch +- drop integrated libreoffice-fdo31271.icu.patch + +* Tue Apr 05 2011 Caolán McNamara 3.3.2.2-6 +- Resolves: rhbz#655686 get order of shutdown correct + +* Wed Mar 30 2011 Caolán McNamara 3.3.2.2-5 +- Add application/vnd.oasis.opendocument.text-flat-xml, etc. to + .desktop files for mcepl + +* Tue Mar 29 2011 Caolán McNamara 3.3.2.2-4 +- Resolves: rhbz#684580 improve X and / strike-through + +* Thu Mar 24 2011 David Tardon 3.3.2.2-3 +- Resolves: rhbz#680766 crash in mdds + +* Wed Mar 23 2011 David Tardon 3.3.2.2-2 +- Related: rhbz#689268 versioned deps need to contain epoch + +* Tue Mar 22 2011 Caolán McNamara 3.3.2.2-1 +- latest version +- drop integrated 0001-Resolves-fdo-33701-ensure-node-outlives-path.patch +- drop integrated 0001-valgrind-don-t-leave-an-evil-thread-running-after-ma.patch + +* Tue Mar 22 2011 Caolán McNamara 3.3.1.2-12 +- Fix fontoptions cache +- avoid crash in calc on changing size of rows (dtardon) + +* Mon Mar 21 2011 Caolán McNamara 3.3.1.2-11 +- Resolves: rhbz#689268 autocorrs from OOo F14 not upgraded + +* Wed Mar 16 2011 Caolán McNamara 3.3.1.2-10 +- Resolves: rhbz#680460 honour lcdfilter and subpixeling + +* Tue Mar 15 2011 Caolán McNamara 3.3.1.2-9 +- Resolves: fdo#33947 sd print crash + +* Mon Mar 14 2011 Caolán McNamara 3.3.1.2-8 +- Related: rhbz#684477 make sure this is thread safe +- Resolves: rhbz#684620 crash with NULL pTableBox + +* Sun Mar 13 2011 Marek Kasik 3.3.1.2-7 +- Rebuild (poppler-0.16.3) + +* Wed Mar 09 2011 Caolán McNamara 3.3.1.2-6 +- Resolves: rhbz#682621 better resizing of overtall glyphsubs + +* Tue Mar 08 2011 Caolán McNamara 3.3.1.2-5 +- Resolves: rhbz#682716 pa-IN isn't handled well by fontconfig + +* Tue Mar 08 2011 David Tardon 3.3.1.2-4 +- install 128x128 px icons + +* Wed Mar 02 2011 Caolán McNamara 3.3.1.2-3 +- Resolves: rhbz#681159 crash in writer +- Resolves: rhbz#672818 crash in writer +- Resolves: fdo#33701 ensure node outlives path +- Resolves: rhbz#681738 crash on writing config post-main + +* Thu Feb 17 2011 Caolán McNamara 3.3.1.2-2 +- Resolves: rhbz#678284 Calc crashes during cell select with keys + (dtardon) + +* Thu Feb 17 2011 Caolán McNamara 3.3.1.2-1 +- RC2 + +* Wed Feb 16 2011 Caolán McNamara 3.3.1.1-2 +- Resolves: rhbz#674330 dereference of NULL mpBase + +* Fri Feb 11 2011 Caolán McNamara 3.3.1.1-1 +- 3.3.1 rc1 +- drop integrated 0001-don-t-pushback-and-process-a-corrupt-extension.patch +- drop integrated libreoffice-fdo32561.comphelper.patch +- drop integrated 0001-Related-rhbz-610103-more-woes-on-rpm-upgrade-vs-rpm-.patch +- drop integrated 0001-Resolves-rhbz-673819-crash-on-changing-position-of-d.patch +- drop integrated 0001-rhbz-666440-don-t-pushback-and-process-a-corrupt-extension.patch + +* Thu Feb 10 2011 Caolán McNamara 3.3.0.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild +- Related: rhbz#610103 make this even more robust +- Related: rhbz#672872 cancel gtk file dialog on terminate +- Resolves: fdo#33509/ooo#62414 fix CTL spelling popup +- Resolves: rhbz#673819 crash on changing position of header/footer object +- Resolves: rhbz#670020 crash in slidesorting +- Resolves: rhbz#676539 handle missing pWindows from xWindows +- Resolves: rhbz#649310 don't crash deregistering diff. platform ext. + (dtardon) +- Resolves: rhbz#666440 don't pushback and process a corrupt extension + +* Mon Jan 24 2011 Caolán McNamara 3.3.0.4-2 +- Resolves: rhbz#671540 fix lonely ) + +* Thu Jan 20 2011 Caolán McNamara 3.3.0.4-1 +- next release candidate +- drop integrated 0001-fix-presenter-screens-description.xml-build.patch + +* Tue Jan 18 2011 Caolán McNamara 3.3.0.3-2 +- backport fix to get presenter screen working +- make handling busted extensions more robust + +* Wed Jan 12 2011 Caolán McNamara 3.3.0.3-1 +- latest version +- drop integrated 0001-Resoves-rhbz-663857-font-color-missing-C-FAQ-10.3-do.patch +- drop integrated 0001-Avoid-double-paste-when-pasting-text-into-cell-comme.patch +- drop integrated 0001-Resolves-rhbz-660342-Undo-Redo-crash-with-postits.patch +- drop integrated 0001-Resolves-rhbz-666088-clean-up-search-cache-singleton.patch + +* Thu Jan 06 2011 Caolán McNamara 3.3.0.2-5 +- Resolves: rhbz#666088 don't crash on clean up of search cache + +* Wed Jan 05 2011 Lukas Tinkl 3.3.0.2-4 +- create a KDE integration subpackage + +* Mon Jan 03 2011 David Tardon 3.3.0.2-3 +- rebuild with new poppler + +* Wed Dec 22 2010 Caolán McNamara 3.3.0.2-2 +- Resolves: rhbz#663724 fdo32572-sc-dont-double-paste.patch +- Resolves: rhbz#660342 Undo/Redo crash with postits + +* Tue Dec 21 2010 Caolán McNamara 3.3.0.2-1 +- latest version + +* Sat Dec 18 2010 Caolán McNamara 3.3.0.1-4 +- Resolves: rhbz#663857 font color missing in transitions + +* Wed Dec 15 2010 Rex Dieter - 3.3.0.1-3 +- rebuild (poppler) + +* Wed Dec 15 2010 Caolán McNamara 3.3.0.1-2 +- Fix up some doc imports + +* Sun Dec 05 2010 Caolán McNamara 3.3.0.1-1 +- release candidate 1 +- drop integrated qstart.dont-forceenabled-on-post-reg-restart.patch +- drop integrated exit.quickstarter.when.deleted.patch +- drop integrated 0001-destroydesktop.in.timeout.patch +- drop integrated openoffice.org-3.3.0.rhbz657541.join-paragraphs.patch + +* Sat Nov 27 2010 Caolán McNamara 3.2.99.3-2 +- Resolves: rhbz#610103 exit quickstarter when libs deleted +- Resolves: rhbz#652695 release desktop in timeout +- Resolves: rhbz#657541 don't crash during processing of auto. styles + when joining paragraphs (dtardon) + +* Thu Nov 18 2010 Caolán McNamara 3.2.99.2-5 +- Resolves: rhbz#649210 add Sinhalese langpack + +* Sat Oct 30 2010 Caolán McNamara 3.2.99.2-4 +- langpack macro hard-coded version number + +* Fri Oct 22 2010 Caolán McNamara 3.2.99.2-3 +- Resolves: xdg632229 gnomeshell app tracking + +* Tue Oct 12 2010 David Tardon 3.2.99.2-2 +- use macros to define auto-correction and language pack subpackages + +* Mon Oct 11 2010 Caolán McNamara 3.2.99.2-1 +- next LibreOffice milestone +- drop integrated openoffice.org-2.3.0.ooo76649.httpencoding.patch +- drop integrated workspace.dtardon03.patch +- drop integrated openoffice.org-3.1.0.ooo61927.sw.ww6.unicodefontencoding.patch +- drop integrated workspace.impress195.patch +- drop integrated workspace.srb1.patch +- drop integrated openoffice.org-3.2.0.ooo106502.svx.fixspelltimer.patch +- drop integrated openoffice.org-3.3.0.ooo108246.svx.hide-sql-group-when-inactive.patch +- drop integrated openoffice.org-3.2.0.ooo95369.sw.sortedobjs.patch +- drop integrated openoffice.org-3.2.0.ooo110142.svx.safercolornames.patch +- drop integrated openoffice.org-3.3.0.ooo111758.sd.xerror.patch +- drop integrated openoffice.org-3.2.0.ooo111741.extras.malformed-xml-file.patch +- drop integrated openoffice.org-3.3.0.ooo112059.sw.avoid-null-ptr-deref.patch +- drop integrated openoffice.org-3.3.0.ooo100686.wizards.types.not.mediatypes.patch +- drop integrated workspace.vcl113.patch +- drop integrated openoffice.org-3.3.0.ooo112384.sw.export.doc.styledoesntexist.patch +- drop integrated workspace.cmcfixes77.patch +- drop integrated workspace.vcl114.patch +- drop integrated openoffice.org-3.3.0.ooo106591.sal.tradcopy.patch +- drop integrated workspace.vcl115.patch +- drop integrated workspace.cmcfixes78.patch +- drop integrated openoffice.org-3.3.0.ooo114012.sd.bada11ychain.patch +- drop integrated workspace.cmcfixes79.patch +- drop integrated openoffice.org-3.3.0.ooo114703.vcl.betterlocalize.font.patch +- drop integrated openoffice.org-3.3.0.rh638185.editeng.cjkctlhtmlsizes.patch +- drop integrated openoffice.org-3.3.0.rh637738.libgcrypt.addmutex.patch +- drop integrated openoffice.org-3.2.0.rh632236.writerfilter.cleanup-cell-props.patch +- drop workspace.gtk3.patch + +* Wed Oct 06 2010 Caolán McNamara 3.2.99.1-2 +- Related: rhbz#639945 pull in review changes + + redland build-fix + + replace awk script + + validate .destop files + +* Wed Sep 29 2010 Caolán McNamara 3.2.99.1-1 +- initial import of the leviathan