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