From f045768636399e028963a259dc074afcaa4bef2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Wed, 10 Jan 2018 14:27:35 +0000 Subject: [PATCH] limit WEBSERVICE to http[s] protocols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and like excel... 'For protocols that aren’t supported, such as ftp:// or file://, WEBSERVICE returns the #VALUE! error value.' Reviewed-on: https://gerrit.libreoffice.org/47776 Tested-by: Jenkins Reviewed-by: Markus Mohrhard Better handle ScDde formulas with missing dde-link entries typically each ScDde formula has a matching table:dde-link which results in a ScDdeLink getting inserted during the load. If that dde-link is missing then no ScDdeLink exists and ScDde() will create a new one without cached content. So detect that ScDde is used in the freshing loaded ods and defer fetching new content until the right time. only call GetHasMacroFunc to set SetHasMacroFunc and bHasMacroFunc is not accessed any other way, so this is an oxbow Reviewed-on: https://gerrit.libreoffice.org/47757 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara (cherry picked from commit b0597ba5d745974fce752e1b677451a19350d351) Reviewed-on: https://gerrit.libreoffice.org/47818 Reviewed-by: Eike Rathke handle ocWebservice similarly to ocDde might have too much in here seeing as we don't need to worry about ocWebservice calling into itself Reviewed-on: https://gerrit.libreoffice.org/47819 Tested-by: Jenkins Reviewed-by: Eike Rathke CheckLinkFormulaNeedingCheck() for .xls and .xlsx formula cells This is a combination of 3 commits. Move implementation to CheckLinkFormulaNeedingCheck() for further reuse (cherry picked from commit 55e484c7bcd3ef218e08d3fd93f97bf98fd8cb7f) CheckLinkFormulaNeedingCheck() for .xlsx cell formulas (cherry picked from commit f96dbc3dd9c33202f75e29ef49d962386595995d) CheckLinkFormulaNeedingCheck() for .xls cell formulas (cherry picked from commit 6bc48275558c3f76c4da25eb8af3c48583ac5599) a6dd195f7eb4d43483e87eeca59f651e7bf2dcb8 2587fbc4fec39b6f2c8e733331815a2953dee308 Reviewed-on: https://gerrit.libreoffice.org/48143 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara CheckLinkFormulaNeedingCheck() for conditional format expressions This is a combination of 4 commits. Prepare CheckLinkFormulaNeedingCheck() to use either RPN or tokenized code Conditional format formulas aren't finally compiled until needed so the check will have to operate on the tokenized expression instead of RPN code. (cherry picked from commit faa0305ba3d0dc698fce4915d4f3a1fb52422380) CheckLinkFormulaNeedingCheck() for .ods conditional format expressions (cherry picked from commit 2930ba2ac5d9423f2848b968edcd8ddc71966186) CheckLinkFormulaNeedingCheck() for .xlsx conditional format expressions (cherry picked from commit fef24d9f999ee54d7936900485d97ff26656f517) CheckLinkFormulaNeedingCheck() for .xls conditional format expressions (cherry picked from commit af2a2a0c72db312902e466c36697b5c198041e82) 45eb1ab5efa0ec9da2663f20427d2474ce300826 31ede1a23223a798141a0891deeabd8cf88fff58 afa112cc591b411d80ead48bf726788d361f6eb3 Reviewed-on: https://gerrit.libreoffice.org/48719 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara CheckLinkFormulaNeedingCheck() for named expressions This is a combination of 3 commits. CheckLinkFormulaNeedingCheck() for .ods named expressions This is specifically necessary for named expressions that are used in conditional format formulas, for which RPN is generated at a later stage, not during import. (cherry picked from commit eae9648e99be53ba441d9d8207aac6f3ce211ef2) CheckLinkFormulaNeedingCheck() for .xls named expressions (cherry picked from commit 8512f13c42ae3fbb287a555616fe10ff04295616) CheckLinkFormulaNeedingCheck() for .xlsx named expressions (cherry picked from commit a1f933ee2b9e23a505d937035821e9571cf4119c) Conflicts: sc/source/filter/oox/defnamesbuffer.cxx e03cb5767c34f8157a492a6d6c3b0700d065052d 217c89822ab477a6c383d170ae739e44efd10fa3 Change-Id: I0e9c6fd3426fad56a199eafac48de9b0f23914b3 016b53288076d83dd49e92e245346a5f7f560522 0145f38cc1c1f9ff514a496f7101d81cde9e7c67 541d2b6e12a88371c064b901b00e71206ee0c18e 68837e9bd33f125ab47b10b1a6fa18175abd1627 54ab8dc14f81d6b18b0d17f448187d19d8e396fc Reviewed-on: https://gerrit.libreoffice.org/48858 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara --- sc/Library_sc.mk | 1 + sc/inc/document.hxx | 8 ++- sc/inc/documentlinkmgr.hxx | 6 +- sc/source/core/data/conditio.cxx | 6 ++ sc/source/core/data/documen2.cxx | 2 +- sc/source/core/data/documen8.cxx | 23 +++++++ sc/source/core/data/formulacell.cxx | 7 +- sc/source/core/inc/webservicelink.hxx | 49 ++++++++++++++ sc/source/core/tool/interpr2.cxx | 8 ++- sc/source/core/tool/interpr7.cxx | 106 ++++++++++++++++++++++-------- sc/source/core/tool/rangenam.cxx | 8 ++- sc/source/core/tool/webservicelink.cxx | 106 ++++++++++++++++++++++++++++++ sc/source/filter/excel/excform.cxx | 1 + sc/source/filter/excel/excform8.cxx | 1 + sc/source/filter/excel/impop.cxx | 1 + sc/source/filter/excel/xicontent.cxx | 6 ++ sc/source/filter/excel/xiname.cxx | 3 + sc/source/filter/oox/condformatbuffer.cxx | 2 + sc/source/filter/oox/defnamesbuffer.cxx | 2 + sc/source/filter/oox/formulabuffer.cxx | 4 ++ sc/source/ui/docshell/docsh4.cxx | 4 +- sc/source/ui/docshell/documentlinkmgr.cxx | 20 ++++-- sc/source/ui/view/tabvwsh4.cxx | 2 +- 23 files changed, 327 insertions(+), 49 deletions(-) create mode 100644 sc/source/core/inc/webservicelink.hxx create mode 100644 sc/source/core/tool/webservicelink.cxx diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index d2fd5cd..02d3b7d 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -282,6 +282,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/tool/unitconv \ sc/source/core/tool/userlist \ sc/source/core/tool/viewopti \ + sc/source/core/tool/webservicelink \ sc/source/core/tool/zforauto \ sc/source/filter/xml/datastreamimport \ sc/source/filter/xml/XMLCalculationSettingsContext \ diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 69e6f5b..77ff388 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -429,7 +429,7 @@ private: bool bDetectiveDirty; sal_uInt8 nMacroCallMode; // Macros per warning dialog disabled? - bool bHasMacroFunc; // valid only after loading + bool bLinkFormulaNeedingCheck; // valid only after loading, for ocDde and ocWebservice sal_uInt8 nVisSpellState; @@ -1793,8 +1793,10 @@ public: sal_uInt8 GetMacroCallMode() const { return nMacroCallMode; } void SetMacroCallMode(sal_uInt8 nNew) { nMacroCallMode = nNew; } - bool GetHasMacroFunc() const { return bHasMacroFunc; } - void SetHasMacroFunc(bool bSet) { bHasMacroFunc = bSet; } + bool HasLinkFormulaNeedingCheck() const { return bLinkFormulaNeedingCheck; } + void SetLinkFormulaNeedingCheck(bool bSet) { bLinkFormulaNeedingCheck = bSet; } + /** Check token array and set link check if ocDde/ocWebservice is contained. */ + SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck( const ScTokenArray& rCode ); static bool CheckMacroWarn(); diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx index cc42410..d7972b1 100644 --- a/sc/inc/documentlinkmgr.hxx +++ b/sc/inc/documentlinkmgr.hxx @@ -53,9 +53,9 @@ public: bool idleCheckLinks(); bool hasDdeLinks() const; - bool hasDdeOrOleLinks() const; + bool hasDdeOrOleOrWebServiceLinks() const; - bool updateDdeOrOleLinks(vcl::Window* pWin); + bool updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin); bool updateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem ); @@ -63,7 +63,7 @@ public: void disconnectDdeLinks(); private: - bool hasDdeOrOleLinks(bool bDde, bool bOle) const; + bool hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const; }; } diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index f087af6..8627367 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -471,6 +471,12 @@ void ScConditionEntry::CompileXML() Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1), GetExpression(aSrcPos, 1, 0, eTempGrammar2), aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, true ); + + // Importing ocDde/ocWebservice? + if (pFormula1) + mpDoc->CheckLinkFormulaNeedingCheck(*pFormula1); + if (pFormula2) + mpDoc->CheckLinkFormulaNeedingCheck(*pFormula2); } void ScConditionEntry::SetSrcString( const OUString& rNew ) diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 8d3e4e3..0d494c4 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -202,7 +202,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : bExpandRefs( false ), bDetectiveDirty( false ), nMacroCallMode( SC_MACROCALL_ALLOWED ), - bHasMacroFunc( false ), + bLinkFormulaNeedingCheck( false ), nVisSpellState( 0 ), nAsianCompression(SC_ASIANCOMPRESSION_INVALID), nAsianKerning(SC_ASIANKERNING_INVALID), diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 2bdfa30..7391e1c 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -88,6 +88,7 @@ #include "stringutil.hxx" #include #include +#include #include @@ -1158,6 +1159,28 @@ void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode, } } +void ScDocument::CheckLinkFormulaNeedingCheck( const ScTokenArray& rCode ) +{ + if (HasLinkFormulaNeedingCheck()) + return; + + // Prefer RPN over tokenized formula if available. + if (rCode.GetCodeLen()) + { + if (rCode.HasOpCodeRPN(ocDde) || rCode.HasOpCodeRPN(ocWebservice)) + SetLinkFormulaNeedingCheck(true); + } + else if (rCode.GetLen()) + { + if (rCode.HasOpCode(ocDde) || rCode.HasOpCode(ocWebservice)) + SetLinkFormulaNeedingCheck(true); + } + else + { + assert(!"called with empty ScTokenArray"); + } +} + // TimerDelays etc. void ScDocument::KeyInput( const KeyEvent& ) { diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index ceb7f68..49d3133 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1351,10 +1351,9 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr bChanged = true; } - // Same as in Load: after loading, it must be known if ocMacro is in any formula - // (for macro warning, CompileXML is called at the end of loading XML file) - if ( !pDocument->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) ) - pDocument->SetHasMacroFunc( true ); + // After loading, it must be known if ocDde/ocWebservice is in any formula + // (for external links warning, CompileXML is called at the end of loading XML file) + pDocument->CheckLinkFormulaNeedingCheck(*pCode); //volatile cells must be added here for import if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() || diff --git a/sc/source/core/inc/webservicelink.hxx b/sc/source/core/inc/webservicelink.hxx new file mode 100644 index 0000000..e61ebfd --- /dev/null +++ b/sc/source/core/inc/webservicelink.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#ifndef INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX +#define INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX + +#include +#include +#include +#include + +class ScDocument; + +class ScWebServiceLink : public ::sfx2::SvBaseLink, public SvtBroadcaster +{ +private: + ScDocument* pDoc; + OUString aURL; // connection/ link data + bool bHasResult; // is set aResult is useful + OUString aResult; + +public: + ScWebServiceLink(ScDocument* pD, const OUString& rURL); + virtual ~ScWebServiceLink() override; + + // SvBaseLink override: + virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(const OUString& rMimeType, + const css::uno::Any& rValue) override; + + // SvtBroadcaster override: + virtual void ListenersGone() override; + + // for interpreter: + + const OUString& GetResult() const { return aResult; } + bool HasResult() const { return bHasResult; } + + const OUString& GetURL() const { return aURL; } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index d82bc29..5f6b5af 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -2421,8 +2421,14 @@ void ScInterpreter::ScDde() pBindings->Invalidate( SID_LINKS ); // Link-Manager enablen } + //if the document was just loaded, but the ScDdeLink entry was missing, then + //don't update this link until the links are updated in response to the users + //decision + if (!pDok->HasLinkFormulaNeedingCheck()) + { //TODO: evaluate asynchron ??? - pLink->TryUpdate(); // TryUpdate doesn't call Update multiple times + pLink->TryUpdate(); // TryUpdate doesn't call Update multiple times + } if (pMyFormulaCell) { diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx index ce69848..53524a1 100644 --- a/sc/source/core/tool/interpr7.cxx +++ b/sc/source/core/tool/interpr7.cxx @@ -10,7 +10,10 @@ #include "interpre.hxx" #include #include +#include +#include #include +#include #include #include @@ -20,6 +23,11 @@ #include #include #include +#include "formulacell.hxx" +#include +#include + +#include #include #include @@ -145,6 +153,22 @@ void ScInterpreter::ScFilterXML() } } +static ScWebServiceLink* lcl_GetWebServiceLink(const sfx2::LinkManager* pLinkMgr, const OUString& rURL) +{ + size_t nCount = pLinkMgr->GetLinks().size(); + for (size_t i=0; iGetLinks()[i]; + if (ScWebServiceLink* pLink = dynamic_cast(pBase)) + { + if (pLink->GetURL() == rURL) + return pLink; + } + } + + return nullptr; +} + void ScInterpreter::ScWebservice() { sal_uInt8 nParamCount = GetByte(); @@ -152,54 +176,78 @@ void ScInterpreter::ScWebservice() { OUString aURI = GetString().getString(); - if(aURI.isEmpty()) + if (aURI.isEmpty()) { PushError( errNoValue ); return; } - uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY ); - if(!xFileAccess.is()) + INetURLObject aObj(aURI, INetProtocol::File); + INetProtocol eProtocol = aObj.GetProtocol(); + if (eProtocol != INetProtocol::Http && eProtocol != INetProtocol::Https) { - PushError( errNoValue ); + PushError(errNoValue); return; } - uno::Reference< io::XInputStream > xStream; - try { - xStream = xFileAccess->openFileRead( aURI ); - } - catch (...) + sfx2::LinkManager* pLinkMgr = pDok->GetLinkManager(); + if (!pLinkMgr) { - // don't let any exceptions pass - PushError( errNoValue ); - return; - } - if ( !xStream.is() ) - { - PushError( errNoValue ); + PushError(errNoValue); return; } - const sal_Int32 BUF_LEN = 8000; - uno::Sequence< sal_Int8 > buffer( BUF_LEN ); - OStringBuffer aBuffer( 64000 ); + // Need to reinterpret after loading (build links) + if (rArr.IsRecalcModeNormal()) + rArr.SetExclusiveRecalcModeOnLoad(); - sal_Int32 nRead = 0; - while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN ) - { - aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); - } + // while the link is not evaluated, idle must be disabled (to avoid circular references) + bool bOldEnabled = pDok->IsIdleEnabled(); + pDok->EnableIdle(false); + + // Get/ Create link object + ScWebServiceLink* pLink = lcl_GetWebServiceLink(pLinkMgr, aURI); - if ( nRead > 0 ) + bool bWasError = (pMyFormulaCell && pMyFormulaCell->GetRawError() != 0); + + if (!pLink) { - aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); + pLink = new ScWebServiceLink(pDok, aURI); + pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, aURI); + if ( pLinkMgr->GetLinks().size() == 1 ) // the first one? + { + SfxBindings* pBindings = pDok->GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_LINKS ); // Link-Manager enabled + } + + //if the document was just loaded, but the ScDdeLink entry was missing, then + //don't update this link until the links are updated in response to the users + //decision + if (!pDok->HasLinkFormulaNeedingCheck()) + { + pLink->Update(); + } + + if (pMyFormulaCell) + { + // StartListening after the Update to avoid circular references + pMyFormulaCell->StartListening(*pLink); + } } - xStream->closeInput(); + // If an new Error from Reschedule appears when the link is executed then reset the errorflag + if (pMyFormulaCell && pMyFormulaCell->GetRawError() != 0 && !bWasError) + pMyFormulaCell->SetErrCode(0); + + // check the value + if (pLink->HasResult()) + PushString(pLink->GetResult()); + else + PushError(errNoValue); - OUString aContent = OStringToOUString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ); - PushString( aContent ); + pDok->EnableIdle(bOldEnabled); + pLinkMgr->CloseCachedComps(); } } diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 4235ef7..f1f8b9d 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -63,9 +63,14 @@ ScRangeData::ScRangeData( ScDocument* pDok, mnMaxCol (-1) { if (!rSymbol.isEmpty()) - CompileRangeData( rSymbol, pDoc->IsImportingXML()); + { // Let the compiler set an error on unknown names for a subsequent // CompileUnresolvedXML(). + const bool bImporting = pDoc->IsImportingXML(); + CompileRangeData( rSymbol, bImporting); + if (bImporting) + pDoc->CheckLinkFormulaNeedingCheck( *pCode); + } else { // #i63513#/#i65690# don't leave pCode as NULL. @@ -198,6 +203,7 @@ void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ) // Don't let the compiler set an error for unknown names on final // compile, errors are handled by the interpreter thereafter. CompileRangeData( aSymbol, false); + rCxt.getDoc()->CheckLinkFormulaNeedingCheck( *pCode); } } diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx new file mode 100644 index 0000000..82310f2 --- /dev/null +++ b/sc/source/core/tool/webservicelink.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ScWebServiceLink::ScWebServiceLink(ScDocument* pD, const OUString& rURL) + : ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS, SotClipboardFormatId::STRING) + , pDoc(pD) + , aURL(rURL) + , bHasResult(false) +{ +} + +ScWebServiceLink::~ScWebServiceLink() {} + +sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&) +{ + aResult.clear(); + bHasResult = false; + + css::uno::Reference xFileAccess( + css::ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext()), + css::uno::UNO_QUERY); + if (!xFileAccess.is()) + return ERROR_GENERAL; + + css::uno::Reference xStream; + try + { + xStream = xFileAccess->openFileRead(aURL); + } + catch (...) + { + // don't let any exceptions pass + return ERROR_GENERAL; + } + if (!xStream.is()) + return ERROR_GENERAL; + + const sal_Int32 BUF_LEN = 8000; + css::uno::Sequence buffer(BUF_LEN); + OStringBuffer aBuffer(64000); + + sal_Int32 nRead = 0; + while ((nRead = xStream->readBytes(buffer, BUF_LEN)) == BUF_LEN) + aBuffer.append(reinterpret_cast(buffer.getConstArray()), nRead); + + if (nRead > 0) + aBuffer.append(reinterpret_cast(buffer.getConstArray()), nRead); + + xStream->closeInput(); + + aResult = OStringToOUString(aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + bHasResult = true; + + // Something happened... + if (HasListeners()) + { + Broadcast(ScHint(SC_HINT_DATACHANGED, ScAddress())); + pDoc->TrackFormulas(); // must happen immediately + pDoc->StartTrackTimer(); + } + + return SUCCESS; +} + +void ScWebServiceLink::ListenersGone() +{ + ScDocument* pStackDoc = pDoc; // member pDoc can't be used after removing the link + + sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager(); + pLinkMgr->Remove(this); // deletes this + + if (pLinkMgr->GetLinks().empty()) // deleted the last one ? + { + SfxBindings* pBindings = pStackDoc->GetViewBindings(); // don't use member pDoc! + if (pBindings) + pBindings->Invalidate(SID_LINKS); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx index 0839955..14be167 100644 --- a/sc/source/filter/excel/excform.cxx +++ b/sc/source/filter/excel/excform.cxx @@ -157,6 +157,7 @@ void ImportExcel::Formula( { pCell = new ScFormulaCell(&rDoc.getDoc(), aScPos, *pResult); pCell->GetCode()->WrapReference(aScPos, EXC_MAXCOL8, EXC_MAXROW8); + rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode()); rDoc.getDoc().EnsureTable(aScPos.Tab()); rDoc.setFormulaCell(aScPos, pCell); SetLastFormula(aScPos.Col(), aScPos.Row(), fCurVal, nXF, pCell); diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx index ebe3b64..c7e56af 100644 --- a/sc/source/filter/excel/excform8.cxx +++ b/sc/source/filter/excel/excform8.cxx @@ -729,6 +729,7 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn, << nMerk0 << ocClose; aPool >> aStack; pExtName->CreateDdeData( GetDoc(), aApplic, aTopic ); + GetDoc().SetLinkFormulaNeedingCheck(true); } } break; diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx index 904209d..69e536e 100644 --- a/sc/source/filter/excel/impop.cxx +++ b/sc/source/filter/excel/impop.cxx @@ -866,6 +866,7 @@ void ImportExcel::Shrfmla() ScFormulaCell* pCell = new ScFormulaCell(pD, aPos, *pErgebnis); pCell->GetCode()->WrapReference(aPos, EXC_MAXCOL8, EXC_MAXROW8); + rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode()); rDoc.getDoc().EnsureTable(aPos.Tab()); rDoc.setFormulaCell(aPos, pCell); pCell->SetNeedNumberFormat(false); diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index 9613019..589ce4b 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -641,7 +641,10 @@ void XclImpCondFormat::ReadCF( XclImpStream& rStrm ) rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize1, false, FT_CondFormat ); // formula converter owns pTokArr -> create a copy of the token array if( pTokArr ) + { xTokArr1.reset( pTokArr->Clone() ); + GetDocPtr()->CheckLinkFormulaNeedingCheck( *xTokArr1); + } } ::std::unique_ptr< ScTokenArray > pTokArr2; @@ -652,7 +655,10 @@ void XclImpCondFormat::ReadCF( XclImpStream& rStrm ) rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize2, false, FT_CondFormat ); // formula converter owns pTokArr -> create a copy of the token array if( pTokArr ) + { pTokArr2.reset( pTokArr->Clone() ); + GetDocPtr()->CheckLinkFormulaNeedingCheck( *pTokArr2); + } } // *** create the Calc conditional formatting *** diff --git a/sc/source/filter/excel/xiname.cxx b/sc/source/filter/excel/xiname.cxx index c1bee5a..344ecb6 100644 --- a/sc/source/filter/excel/xiname.cxx +++ b/sc/source/filter/excel/xiname.cxx @@ -264,7 +264,10 @@ void XclImpName::InsertName(const ScTokenArray* pArray) } } if (pData) + { + GetDoc().CheckLinkFormulaNeedingCheck( *pData->GetCode()); mpScData = pData; // cache for later use + } } XclImpNameManager::XclImpNameManager( const XclImpRoot& rRoot ) : diff --git a/sc/source/filter/oox/condformatbuffer.cxx b/sc/source/filter/oox/condformatbuffer.cxx index 955b304..9ffcf51 100644 --- a/sc/source/filter/oox/condformatbuffer.cxx +++ b/sc/source/filter/oox/condformatbuffer.cxx @@ -882,11 +882,13 @@ void CondFormatRule::finalizeImport() { pTokenArray2.reset(new ScTokenArray()); ScTokenConversion::ConvertToTokenArray( rDoc, *pTokenArray2.get(), maModel.maFormulas[ 1 ] ); + rDoc.CheckLinkFormulaNeedingCheck( *pTokenArray2.get()); } ScTokenArray aTokenArray; OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId ); ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, maModel.maFormulas[ 0 ] ); + rDoc.CheckLinkFormulaNeedingCheck( aTokenArray); ScCondFormatEntry* pNewEntry = new ScCondFormatEntry(eOperator, &aTokenArray, pTokenArray2.get(), &rDoc, aPos, aStyleName); mpFormat->AddEntry(pNewEntry); diff --git a/sc/source/filter/oox/defnamesbuffer.cxx b/sc/source/filter/oox/defnamesbuffer.cxx index fa2a0cf..c4cb011 100644 --- a/sc/source/filter/oox/defnamesbuffer.cxx +++ b/sc/source/filter/oox/defnamesbuffer.cxx @@ -38,6 +38,7 @@ #include "tokenarray.hxx" #include "tokenuno.hxx" #include "compiler.hxx" +#include "document.hxx" namespace oox { namespace xls { @@ -392,6 +393,7 @@ std::unique_ptr DefinedName::getScTokens() // after, a resulting error must be reset. sal_uInt16 nErr = pArray->GetCodeError(); aCompiler.CompileTokenArray(); + getScDocument().CheckLinkFormulaNeedingCheck( *pArray); pArray->DelRPN(); pArray->SetCodeError(nErr); diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index 189017d..2d20e9d 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -229,6 +229,10 @@ void applyCellFormulas( continue; aCompiler.CompileTokenArray(); // Generate RPN tokens. + + // Check if ocDde/ocWebservice is in any formula for external links warning. + rDoc.getDoc().CheckLinkFormulaNeedingCheck(*pCode); + ScFormulaCell* pCell = new ScFormulaCell(&rDoc.getDoc(), aPos, pCode); rDoc.setFormulaCell(aPos, pCell); rCache.store(aPos, pCell); diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index 9fcf549..2645c7f 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -455,7 +455,7 @@ void ScDocShell::Execute( SfxRequest& rReq ) ReloadTabLinks(); aDocument.UpdateExternalRefLinks(GetActiveDialogParent()); - bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleLinks(GetActiveDialogParent()); + bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(GetActiveDialogParent()); if (bAnyDde) { @@ -477,6 +477,8 @@ void ScDocShell::Execute( SfxRequest& rReq ) rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); rReq.Ignore(); } + + rDoc.SetLinkFormulaNeedingCheck(false); } break; diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx index 8e5a5c3..ae8984b 100644 --- a/sc/source/ui/docshell/documentlinkmgr.cxx +++ b/sc/source/ui/docshell/documentlinkmgr.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -115,15 +116,15 @@ bool DocumentLinkManager::idleCheckLinks() bool DocumentLinkManager::hasDdeLinks() const { - return hasDdeOrOleLinks(true, false); + return hasDdeOrOleOrWebServiceLinks(true, false, false); } -bool DocumentLinkManager::hasDdeOrOleLinks() const +bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks() const { - return hasDdeOrOleLinks(true, true); + return hasDdeOrOleOrWebServiceLinks(true, true, true); } -bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const +bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const { if (!mpImpl->mpLinkManager) return false; @@ -136,12 +137,14 @@ bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const return true; if (bOle && dynamic_cast(pBase)) return true; + if (bWebService && dynamic_cast(pBase)) + return true; } return false; } -bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin ) +bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin) { if (!mpImpl->mpLinkManager) return false; @@ -163,6 +166,13 @@ bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin ) continue; } + ScWebServiceLink* pWebserviceLink = dynamic_cast(pBase); + if (pWebserviceLink) + { + pWebserviceLink->Update(); + continue; + } + ScDdeLink* pDdeLink = dynamic_cast(pBase); if (!pDdeLink) continue; diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index ff3a5a1..c7209c1 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -1584,7 +1584,7 @@ void ScTabViewShell::Construct( TriState nForceDesignMode ) if (!bLink) { const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager(); - if (rMgr.hasDdeOrOleLinks() || rDoc.HasAreaLinks()) + if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasDdeOrOleOrWebServiceLinks()) bLink = true; } if (bLink) -- 2.14.3