Software /
code /
prosody
Changeset
5342:4c8c8285bf88
Merge 0.9->trunk
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 10 Mar 2013 11:29:47 +0000 |
parents | 5321:33813f000015 (current diff) 5341:760c22c822be (diff) |
children | 5346:b8fbb9d07efc |
files | |
diffstat | 12 files changed, 262 insertions(+), 71 deletions(-) [+] |
line wrap: on
line diff
--- a/net/dns.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/net/dns.lua Sun Mar 10 11:29:47 2013 +0000 @@ -223,7 +223,7 @@ function dns.random(...) -- - - - - - - - - - - - - - - - - - - dns.random - math.randomseed(math.floor(10000*socket.gettime())); + math.randomseed(math.floor(10000*socket.gettime()) % 0x100000000); dns.random = math.random; return dns.random(...); end
--- a/net/http/parser.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/net/http/parser.lua Sun Mar 10 11:29:47 2013 +0000 @@ -99,6 +99,7 @@ parsed_url = { path = _path, query = _query }; else parsed_url = url_parse(path); + if not(parsed_url and parsed_url.path) then error = true; return error_cb("invalid-url"); end end path = preprocess_path(parsed_url.path); headers.host = parsed_url.host or headers.host;
--- a/net/http/server.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/net/http/server.lua Sun Mar 10 11:29:47 2013 +0000 @@ -89,29 +89,30 @@ local pending = {}; local waiting = false; local function process_next() - --if waiting then log("debug", "can't process_next, waiting"); return; end - if sessions[conn] and #pending > 0 then + if waiting then log("debug", "can't process_next, waiting"); return; end + waiting = true; + while sessions[conn] and #pending > 0 do local request = t_remove(pending); --log("debug", "process_next: %s", request.path); - waiting = true; --handle_request(conn, request, process_next); _1, _2, _3 = conn, request, process_next; if not xpcall(_handle_request, _traceback_handler) then conn:write("HTTP/1.0 500 Internal Server Error\r\n\r\n"..events.fire_event("http-error", { code = 500, private_message = last_err })); conn:close(); end - else - --log("debug", "ready for more"); - waiting = false; end + --log("debug", "ready for more"); + waiting = false; end local function success_cb(request) --log("debug", "success_cb: %s", request.path); + if waiting then + log("error", "http connection handler is not reentrant: %s", request.path); + assert(false, "http connection handler is not reentrant"); + end request.secure = secure; t_insert(pending, request); - if not waiting then - process_next(); - end + process_next(); end local function error_cb(err) log("debug", "error_cb: %s", err or "<nil>");
--- a/net/server_event.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/net/server_event.lua Sun Mar 10 11:29:47 2013 +0000 @@ -460,7 +460,6 @@ local handleclient; do local string_sub = string.sub -- caching table lookups - local string_len = string.len local addevent = base.addevent local socket_gettime = socket.gettime function handleclient( client, ip, port, server, pattern, listener, sslctx ) -- creates an client interface
--- a/net/server_select.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/net/server_select.lua Sun Mar 10 11:29:47 2013 +0000 @@ -10,11 +10,6 @@ local use = function( what ) return _G[ what ] end -local clean = function( tbl ) - for i, k in pairs( tbl ) do - tbl[ i ] = nil - end -end local log, table_concat = require ("util.logger").init("socket"), table.concat; local out_put = function (...) return log("debug", table_concat{...}); end @@ -47,7 +42,6 @@ local math_min = math.min local math_huge = math.huge local table_concat = table.concat -local string_len = string.len local string_sub = string.sub local coroutine_wrap = coroutine.wrap local coroutine_yield = coroutine.yield @@ -118,11 +112,10 @@ local _sendtimeout local _readtimeout -local _cleanqueue - local _timer -local _maxclientsperserver +local _maxselectlen +local _maxfd local _maxsslhandshake @@ -154,17 +147,20 @@ _sendtimeout = 60000 -- allowed send idle time in secs _readtimeout = 6 * 60 * 60 -- allowed read idle time in secs -_cleanqueue = false -- clean bufferqueue after using - -_maxclientsperserver = 1000 +_maxfd = luasocket._SETSIZE or 1024 -- We should ignore this on Windows. Perhaps by simply setting it to math.huge or something. +_maxselectlen = luasocket._SETSIZE or 1024 -- But this still applies on Windows _maxsslhandshake = 30 -- max handshake round-trips ----------------------------------// PRIVATE //-- -wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections ) -- this function wraps a server +wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx ) -- this function wraps a server -- FIXME Make sure FD < _maxfd - maxconnections = maxconnections or _maxclientsperserver + if socket:getfd() >= _maxfd then + out_error("server.lua: Disallowed FD number: "..socket:getfd()) + socket:close() + return nil, "fd-too-large" + end local connections = 0 @@ -201,20 +197,23 @@ --mem_free( ) out_put "server.lua: closed server handler and removed sockets from list" end - handler.pause = function() + handler.pause = function( hard ) if not handler.paused then - socket:close( ) - _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) _readlistlen = removesocket( _readlist, socket, _readlistlen ) - _socketlist[ socket ] = nil - socket = nil; + if hard then + _socketlist[ socket ] = nil + socket:close( ) + socket = nil; + end handler.paused = true; end end - handler.resume = function() + handler.resume = function( ) if handler.paused then - socket = socket_bind( ip, serverport ); - socket:settimeout( 0 ) + if not socket then + socket = socket_bind( ip, serverport ); + socket:settimeout( 0 ) + end _readlistlen = addsocket(_readlist, socket, _readlistlen) _socketlist[ socket ] = handler handler.paused = false; @@ -230,7 +229,7 @@ return socket end handler.readbuffer = function( ) - if connections > maxconnections then + if _readlistlen >= _maxselectlen or _sendlistlen >= _maxselectlen then handler.pause( ) out_put( "server.lua: refused new client connection: server full" ) return false @@ -258,6 +257,12 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object + if socket:getfd() >= _maxfd then + out_error("server.lua: Disallowed FD number: "..socket:getfd()) -- PROTIP: Switch to libevent + socket:close( ) -- Should we send some kind of error here? + server.pause( ) + return nil, nil, "fd-too-large" + end socket:settimeout( 0 ) --// local import of socket methods //-- @@ -335,9 +340,6 @@ handler.force_close = function ( self, err ) if bufferqueuelen ~= 0 then out_put("server.lua: discarding unwritten data for ", tostring(ip), ":", tostring(clientport)) - for i = bufferqueuelen, 1, -1 do - bufferqueue[i] = nil; - end bufferqueuelen = 0; end return self:close(err); @@ -391,7 +393,7 @@ return clientport end local write = function( self, data ) - bufferlen = bufferlen + string_len( data ) + bufferlen = bufferlen + #data if bufferlen > maxsendlen then _closelist[ handler ] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle handler.write = idfalse -- dont write anymore @@ -473,7 +475,7 @@ local buffer, err, part = receive( socket, pattern ) -- receive buffer with "pattern" if not err or (err == "wantread" or err == "timeout") then -- received something local buffer = buffer or part or "" - local len = string_len( buffer ) + local len = #buffer if len > maxreadlen then handler:close( "receive buffer exceeded" ) return false @@ -499,7 +501,9 @@ count = ( succ or byte or 0 ) * STAT_UNIT sendtraffic = sendtraffic + count _sendtraffic = _sendtraffic + count - _ = _cleanqueue and clean( bufferqueue ) + for i = bufferqueuelen,1,-1 do + bufferqueue[ i ] = nil + end --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) else succ, err, count = false, "unexpected close", 0; @@ -721,7 +725,7 @@ out_error( "server.lua, [", addr, "]:", port, ": ", err ) return nil, err end - local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket + local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx ) -- wrap new server socket if not handler then server:close( ) return nil, err @@ -765,7 +769,7 @@ end getsettings = function( ) - return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake + return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, nil, _maxselectlen, _maxsslhandshake, _maxfd end changesettings = function( new ) @@ -779,9 +783,9 @@ _checkinterval = tonumber( new.select_idle_check_interval ) or _checkinterval _sendtimeout = tonumber( new.send_timeout ) or _sendtimeout _readtimeout = tonumber( new.read_timeout ) or _readtimeout - _cleanqueue = new.select_clean_queue - _maxclientsperserver = new.max_connections or _maxclientsperserver + _maxselectlen = new.max_connections or _maxselectlen _maxsslhandshake = new.max_ssl_handshake_roundtrips or _maxsslhandshake + _maxfd = new.highest_allowed_fd or _maxfd return true end @@ -831,8 +835,8 @@ for handler, err in pairs( _closelist ) do handler.disconnect( )( handler, err ) handler:force_close() -- forced disconnect + _closelist[ handler ] = nil; end - clean( _closelist ) _currenttime = luasocket_gettime( ) if _currenttime - _timer >= math_min(next_timer_time, 1) then next_timer_time = math_huge; @@ -862,7 +866,8 @@ --// EXPERIMENTAL //-- local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx ) - local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx ) + local handler, socket, err = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx ) + if not handler then return nil, err end _socketlist[ socket ] = handler if not sslctx then _sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
--- a/plugins/mod_admin_adhoc.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/mod_admin_adhoc.lua Sun Mar 10 11:29:47 2013 +0000 @@ -299,8 +299,7 @@ end end - local query_text = query:__tostring(); -- TODO: Use upcoming pretty_print() function - query_text = query_text:gsub("><", ">\n<"); + local query_text = tostring(query):gsub("><", ">\n<"); local result = get_user_roster_result_layout:form({ accountjid = user.."@"..host, roster = query_text }, "result"); result:add_child(query); @@ -467,6 +466,59 @@ end end +local function globally_load_module_handler(self, data, state) + local layout = dataforms_new { + title = "Globally load module"; + instructions = "Specify the module to be loaded on all hosts"; + + { name = "FORM_TYPE", type = "hidden", value = "http://prosody.im/protocol/modules#global-load" }; + { name = "module", type = "text-single", required = true, label = "Module to globally load:"}; + }; + if state then + local ok_list, err_list = {}, {}; + + if data.action == "cancel" then + return { status = "canceled" }; + end + + local fields, err = layout:data(data.form); + if err then + return generate_error_message(err); + end + + local ok, err = modulemanager.load(data.to, fields.module); + if ok then + ok_list[#ok_list + 1] = data.to; + else + err_list[#err_list + 1] = data.to .. " (Error: " .. tostring(err) .. ")"; + end + + -- Is this a global module? + if modulemanager.is_loaded("*", fields.module) and not modulemanager.is_loaded(data.to, fields.module) then + return { status = "completed", info = 'Global module '..fields.module..' loaded.' }; + end + + -- This is either a shared or "normal" module, load it on all other hosts + for host_name, host in pairs(hosts) do + if host_name ~= data.to and host.type == "local" then + local ok, err = modulemanager.load(host_name, fields.module); + if ok then + ok_list[#ok_list + 1] = host_name; + else + err_list[#err_list + 1] = host_name .. " (Error: " .. tostring(err) .. ")"; + end + end + end + + local info = (#ok_list > 0 and ("The module "..fields.module.." was successfully loaded onto the hosts:\n"..t_concat(ok_list, "\n")) or "") + .. ((#ok_list > 0 and #err_list > 0) and "\n" or "") .. + (#err_list > 0 and ("Failed to load the module "..fields.module.." onto the hosts:\n"..t_concat(err_list, "\n")) or ""); + return { status = "completed", info = info }; + else + return { status = "executing", actions = {"next", "complete", default = "complete"}, form = layout }, "executing"; + end +end + function reload_modules_handler(self, data, state) local layout = dataforms_new { title = "Reload modules"; @@ -492,7 +544,8 @@ err_list[#err_list + 1] = module .. "(Error: " .. tostring(err) .. ")"; end end - local info = (#ok_list > 0 and ("The following modules were successfully reloaded on host "..data.to..":\n"..t_concat(ok_list, "\n")) or "").. + local info = (#ok_list > 0 and ("The following modules were successfully reloaded on host "..data.to..":\n"..t_concat(ok_list, "\n")) or "") + .. ((#ok_list > 0 and #err_list > 0) and "\n" or "") .. (#err_list > 0 and ("Failed to reload the following modules on host "..data.to..":\n"..t_concat(err_list, "\n")) or ""); return { status = "completed", info = info }; else @@ -501,6 +554,67 @@ end end +local function globally_reload_module_handler(self, data, state) + local layout = dataforms_new { + title = "Globally reload module"; + instructions = "Specify the module to reload on all hosts"; + + { name = "FORM_TYPE", type = "hidden", value = "http://prosody.im/protocol/modules#global-reload" }; + { name = "module", type = "list-single", required = true, label = "Module to globally reload:"}; + }; + if state then + if data.action == "cancel" then + return { status = "canceled" }; + end + + local is_global = false; + local fields, err = layout:data(data.form); + if err then + return generate_error_message(err); + end + + if modulemanager.is_loaded("*", fields.module) then + local ok, err = modulemanager.reload("*", fields.module); + if not ok then + return { status = "completed", info = 'Global module '..fields.module..' failed to reload: '..err }; + end + is_global = true; + end + + local ok_list, err_list = {}, {}; + for host_name, host in pairs(hosts) do + if modulemanager.is_loaded(host_name, fields.module) then + local ok, err = modulemanager.reload(host_name, fields.module); + if ok then + ok_list[#ok_list + 1] = host_name; + else + err_list[#err_list + 1] = host_name .. " (Error: " .. tostring(err) .. ")"; + end + end + end + + if #ok_list == 0 and #err_list == 0 then + if is_global then + return { status = "completed", info = 'Successfully reloaded global module '..fields.module }; + else + return { status = "completed", info = 'Module '..fields.module..' not loaded on any host.' }; + end + end + + local info = (#ok_list > 0 and ("The module "..fields.module.." was successfully reloaded on the hosts:\n"..t_concat(ok_list, "\n")) or "") + .. ((#ok_list > 0 and #err_list > 0) and "\n" or "") .. + (#err_list > 0 and ("Failed to reload the module "..fields.module.." on the hosts:\n"..t_concat(err_list, "\n")) or ""); + return { status = "completed", info = info }; + else + local loaded_modules = array(keys(modulemanager.get_modules("*"))); + for _, host in pairs(hosts) do + loaded_modules:append(array(keys(host.modules))); + end + loaded_modules = array(keys(set.new(loaded_modules):items())):sort(); + return { status = "executing", actions = {"next", "complete", default = "complete"}, form = { layout = layout, values = { module = loaded_modules } } }, "executing"; + end +end + function send_to_online(message, server) if server then sessions = { [server] = hosts[server] }; @@ -557,7 +671,7 @@ send_to_online(message); end - timer_add_task(tonumber(fields.delay or "5"), prosody.shutdown); + timer_add_task(tonumber(fields.delay or "5"), function(time) prosody.shutdown("Shutdown by adhoc command") end); return { status = "completed", info = "Server is about to shut down" }; else @@ -590,7 +704,8 @@ err_list[#err_list + 1] = module .. "(Error: " .. tostring(err) .. ")"; end end - local info = (#ok_list > 0 and ("The following modules were successfully unloaded on host "..data.to..":\n"..t_concat(ok_list, "\n")) or "").. + local info = (#ok_list > 0 and ("The following modules were successfully unloaded on host "..data.to..":\n"..t_concat(ok_list, "\n")) or "") + .. ((#ok_list > 0 and #err_list > 0) and "\n" or "") .. (#err_list > 0 and ("Failed to unload the following modules on host "..data.to..":\n"..t_concat(err_list, "\n")) or ""); return { status = "completed", info = info }; else @@ -599,6 +714,68 @@ end end +local function globally_unload_module_handler(self, data, state) + local layout = dataforms_new { + title = "Globally unload module"; + instructions = "Specify a module to unload on all hosts"; + + { name = "FORM_TYPE", type = "hidden", value = "http://prosody.im/protocol/modules#global-unload" }; + { name = "module", type = "list-single", required = true, label = "Module to globally unload:"}; + }; + if state then + if data.action == "cancel" then + return { status = "canceled" }; + end + + local is_global = false; + local fields, err = layout:data(data.form); + if err then + return generate_error_message(err); + end + + if modulemanager.is_loaded("*", fields.module) then + local ok, err = modulemanager.unload("*", fields.module); + if not ok then + return { status = "completed", info = 'Global module '..fields.module..' failed to unload: '..err }; + end + is_global = true; + end + + local ok_list, err_list = {}, {}; + for host_name, host in pairs(hosts) do + if modulemanager.is_loaded(host_name, fields.module) then + local ok, err = modulemanager.unload(host_name, fields.module); + if ok then + ok_list[#ok_list + 1] = host_name; + else + err_list[#err_list + 1] = host_name .. " (Error: " .. tostring(err) .. ")"; + end + end + end + + if #ok_list == 0 and #err_list == 0 then + if is_global then + return { status = "completed", info = 'Successfully unloaded global module '..fields.module }; + else + return { status = "completed", info = 'Module '..fields.module..' not loaded on any host.' }; + end + end + + local info = (#ok_list > 0 and ("The module "..fields.module.." was successfully unloaded on the hosts:\n"..t_concat(ok_list, "\n")) or "") + .. ((#ok_list > 0 and #err_list > 0) and "\n" or "") .. + (#err_list > 0 and ("Failed to unload the module "..fields.module.." on the hosts:\n"..t_concat(err_list, "\n")) or ""); + return { status = "completed", info = info }; + else + local loaded_modules = array(keys(modulemanager.get_modules("*"))); + for _, host in pairs(hosts) do + loaded_modules:append(array(keys(host.modules))); + end + loaded_modules = array(keys(set.new(loaded_modules):items())):sort(); + return { status = "executing", actions = {"next", "complete", default = "complete"}, form = { layout = layout, values = { module = loaded_modules } } }, "executing"; + end +end + + function activate_host_handler(self, data, state) local layout = dataforms_new { title = "Activate host"; @@ -667,9 +844,12 @@ local get_online_users_desc = adhoc_new("Get List of Online Users", "http://jabber.org/protocol/admin#get-online-users", get_online_users_command_handler, "admin"); local list_modules_desc = adhoc_new("List loaded modules", "http://prosody.im/protocol/modules#list", list_modules_handler, "admin"); local load_module_desc = adhoc_new("Load module", "http://prosody.im/protocol/modules#load", load_module_handler, "admin"); +local globally_load_module_desc = adhoc_new("Globally load module", "http://prosody.im/protocol/modules#global-load", globally_load_module_handler, "global_admin"); local reload_modules_desc = adhoc_new("Reload modules", "http://prosody.im/protocol/modules#reload", reload_modules_handler, "admin"); +local globally_reload_module_desc = adhoc_new("Globally reload module", "http://prosody.im/protocol/modules#global-reload", globally_reload_module_handler, "global_admin"); local shut_down_service_desc = adhoc_new("Shut Down Service", "http://jabber.org/protocol/admin#shutdown", shut_down_service_handler, "global_admin"); local unload_modules_desc = adhoc_new("Unload modules", "http://prosody.im/protocol/modules#unload", unload_modules_handler, "admin"); +local globally_unload_module_desc = adhoc_new("Globally unload module", "http://prosody.im/protocol/modules#global-unload", globally_unload_module_handler, "global_admin"); local activate_host_desc = adhoc_new("Activate host", "http://prosody.im/protocol/hosts#activate", activate_host_handler, "global_admin"); local deactivate_host_desc = adhoc_new("Deactivate host", "http://prosody.im/protocol/hosts#deactivate", deactivate_host_handler, "global_admin"); @@ -684,8 +864,11 @@ module:provides("adhoc", get_online_users_desc); module:provides("adhoc", list_modules_desc); module:provides("adhoc", load_module_desc); +module:provides("adhoc", globally_load_module_desc); module:provides("adhoc", reload_modules_desc); +module:provides("adhoc", globally_reload_module_desc); module:provides("adhoc", shut_down_service_desc); module:provides("adhoc", unload_modules_desc); +module:provides("adhoc", globally_unload_module_desc); module:provides("adhoc", activate_host_desc); module:provides("adhoc", deactivate_host_desc);
--- a/plugins/mod_dialback.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/mod_dialback.lua Sun Mar 10 11:29:47 2013 +0000 @@ -170,7 +170,7 @@ end end, 100); -module:hook("s2s-authenticate-legacy", function (event) +module:hook("s2sout-authenticate-legacy", function (event) module:log("debug", "Initiating dialback..."); initiate_dialback(event.origin); return true;
--- a/plugins/mod_http.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/mod_http.lua Sun Mar 10 11:29:47 2013 +0000 @@ -38,9 +38,10 @@ end local function get_base_path(host_module, app_name, default_app_path) - return normalize_path(host_module:get_option("http_paths", {})[app_name] -- Host + return (normalize_path(host_module:get_option("http_paths", {})[app_name] -- Host or module:get_option("http_paths", {})[app_name] -- Global - or default_app_path); -- Default + or default_app_path)) -- Default + :gsub("%$(%w+)", { host = module.host }); end local ports_by_scheme = { http = 80, https = 443, };
--- a/plugins/mod_proxy65.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/mod_proxy65.lua Sun Mar 10 11:29:47 2013 +0000 @@ -106,16 +106,20 @@ module:hook("iq-get/host/http://jabber.org/protocol/disco#info:query", function(event) local origin, stanza = event.origin, event.stanza; - origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#info") - :tag("identity", {category='proxy', type='bytestreams', name=name}):up() - :tag("feature", {var="http://jabber.org/protocol/bytestreams"}) ); - return true; + if not stanza.tags[1].attr.node then + origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#info") + :tag("identity", {category='proxy', type='bytestreams', name=name}):up() + :tag("feature", {var="http://jabber.org/protocol/bytestreams"}) ); + return true; + end end, -1); module:hook("iq-get/host/http://jabber.org/protocol/disco#items:query", function(event) local origin, stanza = event.origin, event.stanza; - origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#items")); - return true; + if not stanza.tags[1].attr.node then + origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#items")); + return true; + end end, -1); module:hook("iq-get/host/http://jabber.org/protocol/bytestreams:query", function(event)
--- a/plugins/mod_s2s/mod_s2s.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/mod_s2s/mod_s2s.lua Sun Mar 10 11:29:47 2013 +0000 @@ -287,7 +287,7 @@ -- If server is pre-1.0, don't wait for features, just do dialback if session.version < 1.0 then if not session.dialback_verifying then - hosts[session.from_host].events.fire_event("s2s-authenticate-legacy", { origin = session }); + hosts[session.from_host].events.fire_event("s2sout-authenticate-legacy", { origin = session }); else s2s_mark_connected(session); end
--- a/plugins/muc/mod_muc.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/muc/mod_muc.lua Sun Mar 10 11:29:47 2013 +0000 @@ -126,9 +126,10 @@ if type == "error" or type == "result" then return; end if stanza.name == "iq" and type == "get" then local xmlns = stanza.tags[1].attr.xmlns; - if xmlns == "http://jabber.org/protocol/disco#info" then + local node = stanza.tags[1].attr.node; + if xmlns == "http://jabber.org/protocol/disco#info" and not node then origin.send(get_disco_info(stanza)); - elseif xmlns == "http://jabber.org/protocol/disco#items" then + elseif xmlns == "http://jabber.org/protocol/disco#items" and not node then origin.send(get_disco_items(stanza)); elseif xmlns == "http://jabber.org/protocol/muc#unique" then origin.send(st.reply(stanza):tag("unique", {xmlns = xmlns}):text(uuid_gen())); -- FIXME Random UUIDs can theoretically have collisions
--- a/plugins/muc/muc.lib.lua Sun Feb 03 15:52:27 2013 +0100 +++ b/plugins/muc/muc.lib.lua Sun Mar 10 11:29:47 2013 +0000 @@ -765,13 +765,9 @@ local type = stanza.attr.type; local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns; if stanza.name == "iq" then - if xmlns == "http://jabber.org/protocol/disco#info" and type == "get" then - if stanza.tags[1].attr.node then - origin.send(st.error_reply(stanza, "cancel", "feature-not-implemented")); - else - origin.send(self:get_disco_info(stanza)); - end - elseif xmlns == "http://jabber.org/protocol/disco#items" and type == "get" then + if xmlns == "http://jabber.org/protocol/disco#info" and type == "get" and not stanza.tags[1].attr.node then + origin.send(self:get_disco_info(stanza)); + elseif xmlns == "http://jabber.org/protocol/disco#items" and type == "get" and not stanza.tags[1].attr.node then origin.send(self:get_disco_items(stanza)); elseif xmlns == "http://jabber.org/protocol/muc#admin" then local actor = stanza.attr.from; @@ -987,7 +983,7 @@ return true; end if actor_affiliation ~= "owner" then - if actor_affiliation ~= "admin" or target_affiliation == "owner" or target_affiliation == "admin" then + if affiliation == "owner" or affiliation == "admin" or actor_affiliation ~= "admin" or target_affiliation == "owner" or target_affiliation == "admin" then return nil, "cancel", "not-allowed"; end elseif target_affiliation == "owner" and jid_bare(actor) == jid then -- self change