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