warn on load when a document binds an event to a macro

a) treat shared/Scripts equivalently to document scripts

This doesn't automatically warn/block running those scripts when used in a
freshly loaded document on its own however

because DocumentMacroMode::checkMacrosOnLoading will see at...

if ( m_xData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() )

that the document contains no macros and flip the allow macros flag to true so
that potentially new uses of macros added by the user during the edit are
allowed to run

b) so, add an additional flag to indicate existence of use of macros in a document

c) for odf import, set it when a script:event-listener tag is encountered
d) for html import when registerScriptEvents or SwFormatINetFormat::SetMacroTable is called
e) for doc import when Read_F_Macro or StoreMacroCmds is called as well for good measure
f) for xls import when registerScriptEvent or ScMacroInfo::SetMacro is called
g) for oox import when VbaProject::attachMacros is called

Change-Id: Ic1203d8ec7dfc217aa217135033ae9db2888e19b
Reviewed-on: https://gerrit.libreoffice.org/77131
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx
index 6115ad0..1027667 100644
--- a/comphelper/source/misc/documentinfo.cxx
+++ b/comphelper/source/misc/documentinfo.cxx
@@ -158,6 +158,20 @@
        return sTitle;
    }

    void DocumentInfo::notifyMacroEventRead(const css::uno::Reference<css::frame::XModel>& rModel)
    {
        if (!rModel.is())
            return;

        // like BreakMacroSignature of XMLScriptContext use XModel::attachResource
        // to propagate this notification
        css::uno::Sequence<css::beans::PropertyValue> aMedDescr = rModel->getArgs();
        sal_Int32 nNewLen = aMedDescr.getLength() + 1;
        aMedDescr.realloc(nNewLen);
        aMedDescr[nNewLen-1].Name = "MacroEventRead";
        aMedDescr[nNewLen-1].Value <<= true;
        rModel->attachResource(rModel->getURL(), aMedDescr);
    }

} // namespace comphelper

diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx
index e27dc8d..9958b6c 100644
--- a/dbaccess/source/core/dataaccess/ModelImpl.cxx
+++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx
@@ -370,6 +370,7 @@
            ,m_bSuppressVersionColumns(true)
            ,m_bModified(false)
            ,m_bDocumentReadOnly(false)
            ,m_bMacroCallsSeenWhileLoading(false)
            ,m_pSharedConnectionManager(nullptr)
            ,m_nControllerLockCount(0)
{
@@ -403,6 +404,7 @@
            ,m_bSuppressVersionColumns(true)
            ,m_bModified(false)
            ,m_bDocumentReadOnly(false)
            ,m_bMacroCallsSeenWhileLoading(false)
            ,m_pSharedConnectionManager(nullptr)
            ,m_nControllerLockCount(0)
{
@@ -1266,6 +1268,11 @@
    return ( *m_aEmbeddedMacros != eNoMacros );
}

bool ODatabaseModelImpl::macroCallsSeenWhileLoading() const
{
    return m_bMacroCallsSeenWhileLoading;
}

Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const
{
    return Reference< XEmbeddedScripts >( getModel_noCreate(), UNO_QUERY );
diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx
index 1962247..21250ea 100644
--- a/dbaccess/source/core/dataaccess/databasedocument.cxx
+++ b/dbaccess/source/core/dataaccess/databasedocument.cxx
@@ -748,15 +748,24 @@
bool ODatabaseDocument::impl_attachResource( const OUString& i_rLogicalDocumentURL,
            const Sequence< PropertyValue >& i_rMediaDescriptor, DocumentGuard& _rDocGuard )
{
    if  (   ( i_rLogicalDocumentURL == getURL() )
        &&  ( i_rMediaDescriptor.getLength() == 1 )
        &&  ( i_rMediaDescriptor[0].Name == "BreakMacroSignature" )
        )
    if  (i_rLogicalDocumentURL == getURL())
    {
        // this is a BAD hack of the Basic importer code ... there should be a dedicated API for this,
        // not this bad mis-using of existing interfaces
        return false;
            // (we do not support macro signatures, so we can ignore this call)
        ::comphelper::NamedValueCollection aArgs(i_rMediaDescriptor);

        // this misuse of attachresource is a hack of the Basic importer code
        // repurposing existing interfaces for uses it probably wasn't intended
        // for

        // we do not support macro signatures, so we can ignore that request
        aArgs.remove("BreakMacroSignature");

        bool bMacroEventRead = false;
        if ((aArgs.get( "MacroEventRead" ) >>= bMacroEventRead) && bMacroEventRead)
            m_pImpl->m_bMacroCallsSeenWhileLoading = true;
        aArgs.remove( "MacroEventRead" );

        if (aArgs.empty())
            return false;
    }

    // if no URL has been provided, the caller was lazy enough to not call our getURL - which is not allowed anymore,
diff --git a/dbaccess/source/core/inc/ModelImpl.hxx b/dbaccess/source/core/inc/ModelImpl.hxx
index 15cda74..0ed9c8d 100644
--- a/dbaccess/source/core/inc/ModelImpl.hxx
+++ b/dbaccess/source/core/inc/ModelImpl.hxx
@@ -207,6 +207,7 @@
    bool                                            m_bSuppressVersionColumns : 1;
    bool                                            m_bModified : 1;
    bool                                            m_bDocumentReadOnly : 1;
    bool                                            m_bMacroCallsSeenWhileLoading : 1;
    css::uno::Reference< css::beans::XPropertyBag >
                                                        m_xSettings;
    css::uno::Sequence< OUString >                      m_aTableFilter;
@@ -435,6 +436,7 @@
    virtual void setCurrentMacroExecMode( sal_uInt16 ) override;
    virtual OUString getDocumentLocation() const override;
    virtual bool documentStorageHasMacros() const override;
    virtual bool macroCallsSeenWhileLoading() const override;
    virtual css::uno::Reference< css::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const override;
    virtual SignatureState getScriptingSignatureState() override;
    virtual bool hasTrustedScriptingSignature( bool bAllowUIToAddAuthor ) override;
diff --git a/include/comphelper/documentinfo.hxx b/include/comphelper/documentinfo.hxx
index d47f1d02..a195722 100644
--- a/include/comphelper/documentinfo.hxx
+++ b/include/comphelper/documentinfo.hxx
@@ -37,8 +37,11 @@
        /** retrieves the UI title of the given document
        */
        COMPHELPER_DLLPUBLIC OUString  getDocumentTitle( const css::uno::Reference< css::frame::XModel >& _rxDocument );
    }

        /** notify that this document contains a macro event handler
        */
        COMPHELPER_DLLPUBLIC void notifyMacroEventRead( const css::uno::Reference< css::frame::XModel >& _rxDocument );
    }

}   // namespace comphelper

diff --git a/include/oox/ole/axcontrol.hxx b/include/oox/ole/axcontrol.hxx
index b53988e..968360a 100644
--- a/include/oox/ole/axcontrol.hxx
+++ b/include/oox/ole/axcontrol.hxx
@@ -334,6 +334,8 @@
                            PropertySet const & rPropSet,
                            sal_Int32& nOrientation );

    const css::uno::Reference<css::frame::XModel> GetDocModel() const { return mxDocModel; }

private:
    css::uno::Reference< css::frame::XModel > mxDocModel;
    const GraphicHelper& mrGraphicHelper;
diff --git a/include/sfx2/docmacromode.hxx b/include/sfx2/docmacromode.hxx
index efd41f7..a15bbbe 100644
--- a/include/sfx2/docmacromode.hxx
+++ b/include/sfx2/docmacromode.hxx
@@ -113,6 +113,12 @@
        virtual bool
                    documentStorageHasMacros() const = 0;

        /** checks whether the document's contained calls to macros or scripts after loading

        */
        virtual bool
                    macroCallsSeenWhileLoading() const = 0;

        /** provides access to the XEmbeddedScripts interface of the document

            Implementations are allowed to return <NULL/> here if and only if they
@@ -274,6 +280,7 @@

            @see isMacroExecutionDisallowed
            @see IMacroDocumentAccess::documentStorageHasMacros
            @see IMacroDocumentAccess::macroCallsSeenWhileLoading
            @see hasMacroLibrary
            @see IMacroDocumentAccess::checkForBrokenScriptingSignatures
        */
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index 5b32dfc..3cdf402 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -413,6 +413,9 @@
    sal_uInt32                  GetModifyPasswordHash() const;
    bool                        SetModifyPasswordHash( sal_uInt32 nHash );

    void                        SetMacroCallsSeenWhileLoading();
    bool                        GetMacroCallsSeenWhileLoading() const;

    const css::uno::Sequence< css::beans::PropertyValue >& GetModifyPasswordInfo() const;
    bool                        SetModifyPasswordInfo( const css::uno::Sequence< css::beans::PropertyValue >& aInfo );

diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx
index 6cbb029..33ab9da 100644
--- a/include/xmloff/xmlimp.hxx
+++ b/include/xmloff/xmlimp.hxx
@@ -235,6 +235,7 @@
protected:
    bool                        mbIsFormsSupported;
    bool                        mbIsTableShapeSupported;
    bool                        mbNotifyMacroEventRead;

    // Create top-level element context.
    // This method is called after the namespace map has been updated, but
@@ -571,6 +572,8 @@
    bool embeddedFontAlreadyProcessed( const OUString& url );

    virtual void NotifyEmbeddedFontRead() {};
    // something referencing a macro/script was imported
    void NotifyMacroEventRead();

    bool needFixPositionAfterZ() const;
};
diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx
index db8de0a..7cafeba3 100644
--- a/oox/source/ole/vbaproject.cxx
+++ b/oox/source/ole/vbaproject.cxx
@@ -31,6 +31,7 @@
#include <com/sun/star/script/vba/XVBAMacroResolver.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <comphelper/configurationhelper.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/storagehelper.hxx>
#include <osl/diagnose.h>
#include <rtl/tencinfo.h>
@@ -515,6 +516,8 @@
{
    if( !maMacroAttachers.empty() && mxContext.is() ) try
    {
        comphelper::DocumentInfo::notifyMacroEventRead(mxDocModel);

        Reference< XMultiComponentFactory > xFactory( mxContext->getServiceManager(), UNO_SET_THROW );
        Sequence< Any > aArgs( 2 );
        aArgs[ 0 ] <<= mxDocModel;
@@ -522,6 +525,7 @@
        Reference< XVBAMacroResolver > xResolver( xFactory->createInstanceWithArgumentsAndContext(
            "com.sun.star.script.vba.VBAMacroResolver", aArgs, mxContext ), UNO_QUERY_THROW );
        maMacroAttachers.forEachMem( &VbaMacroAttacherBase::resolveAndAttachMacro, ::std::cref( xResolver ) );

    }
    catch(const Exception& )
    {
diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx
index 0335bc4..610c698 100644
--- a/sc/source/filter/excel/xiescher.cxx
+++ b/sc/source/filter/excel/xiescher.cxx
@@ -49,6 +49,7 @@
#include <vcl/window.hxx>
#include <vcl/wmf.hxx>
#include <comphelper/classids.hxx>
#include <comphelper/documentinfo.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
@@ -174,7 +175,8 @@
    mbSimpleMacro( true ),
    mbProcessSdr( true ),
    mbInsertSdr( true ),
    mbCustomDff( false )
    mbCustomDff( false ),
    mbNotifyMacroEventRead( false )
{
}

@@ -510,7 +512,18 @@
    return xSdrObj;
}

void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
void XclImpDrawObjBase::NotifyMacroEventRead()
{
    if (mbNotifyMacroEventRead)
        return;
    SfxObjectShell* pDocShell = GetDocShell();
    if (!pDocShell)
        return;
    comphelper::DocumentInfo::notifyMacroEventRead(pDocShell->GetModel());
    mbNotifyMacroEventRead = true;
}

void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj )
{
    // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj()
    rSdrObj.NbcSetLayer( SC_LAYER_FRONT );
@@ -537,7 +550,10 @@
    {
        if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, true ) )
        {
            pInfo->SetMacro( XclTools::GetSbMacroUrl( maMacroName, GetDocShell() ) );
            OUString sMacro = XclTools::GetSbMacroUrl(maMacroName, GetDocShell());
            if (!sMacro.isEmpty())
                NotifyMacroEventRead();
            pInfo->SetMacro(sMacro);
            pInfo->SetHlink( maHyperlink );
        }
    }
@@ -3285,7 +3301,8 @@
XclImpDffConverter::XclImpDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
    XclImpSimpleDffConverter( rRoot, rDffStrm ),
    oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ),
    mnOleImpFlags( 0 )
    mnOleImpFlags( 0 ),
    mbNotifyMacroEventRead(false)
{
    const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
    if( rFilterOpt.IsMathType2Math() )
@@ -3342,7 +3359,7 @@
    SetModel( &xConvData->mrSdrModel, 1440 );
}

void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj )
void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, XclImpDrawObjBase& rDrawObj )
{
    if( rDrawObj.IsProcessSdrObj() )
    {
@@ -3391,6 +3408,14 @@
        SetModel( &maDataStack.back()->mrSdrModel, 1440 );
}

void XclImpDffConverter::NotifyMacroEventRead()
{
    if (mbNotifyMacroEventRead)
        return;
    comphelper::DocumentInfo::notifyMacroEventRead(mxModel);
    mbNotifyMacroEventRead = true;
}

SdrObjectUniquePtr XclImpDffConverter::CreateSdrObject( const XclImpTbxObjBase& rTbxObj, const tools::Rectangle& rAnchorRect )
{
    SdrObjectUniquePtr xSdrObj;
@@ -3413,6 +3438,7 @@
            ScriptEventDescriptor aDescriptor;
            if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) )
            {
                NotifyMacroEventRead();
                Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW );
                xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor );
            }
diff --git a/sc/source/filter/inc/xiescher.hxx b/sc/source/filter/inc/xiescher.hxx
index f9e8d00..37f4579 100644
--- a/sc/source/filter/inc/xiescher.hxx
+++ b/sc/source/filter/inc/xiescher.hxx
@@ -125,7 +125,7 @@
    SdrObjectUniquePtr        CreateSdrObject( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect, bool bIsDff ) const;
    /** Additional processing for the passed SdrObject before insertion into
        the drawing page (calls virtual DoPreProcessSdrObj() function). */
    void                PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const;
    void                PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj );
    /** Additional processing for the passed SdrObject after insertion into the
        drawing page (calls virtual DoPostProcessSdrObj() function). */
    void                PostProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const;
@@ -172,6 +172,9 @@
    virtual void        DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const;
    /** Derived classes may perform additional processing for the passed SdrObject after insertion. */
    virtual void        DoPostProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const;

    /** Notify that the document contains a macro event handler */
    void NotifyMacroEventRead();
private:
    /** Reads the contents of a BIFF3 OBJ record. */
    void                ImplReadObj3( XclImpStream& rStrm );
@@ -202,6 +205,7 @@
    bool                mbProcessSdr;   /// true = Object is valid, do processing and insertion.
    bool                mbInsertSdr;    /// true = Insert the SdrObject into draw page.
    bool                mbCustomDff;    /// true = Recreate SdrObject in DFF import.
    bool                mbNotifyMacroEventRead; /// true == If we have already seen a macro event
};

class XclImpDrawObjVector
@@ -928,7 +932,7 @@
    /** Initially called before the objects of the passed drawing manager are converted. */
    void                InitializeDrawing( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage );
    /** Processes BIFF5 drawing objects without DFF data, inserts into the passed object list. */
    void                ProcessObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj );
    void                ProcessObject( SdrObjList& rObjList, XclImpDrawObjBase& rDrawObj );
    /** Processes all objects in the passed list. */
    void                ProcessDrawing( const XclImpDrawObjVector& rDrawObjs );
    /** Processes a drawing container in the passed DFF stream, converts all objects. */
@@ -1017,6 +1021,8 @@
    void                InsertSdrObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj, SdrObject* pSdrObj );
    /** Initializes the mxCtrlForm referring to the standard controls form. */
    void                InitControlForm();
    /** Notify that this document contains a macro event handler */
    void                NotifyMacroEventRead();

private:
    typedef std::shared_ptr< ScfProgressBar >     ScfProgressBarRef;
@@ -1028,6 +1034,7 @@
    XclImpDffConvDataStack maDataStack;     /// Stack for registered drawing managers.
    sal_uInt32          mnOleImpFlags;      /// Application OLE import settings.
    sal_Int32           mnDefTextMargin;    /// Default margin in text boxes.
    bool mbNotifyMacroEventRead;            /// If we have already seen a macro event
};

// Drawing manager ============================================================
diff --git a/sc/source/ui/vba/vbasheetobject.cxx b/sc/source/ui/vba/vbasheetobject.cxx
index 2df219a..469e670 100644
--- a/sc/source/ui/vba/vbasheetobject.cxx
+++ b/sc/source/ui/vba/vbasheetobject.cxx
@@ -26,6 +26,7 @@
#include <com/sun/star/script/ScriptEventDescriptor.hpp>
#include <com/sun/star/script/XEventAttacherManager.hpp>
#include <com/sun/star/style/VerticalAlignment.hpp>
#include <comphelper/documentinfo.hxx>
#include <ooo/vba/excel/Constants.hpp>
#include <ooo/vba/excel/XlOrientation.hpp>
#include <ooo/vba/excel/XlPlacement.hpp>
@@ -298,7 +299,8 @@
        const uno::Reference< drawing::XControlShape >& rxControlShape ) :
    ScVbaControlObject_BASE( rxParent, rxContext, rxModel, uno::Reference< drawing::XShape >( rxControlShape, uno::UNO_QUERY_THROW ) ),
    mxFormIC( rxFormIC, uno::UNO_SET_THROW ),
    mxControlProps( rxControlShape->getControl(), uno::UNO_QUERY_THROW )
    mxControlProps( rxControlShape->getControl(), uno::UNO_QUERY_THROW ),
    mbNotifyMacroEventRead(false)
{
}

@@ -334,6 +336,14 @@
    return OUString();
}

void ScVbaControlObjectBase::NotifyMacroEventRead()
{
    if (mbNotifyMacroEventRead)
        return;
    comphelper::DocumentInfo::notifyMacroEventRead(mxModel);
    mbNotifyMacroEventRead = true;
}

void SAL_CALL ScVbaControlObjectBase::setOnAction( const OUString& rMacroName )
{
    uno::Reference< script::XEventAttacherManager > xEventMgr( mxFormIC, uno::UNO_QUERY_THROW );
@@ -353,6 +363,7 @@
        aDescriptor.EventMethod = gaEventMethod;
        aDescriptor.ScriptType = "Script";
        aDescriptor.ScriptCode = makeMacroURL( aResolvedMacro.msResolvedMacro );
        NotifyMacroEventRead();
        xEventMgr->registerScriptEvent( nIndex, aDescriptor );
    }
}
diff --git a/sc/source/ui/vba/vbasheetobject.hxx b/sc/source/ui/vba/vbasheetobject.hxx
index e53418a..94d88fbb 100644
--- a/sc/source/ui/vba/vbasheetobject.hxx
+++ b/sc/source/ui/vba/vbasheetobject.hxx
@@ -153,6 +153,9 @@
    virtual sal_Bool SAL_CALL getAutoSize() override;
    virtual void SAL_CALL setAutoSize( sal_Bool bAutoSize ) override;

    /// Notify that the document contains a macro event handler
    void NotifyMacroEventRead();

protected:
    /// @throws css::uno::RuntimeException
    sal_Int32 getModelIndexInForm() const;
@@ -160,6 +163,7 @@
protected:
    css::uno::Reference< css::container::XIndexContainer > mxFormIC;
    css::uno::Reference< css::beans::XPropertySet > mxControlProps;
    bool mbNotifyMacroEventRead;
};

typedef ::cppu::ImplInheritanceHelper< ScVbaControlObjectBase, ov::excel::XButton > ScVbaButton_BASE;
diff --git a/scripting/source/protocolhandler/scripthandler.cxx b/scripting/source/protocolhandler/scripthandler.cxx
index db38087..965827b 100644
--- a/scripting/source/protocolhandler/scripthandler.cxx
+++ b/scripting/source/protocolhandler/scripthandler.cxx
@@ -132,42 +132,32 @@
    {
        try
        {
            css::uno::Reference<css::uri::XUriReferenceFactory> urifac(
                css::uri::UriReferenceFactory::create(m_xContext));
            css::uno::Reference<css::uri::XVndSunStarScriptUrlReference> uri(
                urifac->parse(aURL.Complete), css::uno::UNO_QUERY_THROW);
            auto const loc = uri->getParameter("location");
            bool bIsDocumentScript = loc == "document";
            // obtain the component for our security check
            Reference< XEmbeddedScripts > xDocumentScripts;
            if ( getScriptInvocation() )
                xDocumentScripts.set( m_xScriptInvocation->getScriptContainer(), UNO_SET_THROW );

            if ( bIsDocumentScript )
            OSL_ENSURE( xDocumentScripts.is(), "ScriptProtocolHandler::dispatchWithNotification: can't do the security check!" );
            if ( !xDocumentScripts.is() || !xDocumentScripts->getAllowMacroExecution() )
            {
                // obtain the component for our security check
                Reference< XEmbeddedScripts > xDocumentScripts;
                if ( getScriptInvocation() )
                    xDocumentScripts.set( m_xScriptInvocation->getScriptContainer(), UNO_SET_THROW );

                OSL_ENSURE( xDocumentScripts.is(), "ScriptProtocolHandler::dispatchWithNotification: can't do the security check!" );
                if ( !xDocumentScripts.is() || !xDocumentScripts->getAllowMacroExecution() )
                if ( xListener.is() )
                {
                    if ( xListener.is() )
                    css::frame::DispatchResultEvent aEvent(
                            static_cast< ::cppu::OWeakObject* >( this ),
                            css::frame::DispatchResultState::FAILURE,
                            invokeResult );
                    try
                    {
                        css::frame::DispatchResultEvent aEvent(
                                static_cast< ::cppu::OWeakObject* >( this ),
                                css::frame::DispatchResultState::FAILURE,
                                invokeResult );
                        try
                        {
                            xListener->dispatchFinished( aEvent ) ;
                        }
                        catch(const RuntimeException &)
                        {
                            TOOLS_WARN_EXCEPTION("scripting",
                                "ScriptProtocolHandler::dispatchWithNotification: caught RuntimeException"
                                "while dispatchFinished with failure of the execution");
                        }
                        xListener->dispatchFinished( aEvent ) ;
                    }
                    return;
                    catch(const RuntimeException &)
                    {
                        TOOLS_WARN_EXCEPTION("scripting",
                            "ScriptProtocolHandler::dispatchWithNotification: caught RuntimeException"
                            "while dispatchFinished with failure of the execution");
                    }
                }
                return;
            }

            // Creates a ScriptProvider ( if one is not created already )
@@ -204,8 +194,7 @@

            // attempt to protect the document against the script tampering with its Undo Context
            std::unique_ptr< ::framework::DocumentUndoGuard > pUndoGuard;
            if ( bIsDocumentScript )
                pUndoGuard.reset( new ::framework::DocumentUndoGuard( m_xScriptInvocation ) );
            pUndoGuard.reset( new ::framework::DocumentUndoGuard( m_xScriptInvocation ) );

            bSuccess = false;
            while ( !bSuccess )
diff --git a/sfx2/source/doc/docmacromode.cxx b/sfx2/source/doc/docmacromode.cxx
index cef89b0..d43c1b1 100644
--- a/sfx2/source/doc/docmacromode.cxx
+++ b/sfx2/source/doc/docmacromode.cxx
@@ -394,7 +394,7 @@
        }
        else
        {
            if ( m_xData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() )
            if (m_xData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() || m_xData->m_rDocumentAccess.macroCallsSeenWhileLoading())
            {
                bAllow = adjustMacroMode( rxInteraction );
            }
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx
index d9ab5e4..a61e1e8 100644
--- a/sfx2/source/doc/objmisc.cxx
+++ b/sfx2/source/doc/objmisc.cxx
@@ -1388,13 +1388,7 @@
    Any aException;
    try
    {
        css::uno::Reference<css::uri::XUriReferenceFactory> urifac(
            css::uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()));
        css::uno::Reference<css::uri::XVndSunStarScriptUrlReference> uri(
            urifac->parse(_rScriptURL), css::uno::UNO_QUERY_THROW);
        auto const loc = uri->getParameter("location");
        bool bIsDocumentScript = loc == "document";
        if ( bIsDocumentScript && !lcl_isScriptAccessAllowed_nothrow( _rxScriptContext ) )
        if ( !lcl_isScriptAccessAllowed_nothrow( _rxScriptContext ) )
            return ERRCODE_IO_ACCESSDENIED;

        if ( UnTrustedScript(_rScriptURL) )
@@ -1756,6 +1750,11 @@
    return ::sfx2::DocumentMacroMode::storageHasMacros( m_xDocStorage );
}

bool SfxObjectShell_Impl::macroCallsSeenWhileLoading() const
{
    return rDocShell.GetMacroCallsSeenWhileLoading();
}

Reference< XEmbeddedScripts > SfxObjectShell_Impl::getEmbeddedDocumentScripts() const
{
    return Reference< XEmbeddedScripts >( rDocShell.GetModel(), UNO_QUERY );
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 45326e2..8265329 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -3579,6 +3579,16 @@
    pImpl->m_bConfigOptionsChecked = bChecked;
}

void SfxObjectShell::SetMacroCallsSeenWhileLoading()
{
    pImpl->m_bMacroCallsSeenWhileLoading = true;
}

bool SfxObjectShell::GetMacroCallsSeenWhileLoading() const
{
    return pImpl->m_bMacroCallsSeenWhileLoading;
}

bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference< task::XInteractionHandler >& xHandler )
{
#if !HAVE_FEATURE_SCRIPTING
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index c60af88..5e5cb85 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -235,6 +235,7 @@
    ,m_bSharedXMLFlag( false )
    ,m_bAllowShareControlFileClean( true )
    ,m_bConfigOptionsChecked( false )
    ,m_bMacroCallsSeenWhileLoading( false )
    ,lErr(ERRCODE_NONE)
    ,nEventId ( SfxEventHintId::NONE )
    ,nLoadedFlags ( SfxLoadedFlags::ALL )
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 3d0dc17..7742d5e 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -889,8 +889,15 @@
            pObjectShell->BreakMacroSign_Impl( bBreakMacroSign );
        }

        bool bMacroEventRead = false;
        if ((aArgs.get("MacroEventRead") >>= bMacroEventRead) && bMacroEventRead)
        {
            pObjectShell->SetMacroCallsSeenWhileLoading();
        }

        aArgs.remove( "WinExtent" );
        aArgs.remove( "BreakMacroSignature" );
        aArgs.remove( "MacroEventRead" );
        aArgs.remove( "Stream" );
        aArgs.remove( "InputStream" );
        aArgs.remove( "URL" );
diff --git a/sfx2/source/inc/objshimp.hxx b/sfx2/source/inc/objshimp.hxx
index d31414b..d52ee83 100644
--- a/sfx2/source/inc/objshimp.hxx
+++ b/sfx2/source/inc/objshimp.hxx
@@ -90,7 +90,8 @@
                        bSaveVersionOnClose:1,
                        m_bSharedXMLFlag:1, // whether the document should be edited in shared mode
                        m_bAllowShareControlFileClean:1, // whether the flag should be stored in xml file
                        m_bConfigOptionsChecked:1; // whether or not the user options are checked after the Options dialog is closed.
                        m_bConfigOptionsChecked:1, // whether or not the user options are checked after the Options dialog is closed.
                        m_bMacroCallsSeenWhileLoading:1; // whether or not the user options are checked after the Options dialog is closed.

    IndexBitSet         aBitSet;
    ErrCode             lErr;
@@ -138,6 +139,7 @@
    virtual void setCurrentMacroExecMode( sal_uInt16 nMacroMode ) override;
    virtual OUString getDocumentLocation() const override;
    virtual bool documentStorageHasMacros() const override;
    virtual bool macroCallsSeenWhileLoading() const override;
    virtual css::uno::Reference< css::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const override;
    virtual SignatureState getScriptingSignatureState() override;

diff --git a/sw/source/filter/html/htmlform.cxx b/sw/source/filter/html/htmlform.cxx
index 78c8d82..74ae9f7 100644
--- a/sw/source/filter/html/htmlform.cxx
+++ b/sw/source/filter/html/htmlform.cxx
@@ -18,6 +18,7 @@
 */

#include <hintids.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/string.hxx>
#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
@@ -733,7 +734,7 @@
    rShape->setSize( aSz );
}

static void lcl_html_setEvents(
static bool lcl_html_setEvents(
        const uno::Reference< script::XEventAttacherManager > & rEvtMn,
        sal_uInt32 nPos, const SvxMacroTableDtor& rMacroTable,
        const std::vector<OUString>& rUnoMacroTable,
@@ -762,7 +763,7 @@
    }

    if( 0==nEvents )
        return;
        return false;

    Sequence<script::ScriptEventDescriptor> aDescs( nEvents );
    script::ScriptEventDescriptor* pDescs = aDescs.getArray();
@@ -820,6 +821,7 @@
        }
    }
    rEvtMn->registerScriptEvents( nPos, aDescs );
    return true;
}

static void lcl_html_getEvents( const OUString& rOption, const OUString& rValue,
@@ -1188,10 +1190,12 @@
    // To prevent previous JavaScript-Events from being called, these events will only be set retroactively
    if( !rMacroTable.empty() || !rUnoMacroTable.empty() )
    {
        lcl_html_setEvents( m_pFormImpl->GetControlEventManager(),
        bool bHasEvents = lcl_html_setEvents( m_pFormImpl->GetControlEventManager(),
                            rFormComps->getCount() - 1,
                            rMacroTable, rUnoMacroTable, rUnoMacroParamTable,
                            GetScriptTypeString(m_pFormImpl->GetHeaderAttrs()) );
        if (bHasEvents)
            NotifyMacroEventRead();
    }

    if( bSetFCompPropSet )
@@ -1353,10 +1357,14 @@
    Any aAny( &xForm, cppu::UnoType<XForm>::get());
    rForms->insertByIndex( rForms->getCount(), aAny );
    if( !aMacroTable.empty() )
        lcl_html_setEvents( m_pFormImpl->GetFormEventManager(),
    {
        bool bHasEvents = lcl_html_setEvents( m_pFormImpl->GetFormEventManager(),
                            rForms->getCount() - 1,
                            aMacroTable, aUnoMacroTable, aUnoMacroParamTable,
                            rDfltScriptType );
        if (bHasEvents)
            NotifyMacroEventRead();
    }
}

void SwHTMLParser::EndForm( bool bAppend )
diff --git a/sw/source/filter/html/htmlgrin.cxx b/sw/source/filter/html/htmlgrin.cxx
index 9ca5a22..85991d6 100644
--- a/sw/source/filter/html/htmlgrin.cxx
+++ b/sw/source/filter/html/htmlgrin.cxx
@@ -20,6 +20,7 @@
#include <memory>
#include <hintids.hxx>
#include <comphelper/string.hxx>
#include <comphelper/documentinfo.hxx>
#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
#include <svx/svxids.hrc>
@@ -871,7 +872,10 @@
    }

    if( !aMacroItem.GetMacroTable().empty() )
    {
        NotifyMacroEventRead();
        pFlyFormat->SetFormatAttr( aMacroItem );
    }

    // tdf#87083 If the graphic has not been loaded yet, then load it now.
    // Otherwise it may be loaded during the first paint of the object and it
@@ -1304,7 +1308,10 @@
        aINetFormat.SetName( aName );

        if( !aMacroTable.empty() )
        {
            NotifyMacroEventRead();
            aINetFormat.SetMacroTable( &aMacroTable );
        }

        // set the default attribute
        InsertAttr(&m_xAttrTab->pINetFormat, aINetFormat, xCntxt.get());
@@ -1516,4 +1523,16 @@
    }
}

void SwHTMLParser::NotifyMacroEventRead()
{
    if (m_bNotifyMacroEventRead)
        return;
    SwDocShell *pDocSh = m_xDoc->GetDocShell();
    if (!pDocSh)
        return;
    uno::Reference<frame::XModel> const xModel(pDocSh->GetBaseModel());
    comphelper::DocumentInfo::notifyMacroEventRead(xModel);
    m_bNotifyMacroEventRead = true;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
index 0a9f87b..546040c 100644
--- a/sw/source/filter/html/swhtml.cxx
+++ b/sw/source/filter/html/swhtml.cxx
@@ -311,6 +311,7 @@
    m_bRemoveHidden( false ),
    m_bBodySeen( false ),
    m_bReadingHeaderOrFooter( false ),
    m_bNotifyMacroEventRead( false ),
    m_isInTableStructure(false),
    m_nTableDepth( 0 ),
    m_pTempViewFrame(nullptr)
diff --git a/sw/source/filter/html/swhtml.hxx b/sw/source/filter/html/swhtml.hxx
index 6aa7029..b931042 100644
--- a/sw/source/filter/html/swhtml.hxx
+++ b/sw/source/filter/html/swhtml.hxx
@@ -452,6 +452,7 @@

    bool m_bBodySeen : 1;
    bool m_bReadingHeaderOrFooter : 1;
    bool m_bNotifyMacroEventRead : 1;
    bool m_isInTableStructure;

    sal_Int32 m_nTableDepth;
@@ -923,6 +924,8 @@

    bool IsReqIF() const;

    void NotifyMacroEventRead();

    /// Strips query and fragment from a URL path if base URL is a file:// one.
    static OUString StripQueryFromPath(const OUString& rBase, const OUString& rPath);
};
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 11712b8..c1ac48f 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -42,6 +42,7 @@
#include <unotools/tempfile.hxx>

#include <comphelper/docpasswordrequest.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/propertysequence.hxx>

#include <editeng/outlobj.hxx>
@@ -4308,6 +4309,7 @@
    , m_aTOXEndCps()
    , m_aCurrAttrCP(-1)
    , m_bOnLoadingMain(false)
    , m_bNotifyMacroEventRead(false)
{
    m_pStrm->SetEndian( SvStreamEndian::LITTLE );
    m_aApos.push_back(false);
@@ -4698,6 +4700,8 @@

        try
        {
            NotifyMacroEventRead();

            uno::Reference < io::XStream > xStream =
                    xRoot->openStreamElement( SL::aMSMacroCmds, embed::ElementModes::READWRITE );
            std::unique_ptr<SvStream> xOutStream(::utl::UcbStreamHelper::CreateStream(xStream));
@@ -6555,4 +6559,13 @@
    return xRet;
}

void SwWW8ImplReader::NotifyMacroEventRead()
{
    if (m_bNotifyMacroEventRead)
        return;
    uno::Reference<frame::XModel> const xModel(m_rDoc.GetDocShell()->GetBaseModel());
    comphelper::DocumentInfo::notifyMacroEventRead(xModel);
    m_bNotifyMacroEventRead = true;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 097b330..f043d44 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -1376,6 +1376,7 @@
    cp_vector m_aEndParaPos;
    WW8_CP m_aCurrAttrCP;
    bool m_bOnLoadingMain:1;
    bool m_bNotifyMacroEventRead:1;

    const SprmReadInfo& GetSprmReadInfo(sal_uInt16 nId) const;

@@ -1911,6 +1912,7 @@

    void PostProcessAttrs();
    void ReadEmbeddedData(SvStream& rStrm, SwDocShell const * pDocShell, struct HyperLinksTable& hlStr);
    void NotifyMacroEventRead();
};

bool CanUseRemoteLink(const OUString &rGrfName);
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 8b276ea..2d708ff 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -2272,6 +2272,8 @@
    if( aName.isEmpty() )
        return eF_ResT::TAGIGN;  // makes no sense without Macro-Name

    NotifyMacroEventRead();

    //try converting macro symbol according to macro name
    bool bApplyWingdings = ConvertMacroSymbol( aName, aVText );
    aName = "StarOffice.Standard.Modul1." + aName;
diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx
index b2b04e7..525b557 100644
--- a/xmloff/source/core/xmlimp.cxx
+++ b/xmloff/source/core/xmlimp.cxx
@@ -63,6 +63,7 @@
#include <cppuhelper/supportsservice.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/documentconstants.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/attributelist.hxx>
#include <unotools/fontcvt.hxx>
@@ -400,7 +401,8 @@
    isFastContext( false ),
    maNamespaceHandler( new SvXMLImportFastNamespaceHandler() ),
    mbIsFormsSupported( true ),
    mbIsTableShapeSupported( false )
    mbIsTableShapeSupported( false ),
    mbNotifyMacroEventRead( false )
{
    SAL_WARN_IF( !xContext.is(), "xmloff.core", "got no service manager" );
    InitCtor_();
@@ -2155,6 +2157,16 @@
    }
}

void SvXMLImport::NotifyMacroEventRead()
{
    if (mbNotifyMacroEventRead)
        return;

    comphelper::DocumentInfo::notifyMacroEventRead(mxModel);

    mbNotifyMacroEventRead = true;
}

SvXMLImportFastNamespaceHandler::SvXMLImportFastNamespaceHandler()
{
}
diff --git a/xmloff/source/script/XMLEventImportHelper.cxx b/xmloff/source/script/XMLEventImportHelper.cxx
index ffc6089..42788bb 100644
--- a/xmloff/source/script/XMLEventImportHelper.cxx
+++ b/xmloff/source/script/XMLEventImportHelper.cxx
@@ -36,7 +36,6 @@
{
}


XMLEventImportHelper::~XMLEventImportHelper()
{
    // delete factories
@@ -107,6 +106,8 @@
    const OUString& rXmlEventName,
    const OUString& rLanguage)
{
    rImport.NotifyMacroEventRead();

    SvXMLImportContext* pContext = nullptr;

    // translate event name from xml to api