don't load the document Basic to parse formula names during ODF import
While macros are not yet allowed, a called name is kept as a macro call if the document has Basic libraries at all. A cell macro call now decides the macro mode before it loads the document Basic. Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com> Change-Id: I2f33b51490db8515cd74d5e753bb9a18c5e6a587 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/13626 Reviewed-by: Noel Grandin <noel.grandin@collabora.com> (cherry picked from commit d17fd31994d71c28f503bb3cc93471c307756627) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211523 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
b693937e99
commit
51744f6265
@@ -438,6 +438,9 @@ public:
|
||||
*/
|
||||
bool AdjustMacroMode();
|
||||
|
||||
/// whether macros from this document are already allowed to run, without asking
|
||||
bool IsMacroExecutionAllowed() const;
|
||||
|
||||
static bool UnTrustedScript(const OUString& rScriptURL);
|
||||
|
||||
/// Check if script URL whitelist exists, and if so, if current script url is part of it
|
||||
|
||||
+1
-1
@@ -362,7 +362,7 @@ private:
|
||||
bool ParseDoubleReference( const OUString& rSymbol, const OUString* pErrRef = nullptr );
|
||||
bool ParsePredetectedReference( const OUString& rSymbol );
|
||||
bool ParsePredetectedErrRefReference( const OUString& rName, const OUString* pErrRef );
|
||||
bool ParseMacro( const OUString& );
|
||||
bool ParseMacro( const OUString&, bool bParenFollows );
|
||||
bool ParseNamedRange( const OUString&, bool onlyCheck = false );
|
||||
bool ParseLocalName( const OUString& );
|
||||
bool ParseExternalNamedRange( const OUString& rSymbol, bool& rbInvalidExternalNameRange );
|
||||
|
||||
@@ -62,8 +62,13 @@ ScMacroFunction::ScMacroFunction(const ScInterpreter& rInterpreter, const OUStri
|
||||
return;
|
||||
}
|
||||
|
||||
// The macro security prompt is not raised here. CallBasic checks it when
|
||||
// the macro actually runs.
|
||||
// The macro mode is decided before the document's Basic is loaded.
|
||||
if (!mpDocShell->AdjustMacroMode())
|
||||
{
|
||||
mbInvalid = true;
|
||||
mnError = FormulaError::NoMacro;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the Basic method by name, then keep the library and macro name
|
||||
// strings that CallBasic needs to invoke it.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <vcl/settings.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/docmacromode.hxx>
|
||||
#include <sfx2/objsh.hxx>
|
||||
#include <basic/sbmeth.hxx>
|
||||
#include <basic/sbstar.hxx>
|
||||
@@ -3753,10 +3754,30 @@ bool ScCompiler::ParseReference( const OUString& rName, const OUString* pErrRef
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScCompiler::ParseMacro( const OUString& rName )
|
||||
#if HAVE_FEATURE_SCRIPTING
|
||||
static bool lcl_IsBasicFunction( StarBASIC& rBasic, const OUString& rName )
|
||||
{
|
||||
SbxMethod* pMeth = static_cast<SbxMethod*>(rBasic.Find( rName, SbxClassType::Method ));
|
||||
if( !pMeth )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// It really should be a BASIC function!
|
||||
if( pMeth->GetType() == SbxVOID
|
||||
|| ( pMeth->IsFixed() && pMeth->GetType() == SbxEMPTY )
|
||||
|| dynamic_cast<const SbMethod*>( pMeth) == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ScCompiler::ParseMacro( const OUString& rName, bool bParenFollows )
|
||||
{
|
||||
#if !HAVE_FEATURE_SCRIPTING
|
||||
(void) rName;
|
||||
(void) bParenFollows;
|
||||
|
||||
return false;
|
||||
#else
|
||||
@@ -3780,9 +3801,36 @@ bool ScCompiler::ParseMacro( const OUString& rName )
|
||||
}
|
||||
|
||||
OUString aName( rName);
|
||||
// ODFF recommends to store user-defined functions prefixed with "USER.",
|
||||
// use only unprefixed name if encountered. BASIC doesn't allow '.' in a
|
||||
// function name so a function "USER.FOO" could not exist, and macro check
|
||||
// is assigned the lowest priority in function name check.
|
||||
if (FormulaGrammar::isODFF( GetGrammar()) && aName.startsWithIgnoreAsciiCase("USER."))
|
||||
aName = aName.copy(5);
|
||||
|
||||
StarBASIC* pObj = nullptr;
|
||||
ScDocShell* pDocSh = rDoc.GetDocumentShell();
|
||||
|
||||
// During ODF import the Basic of a document whose macros are not allowed yet stays unloaded.
|
||||
// A called name that is not an application Basic function may be one of the document's own
|
||||
// macros only if the document has Basic libraries. Such a call is kept as a macro call, and the
|
||||
// document is flagged as calling macros.
|
||||
if (pDocSh && rDoc.IsImportingXML() && !pDocSh->IsMacroExecutionAllowed())
|
||||
{
|
||||
if (!bParenFollows)
|
||||
return false;
|
||||
StarBASIC* pAppBasic = SfxApplication::GetBasic();
|
||||
if (!pAppBasic || !lcl_IsBasicFunction(*pAppBasic, aName))
|
||||
{
|
||||
if (!sfx2::DocumentMacroMode::containerHasBasicMacros(pDocSh->GetBasicContainer()))
|
||||
return false;
|
||||
pDocSh->SetMacroCallsSeenWhileLoading();
|
||||
}
|
||||
maRawToken.SetExternal( aName );
|
||||
maRawToken.eOp = ocMacro;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if( pDocSh )//XXX
|
||||
@@ -3795,28 +3843,9 @@ bool ScCompiler::ParseMacro( const OUString& rName )
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pObj)
|
||||
if (!pObj || !lcl_IsBasicFunction(*pObj, aName))
|
||||
return false;
|
||||
|
||||
// ODFF recommends to store user-defined functions prefixed with "USER.",
|
||||
// use only unprefixed name if encountered. BASIC doesn't allow '.' in a
|
||||
// function name so a function "USER.FOO" could not exist, and macro check
|
||||
// is assigned the lowest priority in function name check.
|
||||
if (FormulaGrammar::isODFF( GetGrammar()) && aName.startsWithIgnoreAsciiCase("USER."))
|
||||
aName = aName.copy(5);
|
||||
|
||||
SbxMethod* pMeth = static_cast<SbxMethod*>(pObj->Find( aName, SbxClassType::Method ));
|
||||
if( !pMeth )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// It really should be a BASIC function!
|
||||
if( pMeth->GetType() == SbxVOID
|
||||
|| ( pMeth->IsFixed() && pMeth->GetType() == SbxEMPTY )
|
||||
|| dynamic_cast<const SbMethod*>( pMeth) == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
maRawToken.SetExternal( aName );
|
||||
maRawToken.eOp = ocMacro;
|
||||
return true;
|
||||
@@ -4960,7 +4989,7 @@ Label_Rewind:
|
||||
if (!bParenFollows && ParseColRowName( aUpper ))
|
||||
return true;
|
||||
|
||||
if (ParseMacro( aUpper ))
|
||||
if (ParseMacro( aUpper, bParenFollows ))
|
||||
return true;
|
||||
|
||||
if (ParseOpCode( aUpper, bInArray ))
|
||||
@@ -5047,7 +5076,7 @@ Label_Rewind:
|
||||
// the same user-defined function, so in the call position the macro
|
||||
// takes priority over a same-named defined name. A plain name
|
||||
// reference still resolves as the named range.
|
||||
if (bMayBeName && bParenFollows && ParseMacro(aUpper))
|
||||
if (bMayBeName && bParenFollows && ParseMacro(aUpper, bParenFollows))
|
||||
return true;
|
||||
|
||||
if (ParseNamedRange( aUpper ))
|
||||
@@ -5084,7 +5113,7 @@ Label_Rewind:
|
||||
|
||||
if (bMayBeName)
|
||||
{
|
||||
if (ParseMacro( aUpper ))
|
||||
if (ParseMacro( aUpper, bParenFollows ))
|
||||
return true;
|
||||
|
||||
if (ParseLocalName( aOrg ))
|
||||
|
||||
@@ -1742,6 +1742,11 @@ bool SfxObjectShell::AdjustMacroMode()
|
||||
return pImpl->aMacroMode.adjustMacroMode( xInteraction );
|
||||
}
|
||||
|
||||
bool SfxObjectShell::IsMacroExecutionAllowed() const
|
||||
{
|
||||
return pImpl->getCurrentMacroExecMode() == MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
|
||||
}
|
||||
|
||||
css::uno::Reference<css::awt::XWindow> SfxObjectShell::GetDialogParent( SfxMedium const * pLoadingMedium )
|
||||
{
|
||||
css::uno::Reference<css::awt::XWindow> xWindow;
|
||||
|
||||
Reference in New Issue
Block a user