set Referer on loading IFrames
authorCaolán McNamara <caolanm@redhat.com>
Tue, 11 Apr 2023 09:13:37 +0000 (10:13 +0100)
committerRene Engelhard <rene@debian.org>
Wed, 24 May 2023 18:05:03 +0000 (19:05 +0100)
so tools, options, security, options,
"block any links from document not..."
applies to their contents.

Change-Id: I04839aea6b07a4a76ac147a85045939ccd9c3c79
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150225
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Gbp-Pq: Name CVE-2023-2255.diff

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 669ba884b055df9c662844225cad2741b68c205d..fd5b33a6b3415297eccfe50cbad8ab1c21f78525 100644 (file)
@@ -155,6 +155,37 @@ void OCommonEmbeddedObject::StateChangeNotification_Impl( bool bBeforeChange, sa
     rGuard.reset();
 }
 
+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 )
 {
@@ -228,34 +259,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 683fe0aab3f259b5798cb53984f938370c3e32c7..c17a39accf2c7834e754f2def72de391d26cbbfe 100644 (file)
@@ -47,6 +47,7 @@ uno::Any SAL_CALL OSpecialEmbeddedObject::queryInterface( const uno::Type& rType
     uno::Any 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 ),
@@ -160,4 +161,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 61e939a0c62f9f4ef1a3282c46937e88166450a7..ec4ea7ad2e282770f4248ea112eb4ab3059f22d5 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 85f0125c17b096e71f4c2d4603b0d68eec0aa1af..1b8a9b10b3a2a385faab5473184eac042f442cb2 100644 (file)
@@ -42,6 +42,7 @@ namespace frame { class XModel; }
 namespace svt { class EmbeddedObjectRef; }
 
 class SdrOle2ObjImpl;
+class SvxOle2Shape;
 
 class SVXCORE_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();
 
@@ -200,6 +201,16 @@ public:
     void                Connect() { GetRealObject(); }
 };
 
+class SVXCORE_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 1f948f50574bd7ceff6952751ed5e312dd6e7046..5fe64331842c67d0e93a06882a2f5b43dbf0ecfd 100644 (file)
@@ -607,6 +607,8 @@ public:
     bool createObject( const SvGlobalName &aClassName );
 
     void createLink( const OUString& aLinkURL );
+
+    virtual OUString GetAndClearInitialFrameURL();
 };
 
 
index 1796b02b5434b31f4600ace51a25892c9ada4b0c..fce7829359497e9c4b026fad4426b017d375312d 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 22b18c6e382b00d041ac483164d25034be4b1d99..ea90c4db3b0c01b1c02300655ee3e0dd6e37333c 100644 (file)
 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
 
+#include <comphelper/propertyvalue.hxx>
 #include <cppuhelper/implbase.hxx>
 #include <cppuhelper/supportsservice.hxx>
 #include <svtools/miscopt.hxx>
 #include <svl/itemprop.hxx>
+#include <sfx2/docfile.hxx>
 #include <sfx2/frmdescr.hxx>
 #include <sfx2/objsh.hxx>
 #include <sfx2/sfxdlg.hxx>
@@ -164,41 +166,57 @@ sal_Bool SAL_CALL IFrameObject::load(
         uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) );
         xTrans->parseStrict( aTargetURL );
 
-        if (INetURLObject(aTargetURL.Complete).GetProtocol() == INetProtocol::Macro)
+        INetURLObject aURLObject(aTargetURL.Complete);
+        if (aURLObject.GetProtocol() == INetProtocol::Macro || aURLObject.isSchemeEqualTo(u"vnd.sun.star.script"))
+            return false;
+
+        uno::Reference<frame::XFramesSupplier> xParentFrame = xFrame->getCreator();
+        SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame);
+
+        bool bUpdateAllowed(true);
+        if (pDoc)
+        {
+            comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pDoc->getEmbeddedObjectContainer();
+            bUpdateAllowed = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
+        }
+        if (!bUpdateAllowed)
+            return false;
+
+        OUString sReferer;
+        if (pDoc && pDoc->HasName())
+            sReferer = pDoc->GetMedium()->GetName();
+
+        uno::Reference<css::awt::XWindow> xParentWindow(xFrame->getContainerWindow());
+
+        if (!mxFrame.is())
         {
-            uno::Reference<frame::XFramesSupplier> xParentFrame = xFrame->getCreator();
-            SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame);
-            if (pDoc && !pDoc->AdjustMacroMode())
-                return false;
+            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 );
         }
 
-        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 >() );
-
-        // 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(2);
-        aProps[0].Name = "PluginMode";
-        aProps[0].Value <<= sal_Int16(2);
-        aProps[1].Name = "ReadOnly";
-        aProps[1].Value <<= true;
+        uno::Sequence < beans::PropertyValue > aProps{
+            comphelper::makePropertyValue("PluginMode", sal_Int16(2)),
+            comphelper::makePropertyValue("ReadOnly", true),
+            comphelper::makePropertyValue("Referer", sReferer)
+        };
         uno::Reference < frame::XDispatch > xDisp = mxFrame->queryDispatch( aTargetURL, "_self", 0 );
         if ( xDisp.is() )
             xDisp->dispatch( aTargetURL, aProps );
index 65b30eaed7e3b871bb0d5b48304406f927e5124f..dc0e316fb8e8dc3ece45c0bb630ac22481a8be80 100644 (file)
@@ -67,6 +67,7 @@
 #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>
@@ -591,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:
@@ -608,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;
@@ -808,7 +838,7 @@ bool SdrOle2Obj::IsEmpty() const
     return !mpImpl->mxObjRef.is();
 }
 
-void SdrOle2Obj::Connect()
+void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
 {
     if( IsEmptyPresObj() )
         return;
@@ -821,7 +851,7 @@ void SdrOle2Obj::Connect()
         return;
     }
 
-    Connect_Impl();
+    Connect_Impl(pCreator);
     AddListeners_Impl();
 }
 
@@ -920,24 +950,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, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
-                        mpImpl->mpObjectLink->Connect();
+                        pEmbedObjectLink = new SdrEmbedObjectLink(this);
+                        mpImpl->mpObjectLink = pEmbedObjectLink;
                     }
+                    else
+                        mpImpl->mpObjectLink = new SdrIFrameLink(this);
+                    mpImpl->maLinkURL = aLinkURL;
+                    pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
+                    if (pEmbedObjectLink)
+                        pEmbedObjectLink->Connect();
                 }
             }
         }
@@ -948,7 +1005,7 @@ void SdrOle2Obj::CheckFileLink_Impl()
     }
 }
 
-void SdrOle2Obj::Connect_Impl()
+void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
 {
     if(!mpImpl->aPersistName.isEmpty() )
     {
@@ -988,6 +1045,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() )
@@ -1301,14 +1369,14 @@ SdrObjectUniquePtr 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 a1a4e69630206329f3c62cd79ad6935a57683af9..4381094d380a3c829da398c422b1a1204f236548 100644 (file)
@@ -64,8 +64,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;
@@ -82,6 +85,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 eab0cd5bb1112d6ca2396cb6240af4cab4e97f81..37e3bf930f4f5deaab07e619b5c55fa4387ea1f0 100644 (file)
@@ -174,7 +174,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 @@ 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 8382a42e58dc01f647bdc5233155c4a5e9b3b919..0c6afdc2c676f73074a1aeb76645126f3fc3bf15 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
@@ -90,7 +90,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 1927872ed0d9d6b40e49828f0dea17dfbaa691df..0619f52356411218fb1b55e52a7d3dd02db3e50c 100644 (file)
@@ -146,6 +146,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;
@@ -208,6 +210,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,
@@ -605,18 +645,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, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
-                    mpObjectLink->Connect();
+                    mpObjectLink = new SwIFrameLink(this);
                 }
+                maLinkURL = aLinkURL;
+                GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
+                if (pEmbedObjectLink)
+                    pEmbedObjectLink->Connect();
             }
         }
         catch( uno::Exception& )
index 71a2ee7d637b9754f4ed6a5197ab4b46f082a628..2d6e4952f8b56d72a11c8eab2929e19b4c161cc2 100644 (file)
@@ -3245,9 +3245,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() )
     {
@@ -3256,7 +3282,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 35566e597a2cd12630f43bacdf7ce92b45802761..00bc98fa75e295836775457091ed6fc7ad6029ab 100644 (file)
@@ -513,6 +513,8 @@ private:
     OUString maFrameName;
     OUString maHref;
 
+    css::uno::Reference<css::drawing::XShape> CreateFloatingFrameShape() const;
+
 public:
 
     SdXMLFloatingFrameShapeContext( SvXMLImport& rImport, sal_uInt16 nPrfx,