# HG changeset patch # User Mikael Berthe # Date 1343753214 -7200 # Node ID e193f80521cc89ca6fbabe96b1be25f76cd629cc # Parent 7265595dbc3b95f5a4e98e83ae606a8f94705a3d Backport to Prosody 0.8 diff -r 7265595dbc3b -r e193f80521cc mod_admin_messageconsole.lua --- a/mod_admin_messageconsole.lua Tue Jul 31 18:31:42 2012 +0200 +++ b/mod_admin_messageconsole.lua Tue Jul 31 18:46:54 2012 +0200 @@ -1,6 +1,8 @@ -- Prosody IM -- -- This module depends on Prosody's admin_telnet module +-- and some code (redirect_output() and onincoming() from console_listener) +-- is duplicated here... -- -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain @@ -13,10 +15,9 @@ local st = require "util.stanza"; local um_is_admin = require "core.usermanager".is_admin; -local admin_telnet = module:depends("admin_telnet"); -local telnet_def_env = module:shared("/*/admin_telnet/env"); -local telnet_commands = module:shared("/*/admin_telnet/commands"); -local default_env_mt = { __index = telnet_def_env }; +local telnet_def_env; +local default_env_mt; +local telnet_commands; local host = module.host; @@ -29,6 +30,19 @@ disconnect = function () end; }; + -- Initialization + -- Hack for 0.8 - Let's get dependencies now as we're almost + -- certain the admin_telnet module has been loaded by now. + if not telnet_def_env then + local prosody = _G.prosody; + local console = prosody.console; + + telnet_def_env = console.env; + default_env_mt = { __index = telnet_def_env }; + + telnet_commands = console.commands; + end + session.print = function (...) local t = {}; for i=1,select("#", ...) do @@ -55,7 +69,94 @@ return session; end -local function on_message(event) +-- This function is 100% duplicated from mod_admin_telnet. +function onincoming(session, data) + + local commands = telnet_commands; + local partial = session.partial_data; + if partial then + data = partial..data; + end + + local function redirect_output(_G, session) + local env = setmetatable({ print = session.print }, + { __index = function (t, k) return rawget(_G, k); end }); + env.dofile = function(name) + local f, err = loadfile(name); + if not f then return f, err; end + return setfenv(f, env)(); + end; + return env; + end + + for line in data:gmatch("[^\n]*[\n\004]") do + -- Handle data (loop allows us to break to add \0 after response) + repeat + local useglobalenv; + + if line:match("^>") then + line = line:gsub("^>", ""); + useglobalenv = true; + elseif line == "\004" then + commands["bye"](session, line); + break; + else + local command = line:lower(); + command = line:match("^%w+") or line:match("%p"); + if commands[command] then + commands[command](session, line); + break; + end + end + + session.env._ = line; + + local chunkname = "=console"; + local chunk, err = loadstring("return "..line, chunkname); + if not chunk then + chunk, err = loadstring(line, chunkname); + if not chunk then + err = err:gsub("^%[string .-%]:%d+: ", ""); + err = err:gsub("^:%d+: ", ""); + err = err:gsub("''", "the end of the line"); + session.print("Sorry, I couldn't understand that... "..err); + break; + end + end + + setfenv(chunk, (useglobalenv and redirect_output(_G, session)) or session.env or nil); + + local ranok, taskok, message = pcall(chunk); + + if not (ranok or message or useglobalenv) and commands[line:lower()] then + commands[line:lower()](session, line); + break; + end + + if not ranok then + session.print("Fatal error while running command, it did not complete"); + session.print("Error: "..taskok); + break; + end + + if not message then + session.print("Result: "..tostring(taskok)); + break; + elseif (not taskok) and message then + session.print("Command completed with a problem"); + session.print("Message: "..tostring(message)); + break; + end + + session.print("OK: "..tostring(message)); + until true + + session.send(string.char(0)); + end + session.partial_data = data:match("[^\n]+$"); +end + +function on_message(event) -- Check the type of the incoming stanza to avoid loops: if event.stanza.attr.type == "error" then return; -- We do not want to reply to these, so leave. @@ -80,7 +181,7 @@ local session = new_session(); -- Process the message using admin_telnet's onincoming function - admin_telnet.console_incoming_message(session, body.."\n"); + onincoming(session, body.."\n"); -- Strip trailing blank line session.fulltext = tostring(session.fulltext):gsub("\n\|%s*$", "") @@ -89,7 +190,7 @@ local reply_stanza = st.message({ from = host, to = userjid, type = "chat" }); reply_stanza = reply_stanza:body(session.fulltext); - module:send(reply_stanza); + core_post_stanza(hosts[module.host], reply_stanza); return true; end @@ -114,7 +215,7 @@ local presence_stanza = st.presence({ from = host, to = userjid, type = "subscribed", id = event.stanza.attr.id }); - module:send(presence_stanza); + core_post_stanza(hosts[module.host], presence_stanza); elseif (event.stanza.attr.type == "probe") then send_presence = true; elseif (event.stanza.attr.type == "unsubscribe") then @@ -124,7 +225,9 @@ if (send_presence == true) then -- Send a presence stanza - module:send(st.presence({ from = host, to = userjid })); + local presence_stanza = st.presence({ from = host, + to = userjid }); + core_post_stanza(hosts[module.host], presence_stanza); end return true; end