8ecbd4ea2289c3d882de05efe8ae196583882331
[prosody.git] / plugins / mod_console.lua
1 -- Prosody IM v0.2
2 -- Copyright (C) 2008 Matthew Wild
3 -- Copyright (C) 2008 Waqas Hussain
4 -- 
5 -- This program is free software; you can redistribute it and/or
6 -- modify it under the terms of the GNU General Public License
7 -- as published by the Free Software Foundation; either version 2
8 -- of the License, or (at your option) any later version.
9 -- 
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 -- GNU General Public License for more details.
14 -- 
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 --
19
20 module.host = "*";
21
22 local connlisteners_register = require "net.connlisteners".register;
23
24 local console_listener = { default_port = 5582; default_mode = "*l"; };
25
26 local commands = {};
27 local def_env = {};
28 local default_env_mt = { __index = def_env };
29
30 console = {};
31
32 function console:new_session(conn)
33         local w = function(s) conn.write(s:gsub("\n", "\r\n")); end;
34         local session = { conn = conn;
35                         send = function (t) w(tostring(t)); end;
36                         print = function (t) w("| "..tostring(t).."\n"); end;
37                         disconnect = function () conn.close(); end;
38                         };
39         session.env = setmetatable({}, default_env_mt);
40         
41         -- Load up environment with helper objects
42         for name, t in pairs(def_env) do
43                 if type(t) == "table" then
44                         session.env[name] = setmetatable({ session = session }, { __index = t });
45                 end
46         end
47         
48         return session;
49 end
50
51 local sessions = {};
52
53 function console_listener.listener(conn, data)
54         local session = sessions[conn];
55         
56         if not session then
57                 -- Handle new connection
58                 session = console:new_session(conn);
59                 sessions[conn] = session;
60                 printbanner(session);
61         end
62         if data then
63                 -- Handle data
64                 (function(session, data)
65                         if data:match("[!.]$") then
66                                 local command = data:lower();
67                                 command = data:match("^%w+") or data:match("%p");
68                                 if commands[command] then
69                                         commands[command](session, data);
70                                         return;
71                                 end
72                         end
73                         
74                         session.env._ = data;
75                         
76                         local chunk, err = loadstring("return "..data);
77                         if not chunk then
78                                 chunk, err = loadstring(data);
79                                 if not chunk then
80                                         err = err:gsub("^%[string .-%]:%d+: ", "");
81                                         err = err:gsub("^:%d+: ", "");
82                                         err = err:gsub("'<eof>'", "the end of the line");
83                                         session.print("Sorry, I couldn't understand that... "..err);
84                                         return;
85                                 end
86                         end
87                         
88                         setfenv(chunk, session.env);
89                         local ranok, taskok, message = pcall(chunk);
90                         
91                         if not ranok then
92                                 session.print("Fatal error while running command, it did not complete");
93                                 session.print("Error: "..taskok);
94                                 return;
95                         end
96                         
97                         if not message then
98                                 session.print("Result: "..tostring(taskok));
99                                 return;
100                         elseif (not taskok) and message then
101                                 session.print("Command completed with a problem");
102                                 session.print("Message: "..tostring(message));
103                                 return;
104                         end
105                         
106                         session.print("OK: "..tostring(message));
107                 end)(session, data);
108         end
109         session.send(string.char(0));
110 end
111
112 function console_listener.disconnect(conn, err)
113         
114 end
115
116 connlisteners_register('console', console_listener);
117
118 -- Console commands --
119 -- These are simple commands, not valid standalone in Lua
120
121 function commands.bye(session)
122         session.print("See you! :)");
123         session.disconnect();
124 end
125
126 commands["!"] = function (session, data)
127         if data:match("^!!") then
128                 session.print("!> "..session.env._);
129                 return console_listener.listener(session.conn, session.env._);
130         end
131         local old, new = data:match("^!(.-[^\\])!(.-)!$");
132         if old and new then
133                 local ok, res = pcall(string.gsub, session.env._, old, new);
134                 if not ok then
135                         session.print(res)
136                         return;
137                 end
138                 session.print("!> "..res);
139                 return console_listener.listener(session.conn, res);
140         end
141         session.print("Sorry, not sure what you want");
142 end
143
144 -- Session environment --
145 -- Anything in def_env will be accessible within the session as a global variable
146
147 def_env.server = {};
148 function def_env.server:reload()
149         dofile "prosody"
150         return true, "Server reloaded";
151 end
152
153 def_env.module = {};
154 function def_env.module:load(name, host, config)
155         local mm = require "modulemanager";
156         local ok, err = mm.load(host or self.env.host, name, config);
157         if not ok then
158                 return false, err or "Unknown error loading module";
159         end
160         return true, "Module loaded";
161 end
162
163 function def_env.module:unload(name, host)
164         local mm = require "modulemanager";
165         local ok, err = mm.unload(host or self.env.host, name);
166         if not ok then
167                 return false, err or "Unknown error unloading module";
168         end
169         return true, "Module unloaded";
170 end
171
172 function def_env.module:reload(name, host)
173         local mm = require "modulemanager";
174         local ok, err = mm.reload(host or self.env.host, name);
175         if not ok then
176                 return false, err or "Unknown error reloading module";
177         end
178         return true, "Module reloaded";
179 end
180
181 def_env.config = {};
182 function def_env.config:load(filename, format)
183         local config_load = require "core.configmanager".load;
184         local ok, err = config_load(filename, format);
185         if not ok then
186                 return false, err or "Unknown error loading config";
187         end
188         return true, "Config loaded";
189 end
190
191 function def_env.config:get(host, section, key)
192         local config_get = require "core.configmanager".get
193         return true, tostring(config_get(host, section, key));
194 end
195
196 def_env.hosts = {};
197 function def_env.hosts:list()
198         for host, host_session in pairs(hosts) do
199                 self.session.print(host);
200         end
201         return true, "Done";
202 end
203
204 function def_env.hosts:add(name)
205 end
206
207 -------------
208
209 function printbanner(session)
210 session.print [[
211                    ____                \   /     _       
212                     |  _ \ _ __ ___  ___  _-_   __| |_   _ 
213                     | |_) | '__/ _ \/ __|/ _ \ / _` | | | |
214                     |  __/| | | (_) \__ \ |_| | (_| | |_| |
215                     |_|   |_|  \___/|___/\___/ \__,_|\__, |
216                     A study in simplicity            |___/ 
217
218 ]]
219 session.print("Welcome to the Prosody administration console. For a list of commands, type: help");
220 session.print("You may find more help on using this console in our online documentation at ");
221 session.print("http://prosody.im/doc/console\n");
222 end