desktop/source/app/cmdlineargs.cxx | 10 download.lst | 4 external/nss/ExternalProject_nss.mk | 3 external/nss/asan.patch.1 | 8 external/nss/nss.patch | 8 hwpfilter/source/hwpfile.cxx | 5 hwpfilter/source/hwpfile.h | 4 include/sfx2/sfx.hrc | 2 include/sfx2/viewfrm.hxx | 1 officecfg/registry/schema/org/openoffice/Office/Common.xcs | 16 + sc/inc/documentimport.hxx | 2 sc/inc/table.hxx | 2 sc/source/core/data/document.cxx | 9 sc/source/core/data/documentimport.cxx | 14 + sc/source/core/data/table2.cxx | 15 + sc/source/filter/oox/sheetdatabuffer.cxx | 13 + sfx2/source/appl/macroloader.cxx | 9 sfx2/source/doc/iframe.cxx | 20 + sfx2/source/inc/macroloader.hxx | 2 sfx2/source/view/view.src | 10 sfx2/source/view/viewfrm.cxx | 41 +++ svl/source/inc/passwordcontainer.hxx | 69 ++++- svl/source/passwordcontainer/passwordcontainer.cxx | 165 ++++++++++--- sw/source/filter/html/htmlplug.cxx | 7 sw/source/filter/xml/xmltexti.cxx | 9 uui/source/iahndl-authentication.cxx | 5 wizards/source/access2base/DoCmd.xba | 2 xmloff/source/draw/ximpshap.cxx | 4 28 files changed, 385 insertions(+), 74 deletions(-)
New commits: commit c1c659ad31a569816432e4e17af3af904792a3b6 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Sep 6 11:38:55 2022 +0100 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 21:01:51 2022 +0200 check impress/calc IFrame "FrameURL" target similar to commit c7450d0b9d02c64ae3da467d329040787039767e Date: Tue Aug 30 17:01:08 2022 +0100 check IFrame "FrameURL" target Conflicts: xmloff/source/draw/ximpshap.cxx Change-Id: Ibf28c29acb4476830431d02772f3ecd4b23a6a27 diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 4477ff92e957..7c6d41a75b82 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -82,6 +82,7 @@ #include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/vector/b2dvector.hxx> +#include <tools/urlobj.hxx> #include <config_features.h> @@ -3257,6 +3258,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) ); } } commit fae9b131c776b9d75dd51c8a9175abc2b89a572a Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Thu Sep 1 17:33:51 2022 +0200 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 21:01:01 2022 +0200 Filter out unwanted command URIs Change-Id: I0b7e5329af8cc053d14d5c60ec14fe7f364ef993 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139225 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> Conflicts: desktop/source/app/cmdlineargs.cxx diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx index ad07af0f045a..48336da1b71d 100644 --- a/desktop/source/app/cmdlineargs.cxx +++ b/desktop/source/app/cmdlineargs.cxx @@ -28,6 +28,7 @@ #include "cmdlineargs.hxx" #include <vcl/svapp.hxx> #include <rtl/uri.hxx> +#include <tools/urlobj.hxx> #include <rtl/ustring.hxx> #include <rtl/process.h> #include <comphelper/lok.hxx> @@ -163,7 +164,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; } commit 042625161668f19157ddcde5da9c21b981897dff Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Aug 30 17:01:08 2022 +0100 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 21:00:26 2022 +0200 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 <sberg...@redhat.com> Conflicts: sfx2/source/doc/iframe.cxx sw/source/filter/html/htmlplug.cxx sw/source/filter/xml/xmltexti.cxx diff --git a/sfx2/source/appl/macroloader.cxx b/sfx2/source/appl/macroloader.cxx index ce1e85e0c88b..6ca9a27e5829 100644 --- a/sfx2/source/appl/macroloader.cxx +++ b/sfx2/source/appl/macroloader.cxx @@ -73,10 +73,10 @@ css::uno::Sequence<OUString> SAL_CALL SfxMacroLoader::getSupportedServiceNames() return aSeq; } -SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() +SfxObjectShell* SfxMacroLoader::GetObjectShell(const Reference <XFrame>& xFrame) { SfxObjectShell* pDocShell = nullptr; - Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); + if ( xFrame.is() ) { SfxFrame* pFrame=nullptr; @@ -93,6 +93,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<frame::XDispatch> SAL_CALL SfxMacroLoader::queryDispatch( const util::URL& aURL , diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx index 8070c90c1e2c..413d38482d28 100644 --- a/sfx2/source/doc/iframe.cxx +++ b/sfx2/source/doc/iframe.cxx @@ -39,10 +39,12 @@ #include <svl/ownlist.hxx> #include <svl/itemprop.hxx> #include <sfx2/frmdescr.hxx> +#include <sfx2/objsh.hxx> #include <sfx2/sfxdlg.hxx> #include <sfx2/sfxsids.hrc> #include <toolkit/helper/vclunohelper.hxx> #include <vcl/window.hxx> +#include <macroloader.hxx> using namespace ::com::sun::star; @@ -158,6 +160,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<frame::XFramesSupplier> xParentFrame = xFrame->getCreator(); + SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame); + if (pDoc && !pDoc->AdjustMacroMode()) + return false; + } + DBG_ASSERT( !mxFrame.is(), "Frame already existing!" ); VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() ); @@ -180,11 +195,6 @@ 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; diff --git a/sfx2/source/inc/macroloader.hxx b/sfx2/source/inc/macroloader.hxx index 94fa5165fdd9..e2d5f8fd76c4 100644 --- a/sfx2/source/inc/macroloader.hxx +++ b/sfx2/source/inc/macroloader.hxx @@ -81,6 +81,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<css::frame::XFrame>& xFrame); }; #endif diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx index 98eeb3677cf0..3ddbe667da3f 100644 --- a/sw/source/filter/html/htmlplug.cxx +++ b/sw/source/filter/html/htmlplug.cxx @@ -890,7 +890,12 @@ void SwHTMLParser::InsertFloatingFrame() bool bHasBorder = aFrameDesc.HasFrameBorder(); Size aMargin = aFrameDesc.GetMargin(); - xSet->setPropertyValue("FrameURL", uno::makeAny( OUString( 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 d1498cf3cc71..00dd36135add 100644 --- a/sw/source/filter/xml/xmltexti.cxx +++ b/sw/source/filter/xml/xmltexti.cxx @@ -857,9 +857,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( OUString( URIHelper::SmartRel2Abs( - INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ) ) ); + makeAny( sHRef ) ); xSet->setPropertyValue("FrameName", makeAny( rName ) ); commit bdc87e75d90c3ac2f31fb4d15e0017a8434518c7 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Tue Aug 30 14:04:52 2022 +0200 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:56:50 2022 +0200 These commands are always URLs already Change-Id: I5083765c879689d7f933bbe00ad70bb68e635a21 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139042 Tested-by: Jean-Pierre Ledure <j...@ledure.be> Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> Conflicts: wizards/source/scriptforge/SF_Session.xba diff --git a/wizards/source/access2base/DoCmd.xba b/wizards/source/access2base/DoCmd.xba index b52cbbdccde9..e213f0e66ffc 100644 --- a/wizards/source/access2base/DoCmd.xba +++ b/wizards/source/access2base/DoCmd.xba @@ -2652,7 +2652,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 </script:module> \ No newline at end of file commit ae65c8294203d43fceeea9ab4bd73ae40830917b Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Wed Jun 1 12:14:44 2022 +0200 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:48 2022 +0200 nss: upgrade to release 3.79 Fixes CVE-2022-1097 and moz#1767590 "memory safety violations" Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135234 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135248 Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> (cherry picked from commit bb5216e345c42be440bce60b127af517c036c8ef) Change-Id: I6895f066ad943402231b616dae0d7ed6f5678b5e Conflicts: download.lst external/nss/asan.patch.1 diff --git a/download.lst b/download.lst index da08c1c0b47f..c68e5b6fdc70 100644 --- a/download.lst +++ b/download.lst @@ -164,8 +164,8 @@ export MYTHES_SHA256SUM := 1e81f395d8c851c3e4e75b568e20fa2fa549354e75ab397f9de4b export MYTHES_TARBALL := a8c2c5b8f09e7ede322d5c602ff6a4b6-mythes-1.2.4.tar.gz export NEON_SHA256SUM := 00c626c0dc18d094ab374dbd9a354915bfe4776433289386ed489c2ec0845cdd export NEON_TARBALL := 231adebe5c2f78fded3e3df6e958878e-neon-0.30.1.tar.gz -export NSS_SHA256SUM := 07a9e5b70f121a62706140d4cacc3006d3efb869da40f3a2bf7a65d37847f4d9 -export NSS_TARBALL := nss-3.73-with-nspr-4.32.tar.gz +export NSS_SHA256SUM := 5369ed274a19f480ec94e1faef04da63e3cbac1a82e15bb1751e58b2f274b835 +export NSS_TARBALL := nss-3.79-with-nspr-4.34.tar.gz export ODFGEN_SHA256SUM := 2c7b21892f84a4c67546f84611eccdad6259875c971e98ddb027da66ea0ac9c2 export ODFGEN_VERSION_MICRO := 6 export ODFGEN_TARBALL := libodfgen-0.1.$(ODFGEN_VERSION_MICRO).tar.bz2 diff --git a/external/nss/asan.patch.1 b/external/nss/asan.patch.1 index 0685adb1dc4b..ce584a34a3b5 100644 --- a/external/nss/asan.patch.1 +++ b/external/nss/asan.patch.1 @@ -1,12 +1,12 @@ diff -ur nss.org/nss/coreconf/Linux.mk nss/nss/coreconf/Linux.mk --- nss.org/nss/coreconf/Linux.mk 2014-05-06 04:36:01.817838877 +0200 +++ nss/nss/coreconf/Linux.mk 2014-05-06 04:37:25.387835456 +0200 -@@ -158,7 +158,7 @@ +@@ -146,7 +146,7 @@ # we don't use -z defs there. # Also, -z defs conflicts with Address Sanitizer, which emits relocations # against the libsanitizer runtime built into the main executable. -ZDEFS_FLAG = -Wl,-z,defs +ZDEFS_FLAG = - ifneq ($(USE_ASAN),1) - DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) -Wl,-z,origin '-Wl,-rpath,$$ORIGIN' - endif + DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell $(LD) -v)),,$(ZDEFS_FLAG)) $(if $(filter-out $(OS),ANDROID),-Wl$(COMMA)-z$(COMMA)origin '-Wl$(COMMA)-rpath$(COMMA)$$ORIGIN') + LDFLAGS += $(ARCHFLAG) -z noexecstack + diff --git a/external/nss/nss.patch b/external/nss/nss.patch index d9aaee5199bb..66fbe37dc5ed 100644 --- a/external/nss/nss.patch +++ b/external/nss/nss.patch @@ -87,9 +87,9 @@ # Also, -z defs conflicts with Address Sanitizer, which emits relocations # against the libsanitizer runtime built into the main executable. ZDEFS_FLAG = -Wl,-z,defs --DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) -+DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) $(if $(filter-out $(OS),ANDROID),-Wl$(COMMA)-z$(COMMA)origin '-Wl$(COMMA)-rpath$(COMMA)$$ORIGIN') - LDFLAGS += $(ARCHFLAG) -z noexecstack +-DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell $(LD) -v)),,$(ZDEFS_FLAG)) ++DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell $(LD) -v)),,$(ZDEFS_FLAG)) $(if $(filter-out $(OS),ANDROID),-Wl$(COMMA)-z$(COMMA)origin '-Wl$(COMMA)-rpath$(COMMA)$$ORIGIN') + LDFLAGS += $(ARCHFLAG) -z noexecstack # On Maemo, we need to use the -rpath-link flag for even the standard system @@ -177,8 +177,13 @@ commit faa1838285b7ff641d8d21e8b87cd808568351c2 Author: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> AuthorDate: Fri Sep 15 17:59:40 2017 +0200 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 nss: no rpath/origin flag for Android (unused DT entry/DT_FLAGS warnings) Change-Id: I15d322f7361a26060ea37a720f85890e17630ebe Reviewed-on: https://gerrit.libreoffice.org/42336 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> Conflicts: external/nss/ExternalProject_nss.mk diff --git a/external/nss/ExternalProject_nss.mk b/external/nss/ExternalProject_nss.mk index caef94705358..7114f4da1e98 100644 --- a/external/nss/ExternalProject_nss.mk +++ b/external/nss/ExternalProject_nss.mk @@ -58,7 +58,8 @@ $(call gb_ExternalProject_get_state_target,nss,build): $(call gb_ExternalProject $(MAKE) AR="$(AR)" \ RANLIB="$(RANLIB)" \ NMEDIT="$(NM)edit" \ - CCC="$(CXX)" \ + COMMA=$(COMMA) \ + CC="$(CC)" CCC="$(CXX)" \ $(if $(CROSS_COMPILING),NSPR_CONFIGURE_OPTS="--build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM)") \ nss_build_all \ && rm -f $(call gb_UnpackedTarball_get_dir,nss)/dist/out/lib/*.a \ diff --git a/external/nss/nss.patch b/external/nss/nss.patch index c1f994787ecb..d9aaee5199bb 100644 --- a/external/nss/nss.patch +++ b/external/nss/nss.patch @@ -5,7 +5,7 @@ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS=-fPIC - DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' -+ DSO_LDOPTS='-shared -Wl,-z,origin -Wl,-rpath,\$$ORIGIN -Wl,-soname -Wl,$(notdir $@)' ++ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@) $(if $(filter-out $(OS),ANDROID),-Wl$(COMMA)-z$(COMMA)origin -Wl$(COMMA)-rpath$(COMMA)\$$ORIGIN)' _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that # combo is not yet good at debugging inlined @@ -88,7 +88,7 @@ # against the libsanitizer runtime built into the main executable. ZDEFS_FLAG = -Wl,-z,defs -DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) -+DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) -Wl,-z,origin '-Wl,-rpath,$$ORIGIN' ++DSO_LDOPTS += $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG)) $(if $(filter-out $(OS),ANDROID),-Wl$(COMMA)-z$(COMMA)origin '-Wl$(COMMA)-rpath$(COMMA)$$ORIGIN') LDFLAGS += $(ARCHFLAG) -z noexecstack # On Maemo, we need to use the -rpath-link flag for even the standard system commit c5ed8404a0caf2460c8b70e800e2bad774e03652 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Mar 23 13:03:30 2022 +0000 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 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 <michael.st...@allotropia.de> (cherry picked from commit bbd196ff82bda9f66b4ba32a412f10cefe6da60e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132307 Reviewed-by: Sophie Gautier <so...@libreoffice.org> Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> (cherry picked from commit c5d01b11db3c83cb4a89d3b388d78e20dd3990b5) (cherry picked from commit df05d27336927373bf83664a90156fbe505fc546) Change-Id: Id99cbf2b50a4ebf289dae6fc67e22e20afcda35b Conflicts: include/sfx2/strings.hrc sfx2/source/view/viewfrm.cxx diff --git a/include/sfx2/sfx.hrc b/include/sfx2/sfx.hrc index c9de431bd10a..a72a57dfe180 100644 --- a/include/sfx2/sfx.hrc +++ b/include/sfx2/sfx.hrc @@ -122,6 +122,8 @@ #define STR_SIGNATURE_NOTVALIDATED (RID_SFX_START+142) #define STR_SIGNATURE_PARTIAL_OK (RID_SFX_START+143) #define STR_SIGNATURE_OK (RID_SFX_START+144) +#define STR_REFRESH_MASTER_PASSWORD (RID_SFX_START+145) +#define STR_REFRESH_PASSWORD (RID_SFX_START+146) // group ids diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx index 6276f411485b..587336f3c4f8 100644 --- a/include/sfx2/viewfrm.hxx +++ b/include/sfx2/viewfrm.hxx @@ -81,6 +81,7 @@ protected: 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/view.src b/sfx2/source/view/view.src index f42bedaefb68..2444ac1798ee 100644 --- a/sfx2/source/view/view.src +++ b/sfx2/source/view/view.src @@ -162,4 +162,14 @@ String STR_SIGNATURE_SHOW Text[ en-US ] = "Show Signatures"; }; +String STR_REFRESH_MASTER_PASSWORD +{ + Text[ en-US ] = "The master password is stored in an outdated format, you should refresh it"; +}; + +String STR_REFRESH_PASSWORD +{ + Text[ en-US ] = "Refresh Password"; +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx index 89070eb4e591..4d576f60218d 100644 --- a/sfx2/source/view/viewfrm.cxx +++ b/sfx2/source/view/viewfrm.cxx @@ -29,6 +29,7 @@ #include <com/sun/star/frame/XLoadable.hpp> #include <com/sun/star/frame/XLayoutManager.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/task/PasswordContainer.hpp> #include <officecfg/Office/Common.hxx> #include <toolkit/helper/vclunohelper.hxx> #include <vcl/splitwin.hxx> @@ -1138,6 +1139,25 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) rBind.Invalidate( SID_RELOAD ); rBind.Invalidate( SID_EDITDOC ); + if (officecfg::Office::Common::Passwords::HasMaster::get() && + officecfg::Office::Common::Passwords::StorageVersion::get() == 0) + { + // master password stored in deprecated format + VclPtr<SfxInfoBarWindow> pOldMasterPasswordInfoBar = + AppendInfoBar("oldmasterpassword", + SfxResId(STR_REFRESH_MASTER_PASSWORD), InfoBarType::Danger); + if (pOldMasterPasswordInfoBar) + { + VclPtrInstance<PushButton> 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; if ( m_xObjSh->IsReadOnly() && @@ -1265,6 +1285,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<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface(); + css::uno::Reference<css::awt::XWindow> xContainerWindow = xFrame->getContainerWindow(); + + uno::Reference<task::XInteractionHandler> 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; commit c112b760384252b05102598757b8a40201c7e94d Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Mar 22 17:22:22 2022 +0000 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 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 <michael.st...@allotropia.de> (cherry picked from commit 192fa1e3bfc6269f2ebb91716471485a56074aea) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132306 Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> (cherry picked from commit ab77587ec300f5c30084471000663c46ddf25dad) Change-Id: I6fe3b02fafcce1b5e7133e77e76a5118177d77af Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133907 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Conflicts: svl/source/inc/passwordcontainer.hxx svl/source/passwordcontainer/passwordcontainer.cxx diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index 36025ce5d2a3..fa961f0ea4bd 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -27,6 +27,11 @@ <info> <desc>Contains a container for passwords.</desc> </info> + <prop oor:name="InitializationVector" oor:type="xs:string"> + <info> + <desc>Contains an initialization vector for the password encryption.</desc> + </info> + </prop> <prop oor:name="Password" oor:type="xs:string" oor:localized="false"> <info> <desc>Contains a password encoded with the master password.</desc> @@ -916,6 +921,11 @@ </info> <value>false</value> </prop> + <prop oor:name="MasterInitializationVector" oor:type="xs:string"> + <info> + <desc>Contains an initialization vector for the master password encryption.</desc> + </info> + </prop> <prop oor:name="Master" oor:type="xs:string" oor:nillable="false"> <info> <desc>Contains the master password encrypted by itself.</desc> diff --git a/svl/source/inc/passwordcontainer.hxx b/svl/source/inc/passwordcontainer.hxx index cb1bbea545f5..6d99d19bdda8 100644 --- a/svl/source/inc/passwordcontainer.hxx +++ b/svl/source/inc/passwordcontainer.hxx @@ -37,6 +37,7 @@ #include <unotools/configitem.hxx> #include <ucbhelper/interactionrequest.hxx> +#include <rtl/random.h> #include <rtl/ref.hxx> #include <osl/mutex.hxx> @@ -55,11 +56,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 ) @@ -67,7 +69,10 @@ class NamePassRecord m_bHasPersPass = bHasPersistentList; if ( bHasPersistentList ) + { m_aPersPass = aPersistentList; + m_aPersistentIV = aPersistentIV; + } } public: @@ -79,11 +84,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 ) { } @@ -92,7 +98,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 ) @@ -101,7 +108,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; } @@ -137,15 +146,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; } @@ -160,6 +178,7 @@ public: { m_bHasPersPass = false; m_aPersPass.clear(); + m_aPersistentIV.clear(); } } @@ -183,6 +202,7 @@ private: PasswordContainer* mainCont; bool hasEncoded; OUString mEncoded; + OUString mEncodedIV; virtual void ImplCommit() override; @@ -203,8 +223,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(); @@ -225,6 +245,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::list< NamePassRecord >& original, @@ -275,10 +318,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 ); + static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPassword ); /// @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 >& ); diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx index c993ef6f8b8a..0d932b457f7d 100644 --- a/svl/source/passwordcontainer/passwordcontainer.cxx +++ b/svl/source/passwordcontainer/passwordcontainer.cxx @@ -186,17 +186,21 @@ PassMap StorageItem::getInfo() Sequence< OUString > aNodeNames = ConfigItem::GetNodeNames( "Store" ); sal_Int32 aNodeCount = aNodeNames.getLength(); - Sequence< OUString > aPropNames( aNodeCount ); + Sequence< OUString > aPropNames( aNodeCount * 2); sal_Int32 aNodeInd; for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) { aPropNames[aNodeInd] = "Store/Passwordstorage['" + aNodeNames[aNodeInd] + "']/Password"; } + for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) + { + aPropNames[aNodeCount + aNodeInd] = "Store/Passwordstorage['" + aNodeNames[aNodeInd] + "']/InitializationVector"; + } Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); - if( aPropertyValues.getLength() != aNodeNames.getLength() ) + if( aPropertyValues.getLength() != aNodeCount * 2) { OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading" ); return aResult; @@ -212,14 +216,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.push_back( NamePassRecord( aName, aEPasswd ) ); + aIter->second.push_back( NamePassRecord( aName, aEPasswd, aIV ) ); else { - NamePassRecord aNewRecord( aName, aEPasswd ); + NamePassRecord aNewRecord( aName, aEPasswd, aIV ); list< NamePassRecord > listToAdd( 1, aNewRecord ); aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); @@ -283,17 +289,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 ); @@ -305,32 +313,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; } @@ -366,11 +379,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 ); @@ -440,7 +455,7 @@ void SAL_CALL PasswordContainer::disposing( const EventObject& ) } } -vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aMasterPasswd ) +vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPasswd ) { if( !aMasterPasswd.isEmpty() ) { @@ -455,9 +470,16 @@ vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, co for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) code[ ind ] = (char)(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<char>(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 ) { @@ -489,7 +511,7 @@ vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, co throw RuntimeException("Can't decode!" ); } -OUString PasswordContainer::EncodePasswords(const vector< OUString >& lines, const OUString& aMasterPasswd ) +OUString PasswordContainer::EncodePasswords(const vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPasswd ) { if( !aMasterPasswd.isEmpty() ) { @@ -506,9 +528,16 @@ OUString PasswordContainer::EncodePasswords(const vector< OUString >& lines, con for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) code[ ind ] = (char)(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<char>(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 ) { @@ -576,7 +605,7 @@ void PasswordContainer::UpdateVector( const OUString& aURL, list< NamePassRecord if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) { - aNPIter->SetPersPasswords( aRecord.GetPersPasswords() ); + aNPIter->SetPersPasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV() ); if( writeFile ) { @@ -609,7 +638,9 @@ UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, b { try { - ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) ); + ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), + aRecord.GetPersistentIV(), + GetMasterPassword( aHandler ) ); aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); } catch( NoMasterException& ) @@ -655,6 +686,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 ) { @@ -662,7 +706,11 @@ void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserNam ::std::vector< OUString > aStorePass = comphelper::sequenceToContainer< std::vector<OUString> >( 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 @@ -856,10 +904,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() ) { @@ -881,14 +929,15 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac m_aMasterPasswd = aPass; 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); - vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass ) ); + vector< OUString > aRM( DecodePasswords( aEncodedMP, aEncodedMPIV, aPass ) ); if( aRM.empty() || !aPass.equals( aRM[0] ) ) { bAskAgain = true; @@ -1049,7 +1098,7 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere { sal_Int32 oldLen = aUsers.getLength(); aUsers.realloc( oldLen + 1 ); - aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), comphelper::containerToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) ); + aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), comphelper::containerToSequence( DecodePasswords( aNPIter->GetPersPasswords(), aNP.GetPersistentIV(), GetMasterPassword( xHandler ) ) ) ); } if( aUsers.getLength() ) @@ -1066,12 +1115,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() ) { @@ -1138,8 +1187,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 ) @@ -1159,7 +1208,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< // store the new master password m_aMasterPasswd = aPass; 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 ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) @@ -1186,7 +1236,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 } } @@ -1197,8 +1247,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 ) @@ -1245,8 +1295,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 ) @@ -1263,7 +1313,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 ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) @@ -1289,8 +1339,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() ); } commit 3769c8c19658bcb3f84bd5a6300ef5e279a4ebde Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Mon Mar 21 20:58:34 2022 +0000 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 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 <sberg...@redhat.com> (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 <michael.st...@allotropia.de> (cherry picked from commit bbb8617ece6d946957c2eb96287081029bce530f) Change-Id: I3174c37a5891bfc849984e0ec5c2c392b9c6e7b1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133905 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Conflicts: svl/source/passwordcontainer/passwordcontainer.cxx diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index b3998b6eb52d..36025ce5d2a3 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -904,6 +904,12 @@ </info> <value>false</value> </prop> + <prop oor:name="StorageVersion" oor:type="xs:int" oor:nillable="false"> + <info> + <desc>Specifies what version of encoding scheme the password container uses.</desc> + </info> + <value>0</value> + </prop> <prop oor:name="HasMaster" oor:type="xs:boolean" oor:nillable="false"> <info> <desc>Specifies if there is a valid master password.</desc> diff --git a/svl/source/inc/passwordcontainer.hxx b/svl/source/inc/passwordcontainer.hxx index 477e5f640428..cb1bbea545f5 100644 --- a/svl/source/inc/passwordcontainer.hxx +++ b/svl/source/inc/passwordcontainer.hxx @@ -169,6 +169,10 @@ public: typedef ::std::pair< const OUString, ::std::list< NamePassRecord > > PairUrlRecord; typedef ::std::map< OUString, ::std::list< 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; @@ -197,6 +201,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/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx index 7f17e57c640f..c993ef6f8b8a 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 <sal/config.h> +#include <sal/log.hxx> #include "passwordcontainer.hxx" @@ -263,6 +265,23 @@ bool StorageItem::useStorage() return aResult; } +sal_Int32 StorageItem::getStorageVersion() +{ + Sequence<OUString> 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 ) { @@ -295,15 +314,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 ); @@ -814,6 +835,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<char>(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 ) { @@ -852,6 +885,9 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac } else { + if (m_pStorageFile->getStorageVersion() == 0) + aPass = ReencodeAsOldHash(aPass); + vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass ) ); if( aRM.empty() || !aPass.equals( aRM[0] ) ) { @@ -1060,6 +1096,11 @@ 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.equals( m_aMasterPasswd ) ); aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification } while( !bResult && !aPass.isEmpty() ); diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx index 4cd4ad3fee0e..d074292473f0 100644 --- a/uui/source/iahndl-authentication.cxx +++ b/uui/source/iahndl-authentication.cxx @@ -452,8 +452,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()); } commit 13760bb673751fbd74e818b8ebb6b2f6a9c86921 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Feb 22 16:09:53 2022 +0000 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 keep paragraph's that failed to load until import is complete LIBREOFFICE-509JU93T Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130326 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit 32e8d3e45698a3cc09f66460b460db1d10ac50b5) Change-Id: I526edb182fed4fa023cce58e78a650a7c2046ed3 Conflicts: hwpfilter/source/hwpfile.cxx hwpfilter/source/hwpfile.h diff --git a/hwpfilter/source/hwpfile.cxx b/hwpfilter/source/hwpfile.cxx index 0aa1e9541af0..a414223885e3 100644 --- a/hwpfilter/source/hwpfile.cxx +++ b/hwpfilter/source/hwpfile.cxx @@ -71,6 +71,10 @@ HWPFile::~HWPFile() for (; it != plist.end(); ++it) delete *it; + std::list < HWPPara* >::iterator it2 = pfailedlist.begin(); + for (; it2 != plist.end(); ++it2) + delete *it2; + std::vector< Table* >::iterator tbl = tables.begin(); for (; tbl != tables.end(); ++tbl) delete *tbl; @@ -273,6 +277,7 @@ bool HWPFile::ReadParaList(std::list < HWPPara* > &aplist, unsigned char flag) aplist.push_back(spNode.release()); spNode.reset( new HWPPara ); } + pfailedlist.push_back(std::move(spNode)); return true; } diff --git a/hwpfilter/source/hwpfile.h b/hwpfilter/source/hwpfile.h index c98f90c82fe2..62a92bc9fca5 100644 --- a/hwpfilter/source/hwpfile.h +++ b/hwpfilter/source/hwpfile.h @@ -276,6 +276,10 @@ class DLLEXPORT HWPFile std::list<ColumnInfo*> columnlist; // paragraph linked list std::list<HWPPara*> plist; + // keep paragraph's that failed to load until + // import is complete to avoid dangling references + // elsewhere + std::list<HWPPara*> pfailedlist; // floating box linked list std::list<FBox*> blist; // embedded picture list(tag datas) commit fbc233d36eac3a59ea6ed326c1c7c7f7ab1e7da6 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Thu Feb 17 15:27:59 2022 +0100 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 fix range checking in calls like ScDocument::GetNote() Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130076 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> (cherry picked from commit 957d99a539df6e21fd40370938ca5dab1613cf8c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130105 Reviewed-by: Caolán McNamara <caol...@redhat.com> (cherry picked from commit 77bef67094579e7d0d2a515f5f8a5def8abe49e8) Change-Id: I5612e765b3484b0515f4a16030ee19133ae3126a diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index ef94249026b4..45e0757a10af 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -427,6 +427,8 @@ public: void GetLastDataPos(SCCOL& rCol, SCROW& rRow) const; ScPostIt* ReleaseNote( SCCOL nCol, SCROW nRow ); + ScPostIt* GetNote( SCCOL nCol, SCROW nRow ); + void SetNote( SCCOL nCol, SCROW nRow, ScPostIt* pNote ); size_t GetNoteCount( SCCOL nCol ) const; SCROW GetNotePosition( SCCOL nCol, size_t nIndex ) const; diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 24f8725b853e..53813bec0dc3 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6388,7 +6388,7 @@ ScPostIt* ScDocument::GetNote(const ScAddress& rPos) ScPostIt* ScDocument::GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab) { if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) - return maTabs[nTab]->aCol[nCol].GetCellNote(nRow); + return maTabs[nTab]->GetNote(nCol, nRow); else return nullptr; @@ -6401,7 +6401,8 @@ void ScDocument::SetNote(const ScAddress& rPos, ScPostIt* pNote) void ScDocument::SetNote(SCCOL nCol, SCROW nRow, SCTAB nTab, ScPostIt* pNote) { - return maTabs[nTab]->aCol[nCol].SetCellNote(nRow, pNote); + if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) + maTabs[nTab]->SetNote(nCol, nRow, std::move(pNote)); } bool ScDocument::HasNote(const ScAddress& rPos) const @@ -6431,6 +6432,9 @@ bool ScDocument::HasColNotes(SCCOL nCol, SCTAB nTab) const if (!pTab) return false; + if (nCol >= MAXCOLCOUNT) + return false; + return pTab->aCol[nCol].HasCellNotes(); } @@ -6474,6 +6478,7 @@ ScPostIt* ScDocument::GetOrCreateNote(const ScAddress& rPos) else return CreateNote(rPos); } + ScPostIt* ScDocument::CreateNote(const ScAddress& rPos) { ScPostIt* pPostIt = new ScPostIt(*this, rPos); diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 49f040d5e5de..b845cb02b431 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1567,6 +1567,21 @@ ScPostIt* ScTable::ReleaseNote( SCCOL nCol, SCROW nRow ) return aCol[nCol].ReleaseNote(nRow); } +ScPostIt* ScTable::GetNote( SCCOL nCol, SCROW nRow ) +{ + if (!ValidCol(nCol) || nCol >= MAXCOLCOUNT) + return nullptr; + return aCol[nCol].GetCellNote(nRow); +} + +void ScTable::SetNote( SCCOL nCol, SCROW nRow, ScPostIt* pNote ) +{ + if (!ValidColRow(nCol, nRow)) + return; + + CreateColumnIfNotExists(nCol).SetCellNote(nRow, std::move(pNote)); +} + size_t ScTable::GetNoteCount( SCCOL nCol ) const { if (!ValidCol(nCol)) commit 583ccac51274355a018f15c2196127111fd293f2 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Feb 16 11:14:48 2022 +0000 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Wed Sep 7 20:54:47 2022 +0200 clear ScDocumentImport position cache if iterators are invalid SheetDataBuffer::finalizeArrayFormula calls ScCellRangeObj::setArrayTokens ScDocFunc::EnterMatrix ScDocument::InsertMatrixFormula and InsertMatrixFormula calls the variant of ScColumn::SetFormulaCell which doesn't take a sc::ColumnBlockPosition& param when SetFormulaCell adds a cell to the column so any iterators belonging to ScDocumentImport are invalid. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130151 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> (cherry picked from commit fea55f5ef8dba16706033c9efdd33c45477eb333) Change-Id: Ic2814ecbeafdeb99632d2a255ed6c1dedf7376b1 Conflicts: sc/inc/documentimport.hxx sc/source/core/data/documentimport.cxx sc/source/filter/oox/sheetdatabuffer.cxx diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx index 96dbc12db20f..94a33f8434e9 100644 --- a/sc/inc/documentimport.hxx +++ b/sc/inc/documentimport.hxx @@ -110,6 +110,8 @@ public: void setRowsVisible(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, bool bVisible); + void invalidateBlockPositionSet(SCTAB nTab); + void finalize(); private: diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx index c0e4d3c9e60f..bc348243523a 100644 --- a/sc/source/core/data/documentimport.cxx +++ b/sc/source/core/data/documentimport.cxx @@ -94,6 +94,15 @@ struct ScDocumentImportImpl return rTab.getBlockPosition(nCol); } + void invalidateBlockPositionSet(SCTAB nTab) + { + if (sal_uInt16(nTab) >= maBlockPosSet.size()) + return; + + sc::TableColumnBlockPositionSet& rTab = maBlockPosSet[nTab]; + rTab.invalidate(); + } + void initForSheets() { size_t n = mrDoc.GetTableCount(); @@ -174,6 +183,11 @@ void ScDocumentImport::setOriginDate(sal_uInt16 nYear, sal_uInt16 nMonth, sal_uI mpImpl->mrDoc.pDocOptions->SetDate(nDay, nMonth, nYear); } +void ScDocumentImport::invalidateBlockPositionSet(SCTAB nTab) +{ + mpImpl->invalidateBlockPositionSet(nTab); +} + void ScDocumentImport::setAutoInput(const ScAddress& rPos, const OUString& rStr, ScSetStringParam* pStringParam) { ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab()); diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx index e5ee2cf637fc..0139a6027f3e 100644 --- a/sc/source/filter/oox/sheetdatabuffer.cxx +++ b/sc/source/filter/oox/sheetdatabuffer.cxx @@ -402,10 +402,23 @@ void SheetDataBuffer::addColXfStyle( sal_Int32 nXfId, sal_Int32 nFormatId, const void SheetDataBuffer::finalizeImport() { + ScDocumentImport& rDocImport = getDocImport(); + + SCTAB nStartTabInvalidatedIters(SCTAB_MAX); + SCTAB nEndTabInvalidatedIters(0); + // create all array formulas for( ArrayFormulaList::iterator aIt = maArrayFormulas.begin(), aEnd = maArrayFormulas.end(); aIt != aEnd; ++aIt ) + { finalizeArrayFormula( aIt->first, aIt->second ); + nStartTabInvalidatedIters = std::min(aIt->first.aStart.Tab(), nStartTabInvalidatedIters); + nEndTabInvalidatedIters = std::max(aIt->first.aEnd.Tab(), nEndTabInvalidatedIters); + } + + for (SCTAB nTab = nStartTabInvalidatedIters; nTab <= nEndTabInvalidatedIters; ++nTab) + rDocImport.invalidateBlockPositionSet(nTab); + // create all table operations for( TableOperationList::iterator aIt = maTableOperations.begin(), aEnd = maTableOperations.end(); aIt != aEnd; ++aIt ) finalizeTableOperation( aIt->first, aIt->second );