extensions/urho3d: Provide the API and an improved version of SubscribeToEvent() to the unsafe environment

master
Perttu Ahola 2014-09-26 08:55:10 +03:00
parent 990569c02a
commit 4cd96ea32a
2 changed files with 102 additions and 14 deletions

View File

@ -3,6 +3,7 @@ Buildat Client API
Lua code is run in two subtly different environments.
Interface common to both environments
=====================================
@ -26,6 +27,7 @@ buildat.unsub_packet(function)
buildat.run_script_file(name)
- Run script file gotten from server in sandbox environment
The extension environment
=========================
@ -43,6 +45,7 @@ requires the module, it only gets the plain safe interface.
Extensions and modules use require("buildat/extension/<name>") to use extensions.
The sandbox environment
=======================
@ -53,6 +56,7 @@ buildat.make_global(table)
still not leak into the scope of other files running in the sandbox. Useful if
you want to remove the "namespace table" of an extension.
Safe interfaces of built-in extensions
======================================
@ -99,3 +103,27 @@ Whitelist-based wrapper for the Urho3D Lua API.
File paths and other things are converted automatically.
Additions to regular Urho3D:
SubscribeToEvent(event_name, callback)
- Callback can be a function, unlike in plain Urho3D where it must be a global
function name.
Unsafe interfaces of built-in extensions
========================================
urho3d
------
The unsafe version of the urho3d extension actually just wraps to the global
environment, except for the additions to the API documented here.
Note that Urho3D's API is currently always globally defined in the extension
environment, but this will not be supported in the future.
Additions to regular Urho3D:
SubscribeToEvent(event_name, callback)
- Callback can be a function, unlike in plain Urho3D where it must be a global
function name.

View File

@ -5,6 +5,10 @@ local log = buildat.Logger("extension/urho3d")
local dump = buildat.dump
local M = {safe = {}}
--
-- Safe interface
--
-- Set every plain value in global environment to the sandbox
-- ...it's maybe safe enough... TODO: Not safe
for k, v in pairs(_G) do
@ -156,27 +160,83 @@ M.safe.cache = {
-- SubscribeToEvent
local sandbox_function_name_to_global_function_name = {}
local next_global_function_i = 1
local sandbox_callback_to_global_function_name = {}
local next_sandbox_global_function_i = 1
function M.safe.SubscribeToEvent(event_name, function_name)
local caller_environment = getfenv(2)
local callback = caller_environment[function_name]
if type(callback) ~= 'function' then
error("SubscribeToEvent(): '"..function_name..
"' is not a global function in current sandbox environment")
function M.safe.SubscribeToEvent(event_name, callback)
if type(callback) == 'string' then
-- Allow supplying callback function name like Urho3D does by default
local caller_environment = getfenv(2)
callback = caller_environment[callback]
if type(callback) ~= 'function' then
error("SubscribeToEvent(): '"..callback..
"' is not a global function in current sandbox environment")
end
else
-- Allow directly supplying callback function
end
local global_function_i = next_global_function_i
next_global_function_i = next_global_function_i + 1
local global_function_name = "__buildat_sandbox_callback_"..global_function_i
sandbox_function_name_to_global_function_name[function_name] = global_function_name
_G[global_function_name] = function(eventType, eventData)
local global_function_i = next_sandbox_global_function_i
next_sandbox_global_function_i = next_sandbox_global_function_i + 1
local global_callback = "__buildat_sandbox_callback_"..global_function_i
sandbox_callback_to_global_function_name[callback] = global_callback
_G[global_callback] = function(eventType, eventData)
local f = function()
callback(eventType, eventData)
end
__buildat_run_function_in_sandbox(f)
end
SubscribeToEvent(event_name, global_function_name)
SubscribeToEvent(event_name, global_callback)
end
--
-- Unsafe interface
--
-- Just wrap everything to the global environment as we don't have a full list
-- of Urho3D's API available.
setmetatable(M, {
__index = function(t, k)
local v = rawget(t, k)
if v ~= nil then return v end
return _G[k]
end,
})
-- Add GetResource wrapper to ResourceCache instance
--[[M.cache.GetResource = function(self, resource_type, resource_name)
local path = M.resave_file(resource_name)
-- Note: path is unused
resource_name = M.check_safe_resource_name(resource_name)
return M.cache:GetResource(resource_type, resource_name)
end]]
-- Unsafe SubscribeToEvent with function support
local unsafe_callback_to_global_function_name = {}
local next_unsafe_global_function_i = 1
function M.SubscribeToEvent(event_name, callback)
if type(callback) == 'string' then
-- Allow supplying callback function name like Urho3D does by default
local caller_environment = getfenv(2)
callback = caller_environment[callback]
if type(callback) ~= 'function' then
error("SubscribeToEvent(): '"..callback..
"' is not a global function in current unsafe environment")
end
else
-- Allow directly supplying callback function
end
local global_function_i = next_unsafe_global_function_i
next_unsafe_global_function_i = next_unsafe_global_function_i + 1
local global_callback = "__buildat_unsafe_callback_"..global_function_i
unsafe_callback_to_global_function_name[callback] = global_callback
_G[global_callback] = function(eventType, eventData)
callback(eventType, eventData)
end
SubscribeToEvent(event_name, global_callback)
end
return M