Mercurial > prosody-modules
view mod_storage_appendmap/mod_storage_appendmap.lua @ 5516:f25df3af02c1
mod_client_management: Include client software version number in listing
Should you ever wish to revoke a client by version number, e.g. for
security reasons affecting certain versions, then it would be good to at
the very least see which version is used.
Also includes the OAuth2 software ID, an optional unique identifier that
should be the same for all installations of a particular software.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 03 Jun 2023 19:21:39 +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);