diff options
author | Singularis <singularis@volny.cz> | 2022-07-05 06:48:19 +0200 |
---|---|---|
committer | orwell <orwell@bleipb.de> | 2025-05-27 20:22:01 +0200 |
commit | ec223d6f3d5d1a7e1257c468d169a0353ec0963e (patch) | |
tree | 683c7a10e32e077b37ece37004442e8c66ebb7f8 /advtrains_luaautomation/environment.lua | |
parent | 744aee2cdd319bc19e83cc9efb52a07ae6adbb06 (diff) | |
download | advtrains-ec223d6f3d5d1a7e1257c468d169a0353ec0963e.tar.gz advtrains-ec223d6f3d5d1a7e1257c468d169a0353ec0963e.tar.bz2 advtrains-ec223d6f3d5d1a7e1257c468d169a0353ec0963e.zip |
[advtrains]
- odebrán mód advtrains_luaautomation
- lokalizace
- zastaralá funkce getpos() nahrazena za get_pos()
Diffstat (limited to 'advtrains_luaautomation/environment.lua')
-rwxr-xr-x | advtrains_luaautomation/environment.lua | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/advtrains_luaautomation/environment.lua b/advtrains_luaautomation/environment.lua deleted file mode 100755 index 6b1a283..0000000 --- a/advtrains_luaautomation/environment.lua +++ /dev/null @@ -1,384 +0,0 @@ -------------- --- lua sandboxed environment - --- function to cross out functions and userdata. --- modified from dump() -function atlatc.remove_invalid_data(o, nested) - if o==nil then return nil end - local valid_dt={["nil"]=true, boolean=true, number=true, string=true} - if type(o) ~= "table" then - --check valid data type - if not valid_dt[type(o)] then - return nil - end - return o - end - -- Contains table -> true/nil of currently nested tables - nested = nested or {} - if nested[o] then - return nil - end - nested[o] = true - for k, v in pairs(o) do - v = atlatc.remove_invalid_data(v, nested) - end - nested[o] = nil - return o -end - - -local env_proto={ - load = function(self, envname, data) - self.name=envname - self.sdata=data.sdata and atlatc.remove_invalid_data(data.sdata) or {} - self.fdata={} - self.init_code=data.init_code or "" - self.subscribers=data.subscribers or {} - end, - save = function(self) - -- throw any function values out of the sdata table - self.sdata = atlatc.remove_invalid_data(self.sdata) - return {sdata = self.sdata, init_code=self.init_code, subscribers=self.subscribers} - end, -} - ---Environment ---Code modified from mesecons_luacontroller (credit goes to Jeija and mesecons contributors) - -local safe_globals = { - "assert", "error", "ipairs", "next", "pairs", "select", - "tonumber", "tostring", "type", "unpack", "_VERSION" -} - -local function safe_date(f, t) - if not f then - -- fall back to old behavior - return(os.date("*t",os.time())) - else - --pass parameters - return os.date(f,t) - end -end - --- string.rep(str, n) with a high value for n can be used to DoS --- the server. Therefore, limit max. length of generated string. -local function safe_string_rep(str, n) - if #str * n > 2000 then - debug.sethook() -- Clear hook - error("string.rep: string length overflow", 2) - end - - return string.rep(str, n) -end - --- string.find with a pattern can be used to DoS the server. --- Therefore, limit string.find to patternless matching. --- Note: Disabled security since there are enough security leaks and this would be unneccessary anyway to DoS the server -local function safe_string_find(...) - --if (select(4, ...)) ~= true then - -- debug.sethook() -- Clear hook - -- error("string.find: 'plain' (fourth parameter) must always be true for security reasons.") - --end - - return string.find(...) -end - -local mp=minetest.get_modpath("advtrains_luaautomation") - -local static_env = { - --core LUA functions - string = { - byte = string.byte, - char = string.char, - format = string.format, - len = string.len, - lower = string.lower, - upper = string.upper, - rep = safe_string_rep, - reverse = string.reverse, - sub = string.sub, - find = safe_string_find, - }, - math = { - abs = math.abs, - acos = math.acos, - asin = math.asin, - atan = math.atan, - atan2 = math.atan2, - ceil = math.ceil, - cos = math.cos, - cosh = math.cosh, - deg = math.deg, - exp = math.exp, - floor = math.floor, - fmod = math.fmod, - frexp = math.frexp, - huge = math.huge, - ldexp = math.ldexp, - log = math.log, - log10 = math.log10, - max = math.max, - min = math.min, - modf = math.modf, - pi = math.pi, - pow = math.pow, - rad = math.rad, - random = math.random, - sin = math.sin, - sinh = math.sinh, - sqrt = math.sqrt, - tan = math.tan, - tanh = math.tanh, - }, - table = { - concat = table.concat, - insert = table.insert, - maxn = table.maxn, - remove = table.remove, - sort = table.sort, - }, - os = { - clock = os.clock, - difftime = os.difftime, - time = os.time, - date = safe_date, - }, - POS = function(x,y,z) return {x=x, y=y, z=z} end, - getstate = advtrains.getstate, - setstate = advtrains.setstate, - is_passive = advtrains.is_passive, - --interrupts are handled per node, position unknown. (same goes for digilines) - --however external interrupts can be set here. - interrupt_pos = function(parpos, imesg) - local pos=atlatc.pcnaming.resolve_pos(parpos, "interrupt_pos") - atlatc.interrupt.add(0, pos, {type="ext_int", ext_int=true, message=imesg}) - end, - -- sends an atc command to train regardless of where it is in the world - atc_send_to_train = function(train_id, command) - assertt(command, "string") - local train = advtrains.trains[train_id] - if train then - advtrains.atc.train_set_command(train, command, true) - return true - else - return false - end - end, -} - --- If interlocking is present, enable route setting functions -if advtrains.interlocking then - local function gen_checks(signal, route_name, noroutesearch) - assertt(route_name, "string") - local pos = atlatc.pcnaming.resolve_pos(signal) - local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos) - if not sigd then - error("There's no signal at "..minetest.pos_to_string(pos)) - end - local tcbs = advtrains.interlocking.db.get_tcbs(sigd) - if not tcbs then - error("Inconsistent configuration, no tcbs for signal at "..minetest.pos_to_string(pos)) - end - - local routeid, route - if not noroutesearch then - for routeidt, routet in ipairs(tcbs.routes) do - if routet.name == route_name then - routeid = routeidt - route = routet - break - end - end - if not route then - error("No route called "..route_name.." at "..minetest.pos_to_string(pos)) - end - end - return pos, sigd, tcbs, routeid, route - end - - - static_env.can_set_route = function(signal, route_name) - local pos, sigd, tcbs, routeid, route = gen_checks(signal, route_name) - -- if route is already set on signal, return whether it's committed - if tcbs.routeset == routeid then - return tcbs.route_committed - end - -- actually try setting route (parameter 'true' designates try-run - local ok = advtrains.interlocking.route.set_route(sigd, route, true) - return ok - end - static_env.set_route = function(signal, route_name) - local pos, sigd, tcbs, routeid, route = gen_checks(signal, route_name) - return advtrains.interlocking.route.update_route(sigd, tcbs, routeid) - end - static_env.cancel_route = function(signal) - local pos, sigd, tcbs, routeid, route = gen_checks(signal, "", true) - return advtrains.interlocking.route.update_route(sigd, tcbs, nil, true) - end - static_env.get_aspect = function(signal) - local pos = atlatc.pcnaming.resolve_pos(signal) - return advtrains.interlocking.signal_get_aspect(pos) - end - static_env.set_aspect = function(signal, asp) - local pos = atlatc.pcnaming.resolve_pos(signal) - return advtrains.interlocking.signal_set_aspect(pos) - end - - --section_occupancy() - static_env.section_occupancy = function(ts_id) - if not ts_id then return nil end - ts_id = tostring(ts_id) - local response = advtrains.interlocking.db.get_ts(ts_id) - if response == nil then - return false - else - return response.trains - end - end -end - --- Lines-specific: -if advtrains.lines then - local atlrwt = advtrains.lines.rwt - static_env.rwt = { - now = atlrwt.now, - new = atlrwt.new, - copy = atlrwt.copy, - to_table = atlrwt.to_table, - to_secs = atlrwt.to_secs, - to_string = atlrwt.to_string, - add = atlrwt.add, - diff = atlrwt.diff, - sub = atlrwt.sub, - adj_diff = atlrwt.adj_diff, - adjust_cycle = atlrwt.adjust_cycle, - adjust = atlrwt.adjust, - to_string = atlrwt.to_string, - get_time_until = atlrwt.get_time_until, - next_rpt = atlrwt.next_rpt, - last_rpt = atlrwt.last_rpt, - time_from_last_rpt = atlrwt.time_from_last_rpt, - time_to_next_rpt = atlrwt.time_to_next_rpt, - } -end - -for _, name in pairs(safe_globals) do - static_env[name] = _G[name] -end - ---The environment all code calls get is a table that has set static_env as metatable. ---In general, every variable is local to a single code chunk, but kept persistent over code re-runs. Data is also saved, but functions and userdata and circular references are removed ---Init code and step code's environments are not saved --- S - Table that can contain any save data global to the environment. Will be saved statically. Can't contain functions or userdata or circular references. --- F - Table global to the environment, can contain volatile data that is deleted when server quits. --- The init code should populate this table with functions and other definitions. - -local proxy_env={} ---proxy_env gets a new metatable in every run, but is the shared environment of all functions ever defined. - --- returns: true, fenv if successful; nil, error if error -function env_proto:execute_code(localenv, code, evtdata, customfct) - -- create us a print function specific for this environment - if not self.safe_print_func then - local myenv = self - self.safe_print_func = function(...) - myenv:log("info", ...) - end - end - - local metatbl ={ - __index = function(t, i) - if i=="S" then - return self.sdata - elseif i=="F" then - return self.fdata - elseif i=="event" then - return evtdata - elseif customfct and customfct[i] then - return customfct[i] - elseif localenv and localenv[i] then - return localenv[i] - elseif i=="print" then - return self.safe_print_func - end - return static_env[i] - end, - __newindex = function(t, i, v) - if i=="S" or i=="F" or i=="event" or (customfct and customfct[i]) or static_env[i] then - debug.sethook() - error("Trying to overwrite environment contents") - end - localenv[i]=v - end, - } - setmetatable(proxy_env, metatbl) - local fun, err=loadstring(code) - if not fun then - return false, err - end - - setfenv(fun, proxy_env) - local succ, data = pcall(fun) - if succ then - data=localenv - end - return succ, data -end - -function env_proto:run_initcode() - if self.init_code and self.init_code~="" then - local old_fdata=self.fdata - self.fdata = {} - --atprint("[atlatc]Running initialization code for environment '"..self.name.."'") - local succ, err = self:execute_code({}, self.init_code, {type="init", init=true}) - if not succ then - self:log("error", "Executing InitCode for '"..self.name.."' failed:"..err) - self.init_err=err - if old_fdata then - self.fdata=old_fdata - self:log("warning", "The 'F' table has been restored to the previous state.") - end - end - end -end - --- log to environment subscribers. severity can be "error", "warning" or "info" (used by internal print) -function env_proto:log(severity, ...) - local text=advtrains.print_concat_table({"[atlatc "..self.name.." "..severity.."]", ...}) - minetest.log("action", text) - for _, pname in ipairs(self.subscribers) do - minetest.chat_send_player(pname, text) - end -end - --- env.subscribers table may be directly altered by callers. - - ---- class interface - -function atlatc.env_new(name) - local newenv={ - name=name, - init_code="", - sdata={}, - subscribers={}, - } - setmetatable(newenv, {__index=env_proto}) - return newenv -end -function atlatc.env_load(name, data) - local newenv={} - setmetatable(newenv, {__index=env_proto}) - newenv:load(name, data) - return newenv -end - -function atlatc.run_initcode() - for envname, env in pairs(atlatc.envs) do - env:run_initcode() - end -end - - - - |