From 92ffd5b909badeafabbf73b73a6946a5440c8be5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 16 Aug 2013 23:11:56 +0200
Subject: Fix building sluift as .dll on Mac OS X.

Change-Id: Ia8043d66ef676048e7fe1d0347b65e8d64aa3bd5

diff --git a/.scons2ninja.conf b/.scons2ninja.conf
index f6c470e..9a5e68c 100644
--- a/.scons2ninja.conf
+++ b/.scons2ninja.conf
@@ -14,3 +14,9 @@ def ninja_post(ninja) :
 		ninja.build(['Swift', 'swift'], 'phony', 'Swift/QtUI/swift-im')
 	else :
 		ninja.build(['Swift', 'swift'], 'phony', re.compile('Swift/QtUI/Swift\.app/(.*)'))
+	
+	# Sluift
+	if sys.platform == 'win32' :
+		ninja.build(['Sluift', 'sluift'], 'phony', ['Sluift/sluift.exe', 'Sluift/sluift.dll'])
+	elif sys.platform in ['posix', 'darwin'] :
+		ninja.build(['Sluift', 'sluift'], 'phony', ['Sluift/sluift', 'Sluift/sluift.so'])
diff --git a/3rdParty/Lua/SConscript b/3rdParty/Lua/SConscript
index acb2fba..f73286f 100644
--- a/3rdParty/Lua/SConscript
+++ b/3rdParty/Lua/SConscript
@@ -31,10 +31,6 @@ if env.get("LUA_BUNDLED", False) :
 
 	if env["SCONS_STAGE"] == "build" :
 		myenv = env.Clone()
-		if env["PLATFORM"] == "win32" :
-			myenv.Append(CFLAGS = ["/TP"])
-		else :
-			myenv.Append(CFLAGS = ["-x", "c++"])
 
 		# Remove warn flags
 		myenv.Replace(CCFLAGS = [flag for flag in env["CCFLAGS"] if not flag.startswith("-W")])
diff --git a/3rdParty/Lua/src/lua.hpp b/3rdParty/Lua/src/lua.hpp
new file mode 100644
index 0000000..5060a4e
--- /dev/null
+++ b/3rdParty/Lua/src/lua.hpp
@@ -0,0 +1,5 @@
+extern "C" {
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+}
diff --git a/Sluift/ClientHelpers.cpp b/Sluift/ClientHelpers.cpp
new file mode 100644
index 0000000..8e07112
--- /dev/null
+++ b/Sluift/ClientHelpers.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ClientHelpers.h>
+
+#include <Swiften/Client/ClientError.h>
+
+using namespace Swift;
+
+std::string Swift::getClientErrorString(const ClientError& error) {
+	std::string reason = "Disconnected: ";
+	switch(error.getType()) {
+		case ClientError::UnknownError: reason += "Unknown Error"; break;
+		case ClientError::DomainNameResolveError: reason += "Unable to find server"; break;
+		case ClientError::ConnectionError: reason += "Error connecting to server"; break;
+		case ClientError::ConnectionReadError: reason += "Error while receiving server data"; break;
+		case ClientError::ConnectionWriteError: reason += "Error while sending data to the server"; break;
+		case ClientError::XMLError: reason += "Error parsing server data"; break;
+		case ClientError::AuthenticationFailedError: reason += "Login/password invalid"; break;
+		case ClientError::CompressionFailedError: reason += "Error while compressing stream"; break;
+		case ClientError::ServerVerificationFailedError: reason += "Server verification failed"; break;
+		case ClientError::NoSupportedAuthMechanismsError: reason += "Authentication mechanisms not supported"; break;
+		case ClientError::UnexpectedElementError: reason += "Unexpected response"; break;
+		case ClientError::ResourceBindError: reason += "Error binding resource"; break;
+		case ClientError::RevokedError: reason += "Certificate got revoked"; break;
+		case ClientError::RevocationCheckFailedError: reason += "Failed to do revokation check"; break;
+		case ClientError::SessionStartError: reason += "Error starting session"; break;
+		case ClientError::StreamError: reason += "Stream error"; break;
+		case ClientError::TLSError: reason += "Encryption error"; break;
+		case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid password?)"; break;
+		case ClientError::ClientCertificateError: reason += "Certificate not authorized"; break;
+		case ClientError::UnknownCertificateError: reason += "Unknown certificate"; break;
+		case ClientError::CertificateCardRemoved: reason += "Certificate card removed"; break;
+		case ClientError::CertificateExpiredError: reason += "Certificate has expired"; break;
+		case ClientError::CertificateNotYetValidError: reason += "Certificate is not yet valid"; break;
+		case ClientError::CertificateSelfSignedError: reason += "Certificate is self-signed"; break;
+		case ClientError::CertificateRejectedError: reason += "Certificate has been rejected"; break;
+		case ClientError::CertificateUntrustedError: reason += "Certificate is not trusted"; break;
+		case ClientError::InvalidCertificatePurposeError: reason += "Certificate cannot be used for encrypting your connection"; break;
+		case ClientError::CertificatePathLengthExceededError: reason += "Certificate path length constraint exceeded"; break;
+		case ClientError::InvalidCertificateSignatureError: reason += "Invalid certificate signature"; break;
+		case ClientError::InvalidCAError: reason += "Invalid Certificate Authority"; break;
+		case ClientError::InvalidServerIdentityError: reason += "Certificate does not match the host identity"; break;
+	}
+	return reason;
+}
+
diff --git a/Sluift/ClientHelpers.h b/Sluift/ClientHelpers.h
new file mode 100644
index 0000000..eb78ba6
--- /dev/null
+++ b/Sluift/ClientHelpers.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/Override.h>
+#include <Swiften/Base/API.h>
+
+#include <string>
+
+namespace Swift {
+	class ClientError;
+
+	std::string getClientErrorString(const ClientError& error);
+}
diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp
index 817cbf3..4f8078e 100644
--- a/Sluift/Lua/Value.cpp
+++ b/Sluift/Lua/Value.cpp
@@ -6,7 +6,9 @@
 
 #include "Value.h"
 
-#include <lualib.h>
+extern "C" {
+	#include <lualib.h>
+}
 #include <boost/variant/apply_visitor.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 #include <Swiften/Base/foreach.h>
diff --git a/Sluift/SConscript b/Sluift/SConscript
index 2c247d8..af3cf8c 100644
--- a/Sluift/SConscript
+++ b/Sluift/SConscript
@@ -8,17 +8,13 @@ if env["SCONS_STAGE"] == "build" and not GetOption("help") and not env.get("HAVE
 		env["PROJECTS"].remove("Sluift")
 		
 elif env["SCONS_STAGE"] == "build" :
-	lib_env = env.Clone()
-	lib_env.UseFlags(env["LUA_FLAGS"])
-	lib_env.UseFlags(env["SWIFTEN_FLAGS"])
-	lib_env.UseFlags(env["SWIFTEN_DEP_FLAGS"])
-	sluift_lib = lib_env.StaticLibrary("SluiftCore", [
-			"Lua/Value.cpp",
-			"sluift.cpp"
-		]);
+	sluift_sources = [
+		"Lua/Value.cpp",
+		"ClientHelpers.cpp",
+		"sluift.cpp"
+	]
 
 	myenv = env.Clone()
-	myenv.Append(LIBS = sluift_lib)
 	myenv.UseFlags(env.get("LUA_FLAGS", {}))
 	myenv.UseFlags(env["SWIFTEN_FLAGS"])
 	myenv.UseFlags(env["SWIFTEN_DEP_FLAGS"])
@@ -27,10 +23,6 @@ elif env["SCONS_STAGE"] == "build" :
 		myenv.Append(CPPDEFINES = ["SLUIFT_BUILD_DLL"])
 	elif myenv["PLATFORM"] == "darwin" :
 		myenv["SHLIBSUFFIX"] = ".so"
-	if env["PLATFORM"] == "win32" :
-		myenv.Append(CFLAGS = ["/TP"])
-	else :
-		myenv.Append(CFLAGS = ["-x", "c++"])
 
 	myenv["SLUIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "sluift")
 	def patchLua(env, target, source) :
@@ -51,13 +43,13 @@ elif env["SCONS_STAGE"] == "build" :
 	if myenv.get("HAVE_READLINE", False) :
 		myenv.Append(CPPDEFINES = ["LUA_USE_READLINE"])
 		myenv.MergeFlags(myenv["READLINE_FLAGS"])
-	env["SLUIFT"] = myenv.Program("sluift", [
+	env["SLUIFT"] = myenv.Program("sluift", sluift_sources + [
 			"lua.c",
 			"linit.c",
 		])
 
 	myenv.WriteVal("dll.c", myenv.Value(""))
-	myenv.SharedLibrary("sluift", ["dll.c"])
+	myenv.SharedLibrary("sluift", sluift_sources + ["dll.c"])
 
 	if env["PLATFORM"] == "win32" :
 		ssl_libs = []
diff --git a/Sluift/SluiftException.h b/Sluift/SluiftException.h
deleted file mode 100644
index 6964523..0000000
--- a/Sluift/SluiftException.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <string>
-
-#include <Swiften/Client/ClientError.h>
-
-namespace Swift {
-	class SluiftException : public std::exception {
-		public:
-			virtual ~SluiftException() throw() {}
-			
-			SluiftException(const std::string& reason) : reason(reason) {
-			}
-
-			SluiftException(const ClientError& error) {
-				reason = "Disconnected: ";
-				switch(error.getType()) {
-					case ClientError::UnknownError: reason += "Unknown Error"; break;
-					case ClientError::DomainNameResolveError: reason += "Unable to find server"; break;
-					case ClientError::ConnectionError: reason += "Error connecting to server"; break;
-					case ClientError::ConnectionReadError: reason += "Error while receiving server data"; break;
-					case ClientError::ConnectionWriteError: reason += "Error while sending data to the server"; break;
-					case ClientError::XMLError: reason += "Error parsing server data"; break;
-					case ClientError::AuthenticationFailedError: reason += "Login/password invalid"; break;
-					case ClientError::CompressionFailedError: reason += "Error while compressing stream"; break;
-					case ClientError::ServerVerificationFailedError: reason += "Server verification failed"; break;
-					case ClientError::NoSupportedAuthMechanismsError: reason += "Authentication mechanisms not supported"; break;
-					case ClientError::UnexpectedElementError: reason += "Unexpected response"; break;
-					case ClientError::ResourceBindError: reason += "Error binding resource"; break;
-					case ClientError::RevokedError: reason += "Certificate got revoked"; break;
-					case ClientError::RevocationCheckFailedError: reason += "Failed to do revokation check"; break;
-					case ClientError::SessionStartError: reason += "Error starting session"; break;
-					case ClientError::StreamError: reason += "Stream error"; break;
-					case ClientError::TLSError: reason += "Encryption error"; break;
-					case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid password?)"; break;
-					case ClientError::ClientCertificateError: reason += "Certificate not authorized"; break;
-					case ClientError::UnknownCertificateError: reason += "Unknown certificate"; break;
-					case ClientError::CertificateCardRemoved: reason += "Certificate card removed"; break;
-					case ClientError::CertificateExpiredError: reason += "Certificate has expired"; break;
-					case ClientError::CertificateNotYetValidError: reason += "Certificate is not yet valid"; break;
-					case ClientError::CertificateSelfSignedError: reason += "Certificate is self-signed"; break;
-					case ClientError::CertificateRejectedError: reason += "Certificate has been rejected"; break;
-					case ClientError::CertificateUntrustedError: reason += "Certificate is not trusted"; break;
-					case ClientError::InvalidCertificatePurposeError: reason += "Certificate cannot be used for encrypting your connection"; break;
-					case ClientError::CertificatePathLengthExceededError: reason += "Certificate path length constraint exceeded"; break;
-					case ClientError::InvalidCertificateSignatureError: reason += "Invalid certificate signature"; break;
-					case ClientError::InvalidCAError: reason += "Invalid Certificate Authority"; break;
-					case ClientError::InvalidServerIdentityError: reason += "Certificate does not match the host identity"; break;
-				}
-			}
-
-			const std::string& getReason() const {
-				return reason;
-			}
-
-			virtual const char* what() const throw() {
-				return getReason().c_str();
-			}
-
-
-		private:
-			std::string reason;
-	};
-}
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 0a653bb..397d7f3 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,9 +17,9 @@
 #include <Swiften/Swiften.h>
 
 #include "Watchdog.h"
-#include "SluiftException.h"
 #include "ResponseSink.h"
 #include "Lua/Value.h"
+#include "ClientHelpers.h"
 
 using namespace Swift;
 
@@ -42,7 +42,7 @@ static BoostNetworkFactories networkFactories(&eventLoop);
 
 class SluiftClient {
 	public:
-		SluiftClient(const JID& jid, const std::string& password) : tracer(NULL) {
+		SluiftClient(const JID& jid, const std::string& password, lua_State* L) : L(L), tracer(NULL) {
 			client = new Client(jid, password, &networkFactories);
 			client->setAlwaysTrustCertificates();
 			client->onDisconnected.connect(boost::bind(&SluiftClient::handleDisconnected, this, _1));
@@ -85,7 +85,7 @@ class SluiftClient {
 			}
 			if (watchdog.getTimedOut()) {
 				client->disconnect();
-				throw SluiftException("Timeout while connecting");
+				luaL_error(L, "Timeout while connecting");
 			}
 		}
 
@@ -183,11 +183,12 @@ class SluiftClient {
 
 		void handleDisconnected(const boost::optional<ClientError>& error) {
 			if (error) {
-				throw SluiftException(*error);
+				luaL_error(L, getClientErrorString(*error).c_str());
 			}
 		}
 	
 	private:
+		lua_State* L;
 		Client* client;
 		ClientOptions options;
 		ClientXMLTracer* tracer;
@@ -205,44 +206,29 @@ static inline SluiftClient* getClient(lua_State* L) {
 }
 
 static int sluift_client_connect(lua_State *L) {
-	try {
-		SluiftClient* client = getClient(L);
-		std::string host;
-		if (lua_type(L, 2) != LUA_TNONE) {
-			host = luaL_checkstring(L, 2);
-		}
-		if (host.empty()) {
-			client->connect();
-		}
-		else {
-			client->connect(host);
-		}
-		client->waitConnected();
-		return 1;
+	SluiftClient* client = getClient(L);
+	std::string host;
+	if (lua_type(L, 2) != LUA_TNONE) {
+		host = luaL_checkstring(L, 2);
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	if (host.empty()) {
+		client->connect();
 	}
+	else {
+		client->connect(host);
+	}
+	client->waitConnected();
+	return 1;
 }
 
 static int sluift_client_async_connect(lua_State *L) {
-	try {
-		getClient(L)->connect();
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->connect();
+	return 1;
 }
 
 static int sluift_client_wait_connected(lua_State *L) {
-	try {
-		getClient(L)->waitConnected();
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->waitConnected();
+	return 1;
 }
 
 static int sluift_client_is_connected(lua_State *L) {
@@ -251,221 +237,176 @@ static int sluift_client_is_connected(lua_State *L) {
 }
 
 static int sluift_client_disconnect(lua_State *L) {
-	try {
-		getClient(L)->disconnect();
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->disconnect();
+	return 1;
 }
 
 static int sluift_client_set_version(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		SluiftClient* client = getClient(L);
-		luaL_checktype(L, 2, LUA_TTABLE);
-		lua_getfield(L, 2, "name");
-		const char* rawName = lua_tostring(L, -1);
-		lua_getfield(L, 2, "version");
-		const char* rawVersion = lua_tostring(L, -1);
-		lua_getfield(L, 2, "os");
-		const char* rawOS = lua_tostring(L, -1);
-		client->setSoftwareVersion(rawName ? rawName : "", rawVersion ? rawVersion : "", rawOS ? rawOS : "");
-		lua_pop(L, 3);
-		lua_pushvalue(L, 1);
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	SluiftClient* client = getClient(L);
+	luaL_checktype(L, 2, LUA_TTABLE);
+	lua_getfield(L, 2, "name");
+	const char* rawName = lua_tostring(L, -1);
+	lua_getfield(L, 2, "version");
+	const char* rawVersion = lua_tostring(L, -1);
+	lua_getfield(L, 2, "os");
+	const char* rawOS = lua_tostring(L, -1);
+	client->setSoftwareVersion(rawName ? rawName : "", rawVersion ? rawVersion : "", rawOS ? rawOS : "");
+	lua_pop(L, 3);
+	lua_pushvalue(L, 1);
+	return 1;
 }
 
 static int sluift_client_get_contacts(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		SluiftClient* client = getClient(L);
-		Lua::Table contactsTable;
-		foreach(const XMPPRosterItem& item, client->getRoster()) {
-			std::string subscription;
-			switch(item.getSubscription()) {
-				case RosterItemPayload::None: subscription = "none"; break;
-				case RosterItemPayload::To: subscription = "to"; break;
-				case RosterItemPayload::From: subscription = "from"; break;
-				case RosterItemPayload::Both: subscription = "both"; break;
-				case RosterItemPayload::Remove: subscription = "remove"; break;
-			}
-			Lua::Value groups(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end()));
-			Lua::Table itemTable = boost::assign::map_list_of
-				("jid", boost::make_shared<Lua::Value>(item.getJID().toString()))
-				("name", boost::make_shared<Lua::Value>(item.getName()))
-				("subscription", boost::make_shared<Lua::Value>(subscription))
-				("groups", boost::make_shared<Lua::Value>(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end())));
-			contactsTable[item.getJID().toString()] = boost::make_shared<Lua::Value>(itemTable);
-		}
-		pushValue(L, contactsTable);
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	SluiftClient* client = getClient(L);
+	Lua::Table contactsTable;
+	foreach(const XMPPRosterItem& item, client->getRoster()) {
+		std::string subscription;
+		switch(item.getSubscription()) {
+			case RosterItemPayload::None: subscription = "none"; break;
+			case RosterItemPayload::To: subscription = "to"; break;
+			case RosterItemPayload::From: subscription = "from"; break;
+			case RosterItemPayload::Both: subscription = "both"; break;
+			case RosterItemPayload::Remove: subscription = "remove"; break;
+		}
+		Lua::Value groups(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end()));
+		Lua::Table itemTable = boost::assign::map_list_of
+			("jid", boost::make_shared<Lua::Value>(item.getJID().toString()))
+			("name", boost::make_shared<Lua::Value>(item.getName()))
+			("subscription", boost::make_shared<Lua::Value>(subscription))
+			("groups", boost::make_shared<Lua::Value>(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end())));
+		contactsTable[item.getJID().toString()] = boost::make_shared<Lua::Value>(itemTable);
+	}
+	pushValue(L, contactsTable);
+	return 1;
 }
 
 static int sluift_client_get_version(lua_State *L) {
-	try {
-		SluiftClient* client = getClient(L);
-		int timeout = -1;
-		if (lua_type(L, 3) != LUA_TNONE) {
-			timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
-		}
+	SluiftClient* client = getClient(L);
+	int timeout = -1;
+	if (lua_type(L, 3) != LUA_TNONE) {
+		timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
+	}
 
-		ResponseSink<SoftwareVersion> sink;
-		GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(std::string(luaL_checkstring(L, 2)), client->getClient()->getIQRouter());
-		boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
-		request->send();
+	ResponseSink<SoftwareVersion> sink;
+	GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(std::string(luaL_checkstring(L, 2)), client->getClient()->getIQRouter());
+	boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
+	request->send();
 
-		Watchdog watchdog(timeout, networkFactories.getTimerFactory());
-		while (!watchdog.getTimedOut() && !sink.hasResponse()) {
-			eventLoop.runUntilEvents();
-		}
+	Watchdog watchdog(timeout, networkFactories.getTimerFactory());
+	while (!watchdog.getTimedOut() && !sink.hasResponse()) {
+		eventLoop.runUntilEvents();
+	}
 
-		ErrorPayload::ref error = sink.getResponseError();
-		if (error || watchdog.getTimedOut()) {
-			lua_pushnil(L);
-			if (watchdog.getTimedOut()) {
-				lua_pushstring(L, "Timeout");
-			}
-			else if (error->getCondition() == ErrorPayload::RemoteServerNotFound) {
-				lua_pushstring(L, "Remote server not found");
-			}
-			// TODO
-			else {
-				lua_pushstring(L, "Error");
-			}
-			return 2;
+	ErrorPayload::ref error = sink.getResponseError();
+	if (error || watchdog.getTimedOut()) {
+		lua_pushnil(L);
+		if (watchdog.getTimedOut()) {
+			lua_pushstring(L, "Timeout");
 		}
-		else if (SoftwareVersion::ref version = sink.getResponsePayload()) {
-			Lua::Table result = boost::assign::map_list_of
-				("name", boost::make_shared<Lua::Value>(version->getName()))
-				("version", boost::make_shared<Lua::Value>(version->getVersion()))
-				("os", boost::make_shared<Lua::Value>(version->getOS()));
-			Lua::pushValue(L, result);
+		else if (error->getCondition() == ErrorPayload::RemoteServerNotFound) {
+			lua_pushstring(L, "Remote server not found");
 		}
+		// TODO
 		else {
-			lua_pushnil(L);
+			lua_pushstring(L, "Error");
 		}
-		return 1;
+		return 2;
+	}
+	else if (SoftwareVersion::ref version = sink.getResponsePayload()) {
+		Lua::Table result = boost::assign::map_list_of
+			("name", boost::make_shared<Lua::Value>(version->getName()))
+			("version", boost::make_shared<Lua::Value>(version->getVersion()))
+			("os", boost::make_shared<Lua::Value>(version->getOS()));
+		Lua::pushValue(L, result);
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	else {
+		lua_pushnil(L);
 	}
+	return 1;
 }
 
 static int sluift_client_send_message(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		getClient(L)->sendMessage(std::string(luaL_checkstring(L, 2)), luaL_checkstring(L, 3));
-		lua_pushvalue(L, 1);
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->sendMessage(std::string(luaL_checkstring(L, 2)), luaL_checkstring(L, 3));
+	lua_pushvalue(L, 1);
+	return 1;
 }
 
 static int sluift_client_send_presence(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2)));
-		lua_pushvalue(L, 1);
-		return 0;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2)));
+	lua_pushvalue(L, 1);
+	return 0;
 }
 
 static int sluift_client_get(lua_State *L) {
-	try {
-		SluiftClient* client = getClient(L);
-		JID jid;
-		std::string data;
-		int timeout = -1;
-		if (lua_type(L, 3) == LUA_TSTRING) {
-			jid = JID(std::string(luaL_checkstring(L, 2)));
-			data = std::string(luaL_checkstring(L, 3));
-			if (lua_type(L, 4) != LUA_TNONE) {
-				timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
-			}
-		}
-		else {
-			data = std::string(luaL_checkstring(L, 2));
-			if (lua_type(L, 3) != LUA_TNONE) {
-				timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
-			}
-		}
-		boost::optional<std::string> result = client->sendQuery(jid, IQ::Get, data, timeout);
-		if (result) {
-			lua_pushstring(L, result->c_str());
+	SluiftClient* client = getClient(L);
+	JID jid;
+	std::string data;
+	int timeout = -1;
+	if (lua_type(L, 3) == LUA_TSTRING) {
+		jid = JID(std::string(luaL_checkstring(L, 2)));
+		data = std::string(luaL_checkstring(L, 3));
+		if (lua_type(L, 4) != LUA_TNONE) {
+			timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
 		}
-		else {
-			lua_pushnil(L);
+	}
+	else {
+		data = std::string(luaL_checkstring(L, 2));
+		if (lua_type(L, 3) != LUA_TNONE) {
+			timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
 		}
-		return 1;
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	boost::optional<std::string> result = client->sendQuery(jid, IQ::Get, data, timeout);
+	if (result) {
+		lua_pushstring(L, result->c_str());
 	}
+	else {
+		lua_pushnil(L);
+	}
+	return 1;
 }
 
 static int sluift_client_set(lua_State *L) {
-	try {
-		SluiftClient* client = getClient(L);
-		JID jid;
-		std::string data;
-		int timeout = -1;
-		if (lua_type(L, 3) == LUA_TSTRING) {
-			jid = JID(std::string(luaL_checkstring(L, 2)));
-			data = std::string(luaL_checkstring(L, 3));
-			if (lua_type(L, 4) != LUA_TNONE) {
-				timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
-			}
-		}
-		else {
-			data = std::string(luaL_checkstring(L, 2));
-			if (lua_type(L, 3) != LUA_TNONE) {
-				timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
-			}
-		}
-		boost::optional<std::string> result = client->sendQuery(jid, IQ::Set, data, timeout);
-		if (result) {
-			lua_pushstring(L, result->c_str());
+	SluiftClient* client = getClient(L);
+	JID jid;
+	std::string data;
+	int timeout = -1;
+	if (lua_type(L, 3) == LUA_TSTRING) {
+		jid = JID(std::string(luaL_checkstring(L, 2)));
+		data = std::string(luaL_checkstring(L, 3));
+		if (lua_type(L, 4) != LUA_TNONE) {
+			timeout = boost::numeric_cast<int>(luaL_checknumber(L, 4));
 		}
-		else {
-			lua_pushnil(L);
+	}
+	else {
+		data = std::string(luaL_checkstring(L, 2));
+		if (lua_type(L, 3) != LUA_TNONE) {
+			timeout = boost::numeric_cast<int>(luaL_checknumber(L, 3));
 		}
-		return 1;
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	boost::optional<std::string> result = client->sendQuery(jid, IQ::Set, data, timeout);
+	if (result) {
+		lua_pushstring(L, result->c_str());
+	}
+	else {
+		lua_pushnil(L);
 	}
+	return 1;
 }
 
 static int sluift_client_send(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		getClient(L)->getClient()->sendData(std::string(luaL_checkstring(L, 2)));
-		lua_pushvalue(L, 1);
-		return 0;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	getClient(L)->getClient()->sendData(std::string(luaL_checkstring(L, 2)));
+	lua_pushvalue(L, 1);
+	return 0;
 }
 
 static int sluift_client_set_options(lua_State* L) {
@@ -509,131 +450,91 @@ static void pushEvent(lua_State* L, Stanza::ref event) {
 }
 
 static int sluift_client_for_event(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		SluiftClient* client = getClient(L);
-		luaL_checktype(L, 2, LUA_TFUNCTION);
-		int timeout = -1;
-		if (lua_type(L, 3) != LUA_TNONE) {
-			timeout = boost::numeric_cast<int>(lua_tonumber(L, 3));
-		}
+	SluiftClient* client = getClient(L);
+	luaL_checktype(L, 2, LUA_TFUNCTION);
+	int timeout = -1;
+	if (lua_type(L, 3) != LUA_TNONE) {
+		timeout = boost::numeric_cast<int>(lua_tonumber(L, 3));
+	}
 
-		while (true) {
-			Stanza::ref event = client->getNextEvent(timeout);
-			if (!event) {
-				// We got a timeout
-				lua_pushnil(L);
-				return 1;
-			}
-			else {
-				// Push the function and event on the stack
-				lua_pushvalue(L, 2);
-				pushEvent(L, event);
-				int oldTop = lua_gettop(L) - 2;
-				lua_call(L, 1, LUA_MULTRET);
-				int returnValues = lua_gettop(L) - oldTop;
-				if (returnValues > 0) {
-					lua_remove(L, -1 - returnValues);
-					return returnValues;
-				}
+	while (true) {
+		Stanza::ref event = client->getNextEvent(timeout);
+		if (!event) {
+			// We got a timeout
+			lua_pushnil(L);
+			return 1;
+		}
+		else {
+			// Push the function and event on the stack
+			lua_pushvalue(L, 2);
+			pushEvent(L, event);
+			int oldTop = lua_gettop(L) - 2;
+			lua_call(L, 1, LUA_MULTRET);
+			int returnValues = lua_gettop(L) - oldTop;
+			if (returnValues > 0) {
+				lua_remove(L, -1 - returnValues);
+				return returnValues;
 			}
 		}
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
 }
 
 static int sluift_client_get_next_event(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		SluiftClient* client = getClient(L);
-		int timeout = -1;
-		if (lua_type(L, 2) != LUA_TNONE) {
-			timeout = boost::numeric_cast<int>(lua_tonumber(L, 2));
-		}
-		pushEvent(L, client->getNextEvent(timeout));
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	SluiftClient* client = getClient(L);
+	int timeout = -1;
+	if (lua_type(L, 2) != LUA_TNONE) {
+		timeout = boost::numeric_cast<int>(lua_tonumber(L, 2));
 	}
+	pushEvent(L, client->getNextEvent(timeout));
+	return 1;
 }
 
 
 static int sluift_client_add_contact(lua_State* L) {
-	try {
-		eventLoop.runOnce();
-		SluiftClient* client = getClient(L);
-		RosterItemPayload item;
-		if (lua_type(L, 2) == LUA_TTABLE) {
-			lua_getfield(L, 2, "jid");
-			const char* rawJID = lua_tostring(L, -1);
-			if (rawJID) {
-				item.setJID(std::string(rawJID));
-			}
-			lua_getfield(L, 2, "name");
-			const char* rawName = lua_tostring(L, -1);
-			if (rawName) {
-				item.setName(rawName);
-			}
-			lua_getfield(L, 2, "groups");
-			if (!lua_isnil(L, -1)) {
-				if (lua_type(L, -1) == LUA_TTABLE) {
-					for (size_t i = 1; i <= lua_objlen(L, -1); ++i) {
-						lua_rawgeti(L, -1, boost::numeric_cast<int>(i));
-						const char* rawGroup = lua_tostring(L, -1);
-						if (rawGroup) {
-							item.addGroup(rawGroup);
-						}
-						lua_pop(L, 1);
+	eventLoop.runOnce();
+	SluiftClient* client = getClient(L);
+	RosterItemPayload item;
+	if (lua_type(L, 2) == LUA_TTABLE) {
+		lua_getfield(L, 2, "jid");
+		const char* rawJID = lua_tostring(L, -1);
+		if (rawJID) {
+			item.setJID(std::string(rawJID));
+		}
+		lua_getfield(L, 2, "name");
+		const char* rawName = lua_tostring(L, -1);
+		if (rawName) {
+			item.setName(rawName);
+		}
+		lua_getfield(L, 2, "groups");
+		if (!lua_isnil(L, -1)) {
+			if (lua_type(L, -1) == LUA_TTABLE) {
+				for (size_t i = 1; i <= lua_objlen(L, -1); ++i) {
+					lua_rawgeti(L, -1, boost::numeric_cast<int>(i));
+					const char* rawGroup = lua_tostring(L, -1);
+					if (rawGroup) {
+						item.addGroup(rawGroup);
 					}
-				}
-				else {
-					return luaL_error(L, "Groups should be a table");
+					lua_pop(L, 1);
 				}
 			}
-		}
-		else {
-			item.setJID(luaL_checkstring(L, 2));
-		}
-
-		client->getRoster();
-		if (!client->getClient()->getRoster()->containsJID(item.getJID())) {
-			RosterPayload::ref roster = boost::make_shared<RosterPayload>();
-			roster->addItem(item);
-
-			ResponseSink<RosterPayload> sink;
-			SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
-			boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
-			request->send();
-			while (!sink.hasResponse()) {
-				eventLoop.runUntilEvents();
-			}
-			if (sink.getResponseError()) {
-				lua_pushboolean(L, false);
-				return 1;
+			else {
+				return luaL_error(L, "Groups should be a table");
 			}
 		}
-		client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID());
-		lua_pushboolean(L, true);
-		return 1;
 	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	else {
+		item.setJID(luaL_checkstring(L, 2));
 	}
-}
-
-static int sluift_client_remove_contact(lua_State* L) {
-	try {
-		eventLoop.runOnce();
-		SluiftClient* client = getClient(L);
-		JID jid(luaL_checkstring(L, 2));
 
+	client->getRoster();
+	if (!client->getClient()->getRoster()->containsJID(item.getJID())) {
 		RosterPayload::ref roster = boost::make_shared<RosterPayload>();
-		roster->addItem(RosterItemPayload(JID(luaL_checkstring(L, 2)), "", RosterItemPayload::Remove));
+		roster->addItem(item);
+
 		ResponseSink<RosterPayload> sink;
 		SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
 		boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
@@ -641,38 +542,48 @@ static int sluift_client_remove_contact(lua_State* L) {
 		while (!sink.hasResponse()) {
 			eventLoop.runUntilEvents();
 		}
-		lua_pushboolean(L, !sink.getResponseError());
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+		if (sink.getResponseError()) {
+			lua_pushboolean(L, false);
+			return 1;
+		}
 	}
+	client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID());
+	lua_pushboolean(L, true);
+	return 1;
+}
+
+static int sluift_client_remove_contact(lua_State* L) {
+	eventLoop.runOnce();
+	SluiftClient* client = getClient(L);
+	JID jid(luaL_checkstring(L, 2));
+
+	RosterPayload::ref roster = boost::make_shared<RosterPayload>();
+	roster->addItem(RosterItemPayload(JID(luaL_checkstring(L, 2)), "", RosterItemPayload::Remove));
+	ResponseSink<RosterPayload> sink;
+	SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
+	boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
+	request->send();
+	while (!sink.hasResponse()) {
+		eventLoop.runUntilEvents();
+	}
+	lua_pushboolean(L, !sink.getResponseError());
+	return 1;
 }
 
 static int sluift_client_confirm_subscription(lua_State* L) {
-	try {
-		eventLoop.runOnce();
-		SluiftClient* client = getClient(L);
-		JID jid(luaL_checkstring(L, 2));
-		client->getClient()->getSubscriptionManager()->confirmSubscription(jid);
-		return 0;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	eventLoop.runOnce();
+	SluiftClient* client = getClient(L);
+	JID jid(luaL_checkstring(L, 2));
+	client->getClient()->getSubscriptionManager()->confirmSubscription(jid);
+	return 0;
 }
 
 static int sluift_client_cancel_subscription(lua_State* L) {
-	try {
-		eventLoop.runOnce();
-		SluiftClient* client = getClient(L);
-		JID jid(luaL_checkstring(L, 2));
-		client->getClient()->getSubscriptionManager()->cancelSubscription(jid);
-		return 0;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	eventLoop.runOnce();
+	SluiftClient* client = getClient(L);
+	JID jid(luaL_checkstring(L, 2));
+	client->getClient()->getSubscriptionManager()->cancelSubscription(jid);
+	return 0;
 }
 
 static int sluift_client_gc (lua_State *L) {
@@ -711,20 +622,16 @@ static const luaL_reg sluift_client_functions[] = {
  ******************************************************************************/
 
 static int sluift_new_client(lua_State *L) {
-	try {
-		JID jid(std::string(luaL_checkstring(L, 1)));
-		std::string password(luaL_checkstring(L, 2));
+	luaL_checkstring(L, 1);
+	JID jid(std::string(luaL_checkstring(L, 1)));
+	std::string password(luaL_checkstring(L, 2));
 
-		SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
-		luaL_getmetatable(L, SLUIFT_CLIENT);
-		lua_setmetatable(L, -2);
+	SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
+	luaL_getmetatable(L, SLUIFT_CLIENT);
+	lua_setmetatable(L, -2);
 
-		*client = new SluiftClient(jid, password);
-		return 1;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
-	}
+	*client = new SluiftClient(jid, password, L);
+	return 1;
 }
 
 static int sluift_jid_to_bare(lua_State *L) {
@@ -752,20 +659,15 @@ static int sluift_jid_resource(lua_State *L) {
 }
 
 static int sluift_sleep(lua_State *L) {
-	try {
-		eventLoop.runOnce();
+	eventLoop.runOnce();
 
-		int timeout = boost::numeric_cast<int>(luaL_checknumber(L, 1));
-		Watchdog watchdog(timeout, networkFactories.getTimerFactory());
-		while (!watchdog.getTimedOut()) {
-			Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
-			eventLoop.runOnce();
-		}
-		return 0;
-	}
-	catch (const SluiftException& e) {
-		return luaL_error(L, e.getReason().c_str());
+	int timeout = boost::numeric_cast<int>(luaL_checknumber(L, 1));
+	Watchdog watchdog(timeout, networkFactories.getTimerFactory());
+	while (!watchdog.getTimedOut()) {
+		Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
+		eventLoop.runOnce();
 	}
+	return 0;
 }
 
 static int sluift_index(lua_State *L) {
diff --git a/Sluift/sluift.h b/Sluift/sluift.h
index 27b4eab..4e0f5ee 100644
--- a/Sluift/sluift.h
+++ b/Sluift/sluift.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -9,9 +9,16 @@
 #if defined(SLUIFT_BUILD_DLL)
 #define SLUIFT_API __declspec(dllexport)
 #else
-#define SLUIFT_API extern
+#define SLUIFT_API
 #endif
 
+#if defined(__cplusplus)
+#include <lua.hpp>
+#else
 #include <lua.h>
+#endif
 
+#if defined(__cplusplus)
+extern "C"
+#endif
 SLUIFT_API int (luaopen_sluift)(lua_State *L);
diff --git a/Swiftob/LuaCommands.h b/Swiftob/LuaCommands.h
index 97ea87c..c5f959d 100644
--- a/Swiftob/LuaCommands.h
+++ b/Swiftob/LuaCommands.h
@@ -9,9 +9,7 @@
 #include <string>
 #include <vector>
 
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
+#include <lua.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/noncopyable.hpp>
 #include <Swiften/Network/NetworkFactories.h>
diff --git a/Swiftob/SConscript b/Swiftob/SConscript
index 424ae72..a830b84 100644
--- a/Swiftob/SConscript
+++ b/Swiftob/SConscript
@@ -13,7 +13,7 @@ elif env["SCONS_STAGE"] == "build":
 	myenv.UseFlags(myenv["SWIFTEN_FLAGS"])
 	myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"])
 	sources = [
-		"linit.cpp",
+		"linit.c",
 		"Swiftob.cpp",
 		"Users.cpp",
 		"Commands.cpp",
diff --git a/Swiftob/linit.c b/Swiftob/linit.c
new file mode 100644
index 0000000..13c5b09
--- /dev/null
+++ b/Swiftob/linit.c
@@ -0,0 +1 @@
+#include "../3rdParty/Lua/src/linit.c"
diff --git a/Swiftob/linit.cpp b/Swiftob/linit.cpp
deleted file mode 100644
index 13c5b09..0000000
--- a/Swiftob/linit.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "../3rdParty/Lua/src/linit.c"
-- 
cgit v0.10.2-6-g49f6