From 7d8d25026c16d22546247b5a9e5d18514b485377 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sun, 24 Jun 2018 22:33:00 +0200 Subject: [PATCH] SaferLua added Lua controller added --- safer_lua/.gitignore | 6 + safer_lua/description.txt | 2 +- safer_lua/environ.lua | 14 ++ safer_lua/init.lua | 8 +- safer_lua/readme.md | 14 +- safer_lua/scanner.lua | 14 ++ safer_lua/store.lua | 14 ++ sl_controller/battery.lua | 121 ++++++++++++++++++ sl_controller/commands.lua | 26 +++- sl_controller/config.lua | 2 + sl_controller/controller.lua | 106 +++++++++++---- sl_controller/description.txt | 2 +- sl_controller/init.lua | 6 +- sl_controller/readme.md | 19 +++ .../textures/sl_controller_battery_green.png | Bin 0 -> 322 bytes .../sl_controller_battery_inventory.png | Bin 0 -> 260 bytes .../textures/sl_controller_battery_red.png | Bin 0 -> 322 bytes 17 files changed, 317 insertions(+), 37 deletions(-) create mode 100644 safer_lua/.gitignore create mode 100644 sl_controller/battery.lua create mode 100644 sl_controller/config.lua create mode 100644 sl_controller/readme.md create mode 100644 sl_controller/textures/sl_controller_battery_green.png create mode 100644 sl_controller/textures/sl_controller_battery_inventory.png create mode 100644 sl_controller/textures/sl_controller_battery_red.png diff --git a/safer_lua/.gitignore b/safer_lua/.gitignore new file mode 100644 index 0000000..b28395b --- /dev/null +++ b/safer_lua/.gitignore @@ -0,0 +1,6 @@ +.buildpath +.project +org.eclipse.* + + +test_*.lua \ No newline at end of file diff --git a/safer_lua/description.txt b/safer_lua/description.txt index 6049760..97257ee 100644 --- a/safer_lua/description.txt +++ b/safer_lua/description.txt @@ -1,4 +1,4 @@ -SaferLUA [safer_lua], a subset of the language LUA for safe and secure LUA sandboxes +SaferLua [safer_lua], a subset of the language Lua for safe and secure Lua sandboxes diff --git a/safer_lua/environ.lua b/safer_lua/environ.lua index 38cb5b7..fddc9a2 100644 --- a/safer_lua/environ.lua +++ b/safer_lua/environ.lua @@ -1,3 +1,17 @@ +--[[ + + SaferLua [safer_lua] + ==================== + + Copyright (C) 2018 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + environ.lua: + +]]-- + safer_lua.MaxCodeSize = 1000 -- size in length of byte code safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts diff --git a/safer_lua/init.lua b/safer_lua/init.lua index 2bce958..32d15e6 100644 --- a/safer_lua/init.lua +++ b/safer_lua/init.lua @@ -1,13 +1,15 @@ --[[ - SaferLUA - ======== - + SaferLua [safer_lua] + ==================== + Copyright (C) 2018 Joachim Stolberg LGPLv2.1+ See LICENSE.txt for more information + environ.lua: + ]]-- safer_lua = {} diff --git a/safer_lua/readme.md b/safer_lua/readme.md index 9571f43..2917d88 100644 --- a/safer_lua/readme.md +++ b/safer_lua/readme.md @@ -1,11 +1,19 @@ -SaferLUA [safer_lua] -==================== +SaferLua [safer_lua] v0.01 +========================== -A subset of the language LUA for safe and secure LUA sandboxes with: +A subset of the language Lua for safe and secure Lua sandboxes with: - limited code length - limited execution time - limited memory use - limited posibilities to call functions +### License +Copyright (C) 2018 Joachim Stolberg +Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt +### Dependencies +none + +### History +- 2018-06-24 v0.01 * first draft diff --git a/safer_lua/scanner.lua b/safer_lua/scanner.lua index 0e48e5a..5676034 100644 --- a/safer_lua/scanner.lua +++ b/safer_lua/scanner.lua @@ -1,3 +1,17 @@ +--[[ + + SaferLua [safer_lua] + ==================== + + Copyright (C) 2018 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + scanner.lua: + +]]-- + local function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end diff --git a/safer_lua/store.lua b/safer_lua/store.lua index 51b13cc..4dcc068 100644 --- a/safer_lua/store.lua +++ b/safer_lua/store.lua @@ -1,3 +1,17 @@ +--[[ + + SaferLua [safer_lua] + ==================== + + Copyright (C) 2018 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + store.lua: + +]]-- + safer_lua.StoreHelp = [[ Store - a secure shell over the LUA table type. diff --git a/sl_controller/battery.lua b/sl_controller/battery.lua new file mode 100644 index 0000000..5de9f59 --- /dev/null +++ b/sl_controller/battery.lua @@ -0,0 +1,121 @@ +--[[ + + sl_controller + ============= + + Copyright (C) 2018 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + battery.lua: + +]]-- + +local function on_timer(pos, elapsed) + local meta = minetest.get_meta(pos) + local percent = (sl_controller.battery_capacity - meta:get_int("content")) + percent = 100 - math.floor((percent * 100.0 / sl_controller.battery_capacity)) + print("percent", percent, meta:get_int("content")) + meta:set_string("infotext", "Battery ("..percent.."%)") + if percent == 0 then + local node = minetest.get_node(pos) + node.name = "sl_controller:battery_empty" + minetest.swap_node(pos, node) + return false + end + return true +end + +minetest.register_node("sl_controller:battery", { + description = "Battery", + inventory_image = 'sl_controller_battery_inventory.png', + wield_image = 'sl_controller_battery_inventory.png', + tiles = { + -- up, down, right, left, back, front + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png^sl_controller_battery_green.png", + }, + + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32}, + }, + }, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_int("content", sl_controller.battery_capacity) + minetest.get_node_timer(pos):start(2) + end, + + on_timer = on_timer, + + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "facedir", + groups = {choppy=1, cracky=1, crumbly=1}, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("sl_controller:battery_empty", { + description = "Battery", + tiles = { + -- up, down, right, left, back, front + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png", + "smartline.png^sl_controller_battery_red.png", + }, + + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32}, + }, + }, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_int("content", nil) + end, + + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "facedir", + groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=1}, + drop = "", + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), +}) + + +if minetest.global_exists("moreores") then + minetest.register_craft({ + output = "sl_controller:battery 2", + recipe = { + {"", "moreores:silver_ingot", ""}, + {"", "default:copper_ingot", ""}, + {"", "moreores:silver_ingot", ""}, + } + }) +else + minetest.register_craft({ + output = "sl_controller:battery 2", + recipe = { + {"", "default:tin_ingot", ""}, + {"", "default:copper_ingot", ""}, + {"", "default:tin_ingot", ""}, + } + }) +end diff --git a/sl_controller/commands.lua b/sl_controller/commands.lua index dc29a5b..2a20d1f 100644 --- a/sl_controller/commands.lua +++ b/sl_controller/commands.lua @@ -17,6 +17,7 @@ sl_controller.register_function("get_input", { cmnd = function(self, num) _G = self._G + num = tostring(num or "") return sl_controller.get_input(self.meta.number, num) end, help = " $get_input(num) --> 'on', 'off', or nil\n".. @@ -28,6 +29,7 @@ sl_controller.register_function("get_input", { sl_controller.register_function("get_status", { cmnd = function(self, num) _G = self._G + num = tostring(num or "") return tubelib.send_request(num, "state", nil) end, help = " $get_status(num) --> 'stopped', 'running',\n".. @@ -65,6 +67,7 @@ sl_controller.register_function("time_as_num", { sl_controller.register_function("playerdetector", { cmnd = function(self, num) _G = self._G + num = tostring(num or "") return tubelib.send_request(num, "name", nil) end, help = " $playerdetector(num) --> e.g. 'Joe'\n".. @@ -75,6 +78,8 @@ sl_controller.register_function("playerdetector", { sl_controller.register_action("send_cmnd", { cmnd = function(self, num, text) _G = self._G + num = tostring(num or "") + text = tostring(text or "") tubelib.send_message(num, self.meta.owner, nil, text, nil) end, help = " $send_cmnd(num, text)\n".. @@ -87,8 +92,10 @@ sl_controller.register_action("send_cmnd", { sl_controller.register_action("display", { cmnd = function(self, num, row, text1, text2, text3) _G = self._G - local text = (text1 or "") .. (text2 or "") .. (text3 or "") - tubelib.send_message(num, self.meta.owner, nil, "row", {row = row, str = text}) + text1 = tostring(text1 or "") + text2 = tostring(text2 or "") + text3 = tostring(text3 or "") + tubelib.send_message(num, self.meta.owner, nil, "row", {row = row, str = text1..text2..text3}) end, help = " $display(num, row, text,...)\n".. " Send a text line to the display with number 'num'.\n".. @@ -100,6 +107,7 @@ sl_controller.register_action("display", { sl_controller.register_action("clear_screen", { cmnd = function(self, num) _G = self._G + num = tostring(num or "") tubelib.send_message(num, self.meta.owner, nil, "clear", nil) end, help = " $clear_screen(num)\n".. @@ -109,18 +117,24 @@ sl_controller.register_action("clear_screen", { }) sl_controller.register_action("chat", { - cmnd = function(self, text) + cmnd = function(self, text1, text2, text3) _G = self._G - minetest.chat_send_player(self.meta.owner, "[SmartLine Controller] "..text) + text1 = tostring(text1 or "") + text2 = tostring(text2 or "") + text3 = tostring(text3 or "") + minetest.chat_send_player(self.meta.owner, "[SmartLine Controller] "..text1..text2..text3) end, - help = " $chat(text)\n".. + help = " $chat(text,...)\n".. " Send yourself a chat message.\n".. - ' example: $chat("Hello")' + " The function accepts up to 3 text parameters\n".. + ' example: $chat("Hello ", name)' }) sl_controller.register_action("door", { cmnd = function(self, pos, text) _G = self._G + pos = tostring(pos or "") + text = tostring(text or "") pos = minetest.string_to_pos("("..pos..")") if pos then local door = doors.get(pos) diff --git a/sl_controller/config.lua b/sl_controller/config.lua new file mode 100644 index 0000000..cfdf0f6 --- /dev/null +++ b/sl_controller/config.lua @@ -0,0 +1,2 @@ +-- Battery capacity in usec CPU time +sl_controller.battery_capacity = tonumber(minetest.setting_get("battery_capacity")) or 10000000 diff --git a/sl_controller/controller.lua b/sl_controller/controller.lua index 844be44..12dded8 100644 --- a/sl_controller/controller.lua +++ b/sl_controller/controller.lua @@ -12,20 +12,16 @@ ]]-- -local sHELP = [[Safer LUA Controller +local sHELP = [[SaferLua Controller Safer LUA is a subset of LUA with the following restrictions: - No loop keywords like: for, while, repeat,... - - No table constructions via: { ... } + - No table construction {..} - Limited set of available functions - Store() as alternative to LUA tables ]] -local mail_exists = minetest.get_modpath("mail") and mail ~= nil - -sl_controller = {} - local Cache = {} local tCommands = {} @@ -74,8 +70,10 @@ sl_controller.register_action("print", { cmnd = function(self, text1, text2, text3) _G = self._G local pos = self.meta.pos - local text = (text1 or "")..(text2 or "")..(text3 or "") - output(pos, text) + text1 = tostring(text1 or "") + text2 = tostring(text2 or "") + text3 = tostring(text3 or "") + output(pos, text1..text2..text3) end, help = "$print(text,...)\n".. "Send a text line to the output window.\n".. @@ -84,6 +82,19 @@ sl_controller.register_action("print", { }) +local function formspec0(meta) + local running = meta:get_int("state") == tubelib.RUNNING + local cmnd = running and "stop;Stop" or "start;Start" + local init = meta:get_string("init") + init = minetest.formspec_escape(init) + return "size[4,3]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "label[0,0;No Battery?]".. + "button[1,2;1.8,1;start;Start]" +end + local function formspec1(meta) local running = meta:get_int("state") == tubelib.RUNNING local cmnd = running and "stop;Stop" or "start;Start" @@ -163,6 +174,7 @@ local function error(pos, err) output(pos, err) local meta = minetest.get_meta(pos) local number = meta:get_string("number") + meta:set_string("formspec", formspec3(meta)) meta:set_string("infotext", "Controller "..number..": error") return false end @@ -182,25 +194,23 @@ local function compile(pos, meta, number) return false end -local function on_timer(pos, elapsed) - local t = minetest.get_us_time() - local meta = minetest.get_meta(pos) - local number = meta:get_string("number") - if Cache[number] or compile(pos, meta, number) then - - local code = Cache[number].code - local res = safer_lua.run_loop(pos, elapsed, code, error) - - t = minetest.get_us_time() - t - print("time", t) - return res +local function battery(pos) + local battery_pos = minetest.find_node_near(pos, 1, {"sl_controller:battery"}) + if battery_pos then + local meta = minetest.get_meta(pos) + meta:set_string("battery", minetest.pos_to_string(battery_pos)) + return true end return false -end +end local function start_controller(pos) local meta = minetest.get_meta(pos) local number = meta:get_string("number") + if not battery(pos) then + meta:set_string("formspec", formspec0(meta)) + return + end if compile(pos, meta, number) then meta:set_int("state", tubelib.RUNNING) minetest.get_node_timer(pos):start(1) @@ -219,6 +229,58 @@ local function stop_controller(pos) meta:set_string("formspec", formspec2(meta)) end +local function no_battery(pos) + local meta = minetest.get_meta(pos) + local number = meta:get_string("number") + meta:set_int("state", tubelib.STOPPED) + minetest.get_node_timer(pos):stop() + meta:set_string("infotext", "Controller "..number..": No battery") + meta:set_string("formspec", formspec0(meta)) +end + +local function update_battery(meta, cpu) + local pos = minetest.string_to_pos(meta:get_string("battery")) + if pos then + meta = minetest.get_meta(pos) + local content = meta:get_int("content") - cpu + print("content", content) + if content <= 0 then + meta:set_int("content", 0) + return false + end + meta:set_int("content", content) + return true + end +end + +local function on_timer(pos, elapsed) + local t = minetest.get_us_time() + local meta = minetest.get_meta(pos) + local number = meta:get_string("number") + if Cache[number] or compile(pos, meta, number) then + + local cpu = meta:get_int("cpu") or 0 + local code = Cache[number].code + local res = safer_lua.run_loop(pos, elapsed, code, error) + if res then + t = minetest.get_us_time() - t + cpu = math.floor(((cpu * 20) + t) / 21) + meta:set_int("cpu", cpu) + meta:set_string("infotext", "Controller "..number..": running ("..cpu.."us)") + if not update_battery(meta, cpu) then + no_battery(pos) + return false + end + else + stop_controller(pos) + end + return res + else + stop_controller(pos) + end + return false +end + local function on_receive_fields(pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return @@ -267,7 +329,7 @@ local function on_receive_fields(pos, formname, fields, player) end minetest.register_node("sl_controller:controller", { - description = "SaferLUA Controller", + description = "SaferLua Controller", inventory_image = "sl_controller_inventory.png", wield_image = "sl_controller_inventory.png", stack_max = 1, diff --git a/sl_controller/description.txt b/sl_controller/description.txt index 077e00a..062f1b3 100644 --- a/sl_controller/description.txt +++ b/sl_controller/description.txt @@ -1,2 +1,2 @@ -tbd. +SaferLua Controller - a controller to be programmed in LUA diff --git a/sl_controller/init.lua b/sl_controller/init.lua index f7b08c8..ccec043 100644 --- a/sl_controller/init.lua +++ b/sl_controller/init.lua @@ -10,5 +10,9 @@ ]]-- +sl_controller = {} + +dofile(minetest.get_modpath("sl_controller") .. "/config.lua") dofile(minetest.get_modpath("sl_controller") .. "/controller.lua") -dofile(minetest.get_modpath("sl_controller") .. "/commands.lua") \ No newline at end of file +dofile(minetest.get_modpath("sl_controller") .. "/commands.lua") +dofile(minetest.get_modpath("sl_controller") .. "/battery.lua") \ No newline at end of file diff --git a/sl_controller/readme.md b/sl_controller/readme.md new file mode 100644 index 0000000..2bb9b76 --- /dev/null +++ b/sl_controller/readme.md @@ -0,0 +1,19 @@ +SaferLua Controller [sl_controller] v0.01 +========================================= + + +A tubelib compatible controller to be programmed in LUA + +The mod uses SaferLua [safer_lua] as Lua sandbox for safe and secure code execution. + + +### License +Copyright (C) 2018 Joachim Stolberg +Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt + + +### Dependencies +tubelib, safer_lua + +### History +- 2018-06-24 v0.01 * first draft diff --git a/sl_controller/textures/sl_controller_battery_green.png b/sl_controller/textures/sl_controller_battery_green.png new file mode 100644 index 0000000000000000000000000000000000000000..b66821fb1838aaea518bc5c3573e979706106cc6 GIT binary patch literal 322 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!j01c^TpL0stJu0ZL?s8LWknTK z#T1tpHng=)nH9bzsek^`xZN4)M+@hz+q!D|_WH{WoAw_#dG12DD5E4$J7YO>_%)r1c48n{Iv*t(u1=&kHeO=ifu}KJOF?QIl2Z}IA zmbgZgIOpf)rskC}I2WZRmZYXAlxLP?D7bt2281{Ai31fSd%8G=L>zv5#Zah0fyX6~ zNys5&&;QJ$O1Exw7`x4^^M|v z&v!)ix#2uv#$E?@eowKdEArU;jMt^xzO2#cXJTMjki`6KJv&3sotFh5M|ryXxvX?g9Z*6 vo^R3G+zt}*%>88ojGNe!9`3)+;m*Kd+^t>lajx_RpaBe?u6{1-oD!M<(L_%E literal 0 HcmV?d00001 diff --git a/sl_controller/textures/sl_controller_battery_red.png b/sl_controller/textures/sl_controller_battery_red.png new file mode 100644 index 0000000000000000000000000000000000000000..fb194d981b07ffe8db29ccb262e757d5b852c9ed GIT binary patch literal 322 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!j01c^TpO-xsMxwWL?v(X@(D=G z+TkA%RZw*xJT|7d{Csk9VMAN%lv(}rm(E+ab=CImoAw_#dG3PSsc(mY+8IlN{DK)A zp4~_Tagw~Fdh=h)qIJONgiW-94a? zWQl7;iF1B#Zfaf$gL6@8Vo7R>LV0FMhJw4NZ$Nk>pEyuavZsq{qu&6b06g&BJt*!exhp03Da?=xPPZu`1Mqo0X^VL=k}Om?