Merge from waqas

Sun, 23 Nov 2008 05:03:36 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Sun, 23 Nov 2008 05:03:36 +0000
changeset 390
160d69c6eb89
parent 383
32b586d9e915 (diff)
parent 389
c747d6963d95 (current diff)
child 391
79bd7a3e906c

Merge from waqas

--- a/core/configmanager.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/core/configmanager.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -1,5 +1,7 @@
 
 local _G = _G;
+local 	setmetatable, loadfile, pcall, rawget, rawset, io = 
+		setmetatable, loadfile, pcall, rawget, rawset, io;
 module "configmanager"
 
 local parsers = {};
@@ -21,6 +23,10 @@
 							end };
 end
 
+function getconfig()
+	return config;
+end
+
 function get(host, section, key)
 	local sec = config[host][section];
 	if sec then
@@ -45,15 +51,20 @@
 end
 
 function load(filename, format)
+	format = format or filename:match("%w+$");
 	if parsers[format] and parsers[format].load then
 		local f = io.open(filename);
 		if f then 
-			local ok, err = parsers[format](f:read("*a"));
+			local ok, err = parsers[format].load(f:read("*a"));
 			f:close();
 			return ok, err;
 		end
 	end
-	return false, "no parser";
+	if not format then
+		return nil, "no parser specified";
+	else
+		return false, "no parser";
+	end
 end
 
 function save(filename, format)
@@ -65,21 +76,28 @@
 	end
 end
 
+-- Built-in Lua parser
 do
+	local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable;
+	local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring;
 	parsers.lua = {};
 	function parsers.lua.load(data)
-		local env = setmetatable({}, { __index = function (t, k)
-											if k:match("^mod_") then
-												return function (settings_table)
+		local env;
+		env = setmetatable({ Host = true; host = true; }, { __index = function (t, k)
+												return rawget(_G, k) or
+														function (settings_table)
 															config[__currenthost or "*"][k] = settings_table;
 														end;
-											end
-											return rawget(_G, k);
+										end,
+								__newindex = function (t, k, v)
+											set(env.__currenthost or "*", "core", k, v);
 										end});
 		
 		function env.Host(name)
-			env.__currenthost = name;
+			rawset(env, "__currenthost", name);
+			set(name or "*", "core", "defined", true);
 		end
+		env.host = env.Host;
 		
 		local chunk, err = loadstring(data);
 		
@@ -95,8 +113,6 @@
 			return nil, err;
 		end
 		
-		
-		
 		return true;
 	end
 	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lxmppd.cfg.lua.dist	Sun Nov 23 05:03:36 2008 +0000
@@ -0,0 +1,74 @@
+-- lxmppd Example Configuration File 
+-- 
+-- If it wasn't already obvious, -- starts a comment, and all 
+-- text after it is ignored by lxmppd.
+--
+-- The config is split into sections, a global section, and one 
+-- for each defined host that we serve. You can add as many host 
+-- sections as you like.
+--
+-- Lists are written { "like", "this", "one" } 
+-- Lists can also be of { 1, 2, 3 } numbers, etc. 
+-- Either commas, or semi-colons; may be used
+-- as seperators.
+--
+-- A table is a list of values, except each value has a name. An 
+-- example would be:
+--
+-- logging = { type = "html", directory = "/var/logs", rotate = "daily" }
+--
+-- Whitespace (that is tabs, spaces, line breaks) is insignificant, so can 
+-- be placed anywhere
+-- that 	you deem fitting. Youcouldalsoremoveitentirely,butforobviousrea
+--sonsIdon'trecommendit.
+--
+-- Tip: You can check that the syntax of this file is correct when you have finished
+-- by running: luac -p lxmppd.cfg.lua
+-- If there are any errors, it will let you know what and where they are, otherwise it 
+-- will keep quiet.
+--
+-- The only thing left to do is rename this file to remove the .dist ending, and fill in the 
+-- blanks. Good luck, and happy Jabbering!
+
+-- Global settings go in this section
+Host "*"
+	
+	-- This is the list of modules lxmppd will load on startup.
+	-- It looks for plugins/mod_modulename.lua, so make sure that exists too.
+	modules_enabled = {
+				"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
+				"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
+				"roster"; -- Allow users to have a roster. Recommended ;)
+				"register"; -- Allow users to register on this server using a client
+				"tls"; -- Add support for secure TLS on c2s/s2s connections
+				"vcard"; -- Allow users to set vCards
+				"private"; -- Private XML storage (for room bookmarks, etc.)
+				"version"; -- Replies to server version requests
+				"dialback"; -- s2s dialback support
+			  };
+	
+	-- These are the SSL/TLS-related settings. If you don't want
+	-- to use SSL/TLS, you may comment or remove this
+	ssl = { 
+		key = "certs/server.key";
+		certificate = "certs/server.crt";
+		}
+
+-- This allows clients to connect to localhost. No harm in it.
+Host "localhost"
+
+-- Section for example.com
+-- (replace example.com with your domain name)
+Host "example.com"
+	-- Assign this host a certificate for TLS, otherwise it would use the one
+	-- set in the global section (if any).
+	-- Note that old-style SSL on port 5223 only supports one certificate, and will always
+	-- use the global one.
+	ssl = { 
+		key = "certs/example.com.key";
+		certificate = "certs/example.com.crt";
+		}
+
+Host "example.org"
+	enabled = false -- This will disable the host, preserving the config, but denying connections
+	
--- a/main.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/main.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -4,22 +4,42 @@
 require "lxp"
 require "socket"
 require "ssl"
+local config = require "core.configmanager"
 
-function log(type, area, message)
-	print(type, area, message);
+log = require "util.logger".init("general");
+
+do
+	-- TODO: Check for other formats when we add support for them
+	-- Use lfs? Make a new conf/ dir?
+	local ok, err = config.load("lxmppd.cfg.lua");
+	if not ok then
+		log("error", "Couldn't load config file: %s", err);
+		log("info", "Falling back to old config file format...")
+		ok, err = pcall(dofile, "lxmppd.cfg");
+		if not ok then
+			log("error", "Old config format loading failed too: %s", err);
+		else
+			for _, host in ipairs(_G.config.hosts) do
+				config.set(host, "core", "defined", true);
+			end
+			
+			config.set("*", "core", "modules_enabled", _G.config.modules);
+			config.set("*", "core", "ssl", _G.config.ssl_ctx);
+		end
+	end
 end
 
-dofile "lxmppd.cfg"
-
 -- Maps connections to sessions --
 sessions = {};
 hosts = {};
 
-if config.hosts and #config.hosts > 0 then
-	for _, host in pairs(config.hosts) do
+local defined_hosts = config.getconfig();
+
+for host, host_config in pairs(defined_hosts) do
+	if host ~= "*" and (host_config.core.enabled == nil or host_config.core.enabled) then
 		hosts[host] = {type = "local", connected = true, sessions = {}, host = host, s2sout = {} };
 	end
-else error("No hosts defined in the configuration file"); end
+end
 
 -- Load and initialise core modules --
 
@@ -32,8 +52,10 @@
 require "core.sessionmanager"
 require "core.stanza_router"
 
+--[[
 pcall(require, "remdebug.engine");
 if remdebug then remdebug.engine.start() end
+]]
 
 local start = require "net.connlisteners".start;
 require "util.stanza"
@@ -42,11 +64,12 @@
 ------------------------------------------------------------------------
 
 -- Initialise modules
-if config.modules and #config.modules > 0 then
-	for _, module in pairs(config.modules) do
+local modules_enabled = config.get("*", "core", "modules_enabled");
+if modules_enabled then
+	for _, module in pairs(modules_enabled) do
 		modulemanager.load(module);
 	end
-else error("No modules enabled in the configuration file"); end
+end
 
 -- setup error handling
 setmetatable(_G, { __index = function (t, k) print("WARNING: ATTEMPT TO READ A NIL GLOBAL!!!", k); error("Attempt to read a non-existent global. Naughty boy.", 2); end, __newindex = function (t, k, v) print("ATTEMPT TO SET A GLOBAL!!!!", tostring(k).." = "..tostring(v)); error("Attempt to set a global. Naughty boy.", 2); end }) --]][][[]][];
@@ -54,9 +77,20 @@
 local protected_handler = function (conn, data, err) local success, ret = pcall(handler, conn, data, err); if not success then print("ERROR on "..tostring(conn)..": "..ret); conn:close(); end end;
 local protected_disconnect = function (conn, err) local success, ret = pcall(disconnect, conn, err); if not success then print("ERROR on "..tostring(conn).." disconnect: "..ret); conn:close(); end end;
 
+
+local global_ssl_ctx = config.get("*", "core", "ssl");
+if global_ssl_ctx then
+	local default_ssl_ctx = { mode = "server", protocol = "sslv23", capath = "/etc/ssl/certs", verify = "none"; };
+	setmetatable(global_ssl_ctx, { __index = default_ssl_ctx });
+end
+
 -- start listening on sockets
-start("xmppclient", { ssl = config.ssl_ctx })
-start("xmppserver", { ssl = config.ssl_ctx })
+start("xmppclient", { ssl = global_ssl_ctx })
+start("xmppserver", { ssl = global_ssl_ctx })
+
+if config.get("*", "core", "console_enabled") then
+	start("console")
+end
 
 modulemanager.fire_event("server-started");
 
--- a/net/connlisteners.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/net/connlisteners.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -38,8 +38,8 @@
 		error("No such connection module: "..name, 0);
 	end
 	return server_add(h, 
-			udata.port or h.default_port or error("Can't start listener "..name.." because no port was specified, and it has no default port", 0), 
-				udata.interface or "*", udata.mode or h.default_mode or 1, udata.ssl );
+			(udata and udata.port) or h.default_port or error("Can't start listener "..name.." because no port was specified, and it has no default port", 0), 
+				(udata and udata.interface) or "*", (udata and udata.mode) or h.default_mode or 1, (udata and udata.ssl) or nil );
 end
 
 return _M;
\ No newline at end of file
--- a/net/dns.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/net/dns.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -19,8 +19,8 @@
 local coroutine, io, math, socket, string, table =
       coroutine, io, math, socket, string, table
 
-local ipairs, next, pairs, print, setmetatable, tostring =
-      ipairs, next, pairs, print, setmetatable, tostring
+local ipairs, next, pairs, print, setmetatable, tostring, assert, error =
+      ipairs, next, pairs, print, setmetatable, tostring, assert, error
 
 local get, set = ztact.get, ztact.set
 
@@ -130,7 +130,7 @@
 
 local rrs_metatable = {}    -- - - - - - - - - - - - - - - - - -  rrs_metatable
 function rrs_metatable.__tostring (rrs)
-  t = {}
+  local t = {}
   for i,rr in pairs (rrs) do  append (t, tostring (rr)..'\n')  end
   return table.concat (t)
   end
@@ -501,8 +501,10 @@
 
 
 function resolver:adddefaultnameservers ()    -- - - - -  adddefaultnameservers
-  for line in io.lines ('/etc/resolv.conf') do
-    address = string.match (line, 'nameserver%s+(%d+%.%d+%.%d+%.%d+)')
+  local resolv_conf = io.open("/etc/resolv.conf");
+  if not resolv_conf then return nil; end
+  for line in resolv_conf:lines() do
+    local address = string.match (line, 'nameserver%s+(%d+%.%d+%.%d+%.%d+)')
     if address then  self:addnameserver (address)  end
     end  end
 
@@ -580,7 +582,7 @@
     for class,types in pairs (self.cache or {}) do
       for type,names in pairs (types) do
         for name,rrs in pairs (names) do
-          prune (rrs, time, 'soft')
+          prune (rrs, self.time, 'soft')
           end  end  end
   else  self.cache = {}  end
   end
@@ -592,7 +594,7 @@
 
   if not self.server then  self:adddefaultnameservers ()  end
 
-  local question = question or encodeQuestion (qname, qtype, qclass)
+  local question = encodeQuestion (qname, qtype, qclass)
   local peek = self:peek (qname, qtype, qclass)
   if peek then  return peek  end
 
@@ -765,7 +767,7 @@
 
   -- this function seems to be redundant with resolver.new ()
 
-  r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {} }
+  local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {} }
   setmetatable (r, resolver)
   setmetatable (r.cache, cache_metatable)
   setmetatable (r.unsorted, { __mode = 'kv' })
--- a/net/server.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/net/server.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -619,7 +619,7 @@
 		return shutdown( socket, pattern )
 	end
 	handler.close = function( closed )
-		if eol and not fatal_send_error then handler._dispatchdata(); end
+		if eol and not fatal_send_error then handler.dispatchdata(); end
 		_ = not closed and shutdown( socket )
 		_ = not closed and close( socket )
 		writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/mod_console.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -0,0 +1,140 @@
+
+local connlisteners_register = require "net.connlisteners".register;
+
+local console_listener = { default_port = 5582; default_mode = "*l"; };
+
+local commands = {};
+local default_env = {};
+local default_env_mt = { __index = default_env };
+
+console = {};
+
+function console:new_session(conn)
+	local w = conn.write;
+	return { conn = conn;
+			send = function (t) w(tostring(t)); end;
+			print = function (t) w("| "..tostring(t).."\n"); end;
+			disconnect = function () conn.close(); end;
+			env = setmetatable({}, default_env_mt);
+			};
+end
+
+local sessions = {};
+
+function console_listener.listener(conn, data)
+	local session = sessions[conn];
+	
+	if not session then
+		-- Handle new connection
+		session = console:new_session(conn);
+		sessions[conn] = session;
+		session.print("Welcome to the lxmppd admin console!");
+	end
+	if data then
+		-- Handle data
+		
+		if data:match("[!.]$") then
+			local command = data:lower();
+			command = data:match("^%w+") or data:match("%p");
+			if commands[command] then
+				commands[command](session, data);
+				return;
+			end
+		end
+		
+		session.env._ = data;
+		
+		local chunk, err = loadstring("return "..data);
+		if not chunk then
+			chunk, err = loadstring(data);
+			if not chunk then
+				err = err:gsub("^%[string .-%]:%d+: ", "");
+				err = err:gsub("^:%d+: ", "");
+				err = err:gsub("'<eof>'", "the end of the line");
+				session.print("Sorry, I couldn't understand that... "..err);
+				return;
+			end
+		end
+		
+		setfenv(chunk, session.env);
+		local ranok, taskok, message = pcall(chunk);
+		
+		if not ranok then
+			session.print("Fatal error while running command, it did not complete");
+			session.print("Error: "..taskok);
+			return;
+		end
+		
+		if not message then
+			session.print("Result: "..tostring(taskok));
+			return;
+		elseif (not taskok) and message then
+			session.print("Command completed with a problem");
+			session.print("Message: "..tostring(message));
+			return;
+		end
+		
+		session.print("OK: "..tostring(message));
+	end
+end
+
+function console_listener.disconnect(conn, err)
+	
+end
+
+connlisteners_register('console', console_listener);
+
+-- Console commands --
+-- These are simple commands, not valid standalone in Lua
+
+function commands.bye(session)
+	session.print("See you! :)");
+	session.disconnect();
+end
+
+commands["!"] = function (session, data)
+	if data:match("^!!") then
+		session.print("!> "..session.env._);
+		return console_listener.listener(session.conn, session.env._);
+	end
+	local old, new = data:match("^!(.-[^\\])!(.-)!$");
+	if old and new then
+		local ok, res = pcall(string.gsub, session.env._, old, new);
+		if not ok then
+			session.print(res)
+			return;
+		end
+		session.print("!> "..res);
+		return console_listener.listener(session.conn, res);
+	end
+	session.print("Sorry, not sure what you want");
+end
+
+-- Session environment --
+-- Anything in default_env will be accessible within the session as a global variable
+
+default_env.server = {};
+function default_env.server.reload()
+	dofile "main.lua"
+	return true, "Server reloaded";
+end
+
+default_env.module = {};
+function default_env.module.load(name)
+	local mm = require "modulemanager";
+	local ok, err = mm.load(name);
+	if not ok then
+		return false, err or "Unknown error loading module";
+	end
+	return true, "Module loaded";
+end
+
+default_env.config = {};
+function default_env.config.load(filename, format)
+	local cfgm_load = require "core.configmanager".load;
+	local ok, err = cfgm_load(filename, format);
+	if not ok then
+		return false, err or "Unknown error loading config";
+	end
+	return true, "Config loaded";
+end
--- a/plugins/mod_selftests.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/plugins/mod_selftests.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -3,6 +3,8 @@
 local register_component = require "core.componentmanager".register_component;
 local core_route_stanza = core_route_stanza;
 local socket = require "socket";
+local config = require "core.configmanager";
+local ping_hosts = config.get("*", "mod_selftests", "ping_hosts") or { "jabber.org" };
 
 local open_pings = {};
 
@@ -10,7 +12,7 @@
 
 local log = require "util.logger".init("mod_selftests");
 
-local tests_jid, host; "self_tests@getjabber.ath.cx";
+local tests_jid = "self_tests@getjabber.ath.cx";
 local host = "getjabber.ath.cx";
 
 if not (tests_jid and host) then
@@ -44,14 +46,8 @@
 							open_pings[id] = socket.gettime();
 						end
 						
-						send_ping "matthewwild.co.uk"
-						send_ping "snikket.com"
-						send_ping "gmail.com"
-						send_ping "isode.com"
-						send_ping "jabber.org"
-						send_ping "chrome.pl"
-						send_ping "swissjabber.ch"
-						send_ping "soapbox.net"
-						send_ping "jabber.ccc.de"
+						for _, host in ipairs(ping_hosts) do
+							send_ping(host);
+						end
 					end);
 end
--- a/util/stanza.lua	Sun Nov 23 03:32:57 2008 +0500
+++ b/util/stanza.lua	Sun Nov 23 05:03:36 2008 +0000
@@ -30,6 +30,11 @@
 function stanza_mt:query(xmlns)
 	return self:tag("query", { xmlns = xmlns });
 end
+
+function stanza_mt:body(text, attr)
+	return self:tag("body", attr):text(text);
+end
+
 function stanza_mt:tag(name, attrs)
 	local s = stanza(name, attrs);
 	(self.last_add[#self.last_add] or self):add_direct_child(s);

mercurial