Software / code / prosody
Comparison
plugins/mod_admin_telnet.lua @ 4989:573123ff2ab0
mod_admin_telnet: Always handle commands terminated by line feeds - ensures consistency even when packets are joined or split on the network
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Mon, 23 Jul 2012 14:03:00 +0100 |
| parent | 4979:5614bbc163e0 |
| child | 5005:ab950c9ff074 |
comparison
equal
deleted
inserted
replaced
| 4988:29bdf68ad142 | 4989:573123ff2ab0 |
|---|---|
| 11 local _G = _G; | 11 local _G = _G; |
| 12 | 12 |
| 13 local prosody = _G.prosody; | 13 local prosody = _G.prosody; |
| 14 local hosts = prosody.hosts; | 14 local hosts = prosody.hosts; |
| 15 | 15 |
| 16 local console_listener = { default_port = 5582; default_mode = "*l"; interface = "127.0.0.1" }; | 16 local console_listener = { default_port = 5582; default_mode = "*a"; interface = "127.0.0.1" }; |
| 17 | 17 |
| 18 local iterators = require "util.iterators"; | 18 local iterators = require "util.iterators"; |
| 19 local keys, values = iterators.keys, iterators.values; | 19 local keys, values = iterators.keys, iterators.values; |
| 20 local jid = require "util.jid"; | 20 local jid = require "util.jid"; |
| 21 local jid_bare, jid_split = jid.bare, jid.split; | 21 local jid_bare, jid_split = jid.bare, jid.split; |
| 74 end | 74 end |
| 75 | 75 |
| 76 function console_listener.onincoming(conn, data) | 76 function console_listener.onincoming(conn, data) |
| 77 local session = sessions[conn]; | 77 local session = sessions[conn]; |
| 78 | 78 |
| 79 -- Handle data (loop allows us to break to add \0 after response) | 79 local partial = session.partial_data; |
| 80 repeat | 80 if partial then |
| 81 local useglobalenv; | 81 data = partial..data; |
| 82 | 82 end |
| 83 if data:match("^>") then | 83 |
| 84 data = data:gsub("^>", ""); | 84 for line in data:gmatch("[^\n]*[\n\004]") do |
| 85 useglobalenv = true; | 85 -- Handle data (loop allows us to break to add \0 after response) |
| 86 elseif data == "\004" then | 86 repeat |
| 87 commands["bye"](session, data); | 87 local useglobalenv; |
| 88 break; | 88 |
| 89 else | 89 if line:match("^>") then |
| 90 local command = data:lower(); | 90 line = line:gsub("^>", ""); |
| 91 command = data:match("^%w+") or data:match("%p"); | 91 useglobalenv = true; |
| 92 if commands[command] then | 92 elseif line == "\004" then |
| 93 commands[command](session, data); | 93 commands["bye"](session, line); |
| 94 break; | 94 break; |
| 95 end | 95 else |
| 96 end | 96 local command = line:lower(); |
| 97 | 97 command = line:match("^%w+") or line:match("%p"); |
| 98 session.env._ = data; | 98 if commands[command] then |
| 99 commands[command](session, line); | |
| 100 break; | |
| 101 end | |
| 102 end | |
| 103 | |
| 104 session.env._ = line; | |
| 105 | |
| 106 local chunkname = "=console"; | |
| 107 local chunk, err = loadstring("return "..line, chunkname); | |
| 108 if not chunk then | |
| 109 chunk, err = loadstring(line, chunkname); | |
| 110 if not chunk then | |
| 111 err = err:gsub("^%[string .-%]:%d+: ", ""); | |
| 112 err = err:gsub("^:%d+: ", ""); | |
| 113 err = err:gsub("'<eof>'", "the end of the line"); | |
| 114 session.print("Sorry, I couldn't understand that... "..err); | |
| 115 break; | |
| 116 end | |
| 117 end | |
| 118 | |
| 119 setfenv(chunk, (useglobalenv and redirect_output(_G, session)) or session.env or nil); | |
| 120 | |
| 121 local ranok, taskok, message = pcall(chunk); | |
| 122 | |
| 123 if not (ranok or message or useglobalenv) and commands[line:lower()] then | |
| 124 commands[line:lower()](session, line); | |
| 125 break; | |
| 126 end | |
| 127 | |
| 128 if not ranok then | |
| 129 session.print("Fatal error while running command, it did not complete"); | |
| 130 session.print("Error: "..taskok); | |
| 131 break; | |
| 132 end | |
| 133 | |
| 134 if not message then | |
| 135 session.print("Result: "..tostring(taskok)); | |
| 136 break; | |
| 137 elseif (not taskok) and message then | |
| 138 session.print("Command completed with a problem"); | |
| 139 session.print("Message: "..tostring(message)); | |
| 140 break; | |
| 141 end | |
| 142 | |
| 143 session.print("OK: "..tostring(message)); | |
| 144 until true | |
| 99 | 145 |
| 100 local chunkname = "=console"; | 146 session.send(string.char(0)); |
| 101 local chunk, err = loadstring("return "..data, chunkname); | 147 end |
| 102 if not chunk then | 148 session.partial_data = data:match("[^\n]+$"); |
| 103 chunk, err = loadstring(data, chunkname); | |
| 104 if not chunk then | |
| 105 err = err:gsub("^%[string .-%]:%d+: ", ""); | |
| 106 err = err:gsub("^:%d+: ", ""); | |
| 107 err = err:gsub("'<eof>'", "the end of the line"); | |
| 108 session.print("Sorry, I couldn't understand that... "..err); | |
| 109 break; | |
| 110 end | |
| 111 end | |
| 112 | |
| 113 setfenv(chunk, (useglobalenv and redirect_output(_G, session)) or session.env or nil); | |
| 114 | |
| 115 local ranok, taskok, message = pcall(chunk); | |
| 116 | |
| 117 if not (ranok or message or useglobalenv) and commands[data:lower()] then | |
| 118 commands[data:lower()](session, data); | |
| 119 break; | |
| 120 end | |
| 121 | |
| 122 if not ranok then | |
| 123 session.print("Fatal error while running command, it did not complete"); | |
| 124 session.print("Error: "..taskok); | |
| 125 break; | |
| 126 end | |
| 127 | |
| 128 if not message then | |
| 129 session.print("Result: "..tostring(taskok)); | |
| 130 break; | |
| 131 elseif (not taskok) and message then | |
| 132 session.print("Command completed with a problem"); | |
| 133 session.print("Message: "..tostring(message)); | |
| 134 break; | |
| 135 end | |
| 136 | |
| 137 session.print("OK: "..tostring(message)); | |
| 138 until true | |
| 139 | |
| 140 session.send(string.char(0)); | |
| 141 end | 149 end |
| 142 | 150 |
| 143 function console_listener.ondisconnect(conn, err) | 151 function console_listener.ondisconnect(conn, err) |
| 144 local session = sessions[conn]; | 152 local session = sessions[conn]; |
| 145 if session then | 153 if session then |