client: Loading resources received from server works
This commit is contained in:
parent
3788d111a5
commit
625d7a53c1
@ -16,6 +16,9 @@ function buildat.dump(thing)
|
||||
if type(thing) == 'number' then
|
||||
return ''..thing
|
||||
end
|
||||
if type(thing) == 'boolean' then
|
||||
if thing then return "true" else return "false" end
|
||||
end
|
||||
if thing == nil then
|
||||
return "nil"
|
||||
end
|
||||
@ -30,7 +33,7 @@ function buildat.dump(thing)
|
||||
s = s.."}"
|
||||
return s
|
||||
end
|
||||
return "(?)"
|
||||
return type(thing)
|
||||
end
|
||||
function buildat.Logger(module)
|
||||
local logger = {}
|
||||
|
@ -6,7 +6,7 @@ local dump = buildat.dump
|
||||
local M = {safe = {}}
|
||||
|
||||
-- Set every plain value in global environment to the sandbox
|
||||
-- ...it's maybe safe enough...
|
||||
-- ...it's maybe safe enough... TODO: Not safe
|
||||
for k, v in pairs(_G) do
|
||||
if type(v) == 'number' or type(v) == 'string' then
|
||||
--log:info("Setting sandbox["..k.."] = "..buildat.dump(v))
|
||||
@ -47,6 +47,101 @@ for _, v in ipairs(safe_globals) do
|
||||
M.safe[v] = _G[v]
|
||||
end
|
||||
|
||||
-- ResourceCache
|
||||
|
||||
-- Checks that this is not an absolute file path or anything funny
|
||||
local allowed_name_pattern = '^[a-zA-Z0-9][a-zA-Z0-9/._ ]*$'
|
||||
function M.check_safe_resource_name(orig_name)
|
||||
local name = orig_name
|
||||
if type(name) ~= "string" then
|
||||
error("Unsafe resource name: "..dump(orig_name).." (not string)")
|
||||
end
|
||||
if string.match(name, '^/.*$') then
|
||||
error("Unsafe resource name: "..dump(orig_name).." (absolute path)")
|
||||
end
|
||||
if not string.match(name, allowed_name_pattern) then
|
||||
error("Unsafe resource name: "..dump(orig_name).." (unneeded chars)")
|
||||
end
|
||||
if string.match(name, '[.][.]') then
|
||||
error("Unsafe resource name: "..dump(orig_name).." (contains ..)")
|
||||
end
|
||||
log:verbose("Safe resource name: "..orig_name.." -> "..name)
|
||||
return name
|
||||
end
|
||||
|
||||
-- Basic tests
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("/etc/passwd")
|
||||
end) == false)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name(" /etc/passwd")
|
||||
end) == false)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("\t /etc/passwd")
|
||||
end) == false)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("Models/Box.mdl")
|
||||
end) == true)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("Fonts/Anonymous Pro.ttf")
|
||||
end) == true)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("test1/pink_texture.png")
|
||||
end) == true)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name(" Box.mdl ")
|
||||
end) == false)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("../../foo")
|
||||
end) == false)
|
||||
assert(pcall(function()
|
||||
M.check_safe_resource_name("abc$de")
|
||||
end) == false)
|
||||
|
||||
local hack_resaved_files = {}
|
||||
|
||||
-- Create temporary file with wanted file name to make Urho3D load it correctly
|
||||
function M.resave_file(resource_name)
|
||||
M.check_safe_resource_name(resource_name)
|
||||
local path = __buildat_get_file_path(resource_name)
|
||||
if path == nil then
|
||||
return nil
|
||||
end
|
||||
local path2 = hack_resaved_files[path]
|
||||
if path2 == nil then
|
||||
path2 = __buildat_get_path("tmp").."/"..resource_name
|
||||
dir2 = string.match(path2, '^(.*)/.+$')
|
||||
if dir2 then
|
||||
if not __buildat_mkdir(dir2) then
|
||||
error("Failed to create directory: \""..dir2.."\"")
|
||||
end
|
||||
end
|
||||
log:info("Temporary path: "..path2)
|
||||
local src = io.open(path, "rb")
|
||||
local dst = io.open(path2, "wb")
|
||||
while true do
|
||||
local buf = src:read(100000)
|
||||
if buf == nil then break end
|
||||
dst:write(buf)
|
||||
end
|
||||
src:close()
|
||||
dst:close()
|
||||
hack_resaved_files[path] = path2
|
||||
end
|
||||
return path2
|
||||
end
|
||||
|
||||
M.safe.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 cache:GetResource(resource_type, resource_name)
|
||||
end,
|
||||
}
|
||||
|
||||
-- SubscribeToEvent
|
||||
|
||||
local sandbox_function_name_to_global_function_name = {}
|
||||
local next_global_function_i = 1
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "core/log.h"
|
||||
#include "client/config.h"
|
||||
#include "client/state.h"
|
||||
#include "interface/fs.h"
|
||||
#include <c55/getopt.h>
|
||||
#include <c55/os.h>
|
||||
#pragma GCC diagnostic push
|
||||
@ -45,18 +46,18 @@ struct CApp: public App, public u3d::Application
|
||||
engineParameters_["LogName"] = "client_Urho3D.log";
|
||||
engineParameters_["FullScreen"] = false;
|
||||
engineParameters_["Headless"] = false;
|
||||
|
||||
// TODO: Proper paths
|
||||
engineParameters_["ResourcePaths"] =
|
||||
"/home/celeron55/softat/Urho3D/Bin/CoreData;"
|
||||
"/home/celeron55/softat/Urho3D/Bin/Data";
|
||||
ss_ tmp_path = interface::getGlobalFilesystem()->get_absolute_path(
|
||||
g_client_config.cache_path+"/tmp");
|
||||
engineParameters_["ResourcePaths"] = u3d::String()+
|
||||
"/home/celeron55/softat/Urho3D/Bin/CoreData;"+
|
||||
"/home/celeron55/softat/Urho3D/Bin/Data;"+
|
||||
tmp_path.c_str();
|
||||
engineParameters_["AutoloadPaths"] = "";
|
||||
|
||||
// Set up on_update event (this runs every frame)
|
||||
SubscribeToEvent(u3d::E_UPDATE, HANDLER(CApp, on_update));
|
||||
|
||||
// TODO: Set up input events (Call stuff like
|
||||
// call_global_if_exists(L, "__buildat_key_down", 1, 0);)
|
||||
// ...or don't? They should be available in Urho3D API.
|
||||
}
|
||||
|
||||
~CApp()
|
||||
@ -129,6 +130,7 @@ struct CApp: public App, public u3d::Application
|
||||
DEF_BUILDAT_FUNC(get_file_content)
|
||||
DEF_BUILDAT_FUNC(get_file_path)
|
||||
DEF_BUILDAT_FUNC(get_path)
|
||||
DEF_BUILDAT_FUNC(mkdir)
|
||||
DEF_BUILDAT_FUNC(pcall)
|
||||
DEF_BUILDAT_FUNC(cereal_binary_input)
|
||||
DEF_BUILDAT_FUNC(cereal_binary_output)
|
||||
@ -140,7 +142,6 @@ struct CApp: public App, public u3d::Application
|
||||
lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
//m_script->ExecuteFile(u3d::String(init_lua_path.c_str()));
|
||||
}
|
||||
|
||||
void on_update(u3d::StringHash eventType, u3d::VariantMap &eventData)
|
||||
@ -276,6 +277,19 @@ struct CApp: public App, public u3d::Application
|
||||
return 0;
|
||||
}
|
||||
|
||||
// mkdir(path: string)
|
||||
static int l_mkdir(lua_State *L)
|
||||
{
|
||||
ss_ path = lua_tocppstring(L, 1);
|
||||
bool ok = interface::getGlobalFilesystem()->create_directories(path);
|
||||
if(!ok)
|
||||
log_w(MODULE, "Failed to create directory: \"%s\"", cs(path));
|
||||
else
|
||||
log_v(MODULE, "Created directory: \"%s\"", cs(path));
|
||||
lua_pushboolean(L, ok);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_error(lua_State *L)
|
||||
{
|
||||
lua_getglobal(L, "debug");
|
||||
|
@ -77,6 +77,7 @@ buildat.sub_packet("test1:add_box", function(data)
|
||||
|
||||
-- 3) First it needs a model. We could just load this binaray blob:
|
||||
object.model = u3d.cache:GetResource("Model", "Models/Box.mdl")
|
||||
assert(object.model)
|
||||
-- TODO: let's not. Let's generate some geometry!
|
||||
--[[local cc = CustomGeometry()
|
||||
cc.SetNumGeometries(1)
|
||||
@ -91,9 +92,11 @@ buildat.sub_packet("test1:add_box", function(data)
|
||||
-- We use this Diff.xml file to define that we want diffuse rendering. It
|
||||
-- doesn't make much sense to define it ourselves as it consists of quite many
|
||||
-- parameters:
|
||||
object.material:SetTechnique(0, u3d.cache:GetResource("Technique", "Techniques/Diff.xml"))
|
||||
object.material:SetTechnique(0,
|
||||
u3d.cache:GetResource("Technique", "Techniques/Diff.xml"))
|
||||
-- And load the texture from a file:
|
||||
object.material:SetTexture(u3d.TU_DIFFUSE, u3d.cache:GetResource("Texture2D", "Textures/LogoLarge.png"))
|
||||
object.material:SetTexture(u3d.TU_DIFFUSE,
|
||||
u3d.cache:GetResource("Texture2D", "test1/pink_texture.png"))
|
||||
|
||||
--
|
||||
-- Make a non-useful but nice reply packet and send it to the server
|
||||
|
7
todo.txt
7
todo.txt
@ -12,12 +12,7 @@ Buildat TODO
|
||||
- Implement easy Lua scripting on the server (Luabind or not? The purpose is to
|
||||
allow recycling the same Lua code on the client and the server, which means
|
||||
that Lua will dictate the function/object design)
|
||||
- Creating globals in Lua should cause an error unless done with a special
|
||||
interface
|
||||
- Move self-contained library-like Lua functions from client/app.cpp to a
|
||||
reusable location so that they can be used from server-side Lua in the future
|
||||
- util/codestyle.sh: Add some CMakeLists.txt formatting (case, whitespace)
|
||||
- Make two extensions for urho3d, one that loads into a table, and one that
|
||||
uses the table one and puts it in the global namespace. Then add engine
|
||||
support for automatically clearing them from the glboal namespace - some kind
|
||||
of a global namespace wrapper table?
|
||||
- Proper whitelisting sandbox for Urho3D's Lua API
|
||||
|
Loading…
x
Reference in New Issue
Block a user