From e418f8a9c642c2b0c1ab06160441de068350ac72 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 02:58:05 +0100 Subject: modulemanager: Call 'load' method when loading a module --- core/modulemanager.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/modulemanager.lua b/core/modulemanager.lua index d6220cec..c7aa5cce 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -134,6 +134,13 @@ function load(host, module_name, config) return nil, ret; end + if module_has_method(pluginenv, "load") then + local ok, err = call_module_method(pluginenv, "load"); + if (not ok) and err then + log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err); + end + end + -- Use modified host, if the module set one modulemap[api_instance.host][module_name] = pluginenv; -- cgit v1.2.3 From 04d4fb4a735cf69c467e9f5782603e4c8364a099 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 02:58:28 +0100 Subject: sessionmanager: Fire event on resource bind --- core/sessionmanager.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 19943db0..103533de 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -149,6 +149,8 @@ function bind_resource(session, resource) session.roster = rm_load_roster(session.username, session.host); + hosts[session.host].events.fire_event("resource-bind", session); + return true; end -- cgit v1.2.3 From 5983be0564fe2ac2adb8f2a283b9a0241e00e04e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 14:14:28 +0100 Subject: rostermanager: Fire event on roster load --- core/rostermanager.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/rostermanager.lua b/core/rostermanager.lua index 867add2c..514d3d8e 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -82,19 +82,24 @@ end function load_roster(username, host) log("debug", "load_roster: asked for: "..username.."@"..host); + local roster; if hosts[host] and hosts[host].sessions[username] then - local roster = hosts[host].sessions[username].roster; + roster = hosts[host].sessions[username].roster; if not roster then log("debug", "load_roster: loading for new user: "..username.."@"..host); roster = datamanager.load(username, host, "roster") or {}; if not roster[false] then roster[false] = { }; end hosts[host].sessions[username].roster = roster; + hosts[host].events.fire_event("roster-load", username, host, roster); end return roster; end + -- Attempt to load roster for non-loaded user log("debug", "load_roster: loading for offline user: "..username.."@"..host); - return datamanager.load(username, host, "roster") or {}; + roster = datamanager.load(username, host, "roster") or {}; + hosts[host].events.fire_event("roster-load", username, host, roster); + return roster; end function save_roster(username, host) -- cgit v1.2.3 From 3e796503e146666c151da1b7d9352d96e5c57120 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 14:15:33 +0100 Subject: util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters --- util/datamanager.lua | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/util/datamanager.lua b/util/datamanager.lua index 41d09f06..54cf1959 100644 --- a/util/datamanager.lua +++ b/util/datamanager.lua @@ -50,7 +50,7 @@ local function mkdir(path) end local data_path = "data"; -local callback; +local callbacks = {}; ------- API ------------- @@ -58,8 +58,32 @@ function set_data_path(path) log("debug", "Setting data path to: %s", path); data_path = path; end -function set_callback(func) - callback = func; + +local function callback(username, host, datastore, data) + for _, f in ipairs(callbacks) do + username, host, datastore, data = f(username, host, datastore, data); + if not username then break; end + end + + return username, host, datastore, data; +end +function add_callback(func) + if not callbacks[func] then -- Would you really want to set the same callback more than once? + callbacks[func] = true; + callbacks[#callbacks+1] = func; + return true; + end +end +function remove_callback(func) + if callbacks[func] then + for i, f in ipairs(callbacks) do + if f == func then + callbacks[i] = nil; + callbacks[f] = nil; + return true; + end + end + end end function getpath(username, host, datastore, ext, create) @@ -97,7 +121,12 @@ function store(username, host, datastore, data) if not data then data = {}; end - if callback and callback(username, host, datastore) then return true; end + + username, host, datastore, data = callback(username, host, datastore, data); + if not username then + return true; -- Don't save this data at all + end + -- save the datastore local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+"); if not f then -- cgit v1.2.3 From 5660552e36f34665610dd16d1edc86062f399b1a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 14:16:06 +0100 Subject: prosody: Switch anonymous_login check to use the new datamanager callback syntax --- prosody | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/prosody b/prosody index 0fd0b735..290aa874 100755 --- a/prosody +++ b/prosody @@ -135,8 +135,11 @@ require "util.jid" local data_path = config.get("*", "core", "data_path") or CFG_DATADIR or "data"; require "util.datamanager".set_data_path(data_path); -require "util.datamanager".set_callback(function(username, host, datastore) - return config.get(host, "core", "anonymous_login"); +require "util.datamanager".add_callback(function(username, host, datastore, data) + if config.get(host, "core", "anonymous_login") then + return false; + end + return username, host, datastore, data; end); ----------- End of out-of-place code -------------- -- cgit v1.2.3 From 23116a45d4daf902d68e77500a4e600509b2052d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 14:22:24 +0100 Subject: mod_groups: Experimental shared roster support --- plugins/mod_groups.lua | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 plugins/mod_groups.lua diff --git a/plugins/mod_groups.lua b/plugins/mod_groups.lua new file mode 100644 index 00000000..8a9e263a --- /dev/null +++ b/plugins/mod_groups.lua @@ -0,0 +1,79 @@ + +local groups = { default = {} }; +local members = {}; + +local groups_file; + +local jid, datamanager = require "util.jid", require "util.datamanager"; +local jid_bare, jid_prep = jid.bare, jid.prep; + +local module_host = module:get_host(); + +function inject_roster_contacts(username, host, roster) + module:log("warn", "Injecting group members to roster"); + local bare_jid = username.."@"..host; + if not members[bare_jid] then return; end -- Not a member of any groups + + -- Find groups this JID is a member of + for _, group_name in ipairs(members[bare_jid]) do + -- Find other people in the same group + for jid in pairs(groups[group_name]) do + -- Add them to roster + --module:log("debug", "processing jid %s in group %s", tostring(jid), tostring(group_name)); + if jid ~= bare_jid then + if not roster[jid] then roster[jid] = {}; end + roster[jid].subscription = "both"; + if not roster[jid].groups then + roster[jid].groups = { [group_name] = true }; + end + roster[jid].groups[group_name] = true; + roster[jid].persist = false; + end + end + end +end + +function remove_virtual_contacts(username, host, datastore, data) + if host == module_host and datastore == "roster" then + local new_roster = {}; + for jid, contact in pairs(data) do + if contact.persist ~= false then + new_roster[jid] = contact; + end + end + return username, host, datastore, new_roster; + end + + return username, host, datastore, data; +end + +function module.load() + groups_file = config.get(module:get_host(), "core", "groups_file"); + if not groups_file then return; end + + module:hook("roster-load", inject_roster_contacts); + datamanager.add_callback(remove_virtual_contacts); + + groups = { default = {} }; + + local curr_group = "default"; + for line in io.lines(groups_file) do + if line:match("^%[%w+%]$") then + curr_group = line:match("^%[(%w+)%]$"); + groups[curr_group] = groups[curr_group] or {}; + else + -- Add JID + local jid = jid_prep(line); + if jid then + groups[curr_group][jid] = true; + members[jid] = members[jid] or {}; + members[jid][#members[jid]+1] = curr_group; + end + end + end + module:log("info", "Groups loaded successfully"); +end + +function module.unload() + datamanager.remove_callback(remove_virtual_contacts); +end -- cgit v1.2.3 From 3d891979efc61afdef96424fbb8a70b95d18cecf Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 16:16:08 +0100 Subject: mod_httpserver: Allow configuration of ports and base path, like mod_bosh --- plugins/mod_httpserver.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/mod_httpserver.lua b/plugins/mod_httpserver.lua index 2bcdab43..ec22a4bf 100644 --- a/plugins/mod_httpserver.lua +++ b/plugins/mod_httpserver.lua @@ -19,4 +19,15 @@ local function handle_request(method, body, request) return data; end -httpserver.new{ port = 5280, base = "files", handler = handle_request, ssl = false} \ No newline at end of file +local ports = config.get(module.host, "core", "http_ports") or { 5280 }; +for _, options in ipairs(ports) do + local port, base, ssl, interface = 5280, "files", false, nil; + if type(options) == "number" then + port = options; + elseif type(options) == "table" then + port, base, ssl, interface = options.port or 5280, options.path or "files", options.ssl or false, options.interface; + elseif type(options) == "string" then + base = options; + end + httpserver.new{ port = port, base = base, handler = handle_request, ssl = ssl } +end -- cgit v1.2.3 From 8441ed782155cead1d9ca6f5a62d74e8ee9bdac5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 18:05:36 +0100 Subject: mod_announce: New module to send a message to all online users --- plugins/mod_announce.lua | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 plugins/mod_announce.lua diff --git a/plugins/mod_announce.lua b/plugins/mod_announce.lua new file mode 100644 index 00000000..992410f3 --- /dev/null +++ b/plugins/mod_announce.lua @@ -0,0 +1,37 @@ +local st, jid, set = require "util.stanza", require "util.jid", require "util.set"; + +local admins = set.new(config.get(module:get_host(), "core", "admins")); + +function handle_announcement(data) + local origin, stanza = data.origin, data.stanza; + local host, resource = select(2, jid.split(stanza.attr.to)); + + if resource ~= "announce/online" then + return; -- Not an announcement + end + + if not admins:contains(jid.bare(origin.full_jid)) then + -- Not an admin? Not allowed! + module:log("warn", "Non-admin %s tried to send server announcement", tostring(jid.bare(origin.full_jid))); + origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); + return; + end + + module:log("info", "Sending server announcement to all online users"); + local host_session = hosts[host]; + local message = st.clone(stanza); + message.attr.type = "headline"; + message.attr.from = host; + + local c = 0; + for user in pairs(host_session.sessions) do + c = c + 1; + message.attr.to = user.."@"..host; + core_post_stanza(host_session, message); + end + + module:log("info", "Announcement sent to %d online users", c); + return true; +end + +module:hook("message/host", handle_announcement); -- cgit v1.2.3 From 4e32c53614b8d7f44cf44e9e2ff8efc3a7baad26 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 21:54:34 +0100 Subject: modulemanager: Fix copy/paste error, should be name instead of module_name --- core/modulemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modulemanager.lua b/core/modulemanager.lua index c7aa5cce..24a0da6c 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -197,7 +197,7 @@ function reload(host, name, ...) local _mod, err = pluginloader.load_code(name); -- checking for syntax errors if not _mod then - log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); + log("error", "Unable to load module '%s': %s", name or "nil", err or "nil"); return nil, err; end -- cgit v1.2.3 From 1fadaf4fa717fe72536989319369f1209b0dbf3e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 21:56:52 +0100 Subject: util.pluginloader: Remove unnecessary return value suppressing the real load error --- util/pluginloader.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/pluginloader.lua b/util/pluginloader.lua index 1bf22f62..86075c90 100644 --- a/util/pluginloader.lua +++ b/util/pluginloader.lua @@ -27,7 +27,7 @@ end function load_code(plugin, resource) local content, err = load_resource(plugin, resource); if not content then return content, err; end - return loadstring(content, err), err; + return loadstring(content, err); end return _M; -- cgit v1.2.3 From 78e3f4adf5e346076de8e1c0031509346c1490c8 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 22 Jun 2009 22:02:04 +0100 Subject: mod_groups: Support for public groups, and extra logging --- plugins/mod_groups.lua | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/plugins/mod_groups.lua b/plugins/mod_groups.lua index 8a9e263a..7a581717 100644 --- a/plugins/mod_groups.lua +++ b/plugins/mod_groups.lua @@ -1,6 +1,6 @@ local groups = { default = {} }; -local members = {}; +local members = { [false] = {} }; local groups_file; @@ -14,9 +14,7 @@ function inject_roster_contacts(username, host, roster) local bare_jid = username.."@"..host; if not members[bare_jid] then return; end -- Not a member of any groups - -- Find groups this JID is a member of - for _, group_name in ipairs(members[bare_jid]) do - -- Find other people in the same group + local function import_jids_to_roster(group_name) for jid in pairs(groups[group_name]) do -- Add them to roster --module:log("debug", "processing jid %s in group %s", tostring(jid), tostring(group_name)); @@ -31,6 +29,16 @@ function inject_roster_contacts(username, host, roster) end end end + + -- Find groups this JID is a member of + for _, group_name in ipairs(members[bare_jid]) do + import_jids_to_roster(group_name); + end + + -- Import public groups + for _, group_name in ipairs(members[false]) do + import_jids_to_roster(group_name); + end end function remove_virtual_contacts(username, host, datastore, data) @@ -55,16 +63,22 @@ function module.load() datamanager.add_callback(remove_virtual_contacts); groups = { default = {} }; - + members = { [false] = {} }; local curr_group = "default"; for line in io.lines(groups_file) do - if line:match("^%[%w+%]$") then - curr_group = line:match("^%[(%w+)%]$"); + if line:match("^%s*%[.-%]%s*$") then + curr_group = line:match("^%s*%[(.-)%]%s*$"); + if curr_group:match("^%+") then + curr_group = curr_group:gsub("^%+", ""); + members[false][#members[false]+1] = curr_group; -- Is a public group + end + module:log("debug", "New group: %s", tostring(curr_group)); groups[curr_group] = groups[curr_group] or {}; else -- Add JID local jid = jid_prep(line); if jid then + module:log("debug", "New member of %s: %s", tostring(curr_group), tostring(jid)); groups[curr_group][jid] = true; members[jid] = members[jid] or {}; members[jid][#members[jid]+1] = curr_group; -- cgit v1.2.3 From a977acec89c829b23d790a02c0abf9bb5dfd5a54 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 23 Jun 2009 01:48:01 +0100 Subject: modulemanager: Expose api table to allow others to extend the module API --- core/modulemanager.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 24a0da6c..19e0a982 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -38,7 +38,8 @@ local _G = _G; module "modulemanager" -local api = {}; -- Module API container +api = {}; +local api = api; -- Module API container local modulemap = { ["*"] = {} }; -- cgit v1.2.3 From 59a30ccb0f2d1d857d5cea2825bc0e2e8574ab3e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 23 Jun 2009 01:50:10 +0100 Subject: prosodyctl: Allow commands to be implemented in modules --- prosodyctl | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/prosodyctl b/prosodyctl index 27fda56d..642b12b8 100755 --- a/prosodyctl +++ b/prosodyctl @@ -94,12 +94,14 @@ local error_messages = setmetatable({ ["no-such-user"] = "The given user does not exist on the server"; ["unable-to-save-data"] = "Unable to store, perhaps you don't have permission?"; ["no-pidfile"] = "There is no pidfile option in the configuration file, see http://prosody.im/doc/prosodyctl#pidfile for help"; + ["no-such-method"] = "This module has no commands"; }, { __index = function (t,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end }); hosts = {}; require "core.hostmanager" require "core.eventmanager".fire_event("server-starting"); +require "core.modulemanager" require "util.prosodyctl" ----------------------- @@ -404,6 +406,41 @@ end --------------------- +if command:match("^mod_") then -- Is a command in a module + local module_name = command:match("^mod_(.+)"); + local ret, err = modulemanager.load("*", module_name); + if not ret then + show_message("Failed to load module '"..module_name.."': "..err); + os.exit(1); + end + + table.remove(arg, 1); + + local module = modulemanager.get_module("*", module_name); + if not module then + show_message("Failed to load module '"..module_name.."': Unknown error"); + os.exit(1); + end + + if not modulemanager.module_has_method(module, "command") then + show_message("Fail: mod_"..module_name.." does not support any commands"); + os.exit(1); + end + + local ok, ret = modulemanager.call_module_method(module, "command", arg); + if ok then + if type(ret) == "number" then + os.exit(ret); + elseif type(ret) == "string" then + show_message(ret); + end + os.exit(0); -- :) + else + show_message("Failed to execute command: "..error_messages[ret]); + os.exit(1); -- :( + end +end + if not commands[command] then -- Show help for all commands function show_usage(usage, desc) print(" "..usage); -- cgit v1.2.3 From 54bbd9c98aa6e40463982ec2a92fa9a444704b43 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 23 Jun 2009 15:40:30 +0100 Subject: README: Update for new MUC address --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index e45b89dd..a28f135d 100644 --- a/README +++ b/README @@ -15,7 +15,7 @@ Documentation: http://prosody.im/doc/ Jabber/XMPP Chat: Address: - prosody@conference.heavy-horse.co.uk + prosody@conference.prosody.im Web interface: http://prosody.im/webchat -- cgit v1.2.3