[2/3] CVE-2023-2255 put floating frames under managed links control
authorCaolán McNamara <caolanm@redhat.com>
Thu, 13 Apr 2023 10:31:17 +0000 (11:31 +0100)
committerBastien Roucariès <rouca@debian.org>
Sat, 12 Aug 2023 19:58:29 +0000 (20:58 +0100)
From 59beb215c3debbdbff0357092b7e7961d69a7298 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Thu, 13 Apr 2023 11:31:17 +0100
Subject: [PATCH 2/3] put floating frames under managed links control
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

like we do for sections and ole objects that link to their content

individual commits in trunk are:

extract a OCommonEmbeddedObject::SetInplaceActiveState for reuse

no behaviour change intended

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150341
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 183e34a3f8c429c0698951e24c17844e416a3825)

use parent window as dialog parent

it makes no odds, but is more convenient for upcoming modification

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150342
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit f93edf343658abd489bde3639d2ffaefd50c0f99)

adjust IFrameObject so it could reuse mxFrame for a reload of content

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150343
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 3a727d26fd9eb6fa140bc3f5cadf3db079d42206)

query getUserAllowsLinkUpdate for the case of content in a floating frame

similarly to how it works for the more common "normal" embedded objects

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149971
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 52aa46468531918eabfa2031dedf50377ae72cf7)

add a route to get writer Floating Frame links under 'manage links'

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150349
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 8b8a2844addbd262befb1a2d193dfb590dfa20be)

allow SvxOle2Shape::resetModifiedState to survive having no SdrObject

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150538
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 02379929bd0e1d1676635f0ca1920422702ebb7c)

create the FloatingFrameShape in a separate step to inserting it

this is derived from the path taken by the AddShape(const OUString&)
function for this case. No change in behavior is intended.

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150526
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit bafec47847a0b9697b3bbe9358e53f8118af3024)

add a route to get calc Floating Frame links under 'manage links'

much harder than writer because the organization and ordering
of properties and object activation etc is different.

This ended up ugly, but functions.

We set FrameURL before AddShape, we have to do it again later because it
gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
FrameURL to exist when AddShape triggers SetPersistName which itself
triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
know what URL will end up being used. So bodge this by setting FrameURL
to the temp pre-SdrOle2Obj attached properties and we can smuggle it
eventually into SdrOle2Obj::SetPersistName at the right point after
PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
in order to inform the link manager that this is an IFrame that links to
a URL

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150539
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 07179a5a5bd00f34acfa8a3f260dd834ae003c63)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150755
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
bc5333b137d2da089b3b701ff615c6ddf43063d0
7eec3132a23faafd9a2878215a0a117a67bc9bf2
83e38dfa2f84907c2de9680e91f779d34864a9ad
f90ff71d6a96342574799312f764badaf97980eb
ea059262c124e3f44249e49b4189732310d28156
d09ae0c65a55a37743ad7c184070fb8dd97d8a7f
67fc199fef9e67fa12ca7873f0fe12137aa16d8f

Change-Id: Ia1d12aa5c9afdc1347f6d4364bc6a0b7f41ee168
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152132
Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
bug: https://www.libreoffice.org/about-us/security/advisories/cve-2023-2255/
bug-debian-security: https://security-tracker.debian.org/tracker/CVE-2023-2255

Gbp-Pq: Name 0079-2-3-CVE-2023-2255-put-floating-frames-under-managed-.patch

15 files changed:
embeddedobj/source/commonembedding/embedobj.cxx
embeddedobj/source/commonembedding/specialobject.cxx
embeddedobj/source/inc/commonembobj.hxx
embeddedobj/source/inc/specialobject.hxx
include/svx/svdoole2.hxx
include/svx/unoshape.hxx
sc/source/ui/docshell/documentlinkmgr.cxx
sfx2/source/doc/iframe.cxx
svx/source/svdraw/svdoole2.cxx
svx/source/unodraw/shapeimpl.hxx
svx/source/unodraw/unoshap4.cxx
sw/inc/ndole.hxx
sw/source/core/ole/ndole.cxx
xmloff/source/draw/ximpshap.cxx
xmloff/source/draw/ximpshap.hxx

index 5eb943273fdf99f4d56c1df40e2fefbf93f52a9c..f8c909cb3bc1e06075f6c24968986d280836f9dc 100644 (file)
@@ -152,6 +152,37 @@ void OCommonEmbeddedObject::StateChangeNotification_Impl( bool bBeforeChange, sa
     }
 }
 
+void OCommonEmbeddedObject::SetInplaceActiveState()
+{
+    if ( !m_xClientSite.is() )
+        throw embed::WrongStateException( "client site not set, yet", *this );
+
+    uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY );
+    if ( !xInplaceClient.is() || !xInplaceClient->canInplaceActivate() )
+        throw embed::WrongStateException(); //TODO: can't activate inplace
+    xInplaceClient->activatingInplace();
+
+    uno::Reference< embed::XWindowSupplier > xClientWindowSupplier( xInplaceClient, uno::UNO_QUERY_THROW );
+
+    m_xClientWindow = xClientWindowSupplier->getWindow();
+    m_aOwnRectangle = xInplaceClient->getPlacement();
+    m_aClipRectangle = xInplaceClient->getClipRectangle();
+    awt::Rectangle aRectangleToShow = GetRectangleInterception( m_aOwnRectangle, m_aClipRectangle );
+
+    // create own window based on the client window
+    // place and resize the window according to the rectangles
+    uno::Reference< awt::XWindowPeer > xClientWindowPeer( m_xClientWindow, uno::UNO_QUERY_THROW );
+
+    // dispatch provider may not be provided
+    uno::Reference< frame::XDispatchProvider > xContainerDP = xInplaceClient->getInplaceDispatchProvider();
+    bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, aRectangleToShow, xContainerDP );
+    m_nObjectState = embed::EmbedStates::INPLACE_ACTIVE;
+    if ( !bOk )
+    {
+        SwitchStateTo_Impl( embed::EmbedStates::RUNNING );
+        throw embed::WrongStateException(); //TODO: can't activate inplace
+    }
+}
 
 void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 nNextState )
 {
@@ -226,34 +257,7 @@ void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 nNextState )
         {
             if ( nNextState == embed::EmbedStates::INPLACE_ACTIVE )
             {
-                if ( !m_xClientSite.is() )
-                    throw embed::WrongStateException( "client site not set, yet", *this );
-
-                uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY );
-                if ( !xInplaceClient.is() || !xInplaceClient->canInplaceActivate() )
-                    throw embed::WrongStateException(); //TODO: can't activate inplace
-                xInplaceClient->activatingInplace();
-
-                uno::Reference< embed::XWindowSupplier > xClientWindowSupplier( xInplaceClient, uno::UNO_QUERY_THROW );
-
-                m_xClientWindow = xClientWindowSupplier->getWindow();
-                m_aOwnRectangle = xInplaceClient->getPlacement();
-                m_aClipRectangle = xInplaceClient->getClipRectangle();
-                awt::Rectangle aRectangleToShow = GetRectangleInterception( m_aOwnRectangle, m_aClipRectangle );
-
-                // create own window based on the client window
-                // place and resize the window according to the rectangles
-                uno::Reference< awt::XWindowPeer > xClientWindowPeer( m_xClientWindow, uno::UNO_QUERY_THROW );
-
-                // dispatch provider may not be provided
-                uno::Reference< frame::XDispatchProvider > xContainerDP = xInplaceClient->getInplaceDispatchProvider();
-                bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, aRectangleToShow, xContainerDP );
-                m_nObjectState = nNextState;
-                if ( !bOk )
-                {
-                    SwitchStateTo_Impl( embed::EmbedStates::RUNNING );
-                    throw embed::WrongStateException(); //TODO: can't activate inplace
-                }
+                SetInplaceActiveState();
             }
             else if ( nNextState == embed::EmbedStates::ACTIVE )
             {
index 09512a28ccfb4a6e16be7e44f3121979d8c37d81..f38472dc594c7d65f0e8e956e8921cd93901c3b0 100644 (file)
@@ -58,6 +58,7 @@ uno::Any SAL_CALL OSpecialEmbeddedObject::queryInterface( const uno::Type& rType
     aReturn = ::cppu::queryInterface( rType,
                                         static_cast< embed::XEmbeddedObject* >( this ),
                                         static_cast< embed::XInplaceObject* >( this ),
+                                        static_cast< embed::XCommonEmbedPersist* >( static_cast< embed::XEmbedPersist* >( this ) ),
                                         static_cast< embed::XVisualObject* >( this ),
                                         static_cast< embed::XClassifiedObject* >( this ),
                                         static_cast< embed::XComponentSupplier* >( this ),
@@ -171,4 +172,12 @@ void SAL_CALL OSpecialEmbeddedObject::doVerb( sal_Int32 nVerbID )
         OCommonEmbeddedObject::doVerb( nVerbID );
 }
 
+void SAL_CALL OSpecialEmbeddedObject::reload(
+                const uno::Sequence< beans::PropertyValue >&,
+                const uno::Sequence< beans::PropertyValue >&)
+{
+    // Allow IFrames to reload their content
+    SetInplaceActiveState();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
index 0ae22154959ed80aca1c92d6141a4ec22930a80b..ec3707469b71a87f8e3aa2f58d25ca9df290d528 100644 (file)
@@ -227,6 +227,9 @@ private:
                     const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
                     const css::uno::Sequence< css::beans::PropertyValue >& lObjArgs );
 
+protected:
+    void SetInplaceActiveState();
+
 public:
     OCommonEmbeddedObject(
         const css::uno::Reference< css::uno::XComponentContext >& rxContext,
index 32ad61a7a58280e17a77d0d4936fea76b901567f..ce5c01b35ae7fb22cc6fb67c6c94d4451d602157 100644 (file)
@@ -48,6 +48,12 @@ public:
     virtual void SAL_CALL changeState( sal_Int32 nNewState ) override;
 
     virtual void SAL_CALL doVerb( sal_Int32 nVerbID ) override;
+
+// XCommonEmbedPersist
+
+    virtual void SAL_CALL reload(
+                const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+                const css::uno::Sequence< css::beans::PropertyValue >& lObjArgs ) override;
 };
 
 #endif
index c7a108c963df4d2e37a1dd467d623e8d5fff27bf..292f6623a907f0b4cecd5e287362d497c04671cb 100644 (file)
@@ -42,6 +42,7 @@ namespace frame { class XModel; }
 namespace svt { class EmbeddedObjectRef; }
 
 class SdrOle2ObjImpl;
+class SvxOle2Shape;
 
 class SVX_DLLPUBLIC SdrOle2Obj : public SdrRectObj
 {
@@ -49,7 +50,7 @@ private:
     std::unique_ptr<SdrOle2ObjImpl> mpImpl;
 
 private:
-    SVX_DLLPRIVATE void Connect_Impl();
+    SVX_DLLPRIVATE void Connect_Impl(SvxOle2Shape* pCreator = nullptr);
     SVX_DLLPRIVATE void Disconnect_Impl();
     SVX_DLLPRIVATE void AddListeners_Impl();
     SVX_DLLPRIVATE void RemoveListeners_Impl();
@@ -105,7 +106,7 @@ public:
     // OLE object has got a separate PersistName member now;
     // !!! use ::SetPersistName( ... ) only, if you know what you do !!!
     const OUString& GetPersistName() const;
-    void        SetPersistName( const OUString& rPersistName );
+    void        SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator = nullptr );
 
     // One can add an application name to a SdrOle2Obj, which can be queried for
     // later on (SD needs this for presentation objects).
@@ -153,7 +154,7 @@ public:
                                          sal_Int64 nAspect );
     static bool Unload( const css::uno::Reference< css::embed::XEmbeddedObject >& xObj, sal_Int64 nAspect );
     bool Unload();
-    void Connect();
+    void Connect(SvxOle2Shape* pCreator = nullptr);
     void Disconnect();
     void ObjectLoaded();
 
@@ -201,6 +202,16 @@ public:
     void                Connect() { GetRealObject(); }
 };
 
+class SVX_DLLPUBLIC SdrIFrameLink final : public sfx2::SvBaseLink
+{
+    SdrOle2Obj* m_pObject;
+
+public:
+    explicit SdrIFrameLink(SdrOle2Obj* pObject);
+    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
+        const OUString& rMimeType, const css::uno::Any & rValue ) override;
+};
+
 #endif // INCLUDED_SVX_SVDOOLE2_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
index d015d8f39820f65411af12ad108acd60a2cf5fd5..ca471182ec596c00f790ceb0ead58cae347d21ea 100644 (file)
@@ -607,6 +607,8 @@ public:
     bool createObject( const SvGlobalName &aClassName );
 
     void createLink( const OUString& aLinkURL );
+
+    virtual OUString GetAndClearInitialFrameURL();
 };
 
 
index b1b66a9a8a8d134ba0421407d63e209e9ad87d59..adbec888754708d154c35293ab76e1cd38a144a7 100644 (file)
@@ -142,7 +142,7 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, boo
         sfx2::SvBaseLink* pBase = rLink.get();
         if (bDde && dynamic_cast<ScDdeLink*>(pBase))
             return true;
-        if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase))
+        if (bOle && (dynamic_cast<SdrEmbedObjectLink*>(pBase) || dynamic_cast<SdrIFrameLink*>(pBase)))
             return true;
         if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase))
             return true;
@@ -173,6 +173,13 @@ bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(weld::Window* pWin)
             continue;
         }
 
+        SdrIFrameLink* pIFrameLink = dynamic_cast<SdrIFrameLink*>(pBase);
+        if (pIFrameLink)
+        {
+            pIFrameLink->Update();
+            continue;
+        }
+
         ScWebServiceLink* pWebserviceLink = dynamic_cast<ScWebServiceLink*>(pBase);
         if (pWebserviceLink)
         {
index dc0c023d87e96c576ba9358f7cca457abc194cfd..8fa65269dfd234606d3f4edab605c524c39aade2 100644 (file)
@@ -176,31 +176,46 @@ sal_Bool SAL_CALL IFrameObject::load(
                 return false;
         }
 
+        bool bUpdateAllowed(true);
+        if (pDoc)
+        {
+            // perhaps should only check for file targets, but lets default to making it strong
+            // unless there is a known need to distinguish
+            comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pDoc->getEmbeddedObjectContainer();
+            bUpdateAllowed = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
+        }
+        if (!bUpdateAllowed)
+            return false;
+
         OUString sReferer;
         if (pDoc && pDoc->HasName())
             sReferer = pDoc->GetMedium()->GetName();
 
-        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() );
-        pWin->SetSizePixel( pParent->GetOutputSizePixel() );
-        pWin->SetBackground();
-        pWin->Show();
-
-        uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY );
-        xFrame->setComponent( xWindow, uno::Reference < frame::XController >() );
+        uno::Reference<css::awt::XWindow> xParentWindow(xFrame->getContainerWindow());
 
-        // we must destroy the IFrame before the parent is destroyed
-        xWindow->addEventListener( this );
-
-        mxFrame = frame::Frame::create( mxContext );
-        uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY );
-        mxFrame->initialize( xWin );
-        mxFrame->setName( maFrmDescr.GetName() );
-
-        uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, uno::UNO_QUERY );
-        if ( xFramesSupplier.is() )
-            mxFrame->setCreator( xFramesSupplier );
+        if (!mxFrame.is())
+        {
+            VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(xParentWindow);
+            VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() );
+            pWin->SetSizePixel( pParent->GetOutputSizePixel() );
+            pWin->SetBackground();
+            pWin->Show();
+
+            uno::Reference < awt::XWindow > xWindow( pWin->GetComponentInterface(), uno::UNO_QUERY );
+            xFrame->setComponent( xWindow, uno::Reference < frame::XController >() );
+
+            // we must destroy the IFrame before the parent is destroyed
+            xWindow->addEventListener( this );
+
+            mxFrame = frame::Frame::create( mxContext );
+            uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), uno::UNO_QUERY );
+            mxFrame->initialize( xWin );
+            mxFrame->setName( maFrmDescr.GetName() );
+
+            uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, uno::UNO_QUERY );
+            if ( xFramesSupplier.is() )
+                mxFrame->setCreator( xFramesSupplier );
+        }
 
         uno::Sequence < beans::PropertyValue > aProps{
             comphelper::makePropertyValue("PluginMode", sal_Int16(2)),
index cddbd3285444e7d2753d56cc6994c5b8ed08d11c..f924016e4ce612cb3e9435505646ec66b8443f2e 100644 (file)
@@ -74,6 +74,8 @@
 #include <sdr/contact/viewcontactofsdrole2obj.hxx>
 #include <svx/svdograf.hxx>
 #include <sdr/properties/oleproperties.hxx>
+#include <svx/unoshape.hxx>
+#include <svx/xlineit0.hxx>
 #include <svx/xlnclit.hxx>
 #include <svx/xbtmpit.hxx>
 #include <svx/xflbmtit.hxx>
@@ -590,6 +592,35 @@ void SdrEmbedObjectLink::Closed()
     SvBaseLink::Closed();
 }
 
+SdrIFrameLink::SdrIFrameLink(SdrOle2Obj* pObject)
+    : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB)
+    , m_pObject(pObject)
+{
+    SetSynchron( false );
+}
+
+::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged(
+    const OUString&, const uno::Any& )
+{
+    uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef();
+    uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY);
+    if (xPersObj.is())
+    {
+        // let the IFrameObject reload the link
+        try
+        {
+            xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>());
+        }
+        catch (const uno::Exception&)
+        {
+        }
+
+        m_pObject->SetChanged();
+    }
+
+    return SUCCESS;
+}
+
 class SdrOle2ObjImpl
 {
 public:
@@ -607,7 +638,7 @@ public:
     bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated loading if load of OLE2 fails
     bool mbConnected:1;
 
-    SdrEmbedObjectLink* mpObjectLink;
+    sfx2::SvBaseLink* mpObjectLink;
     OUString maLinkURL;
 
     rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener;
@@ -807,7 +838,7 @@ bool SdrOle2Obj::IsEmpty() const
     return !mpImpl->mxObjRef.is();
 }
 
-void SdrOle2Obj::Connect()
+void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
 {
     if( IsEmptyPresObj() )
         return;
@@ -820,7 +851,7 @@ void SdrOle2Obj::Connect()
         return;
     }
 
-    Connect_Impl();
+    Connect_Impl(pCreator);
     AddListeners_Impl();
 }
 
@@ -921,24 +952,51 @@ void SdrOle2Obj::CheckFileLink_Impl()
     {
         try
         {
-            uno::Reference< embed::XLinkageSupport > xLinkSupport( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
+            uno::Reference<embed::XEmbeddedObject> xObject = mpImpl->mxObjRef.GetObject();
+            if (!xObject)
+                return;
 
-            if ( xLinkSupport.is() && xLinkSupport->isLink() )
-            {
-                OUString aLinkURL = xLinkSupport->getLinkURL();
+            bool bIFrame = false;
 
-                if ( !aLinkURL.isEmpty() )
+            OUString aLinkURL;
+            uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY);
+            if (xLinkSupport)
+            {
+                if (xLinkSupport->isLink())
+                    aLinkURL = xLinkSupport->getLinkURL();
+            }
+            else
+            {
+                // get IFrame (Floating Frames) listed and updatable from the
+                // manage links dialog
+                SvGlobalName aClassId(xObject->getClassID());
+                if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
                 {
-                    // this is a file link so the model link manager should handle it
-                    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
+                    uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->getPropertyValue("FrameURL") >>= aLinkURL;
+                    bIFrame = true;
+                }
+            }
+
+            if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it
+            {
+                sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
 
-                    if ( pLinkManager )
+                if ( pLinkManager )
+                {
+                    SdrEmbedObjectLink* pEmbedObjectLink = nullptr;
+                    if (!bIFrame)
                     {
-                        mpImpl->mpObjectLink = new SdrEmbedObjectLink( this );
-                        mpImpl->maLinkURL = aLinkURL;
-                        pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
-                        mpImpl->mpObjectLink->Connect();
+                        pEmbedObjectLink = new SdrEmbedObjectLink(this);
+                        mpImpl->mpObjectLink = pEmbedObjectLink;
                     }
+                    else
+                        mpImpl->mpObjectLink = new SdrIFrameLink(this);
+                    mpImpl->maLinkURL = aLinkURL;
+                    pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
+                    if (pEmbedObjectLink)
+                        pEmbedObjectLink->Connect();
                 }
             }
         }
@@ -949,7 +1007,7 @@ void SdrOle2Obj::CheckFileLink_Impl()
     }
 }
 
-void SdrOle2Obj::Connect_Impl()
+void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
 {
     if(!mpImpl->aPersistName.isEmpty() )
     {
@@ -989,6 +1047,17 @@ void SdrOle2Obj::Connect_Impl()
                 }
             }
 
+            if (pCreator)
+            {
+                OUString sFrameURL(pCreator->GetAndClearInitialFrameURL());
+                if (!sFrameURL.isEmpty() && svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject()))
+                {
+                    uno::Reference<beans::XPropertySet> xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->setPropertyValue("FrameURL", uno::Any(sFrameURL));
+                }
+            }
+
             if ( mpImpl->mxObjRef.is() )
             {
                 if ( !mpImpl->mxLightClient.is() )
@@ -1308,14 +1377,14 @@ SdrObject* SdrOle2Obj::getFullDragClone() const
     return createSdrGrafObjReplacement(false);
 }
 
-void SdrOle2Obj::SetPersistName( const OUString& rPersistName )
+void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator )
 {
     DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!");
 
     mpImpl->aPersistName = rPersistName;
     mpImpl->mbLoadingOLEObjectFailed = false;
 
-    Connect();
+    Connect(pCreator);
     SetChanged();
 }
 
index 9b0a713184fab8f1d65ca29c0a8da370f81e95a8..23a886036f320f3df35d91c2b9a1e02ea465fd1c 100644 (file)
@@ -62,8 +62,11 @@ public:
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
 };
+
 class SvxFrameShape : public SvxOle2Shape
 {
+private:
+    OUString m_sInitialFrameURL;
 protected:
     // override these for special property handling in subcasses. Return true if property is handled
     virtual bool setPropertyValueImpl( const OUString& rName, const SfxItemPropertySimpleEntry* pProperty, const css::uno::Any& rValue ) override;
@@ -80,6 +83,8 @@ public:
     virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override;
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
+
+    virtual OUString GetAndClearInitialFrameURL() override;
 };
 
 
index 008be073164505cdbad8d9a9dc43b356aa17dcce..35bd658e2934faf1a7bf5a623b87960590db7600 100644 (file)
@@ -175,7 +175,7 @@ bool SvxOle2Shape::setPropertyValueImpl( const OUString& rName, const SfxItemPro
 #else
             pOle = static_cast<SdrOle2Obj*>(GetSdrObject());
 #endif
-            pOle->SetPersistName( aPersistName );
+            pOle->SetPersistName( aPersistName, this );
             return true;
         }
         break;
@@ -495,10 +495,11 @@ void SvxOle2Shape::createLink( const OUString& aLinkURL )
 
 void SvxOle2Shape::resetModifiedState()
 {
-    ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist();
+    SdrObject* pObject = GetSdrObject();
+    ::comphelper::IEmbeddedHelper* pPersist = pObject ? pObject->getSdrModelFromSdrObject().GetPersist() : nullptr;
     if( pPersist && !pPersist->isEnableSetModified() )
     {
-        SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() );
+        SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >(pObject);
         if( pOle && !pOle->IsEmpty() )
         {
             uno::Reference < util::XModifiable > xMod( pOle->GetObjRef(), uno::UNO_QUERY );
@@ -548,6 +549,11 @@ const SvGlobalName SvxOle2Shape::GetClassName_Impl(OUString& rHexCLSID)
     return aClassName;
 }
 
+OUString SvxOle2Shape::GetAndClearInitialFrameURL()
+{
+    return OUString();
+}
+
 SvxAppletShape::SvxAppletShape(SdrObject* pObject)
     : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, SdrObject::GetGlobalDrawObjectItemPool())  )
 {
@@ -701,8 +707,19 @@ SvxFrameShape::~SvxFrameShape() throw()
 {
 }
 
+OUString SvxFrameShape::GetAndClearInitialFrameURL()
+{
+    OUString sRet(m_sInitialFrameURL);
+    m_sInitialFrameURL.clear();
+    return sRet;
+}
+
 void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage )
 {
+    uno::Reference<beans::XPropertySet> xSet(static_cast<OWeakObject *>(this), uno::UNO_QUERY);
+    if (xSet)
+        xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL;
+
     SvxShape::Create( pNewObj, pNewPage );
     const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID );
     createObject(aIFrameClassId);
index 74c6945abdf78a6d39ba5dbd987f6c38cf438ca1..d0d60dc6ca27d7f1e5093b936a71109a8a4292a3 100644 (file)
@@ -28,7 +28,7 @@ class SwGrfFormatColl;
 class SwDoc;
 class SwOLENode;
 class SwOLEListener_Impl;
-class SwEmbedObjectLink;
+namespace sfx2 { class SvBaseLink; }
 class DeflateData;
 
 class SW_DLLPUBLIC SwOLEObj
@@ -88,7 +88,7 @@ class SW_DLLPUBLIC SwOLENode: public SwNoTextNode
     bool   mbOLESizeInvalid; /**< Should be considered at SwDoc::PrtOLENotify
                                    (e.g. copied). Is not persistent. */
 
-    SwEmbedObjectLink*  mpObjectLink;
+    sfx2::SvBaseLink*  mpObjectLink;
     OUString maLinkURL;
 
     SwOLENode(  const SwNodeIndex &rWhere,
index 5c73a1b3ed3f53a440e8173d90e377a5c672eeff..23e5aedc182e95c9e69d5662cac523539e1d7536 100644 (file)
@@ -143,6 +143,8 @@ void SAL_CALL SwOLEListener_Impl::disposing( const lang::EventObject& )
 // TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control
 //             embedded object different link objects with the same functionality had to be implemented
 
+namespace {
+
 class SwEmbedObjectLink : public sfx2::SvBaseLink
 {
     SwOLENode*          pOleNode;
@@ -205,6 +207,44 @@ void SwEmbedObjectLink::Closed()
     SvBaseLink::Closed();
 }
 
+class SwIFrameLink : public sfx2::SvBaseLink
+{
+    SwOLENode* m_pOleNode;
+
+public:
+    explicit SwIFrameLink(SwOLENode* pNode)
+        : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB)
+        , m_pOleNode(pNode)
+    {
+        SetSynchron( false );
+    }
+
+    ::sfx2::SvBaseLink::UpdateResult DataChanged(
+        const OUString&, const uno::Any& )
+    {
+        uno::Reference<embed::XEmbeddedObject> xObject = m_pOleNode->GetOLEObj().GetOleRef();
+        uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY);
+        if (xPersObj.is())
+        {
+            // let the IFrameObject reload the link
+            try
+            {
+                xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>());
+            }
+            catch (const uno::Exception&)
+            {
+            }
+
+            m_pOleNode->SetChanged();
+        }
+
+        return SUCCESS;
+    }
+
+};
+
+}
+
 SwOLENode::SwOLENode( const SwNodeIndex &rWhere,
                     const svt::EmbeddedObjectRef& xObj,
                     SwGrfFormatColl *pGrfColl,
@@ -597,18 +637,49 @@ void SwOLENode::CheckFileLink_Impl()
     {
         try
         {
-            uno::Reference< embed::XLinkageSupport > xLinkSupport( maOLEObj.m_xOLERef.GetObject(), uno::UNO_QUERY_THROW );
-            if ( xLinkSupport->isLink() )
+            uno::Reference<embed::XEmbeddedObject> xObject = maOLEObj.m_xOLERef.GetObject();
+            if (!xObject)
+                return;
+
+            bool bIFrame = false;
+
+            OUString aLinkURL;
+            uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY);
+            if (xLinkSupport)
+            {
+                if (xLinkSupport->isLink())
+                    aLinkURL = xLinkSupport->getLinkURL();
+            }
+            else
             {
-                const OUString aLinkURL = xLinkSupport->getLinkURL();
-                if ( !aLinkURL.isEmpty() )
+                // get IFrame (Floating Frames) listed and updatable from the
+                // manage links dialog
+                SvGlobalName aClassId(xObject->getClassID());
+                if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
+                {
+                    uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->getPropertyValue("FrameURL") >>= aLinkURL;
+                    bIFrame = true;
+                }
+            }
+
+            if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it
+            {
+                SwEmbedObjectLink* pEmbedObjectLink = nullptr;
+                if (!bIFrame)
+                {
+                    pEmbedObjectLink = new SwEmbedObjectLink(this);
+                    mpObjectLink = pEmbedObjectLink;
+                }
+                else
                 {
-                    // this is a file link so the model link manager should handle it
-                    mpObjectLink = new SwEmbedObjectLink( this );
-                    maLinkURL = aLinkURL;
-                    GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
-                    mpObjectLink->Connect();
+                    mpObjectLink = new SwIFrameLink(this);
                 }
+                maLinkURL = aLinkURL;
+                GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
+                if (pEmbedObjectLink)
+                    pEmbedObjectLink->Connect();
             }
         }
         catch( uno::Exception& )
index 6dae1b00a8b95475ab8805c2e803cbb76fa151c0..2ee7a98be54705d9078d142f3add13cf7003c875 100644 (file)
@@ -3229,9 +3229,35 @@ SdXMLFloatingFrameShapeContext::~SdXMLFloatingFrameShapeContext()
 {
 }
 
+uno::Reference<drawing::XShape> SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const
+{
+    uno::Reference<lang::XMultiServiceFactory> xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
+    if (!xServiceFact.is())
+        return nullptr;
+    uno::Reference<drawing::XShape> xShape(
+            xServiceFact->createInstance("com.sun.star.drawing.FrameShape"), uno::UNO_QUERY);
+    return xShape;
+}
+
 void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< css::xml::sax::XAttributeList >& )
 {
-    AddShape("com.sun.star.drawing.FrameShape");
+    uno::Reference<drawing::XShape> xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape());
+
+    uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY);
+    // set FrameURL before AddShape, we have to do it again later because it
+    // gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
+    // FrameURL to exist when AddShape triggers SetPersistName which itself
+    // triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
+    // know what URL will end up being used. So bodge this by setting FrameURL
+    // to the temp pre-SdrOle2Obj attached properties and we can smuggle it
+    // eventually into SdrOle2Obj::SetPersistName at the right point after
+    // PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
+    // in order to inform the link manager that this is an IFrame that links to
+    // a URL
+    if (xProps && !maHref.isEmpty())
+        xProps->setPropertyValue("FrameURL", Any(maHref));
+
+    AddShape(xShape);
 
     if( mxShape.is() )
     {
@@ -3240,7 +3266,6 @@ void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< cs
         // set pos, size, shear and rotate
         SetTransformation();
 
-        uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
         if( xProps.is() )
         {
             if( !maFrameName.isEmpty() )
index 30f5b149ad9f5efb79befb4865e5b11e6fbd317c..93d96085b85293d591b2646a7d14dd81c8c2cef1 100644 (file)
@@ -521,6 +521,8 @@ private:
     OUString maFrameName;
     OUString maHref;
 
+    css::uno::Reference<css::drawing::XShape> CreateFloatingFrameShape() const;
+
 public:
 
     SdXMLFloatingFrameShapeContext( SvXMLImport& rImport, sal_uInt16 nPrfx,