Software /
code /
prosody-modules
File
mod_storage_muconference_readonly/mod_storage_muconference_readonly.lua @ 4930:13070c6a7ce8
mod_http_muc_log: Fix exception on lack of trailing slash in room path
A request to /room leads to the match call returning nil which in turn
calls nodeprep(nil). In Prosody 0.11.x this does nothing and simply
returns the nil, while in 0.12 it is an error.
Now it redirects to the calendar view at /room/ - even for non-existant
rooms.
Discovered at a deployment with http_paths = { muc_log = "/" } and
requests to /robots.txt and similar, which now result in a uses redirect
before returning 404.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 22 Apr 2022 14:29:32 +0200 |
parent | 2245:a0727d23ee65 |
line wrap: on
line source
-- luacheck: ignore 212/self local sql = require "util.sql"; local xml_parse = require "util.xml".parse; local resolve_relative_path = require "util.paths".resolve_relative_path; local stanza_preserialize = require "util.stanza".preserialize; local unpack = unpack local function iterator(result) return function(result_) local row = result_(); if row ~= nil then return unpack(row); end end, result, nil; end local default_params = { driver = "MySQL" }; local engine; local host = module.host; local room, store; local function get_best_affiliation(a, b) if a == 'owner' or b == 'owner' then return 'owner'; elseif a == 'administrator' or b == 'administrator' then return 'administrator'; elseif a == 'outcast' or b == 'outcast' then return 'outcast'; elseif a == 'member' or b == 'member' then return 'member'; end assert(false); end local function keyval_store_get() if store == "config" then local room_jid = room.."@"..host; local result; for row in engine:select("SELECT `name`,`desc`,`topic`,`public`,`secret` FROM `rooms` WHERE `jid`=? LIMIT 1", room_jid or "") do result = row end local name = result[1]; local desc = result[2]; local subject = result[3]; local public = result[4]; local hidden = public == 0 and true or nil; local secret = result[5]; if secret == '' then secret = nil end local affiliations = {}; for row in engine:select("SELECT `jid_user`,`affil` FROM `rooms_lists` WHERE `jid_room`=?", room_jid or "") do local jid_user = row[1]; local affil = row[2]; -- mu-conference has a bug where full JIDs get stored… local bare_jid = jid_user:gsub('/.*', ''); local old_affil = affiliations[bare_jid]; -- mu-conference has a bug where it can record multiple affiliations… if old_affil ~= nil and old_affil ~= affil then affil = get_best_affiliation(old_affil, affil); end -- terminology is clearly “admin”, not “administrator”. if affil == 'administrator' then affil = 'admin'; end affiliations[bare_jid] = affil; end return { jid = room_jid, _data = { persistent = true, name = name, description = desc, subject = subject, password = secret, hidden = hidden, }, _affiliations = affiliations, }; end end --- Key/value store API (default store type) local keyval_store = {}; keyval_store.__index = keyval_store; function keyval_store:get(roomname) room, store = roomname, self.store; local ok, result = engine:transaction(keyval_store_get); if not ok then module:log("error", "Unable to read from database %s store for %s: %s", store, roomname or "<host>", result); return nil, result; end return result; end function keyval_store:users() local host_length = host:len() + 1; local ok, result = engine:transaction(function() return engine:select("SELECT SUBSTRING_INDEX(jid, '@', 1) FROM `rooms`"); end); if not ok then return ok, result end return iterator(result); end local stores = { keyval = keyval_store; }; --- Implement storage driver API -- FIXME: Some of these operations need to operate on the archive store(s) too local driver = {}; function driver:open(store, typ) local store_mt = stores[typ or "keyval"]; if store_mt then return setmetatable({ store = store }, store_mt); end return nil, "unsupported-store"; end function driver:stores(roomname) local query = "SELECT 'config'"; if roomname == true or not roomname then roomname = ""; end local ok, result = engine:transaction(function() return engine:select(query, host, roomname); end); if not ok then return ok, result end return iterator(result); end --- Initialization local function normalize_params(params) assert(params.driver and params.database, "Configuration error: Both the SQL driver and the database need to be specified"); return params; end function module.load() if prosody.prosodyctl then return; end local engines = module:shared("/*/sql/connections"); local params = normalize_params(module:get_option("sql", default_params)); engine = engines[sql.db2uri(params)]; if not engine then module:log("debug", "Creating new engine"); engine = sql:create_engine(params); engines[sql.db2uri(params)] = engine; end module:provides("storage", driver); end