Files
moonwell-client/reference/FrameXML/RestrictedEnvironment.lua

238 lines
6.3 KiB
Lua

-- RestrictedEnvironment.lua (Part of the new Secure Headers implementation)
--
-- This file defines the environment available to restricted code. The
-- 'base' API functions (everything that's safe to use from the core
-- WoW lua API), and functions which provide the same degree of game state
-- as macro conditionals.
--
-- Nevin Flanagan (alestane@comcast.net)
-- Daniel Stephens (iriel@vigilance-committee.org)
---------------------------------------------------------------------------
---------------------------------------------------------------------------
-- Somewhat extensible print infrastructure for debugging, modelled around
-- error handler code.
--
-- setprinthandler(func) -- Sets the active print handler
-- func = getprinthandler() -- Gets the current print handler
-- print(...) -- Passes its arguments to the current print handler
--
-- The default print handler simply strjoin's its arguments with a " "
-- delimiter and adds it to DEFAULT_CHAT_FRAME
local select = select;
local tostring = tostring;
local type = type;
local LOCAL_ToStringAllTemp = {};
function tostringall(...)
local n = select('#', ...);
-- Simple versions for common argument counts
if (n == 1) then
return tostring(...);
elseif (n == 2) then
local a, b = ...;
return tostring(a), tostring(b);
elseif (n == 3) then
local a, b, c = ...;
return tostring(a), tostring(b), tostring(c);
elseif (n == 0) then
return;
end
local needfix;
for i = 1, n do
local v = select(i, ...);
if (type(v) ~= "string") then
needfix = i;
break;
end
end
if (not needfix) then return ...; end
wipe(LOCAL_ToStringAllTemp);
for i = 1, needfix - 1 do
LOCAL_ToStringAllTemp[i] = select(i, ...);
end
for i = needfix, n do
LOCAL_ToStringAllTemp[i] = tostring(select(i, ...));
end
return unpack(LOCAL_ToStringAllTemp);
end
local LOCAL_PrintHandler =
function(...)
DEFAULT_CHAT_FRAME:AddMessage(strjoin(" ", tostringall(...)));
end
function setprinthandler(func)
if (type(func) ~= "function") then
error("Invalid print handler");
else
LOCAL_PrintHandler = func;
end
end
function getprinthandler() return LOCAL_PrintHandler; end
local geterrorhandler = geterrorhandler;
local forceinsecure = forceinsecure;
local pcall = pcall;
local securecall = securecall;
local function print_inner(...)
forceinsecure();
local ok, err = pcall(LOCAL_PrintHandler, ...);
if (not ok) then
local func = geterrorhandler();
func(err);
end
end
function print(...)
securecall(pcall, print_inner, ...);
end
-- The bare minimum functions that should exist in order to be
-- useful without being ridiculously restrictive.
RESTRICTED_FUNCTIONS_SCOPE = {
math = math;
string = string;
-- table is provided elsewhere, as direct tables are not allowed
select = select;
tonumber = tonumber;
tostring = tostring;
print = print;
-- String methods
format = format;
gmatch = gmatch;
gsub = gsub; -- Restricted table aware rtgsub is added later
strbyte = strbyte;
strchar = strchar;
strconcat = strconcat;
strfind = strfind;
strjoin = strjoin;
strlen = strlen;
strlower = strlower;
strmatch = strmatch;
strrep = strrep;
strrev = strrev;
strsplit = strsplit;
strsub = strsub;
strtrim = strtrim;
strupper = strupper;
-- Math functions
abs = abs;
acos = acos;
asin = asin;
atan = atan;
atan2 = atan2;
ceil = ceil;
cos = cos;
deg = deg;
exp = exp;
floor = floor;
frexp = frexp;
ldexp = ldexp;
log = log;
log10 = log10;
max = max;
min = min;
mod = mod;
rad = rad;
random = random;
sin = sin;
tan = tan;
};
-- Initialize directly available functions so they can be copied into the
-- table
local DIRECT_MACRO_CONDITIONAL_NAMES = {
"SecureCmdOptionParse",
"GetShapeshiftForm", "IsStealthed",
"UnitExists", "UnitIsDead", "UnitIsGhost",
"UnitPlayerOrPetInParty", "UnitPlayerOrPetInRaid",
"IsRightAltKeyDown", "IsLeftAltKeyDown", "IsAltKeyDown",
"IsRightControlKeyDown", "IsLeftControlKeyDown", "IsControlKeyDown",
"IsLeftShiftKeyDown", "IsRightShiftKeyDown", "IsShiftKeyDown",
"IsModifierKeyDown", "IsModifiedClick",
"GetMouseButtonClicked", "GetActionBarPage", "GetBonusBarOffset",
"IsMounted", "IsSwimming", "IsFlying", "IsFlyableArea",
"IsIndoors", "IsOutdoors",
};
local OTHER_SAFE_FUNCTION_NAMES = {
"GetBindingKey", "HasAction",
"IsHarmfulSpell", "IsHarmfulItem", "IsHelpfulSpell", "IsHelpfulItem",
"GetMultiCastTotemSpells"
};
-- Copy the direct functions into the table
for _, name in ipairs( DIRECT_MACRO_CONDITIONAL_NAMES ) do
RESTRICTED_FUNCTIONS_SCOPE[name] = _G[name];
end
-- Copy the other safe functions into the table
for _, name in ipairs( OTHER_SAFE_FUNCTION_NAMES ) do
RESTRICTED_FUNCTIONS_SCOPE[name] = _G[name];
end
-- Now create the remainder (ENV is just an alias for brevity)
local ENV = RESTRICTED_FUNCTIONS_SCOPE;
function ENV.PlayerCanAttack( unit )
return UnitCanAttack( "player", unit )
end
function ENV.PlayerCanAssist( unit )
return UnitCanAssist( "player", unit )
end
function ENV.PlayerIsChanneling()
return (UnitChannelInfo( "player" ) ~= nil)
end
function ENV.PlayerPetSummary()
return UnitCreatureFamily( "pet" ), (UnitName( "pet" ))
end
function ENV.PlayerInCombat()
return UnitAffectingCombat( "player" ) or UnitAffectingCombat( "pet" )
end
function ENV.PlayerInGroup()
return ( GetNumRaidMembers() > 0 and "raid" )
or ( GetNumPartyMembers() > 0 and "party" )
end
function ENV.UnitHasVehicleUI(unit)
unit = tostring(unit);
return UnitHasVehicleUI(unit) and
(UnitCanAssist("player", unit:gsub("(%D+)(%d*)", "%1pet%2")) and true) or
(UnitCanAssist("player", unit) and false);
end
function ENV.RegisterStateDriver(frameHandle, ...)
return RegisterStateDriver(GetFrameHandleFrame(frameHandle), ...)
end
local safeActionTypes = {["spell"] = true, ["companion"] = true, ["item"] = true, ["macro"] = true}
local function scrubActionInfo(actionType, ...)
if ( safeActionTypes[actionType]) then
return actionType, ...
else
return actionType
end
end
function ENV.GetActionInfo(...)
return scrubActionInfo(GetActionInfo(...));
end
ENV = nil;