Mercurial > prosody-modules
view mod_storage_appendmap/mod_storage_appendmap.lua @ 5296:0f5657db1cfc
mod_isolate_host: handle server-generated stanzas
The hook for setting the no_host_isolation is only called for c2s
sessions. This does not work for stanzas generated by the server,
such as PEP notifications or presence probe answers.
To handle that, we do per-stanza checks for the case that the origin
is local.
author | Jonas Schäfer <jonas@wielicki.name> |
---|---|
date | Sat, 01 Apr 2023 12:03:08 +0200 |
parents | e44b868cc575 |
children | ea6c18ec0669 |
line wrap: on
line source
local dump = require "util.serialization".serialize; local load = require "util.envload".envloadfile; local dm = require "core.storagemanager".olddm; local REMOVE = {}; -- Special value for removing keys local driver = {}; local keywords = { ["do"] = true; ["and"] = true; ["else"] = true; ["break"] = true; ["if"] = true; ["end"] = true; ["goto"] = true; ["false"] = true; ["in"] = true; ["for"] = true; ["then"] = true; ["local"] = true; ["or"] = true; ["nil"] = true; ["true"] = true; ["until"] = true; ["elseif"] = true; ["function"] = true; ["not"] = true; ["repeat"] = true; ["return"] = true; ["while"] = true; -- _ENV is not technically a keyword but we need to treat it as such ["_ENV"] = true; }; local function is_usable_identifier(s) return type(s) == "string" and not keywords[s] and s:find("^[%a_][%w_]*$"); end local function serialize_key(key) if is_usable_identifier(key) then return key; else return "_ENV[" .. dump(key) .. "]"; end end local function serialize_value(value) if value == REMOVE then return "nil"; else return dump(value); end end local function serialize_pair(key, value) key = serialize_key(key); value = serialize_value(value); return key .. " = " .. value .. ";\n"; end local function serialize_map(keyvalues) local keys, values = {}, {}; for key, value in pairs(keyvalues) do key = serialize_key(key); value = serialize_value(value); table.insert(keys, key); table.insert(values, value); end return table.concat(keys, ", ") .. " = " .. table.concat(values, ", ") .. ";\n"; end local map = { remove = REMOVE }; local map_mt = { __index = map }; function map:get(user, key) module:log("debug", "map:get(%s, %s)", tostring(user), tostring(key)) local filename = dm.getpath(user, module.host, self.store, "map"); module:log("debug", "File is %s", filename); local env = {}; if _VERSION == "Lua 5.1" then -- HACK env._ENV = env; -- HACK end -- SO MANY HACKS local chunk, err, errno = load(filename, env); if not chunk then if errno == 2 then return end return chunk, err; end local ok, err = pcall(chunk); if not ok then return ok, err; end if _VERSION == "Lua 5.1" then -- HACK env._ENV = nil; -- HACK end -- HACKS EVERYWHERE if key == nil then return env; end return env[key]; end function map:set_keys(user, keyvalues) local data = serialize_map(keyvalues); return dm.append_raw(user, module.host, self.store, "map", data); end function map:set(user, key, value) if _VERSION == "Lua 5.1" then assert(key ~= "_ENV", "'_ENV' is a restricted key"); end if key == nil then local filename = dm.getpath(user, module.host, self.store, "map"); return os.remove(filename); end local data = serialize_pair(key, value); return dm.append_raw(user, module.host, self.store, "map", data); end local keyval = { remove = REMOVE }; local keyval_mt = { __index = keyval }; function keyval:get(user) return map.get(self, user, nil); end function keyval:set(user, keyvalues) local data = serialize_map(keyvalues); return dm.store_raw(dm.getpath(user, module.host, self.store, "map"), data); end -- TODO some kind of periodic compaction thing? function map:_compact(user) local data = self:get(user); return keyval.set(self, user, data); end function driver:open(store, typ) if typ == "map" then return setmetatable({ store = store, }, map_mt); elseif typ == nil or typ == "keyval" then return setmetatable({ store = store, }, keyval_mt); end return nil, "unsupported-store"; end module:provides("storage", driver);