aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2009-06-23 15:58:56 +0100
committerMatthew Wild <mwild1@gmail.com>2009-06-23 15:58:56 +0100
commitf00a5d70b30b132b763b2e20c68accb8ce52789d (patch)
tree0741204836fedee0caea15f4607bd996d7e5fdab
parent3f141a44c2b4564e5d88748f76f53f5fec6c1a33 (diff)
parent54bbd9c98aa6e40463982ec2a92fa9a444704b43 (diff)
downloadprosody-f00a5d70b30b132b763b2e20c68accb8ce52789d.tar.gz
prosody-f00a5d70b30b132b763b2e20c68accb8ce52789d.zip
Automated merge with http://waqas.ath.cx:8000/
-rw-r--r--README2
-rw-r--r--core/modulemanager.lua12
-rw-r--r--core/rostermanager.lua9
-rw-r--r--core/sessionmanager.lua2
-rw-r--r--plugins/mod_announce.lua37
-rw-r--r--plugins/mod_groups.lua93
-rw-r--r--plugins/mod_httpserver.lua13
-rwxr-xr-xprosody7
-rwxr-xr-xprosodyctl37
-rw-r--r--util/datamanager.lua37
-rw-r--r--util/pluginloader.lua2
11 files changed, 238 insertions, 13 deletions
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
diff --git a/core/modulemanager.lua b/core/modulemanager.lua
index f160521f..082dcbb8 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 = { ["*"] = {} };
@@ -134,6 +135,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;
@@ -190,7 +198,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
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)
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
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);
diff --git a/plugins/mod_groups.lua b/plugins/mod_groups.lua
new file mode 100644
index 00000000..7a581717
--- /dev/null
+++ b/plugins/mod_groups.lua
@@ -0,0 +1,93 @@
+
+local groups = { default = {} };
+local members = { [false] = {} };
+
+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
+
+ 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));
+ 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
+
+ -- 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)
+ 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 = {} };
+ members = { [false] = {} };
+ local curr_group = "default";
+ for line in io.lines(groups_file) do
+ 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;
+ end
+ end
+ end
+ module:log("info", "Groups loaded successfully");
+end
+
+function module.unload()
+ datamanager.remove_callback(remove_virtual_contacts);
+end
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
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 --------------
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);
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
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;