client: Loading resources received from server works

This commit is contained in:
Perttu Ahola 2014-09-24 00:00:24 +03:00
parent 3788d111a5
commit 625d7a53c1
5 changed files with 128 additions and 18 deletions

View File

@ -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 = {}

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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