client: Allow loading module's module.lua via require("buildat/module/<name>")
This commit is contained in:
parent
60874360d9
commit
fb51bc6cbe
@ -6,6 +6,7 @@ local log = buildat.Logger("__client/extensions")
|
||||
-- Extension interfaces, indexed by extension name
|
||||
local loaded_extensions = {}
|
||||
|
||||
-- Called by this file and client/sandbox.lua
|
||||
function __buildat_require_extension(name)
|
||||
log:debug("__buildat_require_extension(\""..name.."\")")
|
||||
if loaded_extensions[name] then
|
||||
@ -28,6 +29,8 @@ end
|
||||
|
||||
-- Don't use package.loaders because for whatever reason it doesn't work in the
|
||||
-- Windows version at least in Wine
|
||||
-- TODO: Was that due to the table indexing bug which was fixed by using LuaJIT
|
||||
-- instead of Lua?
|
||||
local old_require = require
|
||||
|
||||
function require(name)
|
||||
|
@ -82,6 +82,7 @@ dofile(__buildat_get_path("share").."/client/packet.lua")
|
||||
dofile(__buildat_get_path("share").."/client/extensions.lua")
|
||||
dofile(__buildat_get_path("share").."/client/sandbox.lua")
|
||||
dofile(__buildat_get_path("share").."/client/replication.lua")
|
||||
dofile(__buildat_get_path("share").."/client/modules.lua")
|
||||
|
||||
local test = require("buildat/extension/test")
|
||||
test.f()
|
||||
|
25
client/modules.lua
Normal file
25
client/modules.lua
Normal file
@ -0,0 +1,25 @@
|
||||
-- Buildat: client/modules.lua
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
-- Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||
local log = buildat.Logger("__client/modules")
|
||||
|
||||
-- Module interfaces, indexed by module name
|
||||
local loaded_modules = {}
|
||||
|
||||
-- Called by client/sandbox.lua
|
||||
function __buildat_require_module(name)
|
||||
log:debug("__buildat_require_module(\""..name.."\")")
|
||||
if loaded_modules[name] then
|
||||
return loaded_modules[name]
|
||||
end
|
||||
local status, err, interface = buildat.run_script_file(name.."/module.lua")
|
||||
if not status then
|
||||
log:error("Module could not be loaded: "..name..": "..err)
|
||||
return nil
|
||||
end
|
||||
loaded_modules[name] = interface
|
||||
return interface
|
||||
end
|
||||
|
||||
-- vim: set noet ts=4 sw=4:
|
||||
|
@ -69,6 +69,16 @@ __buildat_sandbox_environment.require = function(name)
|
||||
log:verbose("Loaded extension \""..name.."\"")
|
||||
return unsafe.safe
|
||||
end
|
||||
-- Allow loading the client-side parts of modules
|
||||
local m = string.match(name, '^buildat/module/([a-zA-Z0-9_]+)$')
|
||||
if m then
|
||||
local interface = __buildat_require_module(m)
|
||||
if interface == nil then
|
||||
error("require: Cannot load module: \""..m.."\"")
|
||||
end
|
||||
log:verbose("Loaded module \""..name.."\"")
|
||||
return interface
|
||||
end
|
||||
-- Disallow loading anything else
|
||||
error("require: \""..name.."\" not found in sandbox")
|
||||
end
|
||||
@ -151,32 +161,40 @@ end
|
||||
local function run_function_in_sandbox(untrusted_function, sandbox)
|
||||
sandbox = wrap_globals(sandbox)
|
||||
setfenv(untrusted_function, sandbox)
|
||||
return __buildat_pcall(untrusted_function)
|
||||
local retval = nil
|
||||
local status, err = __buildat_pcall(function()
|
||||
retval = untrusted_function()
|
||||
end)
|
||||
return status, err, retval
|
||||
end
|
||||
|
||||
function __buildat_run_function_in_sandbox(untrusted_function)
|
||||
local status, err = run_function_in_sandbox(untrusted_function, __buildat_sandbox_environment)
|
||||
local status, err, retval = run_function_in_sandbox(
|
||||
untrusted_function, __buildat_sandbox_environment)
|
||||
if status == false then
|
||||
log:error("Failed to run function:\n"..err)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
return status, err, retval
|
||||
end
|
||||
|
||||
local function run_code_in_sandbox(untrusted_code, sandbox, chunkname)
|
||||
if untrusted_code:byte(1) == 27 then return false, "binary bytecode prohibited" end
|
||||
if untrusted_code:byte(1) == 27 then
|
||||
return false, "binary bytecode prohibited", nil
|
||||
end
|
||||
local untrusted_function, message = loadstring(untrusted_code, chunkname)
|
||||
if not untrusted_function then return false, message end
|
||||
if not untrusted_function then
|
||||
return false, message, nil
|
||||
end
|
||||
return run_function_in_sandbox(untrusted_function, sandbox)
|
||||
end
|
||||
|
||||
function __buildat_run_code_in_sandbox(untrusted_code, chunkname)
|
||||
local status, err = run_code_in_sandbox(untrusted_code, __buildat_sandbox_environment, chunkname)
|
||||
local status, err, retval = run_code_in_sandbox(
|
||||
untrusted_code, __buildat_sandbox_environment, chunkname)
|
||||
if status == false then
|
||||
log:error("Failed to run script:\n"..err)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
return status, err, retval
|
||||
end
|
||||
|
||||
function buildat.run_script_file(name)
|
||||
|
@ -32,4 +32,4 @@ Buildat TODO
|
||||
- Precompiled mode
|
||||
- Singleplayer UI
|
||||
- Modules with no C++ code (eg. just a client-side library)
|
||||
- Show exceptions and errors on client using ui_utils.show_message_dialog
|
||||
- Show all exceptions and errors on client using ui_utils.show_message_dialog
|
||||
|
Loading…
x
Reference in New Issue
Block a user